vellum 0.2.1 → 0.2.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/README.md +15 -2
- package/bun.lock +5 -2
- package/package.json +4 -2
- package/scripts/capture-x-graphql.ts +562 -0
- package/scripts/ipc/check-swift-decoder-drift.ts +2 -1
- package/scripts/test.sh +5 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +133 -34
- package/src/__tests__/account-registry.test.ts +2 -1
- package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
- package/src/__tests__/asset-materialize-tool.test.ts +16 -15
- package/src/__tests__/asset-search-tool.test.ts +23 -22
- package/src/__tests__/attachments-store.test.ts +56 -127
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +5 -4
- package/src/__tests__/browser-skill-endstate.test.ts +4 -3
- package/src/__tests__/call-bridge.test.ts +385 -0
- package/src/__tests__/call-constants.test.ts +40 -0
- package/src/__tests__/call-orchestrator.test.ts +130 -4
- package/src/__tests__/call-recovery.test.ts +518 -0
- package/src/__tests__/call-routes-http.test.ts +459 -0
- package/src/__tests__/call-state-machine.test.ts +143 -0
- package/src/__tests__/call-store.test.ts +216 -1
- package/src/__tests__/cli-discover.test.ts +1 -1
- package/src/__tests__/commit-message-enrichment-service.test.ts +148 -7
- package/src/__tests__/compaction.benchmark.test.ts +176 -0
- package/src/__tests__/computer-use-tools.test.ts +250 -0
- package/src/__tests__/config-schema.test.ts +299 -3
- package/src/__tests__/conflict-store.test.ts +2 -1
- package/src/__tests__/contacts-tools.test.ts +331 -0
- package/src/__tests__/conversation-store.test.ts +30 -32
- package/src/__tests__/credential-security-invariants.test.ts +4 -0
- package/src/__tests__/date-context.test.ts +373 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -3
- package/src/__tests__/followup-tools.test.ts +303 -0
- package/src/__tests__/handlers-twitter-config.test.ts +718 -0
- package/src/__tests__/intent-routing.test.ts +64 -57
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
- package/src/__tests__/ipc-snapshot.test.ts +62 -28
- package/src/__tests__/llm-usage-store.test.ts +3 -8
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
- package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
- package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
- package/src/__tests__/playbook-tools.test.ts +342 -0
- package/src/__tests__/profile-compiler.test.ts +2 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
- package/src/__tests__/recurrence-engine-rruleset.test.ts +78 -0
- package/src/__tests__/recurrence-engine.test.ts +69 -0
- package/src/__tests__/recurrence-types.test.ts +71 -0
- package/src/__tests__/registry.test.ts +5 -3
- package/src/__tests__/relay-server.test.ts +633 -0
- package/src/__tests__/reminder-store.test.ts +6 -3
- package/src/__tests__/reminder.test.ts +43 -77
- package/src/__tests__/run-orchestrator-assistant-events.test.ts +8 -4
- package/src/__tests__/run-orchestrator.test.ts +4 -4
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -6
- package/src/__tests__/runtime-runs-http.test.ts +4 -4
- package/src/__tests__/runtime-runs.test.ts +4 -4
- package/src/__tests__/schedule-store.test.ts +482 -0
- package/src/__tests__/schedule-tools.test.ts +700 -0
- package/src/__tests__/scheduler-recurrence.test.ts +329 -0
- package/src/__tests__/server-history-render.test.ts +14 -13
- package/src/__tests__/session-error.test.ts +28 -0
- package/src/__tests__/session-init.benchmark.test.ts +462 -0
- package/src/__tests__/session-queue.test.ts +71 -48
- package/src/__tests__/session-runtime-assembly.test.ts +161 -0
- package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
- package/src/__tests__/signup-e2e.test.ts +2 -1
- package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
- package/src/__tests__/skill-script-runner.test.ts +159 -0
- package/src/__tests__/speaker-identification.test.ts +52 -0
- package/src/__tests__/subagent-manager-notify.test.ts +42 -10
- package/src/__tests__/subagent-tools.test.ts +141 -41
- package/src/__tests__/task-compiler.test.ts +2 -1
- package/src/__tests__/task-runner.test.ts +2 -1
- package/src/__tests__/task-scheduler.test.ts +2 -1
- package/src/__tests__/task-tools.test.ts +49 -56
- package/src/__tests__/tool-audit-listener.test.ts +1 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
- package/src/__tests__/tool-executor.test.ts +13 -17
- package/src/__tests__/turn-commit.test.ts +218 -3
- package/src/__tests__/twilio-provider.test.ts +143 -0
- package/src/__tests__/twilio-routes.test.ts +789 -0
- package/src/__tests__/twitter-auth-handler.test.ts +581 -0
- package/src/__tests__/view-image-tool.test.ts +217 -0
- package/src/__tests__/workspace-git-service.test.ts +186 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +13 -3
- package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
- package/src/bundler/app-bundler.ts +12 -8
- package/src/calls/call-bridge.ts +95 -0
- package/src/calls/call-constants.ts +43 -5
- package/src/calls/call-domain.ts +276 -0
- package/src/calls/call-orchestrator.ts +43 -17
- package/src/calls/call-recovery.ts +207 -0
- package/src/calls/call-state-machine.ts +68 -0
- package/src/calls/call-store.ts +192 -5
- package/src/calls/relay-server.ts +41 -4
- package/src/calls/speaker-identification.ts +213 -0
- package/src/calls/twilio-provider.ts +10 -6
- package/src/calls/twilio-routes.ts +90 -76
- package/src/calls/types.ts +1 -1
- package/src/cli/config-commands.ts +334 -0
- package/src/cli/core-commands.ts +776 -0
- package/src/cli/doordash.ts +251 -1
- package/src/cli/ipc-client.ts +82 -0
- package/src/cli/map.ts +246 -0
- package/src/cli/twitter.ts +575 -0
- package/src/cli.ts +7 -5
- package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
- package/src/commands/cc-command-registry.ts +209 -0
- package/src/config/bundled-skills/contacts/SKILL.md +39 -0
- package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
- package/src/config/bundled-skills/document/SKILL.md +18 -0
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
- package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
- package/src/config/bundled-skills/doordash/SKILL.md +82 -23
- package/src/config/bundled-skills/followups/SKILL.md +32 -0
- package/src/config/bundled-skills/followups/TOOLS.json +100 -0
- package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -23
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -1
- package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
- package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +9 -0
- package/src/config/bundled-skills/reminder/SKILL.md +20 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
- package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
- package/src/config/bundled-skills/schedule/SKILL.md +74 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
- package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
- package/src/config/bundled-skills/subagent/SKILL.md +25 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
- package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
- package/src/config/bundled-skills/tasks/SKILL.md +28 -0
- package/src/config/bundled-skills/tasks/TOOLS.json +256 -0
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
- package/src/config/bundled-skills/twitter/SKILL.md +134 -0
- package/src/config/bundled-skills/watcher/SKILL.md +27 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
- package/src/config/defaults.ts +33 -0
- package/src/config/loader.ts +4 -1
- package/src/config/schema.ts +161 -1
- package/src/config/system-prompt.ts +61 -16
- package/src/config/templates/IDENTITY.md +7 -0
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +4 -4
- package/src/daemon/assistant-attachments.ts +10 -0
- package/src/daemon/classifier.ts +3 -1
- package/src/daemon/computer-use-session.ts +3 -1
- package/src/daemon/date-context.ts +136 -0
- package/src/daemon/handlers/apps.ts +16 -1
- package/src/daemon/handlers/browser.ts +54 -0
- package/src/daemon/handlers/computer-use.ts +7 -1
- package/src/daemon/handlers/config.ts +163 -5
- package/src/daemon/handlers/diagnostics.ts +5 -1
- package/src/daemon/handlers/documents.ts +18 -29
- package/src/daemon/handlers/home-base.ts +5 -1
- package/src/daemon/handlers/index.ts +40 -277
- package/src/daemon/handlers/misc.ts +9 -1
- package/src/daemon/handlers/publish.ts +6 -1
- package/src/daemon/handlers/sessions.ts +65 -12
- package/src/daemon/handlers/shared.ts +36 -1
- package/src/daemon/handlers/signing.ts +37 -0
- package/src/daemon/handlers/skills.ts +20 -6
- package/src/daemon/handlers/subagents.ts +8 -3
- package/src/daemon/handlers/twitter-auth.ts +169 -0
- package/src/daemon/handlers/work-items.ts +384 -68
- package/src/daemon/ipc-contract-inventory.json +28 -4
- package/src/daemon/ipc-contract.ts +133 -37
- package/src/daemon/ipc-protocol.ts +7 -2
- package/src/daemon/lifecycle.ts +21 -0
- package/src/daemon/main.ts +10 -4
- package/src/daemon/ride-shotgun-handler.ts +74 -10
- package/src/daemon/server.ts +143 -26
- package/src/daemon/session-agent-loop.ts +887 -0
- package/src/daemon/session-attachments.ts +28 -5
- package/src/daemon/session-error.ts +24 -3
- package/src/daemon/session-lifecycle.ts +147 -0
- package/src/daemon/session-media-retry.ts +147 -0
- package/src/daemon/session-messaging.ts +145 -0
- package/src/daemon/session-notifiers.ts +164 -0
- package/src/daemon/session-process.ts +2 -2
- package/src/daemon/session-queue-manager.ts +1 -0
- package/src/daemon/session-runtime-assembly.ts +52 -0
- package/src/daemon/session-skill-tools.ts +124 -5
- package/src/daemon/session-slash.ts +3 -0
- package/src/daemon/session-surfaces.ts +77 -2
- package/src/daemon/session-tool-setup.ts +216 -2
- package/src/daemon/session-usage.ts +0 -2
- package/src/daemon/session.ts +114 -1404
- package/src/daemon/video-thumbnail.ts +60 -0
- package/src/doordash/client.ts +121 -27
- package/src/doordash/queries.ts +1 -2
- package/src/export/formatter.ts +3 -1
- package/src/followups/followup-store.ts +4 -2
- package/src/followups/types.ts +6 -0
- package/src/hooks/templates.ts +1 -1
- package/src/index.ts +32 -1153
- package/src/memory/attachments-store.ts +28 -83
- package/src/memory/channel-delivery-store.ts +7 -21
- package/src/memory/clarification-resolver.ts +6 -5
- package/src/memory/contradiction-checker.ts +3 -2
- package/src/memory/conversation-key-store.ts +10 -29
- package/src/memory/conversation-store.ts +2 -1
- package/src/memory/db.ts +96 -2
- package/src/memory/entity-extractor.ts +6 -3
- package/src/memory/items-extractor.ts +5 -4
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/llm-usage-store.ts +1 -2
- package/src/memory/runs-store.ts +1 -2
- package/src/memory/schema.ts +23 -2
- package/src/messaging/style-analyzer.ts +3 -2
- package/src/messaging/thread-summarizer.ts +8 -12
- package/src/messaging/triage-engine.ts +4 -2
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/registry.ts +8 -0
- package/src/runtime/http-server.ts +108 -20
- package/src/runtime/routes/attachment-routes.ts +2 -3
- package/src/runtime/routes/call-routes.ts +140 -0
- package/src/runtime/routes/channel-routes.ts +5 -10
- package/src/runtime/routes/conversation-routes.ts +5 -5
- package/src/runtime/routes/run-routes.ts +2 -2
- package/src/runtime/run-orchestrator.ts +9 -3
- package/src/schedule/recurrence-engine.ts +138 -0
- package/src/schedule/recurrence-types.ts +67 -0
- package/src/schedule/schedule-store.ts +102 -57
- package/src/schedule/scheduler.ts +9 -6
- package/src/security/oauth2.ts +29 -4
- package/src/security/secret-allowlist.ts +46 -0
- package/src/skills/clawhub.ts +1 -1
- package/src/subagent/manager.ts +40 -8
- package/src/swarm/backend-claude-code.ts +64 -9
- package/src/swarm/worker-prompts.ts +2 -1
- package/src/tasks/SPEC.md +34 -28
- package/src/tasks/ephemeral-permissions.ts +16 -7
- package/src/tasks/task-compiler.ts +5 -4
- package/src/tasks/task-runner.ts +10 -5
- package/src/tasks/task-scheduler.ts +1 -1
- package/src/tasks/tool-sanitizer.ts +36 -0
- package/src/tools/assets/search.ts +4 -4
- package/src/tools/browser/api-map.ts +220 -0
- package/src/tools/browser/auto-navigate.ts +270 -0
- package/src/tools/browser/browser-execution.ts +2 -1
- package/src/tools/browser/browser-manager.ts +2 -2
- package/src/tools/browser/network-recorder.ts +5 -4
- package/src/tools/browser/x-auto-navigate.ts +207 -0
- package/src/tools/calls/call-end.ts +17 -67
- package/src/tools/calls/call-start.ts +24 -85
- package/src/tools/calls/call-status.ts +35 -51
- package/src/tools/claude-code/claude-code.ts +77 -11
- package/src/tools/contacts/contact-merge.ts +46 -78
- package/src/tools/contacts/contact-search.ts +35 -79
- package/src/tools/contacts/contact-upsert.ts +35 -108
- package/src/tools/credentials/vault.ts +20 -4
- package/src/tools/document/document-tool.ts +71 -144
- package/src/tools/executor.ts +129 -10
- package/src/tools/followups/followup_create.ts +46 -88
- package/src/tools/followups/followup_list.ts +34 -74
- package/src/tools/followups/followup_resolve.ts +31 -66
- package/src/tools/host-terminal/cli-discover.ts +2 -1
- package/src/tools/host-terminal/host-shell.ts +10 -0
- package/src/tools/memory/handlers.ts +5 -4
- package/src/tools/network/__tests__/web-search.test.ts +427 -0
- package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
- package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
- package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
- package/src/tools/network/web-fetch.ts +18 -6
- package/src/tools/playbooks/index.ts +4 -5
- package/src/tools/playbooks/playbook-create.ts +3 -47
- package/src/tools/playbooks/playbook-delete.ts +1 -25
- package/src/tools/playbooks/playbook-list.ts +1 -28
- package/src/tools/playbooks/playbook-update.ts +3 -51
- package/src/tools/reminder/reminder.ts +5 -78
- package/src/tools/schedule/create.ts +69 -74
- package/src/tools/schedule/delete.ts +21 -47
- package/src/tools/schedule/list.ts +55 -74
- package/src/tools/schedule/update.ts +77 -84
- package/src/tools/subagent/abort.ts +29 -58
- package/src/tools/subagent/message.ts +30 -63
- package/src/tools/subagent/read.ts +53 -84
- package/src/tools/subagent/spawn.ts +43 -82
- package/src/tools/subagent/status.ts +42 -71
- package/src/tools/swarm/delegate.ts +2 -1
- package/src/tools/tasks/index.ts +8 -8
- package/src/tools/tasks/task-delete.ts +60 -88
- package/src/tools/tasks/task-list.ts +31 -52
- package/src/tools/tasks/task-run.ts +72 -108
- package/src/tools/tasks/task-save.ts +33 -65
- package/src/tools/tasks/work-item-enqueue.ts +183 -215
- package/src/tools/tasks/work-item-list.ts +33 -63
- package/src/tools/tasks/work-item-remove.ts +45 -97
- package/src/tools/tasks/work-item-update.ts +91 -163
- package/src/tools/terminal/backends/native.ts +3 -1
- package/src/tools/tool-manifest.ts +0 -62
- package/src/tools/types.ts +6 -0
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tools/watch/screen-watch.ts +3 -1
- package/src/tools/watcher/create.ts +52 -98
- package/src/tools/watcher/delete.ts +20 -46
- package/src/tools/watcher/digest.ts +36 -70
- package/src/tools/watcher/list.ts +49 -79
- package/src/tools/watcher/update.ts +45 -91
- package/src/twitter/client.ts +690 -0
- package/src/twitter/session.ts +91 -0
- package/src/usage/types.ts +0 -1
- package/src/util/truncate.ts +6 -0
- package/src/watcher/providers/slack.ts +2 -1
- package/src/watcher/watcher-store.ts +3 -2
- package/src/work-items/work-item-store.ts +27 -2
- package/src/workspace/commit-message-enrichment-service.ts +31 -7
- package/src/workspace/git-service.ts +87 -22
- package/src/workspace/provider-commit-message-generator.ts +242 -0
- package/src/workspace/turn-commit.ts +62 -3
- package/src/tools/contacts/index.ts +0 -4
- package/src/tools/document/index.ts +0 -5
- package/src/tools/followups/index.ts +0 -3
- package/src/tools/subagent/index.ts +0 -5
- /package/src/__tests__/{memory-context-benchmark.test.ts → memory-context-benchmark.benchmark.test.ts} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Watcher"
|
|
3
|
+
description: "Polling watcher system for monitoring external sources"
|
|
4
|
+
metadata: {"vellum": {"emoji": "👀"}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Create and manage watchers that poll external services for events and process them with an action prompt.
|
|
8
|
+
|
|
9
|
+
## Concepts
|
|
10
|
+
|
|
11
|
+
- **Provider** — The external service to poll (e.g. "gmail"). Each provider defines how to fetch and parse events.
|
|
12
|
+
- **Action prompt** — LLM instructions for handling detected events. Sent along with event data to a background conversation.
|
|
13
|
+
- **Poll interval** — How often to check for new events (minimum 15 seconds, default 60 seconds).
|
|
14
|
+
- **Digest** — Summary of recent watcher activity, grouped by watcher with time-based filtering.
|
|
15
|
+
|
|
16
|
+
## Lifecycle
|
|
17
|
+
|
|
18
|
+
1. Create a watcher with a name, provider, and action prompt.
|
|
19
|
+
2. The system polls the provider at the configured interval.
|
|
20
|
+
3. Detected events are processed according to the action prompt.
|
|
21
|
+
4. Use `watcher_digest` to review recent activity.
|
|
22
|
+
|
|
23
|
+
## Usage Notes
|
|
24
|
+
|
|
25
|
+
- Use `watcher_create` when the user wants to monitor an external source (e.g. "watch my Gmail for important emails").
|
|
26
|
+
- `watcher_digest` is the go-to tool when the user asks "what happened with my email?" or similar questions about watcher activity.
|
|
27
|
+
- Watchers can be enabled/disabled via `watcher_update` without deleting them.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"tools": [
|
|
4
|
+
{
|
|
5
|
+
"name": "watcher_create",
|
|
6
|
+
"description": "Create a new watcher that polls an external service for events and processes them with an action prompt",
|
|
7
|
+
"category": "watcher",
|
|
8
|
+
"risk": "medium",
|
|
9
|
+
"input_schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "A human-readable name for this watcher (e.g. \"My Gmail\")"
|
|
15
|
+
},
|
|
16
|
+
"provider": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The provider to poll (e.g. \"gmail\")"
|
|
19
|
+
},
|
|
20
|
+
"action_prompt": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Instructions for the LLM on how to handle detected events. This prompt is sent along with event data to a background conversation."
|
|
23
|
+
},
|
|
24
|
+
"poll_interval_ms": {
|
|
25
|
+
"type": "number",
|
|
26
|
+
"description": "How often to poll in milliseconds. Defaults to 60000 (1 minute). Minimum 15000."
|
|
27
|
+
},
|
|
28
|
+
"credential_service": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Override the credential service to use. Defaults to the provider's required service."
|
|
31
|
+
},
|
|
32
|
+
"config": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"description": "Provider-specific configuration (e.g. filter criteria)"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"required": ["name", "provider", "action_prompt"]
|
|
38
|
+
},
|
|
39
|
+
"executor": "tools/watcher-create.ts",
|
|
40
|
+
"execution_target": "host"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "watcher_list",
|
|
44
|
+
"description": "List all watchers with their status, or show details for a specific watcher",
|
|
45
|
+
"category": "watcher",
|
|
46
|
+
"risk": "low",
|
|
47
|
+
"input_schema": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"properties": {
|
|
50
|
+
"watcher_id": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"description": "If provided, show detailed info for this specific watcher including recent events."
|
|
53
|
+
},
|
|
54
|
+
"enabled_only": {
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"description": "When true, only show enabled watchers. Defaults to false."
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"required": []
|
|
60
|
+
},
|
|
61
|
+
"executor": "tools/watcher-list.ts",
|
|
62
|
+
"execution_target": "host"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "watcher_update",
|
|
66
|
+
"description": "Update a watcher's configuration (name, action prompt, interval, enabled state)",
|
|
67
|
+
"category": "watcher",
|
|
68
|
+
"risk": "medium",
|
|
69
|
+
"input_schema": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"watcher_id": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "The ID of the watcher to update"
|
|
75
|
+
},
|
|
76
|
+
"name": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "New name for the watcher"
|
|
79
|
+
},
|
|
80
|
+
"action_prompt": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "New action prompt for event processing"
|
|
83
|
+
},
|
|
84
|
+
"poll_interval_ms": {
|
|
85
|
+
"type": "number",
|
|
86
|
+
"description": "New poll interval in milliseconds (minimum 15000)"
|
|
87
|
+
},
|
|
88
|
+
"enabled": {
|
|
89
|
+
"type": "boolean",
|
|
90
|
+
"description": "Enable or disable the watcher"
|
|
91
|
+
},
|
|
92
|
+
"config": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"description": "New provider-specific configuration"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"required": ["watcher_id"]
|
|
98
|
+
},
|
|
99
|
+
"executor": "tools/watcher-update.ts",
|
|
100
|
+
"execution_target": "host"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "watcher_delete",
|
|
104
|
+
"description": "Delete a watcher and all its event history",
|
|
105
|
+
"category": "watcher",
|
|
106
|
+
"risk": "medium",
|
|
107
|
+
"input_schema": {
|
|
108
|
+
"type": "object",
|
|
109
|
+
"properties": {
|
|
110
|
+
"watcher_id": {
|
|
111
|
+
"type": "string",
|
|
112
|
+
"description": "The ID of the watcher to delete"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"required": ["watcher_id"]
|
|
116
|
+
},
|
|
117
|
+
"executor": "tools/watcher-delete.ts",
|
|
118
|
+
"execution_target": "host"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "watcher_digest",
|
|
122
|
+
"description": "Get a summary of recent watcher activity. Use this when the user asks about what happened with their email, notifications, etc.",
|
|
123
|
+
"category": "watcher",
|
|
124
|
+
"risk": "low",
|
|
125
|
+
"input_schema": {
|
|
126
|
+
"type": "object",
|
|
127
|
+
"properties": {
|
|
128
|
+
"watcher_id": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"description": "Filter to events from a specific watcher. If omitted, shows events from all watchers."
|
|
131
|
+
},
|
|
132
|
+
"hours": {
|
|
133
|
+
"type": "number",
|
|
134
|
+
"description": "How many hours back to look. Defaults to 24."
|
|
135
|
+
},
|
|
136
|
+
"limit": {
|
|
137
|
+
"type": "number",
|
|
138
|
+
"description": "Maximum number of events to return. Defaults to 50."
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"required": []
|
|
142
|
+
},
|
|
143
|
+
"executor": "tools/watcher-digest.ts",
|
|
144
|
+
"execution_target": "host"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../../../../tools/types.js';
|
|
2
|
+
import { executeWatcherCreate } from '../../../../tools/watcher/create.js';
|
|
3
|
+
|
|
4
|
+
export async function run(
|
|
5
|
+
input: Record<string, unknown>,
|
|
6
|
+
context: ToolContext,
|
|
7
|
+
): Promise<ToolExecutionResult> {
|
|
8
|
+
return executeWatcherCreate(input, context);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../../../../tools/types.js';
|
|
2
|
+
import { executeWatcherDelete } from '../../../../tools/watcher/delete.js';
|
|
3
|
+
|
|
4
|
+
export async function run(
|
|
5
|
+
input: Record<string, unknown>,
|
|
6
|
+
context: ToolContext,
|
|
7
|
+
): Promise<ToolExecutionResult> {
|
|
8
|
+
return executeWatcherDelete(input, context);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../../../../tools/types.js';
|
|
2
|
+
import { executeWatcherDigest } from '../../../../tools/watcher/digest.js';
|
|
3
|
+
|
|
4
|
+
export async function run(
|
|
5
|
+
input: Record<string, unknown>,
|
|
6
|
+
context: ToolContext,
|
|
7
|
+
): Promise<ToolExecutionResult> {
|
|
8
|
+
return executeWatcherDigest(input, context);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../../../../tools/types.js';
|
|
2
|
+
import { executeWatcherList } from '../../../../tools/watcher/list.js';
|
|
3
|
+
|
|
4
|
+
export async function run(
|
|
5
|
+
input: Record<string, unknown>,
|
|
6
|
+
context: ToolContext,
|
|
7
|
+
): Promise<ToolExecutionResult> {
|
|
8
|
+
return executeWatcherList(input, context);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../../../../tools/types.js';
|
|
2
|
+
import { executeWatcherUpdate } from '../../../../tools/watcher/update.js';
|
|
3
|
+
|
|
4
|
+
export async function run(
|
|
5
|
+
input: Record<string, unknown>,
|
|
6
|
+
context: ToolContext,
|
|
7
|
+
): Promise<ToolExecutionResult> {
|
|
8
|
+
return executeWatcherUpdate(input, context);
|
|
9
|
+
}
|
package/src/config/defaults.ts
CHANGED
|
@@ -169,6 +169,10 @@ export const DEFAULT_CONFIG: AssistantConfig = {
|
|
|
169
169
|
retentionDays: 30,
|
|
170
170
|
},
|
|
171
171
|
pricingOverrides: [],
|
|
172
|
+
agentHeartbeat: {
|
|
173
|
+
enabled: false,
|
|
174
|
+
intervalMs: 3_600_000,
|
|
175
|
+
},
|
|
172
176
|
swarm: {
|
|
173
177
|
enabled: true,
|
|
174
178
|
maxWorkers: 3,
|
|
@@ -193,5 +197,34 @@ export const DEFAULT_CONFIG: AssistantConfig = {
|
|
|
193
197
|
enrichmentConcurrency: 1,
|
|
194
198
|
enrichmentJobTimeoutMs: 30000,
|
|
195
199
|
enrichmentMaxRetries: 2,
|
|
200
|
+
commitMessageLLM: {
|
|
201
|
+
enabled: false,
|
|
202
|
+
useConfiguredProvider: true,
|
|
203
|
+
providerFastModelOverrides: {},
|
|
204
|
+
timeoutMs: 600,
|
|
205
|
+
maxTokens: 120,
|
|
206
|
+
temperature: 0.2,
|
|
207
|
+
maxFilesInPrompt: 30,
|
|
208
|
+
maxDiffBytes: 12000,
|
|
209
|
+
minRemainingTurnBudgetMs: 1000,
|
|
210
|
+
breaker: {
|
|
211
|
+
openAfterFailures: 3,
|
|
212
|
+
backoffBaseMs: 2000,
|
|
213
|
+
backoffMaxMs: 60000,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
calls: {
|
|
218
|
+
enabled: true,
|
|
219
|
+
provider: 'twilio' as const,
|
|
220
|
+
maxDurationSeconds: 3600,
|
|
221
|
+
userConsultTimeoutSeconds: 120,
|
|
222
|
+
disclosure: {
|
|
223
|
+
enabled: true,
|
|
224
|
+
text: 'At the very beginning of the call, disclose that you are an AI assistant calling on behalf of the user.',
|
|
225
|
+
},
|
|
226
|
+
safety: {
|
|
227
|
+
denyCategories: [],
|
|
228
|
+
},
|
|
196
229
|
},
|
|
197
230
|
};
|
package/src/config/loader.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { AssistantConfig } from './types.js';
|
|
|
10
10
|
const log = getLogger('config');
|
|
11
11
|
|
|
12
12
|
// Providers that store API keys in secure storage (superset of VALID_PROVIDERS)
|
|
13
|
-
export const API_KEY_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'fireworks', 'brave', 'perplexity'] as const;
|
|
13
|
+
export const API_KEY_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'fireworks', 'openrouter', 'brave', 'perplexity'] as const;
|
|
14
14
|
|
|
15
15
|
let cached: AssistantConfig | null = null;
|
|
16
16
|
let loading = false;
|
|
@@ -198,6 +198,9 @@ export function loadConfig(): AssistantConfig {
|
|
|
198
198
|
if (process.env.FIREWORKS_API_KEY) {
|
|
199
199
|
config.apiKeys.fireworks = process.env.FIREWORKS_API_KEY;
|
|
200
200
|
}
|
|
201
|
+
if (process.env.OPENROUTER_API_KEY) {
|
|
202
|
+
config.apiKeys.openrouter = process.env.OPENROUTER_API_KEY;
|
|
203
|
+
}
|
|
201
204
|
if (process.env.BRAVE_API_KEY) {
|
|
202
205
|
config.apiKeys.brave = process.env.BRAVE_API_KEY;
|
|
203
206
|
}
|
package/src/config/schema.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { getDataDir } from '../util/platform.js';
|
|
3
3
|
|
|
4
|
-
const VALID_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'fireworks'] as const;
|
|
4
|
+
const VALID_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'fireworks', 'openrouter'] as const;
|
|
5
5
|
const VALID_WEB_SEARCH_PROVIDERS = ['perplexity', 'brave', 'anthropic-native'] as const;
|
|
6
6
|
const VALID_SECRET_ACTIONS = ['redact', 'warn', 'block', 'prompt'] as const;
|
|
7
7
|
const VALID_MEMORY_EMBEDDING_PROVIDERS = ['auto', 'local', 'openai', 'gemini', 'ollama'] as const;
|
|
8
8
|
const VALID_SANDBOX_BACKENDS = ['native', 'docker'] as const;
|
|
9
9
|
const VALID_DOCKER_NETWORKS = ['none', 'bridge'] as const;
|
|
10
10
|
const VALID_PERMISSIONS_MODES = ['legacy', 'strict'] as const;
|
|
11
|
+
const VALID_CALL_PROVIDERS = ['twilio'] as const;
|
|
11
12
|
|
|
12
13
|
export const TimeoutConfigSchema = z.object({
|
|
13
14
|
shellMaxTimeoutSec: z
|
|
@@ -744,6 +745,83 @@ export const WorkspaceGitConfigSchema = z.object({
|
|
|
744
745
|
.int('workspaceGit.enrichmentMaxRetries must be an integer')
|
|
745
746
|
.nonnegative('workspaceGit.enrichmentMaxRetries must be non-negative')
|
|
746
747
|
.default(2),
|
|
748
|
+
commitMessageLLM: z.object({
|
|
749
|
+
enabled: z.boolean({ error: 'workspaceGit.commitMessageLLM.enabled must be a boolean' }).default(false),
|
|
750
|
+
useConfiguredProvider: z.boolean({ error: 'workspaceGit.commitMessageLLM.useConfiguredProvider must be a boolean' }).default(true),
|
|
751
|
+
providerFastModelOverrides: z.record(z.string(), z.string()).default({}),
|
|
752
|
+
timeoutMs: z.number({ error: 'workspaceGit.commitMessageLLM.timeoutMs must be a number' })
|
|
753
|
+
.int('workspaceGit.commitMessageLLM.timeoutMs must be an integer')
|
|
754
|
+
.positive('workspaceGit.commitMessageLLM.timeoutMs must be a positive integer')
|
|
755
|
+
.default(600),
|
|
756
|
+
maxTokens: z.number({ error: 'workspaceGit.commitMessageLLM.maxTokens must be a number' })
|
|
757
|
+
.int('workspaceGit.commitMessageLLM.maxTokens must be an integer')
|
|
758
|
+
.positive('workspaceGit.commitMessageLLM.maxTokens must be a positive integer')
|
|
759
|
+
.default(120),
|
|
760
|
+
temperature: z.number({ error: 'workspaceGit.commitMessageLLM.temperature must be a number' })
|
|
761
|
+
.min(0, 'workspaceGit.commitMessageLLM.temperature must be >= 0')
|
|
762
|
+
.max(2, 'workspaceGit.commitMessageLLM.temperature must be <= 2')
|
|
763
|
+
.default(0.2),
|
|
764
|
+
maxFilesInPrompt: z.number({ error: 'workspaceGit.commitMessageLLM.maxFilesInPrompt must be a number' })
|
|
765
|
+
.int('workspaceGit.commitMessageLLM.maxFilesInPrompt must be an integer')
|
|
766
|
+
.positive('workspaceGit.commitMessageLLM.maxFilesInPrompt must be a positive integer')
|
|
767
|
+
.default(30),
|
|
768
|
+
maxDiffBytes: z.number({ error: 'workspaceGit.commitMessageLLM.maxDiffBytes must be a number' })
|
|
769
|
+
.int('workspaceGit.commitMessageLLM.maxDiffBytes must be an integer')
|
|
770
|
+
.positive('workspaceGit.commitMessageLLM.maxDiffBytes must be a positive integer')
|
|
771
|
+
.default(12000),
|
|
772
|
+
minRemainingTurnBudgetMs: z.number({ error: 'workspaceGit.commitMessageLLM.minRemainingTurnBudgetMs must be a number' })
|
|
773
|
+
.int('workspaceGit.commitMessageLLM.minRemainingTurnBudgetMs must be an integer')
|
|
774
|
+
.nonnegative('workspaceGit.commitMessageLLM.minRemainingTurnBudgetMs must be non-negative')
|
|
775
|
+
.default(1000),
|
|
776
|
+
breaker: z.object({
|
|
777
|
+
openAfterFailures: z.number({ error: 'workspaceGit.commitMessageLLM.breaker.openAfterFailures must be a number' })
|
|
778
|
+
.int().positive().default(3),
|
|
779
|
+
backoffBaseMs: z.number({ error: 'workspaceGit.commitMessageLLM.breaker.backoffBaseMs must be a number' })
|
|
780
|
+
.int().positive().default(2000),
|
|
781
|
+
backoffMaxMs: z.number({ error: 'workspaceGit.commitMessageLLM.breaker.backoffMaxMs must be a number' })
|
|
782
|
+
.int().positive().default(60000),
|
|
783
|
+
}).default({}),
|
|
784
|
+
}).default({}),
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
export const AgentHeartbeatConfigSchema = z.object({
|
|
788
|
+
enabled: z
|
|
789
|
+
.boolean({ error: 'agentHeartbeat.enabled must be a boolean' })
|
|
790
|
+
.default(false),
|
|
791
|
+
intervalMs: z
|
|
792
|
+
.number({ error: 'agentHeartbeat.intervalMs must be a number' })
|
|
793
|
+
.int('agentHeartbeat.intervalMs must be an integer')
|
|
794
|
+
.positive('agentHeartbeat.intervalMs must be a positive integer')
|
|
795
|
+
.default(3_600_000),
|
|
796
|
+
activeHoursStart: z
|
|
797
|
+
.number({ error: 'agentHeartbeat.activeHoursStart must be a number' })
|
|
798
|
+
.int('agentHeartbeat.activeHoursStart must be an integer')
|
|
799
|
+
.min(0, 'agentHeartbeat.activeHoursStart must be >= 0')
|
|
800
|
+
.max(23, 'agentHeartbeat.activeHoursStart must be <= 23')
|
|
801
|
+
.optional(),
|
|
802
|
+
activeHoursEnd: z
|
|
803
|
+
.number({ error: 'agentHeartbeat.activeHoursEnd must be a number' })
|
|
804
|
+
.int('agentHeartbeat.activeHoursEnd must be an integer')
|
|
805
|
+
.min(0, 'agentHeartbeat.activeHoursEnd must be >= 0')
|
|
806
|
+
.max(23, 'agentHeartbeat.activeHoursEnd must be <= 23')
|
|
807
|
+
.optional(),
|
|
808
|
+
}).superRefine((config, ctx) => {
|
|
809
|
+
const hasStart = config.activeHoursStart != null;
|
|
810
|
+
const hasEnd = config.activeHoursEnd != null;
|
|
811
|
+
if (hasStart !== hasEnd) {
|
|
812
|
+
ctx.addIssue({
|
|
813
|
+
code: z.ZodIssueCode.custom,
|
|
814
|
+
path: [hasStart ? 'activeHoursEnd' : 'activeHoursStart'],
|
|
815
|
+
message: 'agentHeartbeat.activeHoursStart and agentHeartbeat.activeHoursEnd must both be set or both be omitted',
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
if (hasStart && hasEnd && config.activeHoursStart === config.activeHoursEnd) {
|
|
819
|
+
ctx.addIssue({
|
|
820
|
+
code: z.ZodIssueCode.custom,
|
|
821
|
+
path: ['activeHoursEnd'],
|
|
822
|
+
message: 'agentHeartbeat.activeHoursStart and agentHeartbeat.activeHoursEnd must not be equal (would create an empty window)',
|
|
823
|
+
});
|
|
824
|
+
}
|
|
747
825
|
});
|
|
748
826
|
|
|
749
827
|
export const SwarmConfigSchema = z.object({
|
|
@@ -781,6 +859,51 @@ export const SwarmConfigSchema = z.object({
|
|
|
781
859
|
.default('claude-sonnet-4-6'),
|
|
782
860
|
});
|
|
783
861
|
|
|
862
|
+
export const CallsDisclosureConfigSchema = z.object({
|
|
863
|
+
enabled: z
|
|
864
|
+
.boolean({ error: 'calls.disclosure.enabled must be a boolean' })
|
|
865
|
+
.default(true),
|
|
866
|
+
text: z
|
|
867
|
+
.string({ error: 'calls.disclosure.text must be a string' })
|
|
868
|
+
.default('At the very beginning of the call, disclose that you are an AI assistant calling on behalf of the user.'),
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
export const CallsSafetyConfigSchema = z.object({
|
|
872
|
+
denyCategories: z
|
|
873
|
+
.array(z.string({ error: 'calls.safety.denyCategories values must be strings' }))
|
|
874
|
+
.default([]),
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
export const CallsConfigSchema = z.object({
|
|
878
|
+
enabled: z
|
|
879
|
+
.boolean({ error: 'calls.enabled must be a boolean' })
|
|
880
|
+
.default(true),
|
|
881
|
+
provider: z
|
|
882
|
+
.enum(VALID_CALL_PROVIDERS, {
|
|
883
|
+
error: `calls.provider must be one of: ${VALID_CALL_PROVIDERS.join(', ')}`,
|
|
884
|
+
})
|
|
885
|
+
.default('twilio'),
|
|
886
|
+
maxDurationSeconds: z
|
|
887
|
+
.number({ error: 'calls.maxDurationSeconds must be a number' })
|
|
888
|
+
.int('calls.maxDurationSeconds must be an integer')
|
|
889
|
+
.positive('calls.maxDurationSeconds must be a positive integer')
|
|
890
|
+
.max(2_147_483, 'calls.maxDurationSeconds must be at most 2147483 (setTimeout-safe limit)')
|
|
891
|
+
.default(3600),
|
|
892
|
+
userConsultTimeoutSeconds: z
|
|
893
|
+
.number({ error: 'calls.userConsultTimeoutSeconds must be a number' })
|
|
894
|
+
.int('calls.userConsultTimeoutSeconds must be an integer')
|
|
895
|
+
.positive('calls.userConsultTimeoutSeconds must be a positive integer')
|
|
896
|
+
.max(2_147_483, 'calls.userConsultTimeoutSeconds must be at most 2147483 (setTimeout-safe limit)')
|
|
897
|
+
.default(120),
|
|
898
|
+
disclosure: CallsDisclosureConfigSchema.default({
|
|
899
|
+
enabled: true,
|
|
900
|
+
text: 'At the very beginning of the call, disclose that you are an AI assistant calling on behalf of the user.',
|
|
901
|
+
}),
|
|
902
|
+
safety: CallsSafetyConfigSchema.default({
|
|
903
|
+
denyCategories: [],
|
|
904
|
+
}),
|
|
905
|
+
});
|
|
906
|
+
|
|
784
907
|
export const SkillsConfigSchema = z.object({
|
|
785
908
|
entries: z.record(z.string(), SkillEntryConfigSchema).default({}),
|
|
786
909
|
load: SkillsLoadConfigSchema.default({ extraDirs: [], watch: true, watchDebounceMs: 250 }),
|
|
@@ -978,6 +1101,10 @@ export const AssistantConfigSchema = z.object({
|
|
|
978
1101
|
pricingOverrides: z
|
|
979
1102
|
.array(ModelPricingOverrideSchema)
|
|
980
1103
|
.default([]),
|
|
1104
|
+
agentHeartbeat: AgentHeartbeatConfigSchema.default({
|
|
1105
|
+
enabled: false,
|
|
1106
|
+
intervalMs: 3_600_000,
|
|
1107
|
+
}),
|
|
981
1108
|
swarm: SwarmConfigSchema.default({
|
|
982
1109
|
enabled: true,
|
|
983
1110
|
maxWorkers: 3,
|
|
@@ -1002,6 +1129,35 @@ export const AssistantConfigSchema = z.object({
|
|
|
1002
1129
|
enrichmentConcurrency: 1,
|
|
1003
1130
|
enrichmentJobTimeoutMs: 30000,
|
|
1004
1131
|
enrichmentMaxRetries: 2,
|
|
1132
|
+
commitMessageLLM: {
|
|
1133
|
+
enabled: false,
|
|
1134
|
+
useConfiguredProvider: true,
|
|
1135
|
+
providerFastModelOverrides: {},
|
|
1136
|
+
timeoutMs: 600,
|
|
1137
|
+
maxTokens: 120,
|
|
1138
|
+
temperature: 0.2,
|
|
1139
|
+
maxFilesInPrompt: 30,
|
|
1140
|
+
maxDiffBytes: 12000,
|
|
1141
|
+
minRemainingTurnBudgetMs: 1000,
|
|
1142
|
+
breaker: {
|
|
1143
|
+
openAfterFailures: 3,
|
|
1144
|
+
backoffBaseMs: 2000,
|
|
1145
|
+
backoffMaxMs: 60000,
|
|
1146
|
+
},
|
|
1147
|
+
},
|
|
1148
|
+
}),
|
|
1149
|
+
calls: CallsConfigSchema.default({
|
|
1150
|
+
enabled: true,
|
|
1151
|
+
provider: 'twilio',
|
|
1152
|
+
maxDurationSeconds: 3600,
|
|
1153
|
+
userConsultTimeoutSeconds: 120,
|
|
1154
|
+
disclosure: {
|
|
1155
|
+
enabled: true,
|
|
1156
|
+
text: 'At the very beginning of the call, disclose that you are an AI assistant calling on behalf of the user.',
|
|
1157
|
+
},
|
|
1158
|
+
safety: {
|
|
1159
|
+
denyCategories: [],
|
|
1160
|
+
},
|
|
1005
1161
|
}),
|
|
1006
1162
|
}).superRefine((config, ctx) => {
|
|
1007
1163
|
if (config.contextWindow.targetInputTokens >= config.contextWindow.maxInputTokens) {
|
|
@@ -1056,6 +1212,10 @@ export type ModelPricingOverride = z.infer<typeof ModelPricingOverrideSchema>;
|
|
|
1056
1212
|
export type SkillEntryConfig = z.infer<typeof SkillEntryConfigSchema>;
|
|
1057
1213
|
export type SkillsLoadConfig = z.infer<typeof SkillsLoadConfigSchema>;
|
|
1058
1214
|
export type SkillsInstallConfig = z.infer<typeof SkillsInstallConfigSchema>;
|
|
1215
|
+
export type AgentHeartbeatConfig = z.infer<typeof AgentHeartbeatConfigSchema>;
|
|
1059
1216
|
export type SwarmConfig = z.infer<typeof SwarmConfigSchema>;
|
|
1060
1217
|
export type SkillsConfig = z.infer<typeof SkillsConfigSchema>;
|
|
1061
1218
|
export type WorkspaceGitConfig = z.infer<typeof WorkspaceGitConfigSchema>;
|
|
1219
|
+
export type CallsConfig = z.infer<typeof CallsConfigSchema>;
|
|
1220
|
+
export type CallsDisclosureConfig = z.infer<typeof CallsDisclosureConfigSchema>;
|
|
1221
|
+
export type CallsSafetyConfig = z.infer<typeof CallsSafetyConfigSchema>;
|
|
@@ -221,21 +221,35 @@ function buildTaskScheduleReminderRoutingSection(): string {
|
|
|
221
221
|
'**IMPORTANT:** When you call `task_list_show`, the Tasks window opens automatically on the client. Do NOT also create a separate surface/UI (via `ui_show` or `app_create`) to display the task queue. Doing so causes duplicate Task Queue windows. Just call `task_list_show` and let the native window handle the presentation.',
|
|
222
222
|
'',
|
|
223
223
|
'### Schedules (schedule_create / schedule_list / schedule_update / schedule_delete)',
|
|
224
|
-
'For recurring automated jobs that run on a cron
|
|
224
|
+
'For recurring automated jobs that run on a recurrence schedule (cron or RRULE). Use ONLY when the user explicitly wants:',
|
|
225
225
|
'- Recurring automation: "every day at 9am", "weekly on Mondays", "every hour"',
|
|
226
|
+
'- Complex recurrence patterns: "every other Tuesday", "last weekday of the month" (use RRULE)',
|
|
227
|
+
'- Bounded recurrence: "every day for 30 days", "weekly until March" (RRULE with COUNT or UNTIL)',
|
|
226
228
|
'- Periodic background tasks: "check my email every morning", "run this report weekly"',
|
|
227
229
|
'',
|
|
228
|
-
'
|
|
230
|
+
'#### RRULE Set Constructs',
|
|
231
|
+
'When building RRULE expressions, these set lines are supported:',
|
|
232
|
+
'- **RRULE** — one or more recurrence rules (multiple RRULE lines form a union of occurrences)',
|
|
233
|
+
'- **RDATE** — add one-off dates that are not covered by the RRULE pattern',
|
|
234
|
+
'- **EXDATE** — exclude specific dates from the recurrence set',
|
|
235
|
+
'- **EXRULE** — exclude an entire series of dates defined by a recurrence pattern',
|
|
236
|
+
'',
|
|
237
|
+
'Exclusions (EXDATE, EXRULE) take precedence over inclusions (RRULE, RDATE). All RRULE expressions must include a DTSTART line and at least one RRULE or RDATE inclusion.',
|
|
238
|
+
'',
|
|
239
|
+
'### Reminders (reminder_create / reminder_list / reminder_cancel)',
|
|
229
240
|
'For one-time time-triggered notifications. Use ONLY when the user wants:',
|
|
230
241
|
'- A notification at a specific future time: "remind me at 3pm", "remind me in 2 hours"',
|
|
231
242
|
'- A timed alert, not a tracked task',
|
|
232
243
|
'',
|
|
233
244
|
'### Common mistakes to avoid',
|
|
234
|
-
'- "Add this to my tasks" → task_list_add (NOT schedule_create or
|
|
245
|
+
'- "Add this to my tasks" → task_list_add (NOT schedule_create or reminder_create)',
|
|
235
246
|
'- "What\'s on my task list?" → task_list_show (NOT schedule_list)',
|
|
236
247
|
'- "Remind me to buy groceries" without a time → task_list_add (it\'s a task, not a timed reminder)',
|
|
237
|
-
'- "Remind me at 5pm to buy groceries" →
|
|
238
|
-
'- "Check my inbox every morning at 8am" → schedule_create (recurring automation)',
|
|
248
|
+
'- "Remind me at 5pm to buy groceries" → reminder_create (explicit time trigger)',
|
|
249
|
+
'- "Check my inbox every morning at 8am" → schedule_create (recurring automation, cron)',
|
|
250
|
+
'- "Every other Tuesday at 10am" → schedule_create (recurring automation, RRULE)',
|
|
251
|
+
'- "Every weekday except holidays" → schedule_create (RRULE with EXDATE for exclusions)',
|
|
252
|
+
'- "Daily for the next 30 days" → schedule_create (RRULE with COUNT=30)',
|
|
239
253
|
'- "Bump priority on X" → task_list_update (NOT task_list_add)',
|
|
240
254
|
'- "Move this up" / "change this task priority" → task_list_update (NOT task_list_add)',
|
|
241
255
|
'- "Mark X as done" → task_list_update (NOT task_list_add)',
|
|
@@ -308,7 +322,7 @@ function buildDynamicUiSection(): string {
|
|
|
308
322
|
'- **Tool auto-emissions** (e.g. `get_weather`): handled automatically — do nothing extra',
|
|
309
323
|
'- **Predefined domain data** (flights, stocks): `ui_show` with `surface_type: "dynamic_page"` and domain component classes',
|
|
310
324
|
'- **Simple structured data** (key-value, table, list): `ui_show` with `card`/`table`/`list`/`form` surface_type',
|
|
311
|
-
'- **Multi-step tasks** (ordering food, booking, purchasing, multi-phase workflows): `ui_show` with `card` surface_type + `template: "task_progress"` (see below)',
|
|
325
|
+
'- **Multi-step tasks** (ordering food, booking, purchasing, multi-phase workflows): `ui_show` with `card` surface_type + `data.template: "task_progress"` (see below)',
|
|
312
326
|
'- **Interactive apps only**: `app_create` (calculators, dashboards, tools - NOT text content)',
|
|
313
327
|
'',
|
|
314
328
|
'### Loading app tools',
|
|
@@ -413,19 +427,47 @@ function buildDynamicUiSection(): string {
|
|
|
413
427
|
'Interactive surfaces provide a better user experience than asking your user to type their choice. Only fall back to plain text when the interaction is conversational or doesn\'t fit a structured format.',
|
|
414
428
|
'',
|
|
415
429
|
'### Task progress for multi-step workflows',
|
|
416
|
-
'When executing a multi-step task (
|
|
430
|
+
'When executing a multi-step task (booking a flight, purchasing, research with multiple phases), show live progress using the `task_progress` card template. Note: DoorDash ordering auto-emits a task_progress card on the first `vellum doordash` command (surface ID `doordash-progress`), so you only need `ui_update` for DoorDash flows.',
|
|
417
431
|
'',
|
|
418
|
-
'1. **Before starting**, call `ui_show` with `surface_type: "card"
|
|
432
|
+
'1. **Before starting**, call `ui_show` with `surface_type: "card"` and put `template: "task_progress"` inside `data`:',
|
|
419
433
|
' ```json',
|
|
420
|
-
' {
|
|
421
|
-
'
|
|
422
|
-
'
|
|
423
|
-
'
|
|
424
|
-
'
|
|
425
|
-
'
|
|
434
|
+
' {',
|
|
435
|
+
' "surface_type": "card",',
|
|
436
|
+
' "data": {',
|
|
437
|
+
' "title": "Booking Flight",',
|
|
438
|
+
' "body": "",',
|
|
439
|
+
' "template": "task_progress",',
|
|
440
|
+
' "templateData": {',
|
|
441
|
+
' "title": "Booking Flight",',
|
|
442
|
+
' "status": "in_progress",',
|
|
443
|
+
' "steps": [',
|
|
444
|
+
' { "label": "Search flights", "status": "in_progress" },',
|
|
445
|
+
' { "label": "Compare options", "status": "pending" },',
|
|
446
|
+
' { "label": "Select flight", "status": "pending" },',
|
|
447
|
+
' { "label": "Complete booking", "status": "pending" }',
|
|
448
|
+
' ]',
|
|
449
|
+
' }',
|
|
450
|
+
' }',
|
|
451
|
+
' }',
|
|
426
452
|
' ```',
|
|
427
|
-
'2. **As each step completes**, call `ui_update` with the same surface ID
|
|
428
|
-
'
|
|
453
|
+
'2. **As each step completes**, call `ui_update` with the same surface ID and patch `data.templateData` (not top-level `status`/`steps`):',
|
|
454
|
+
' ```json',
|
|
455
|
+
' {',
|
|
456
|
+
' "surface_id": "<surface-id>",',
|
|
457
|
+
' "data": {',
|
|
458
|
+
' "templateData": {',
|
|
459
|
+
' "status": "in_progress",',
|
|
460
|
+
' "steps": [',
|
|
461
|
+
' { "label": "Search flights", "status": "completed", "detail": "Found 12 options" },',
|
|
462
|
+
' { "label": "Compare options", "status": "in_progress" },',
|
|
463
|
+
' { "label": "Select flight", "status": "pending" },',
|
|
464
|
+
' { "label": "Complete booking", "status": "pending" }',
|
|
465
|
+
' ]',
|
|
466
|
+
' }',
|
|
467
|
+
' }',
|
|
468
|
+
' }',
|
|
469
|
+
' ```',
|
|
470
|
+
'3. **On completion**, set `data.templateData.status` to `"completed"`. On failure, set it to `"failed"` and mark the failing step accordingly.',
|
|
429
471
|
'',
|
|
430
472
|
'Use this for ANY multi-step workflow where the user benefits from seeing structured progress instead of just "Running a command...".',
|
|
431
473
|
].join('\n');
|
|
@@ -940,6 +982,9 @@ function buildDynamicSkillWorkflowSection(): string {
|
|
|
940
982
|
'',
|
|
941
983
|
'### Browser Skill Prerequisite',
|
|
942
984
|
'If you need browser capabilities (navigating web pages, clicking elements, extracting content) and `browser_*` tools are not available, load the "browser" skill first using `skill_load`.',
|
|
985
|
+
'',
|
|
986
|
+
'### X (Twitter) Skill',
|
|
987
|
+
'When the user asks to post, reply, or interact with X/Twitter, load the "twitter" skill using `skill_load`. Do NOT use computer-use or the browser skill for X — the X skill provides CLI commands (`vellum x post`, `vellum x reply`) that are faster and more reliable.',
|
|
943
988
|
].join('\n');
|
|
944
989
|
}
|
|
945
990
|
|
|
@@ -14,5 +14,12 @@ _ This file defines who you are. Fill it in during your first conversation. Make
|
|
|
14
14
|
- **Emoji:** [Choose one that matches your personality.]
|
|
15
15
|
- **Style tendency:** [Will be filled in by the evolution system based on personality]
|
|
16
16
|
- **Role:** Personal AI assistant
|
|
17
|
+
- **Home:** Local (~/.vellum/workspace)
|
|
18
|
+
|
|
19
|
+
_ Home describes where this assistant lives. Format examples:
|
|
20
|
+
_ Local (path): Local (~/.vellum/workspace)
|
|
21
|
+
_ GCP: GCP (project: my-project, zone: us-central1-a, instance: vellum-abc)
|
|
22
|
+
_ AWS: AWS (project: my-project, region: us-east-1, instance: vellum-abc)
|
|
23
|
+
_ Custom: Custom (ip: 192.168.1.100, port: 8080)
|
|
17
24
|
|
|
18
25
|
The user can change their emoji at any time — just update this file when they ask.
|
package/src/config/types.ts
CHANGED