vellum 0.2.0 → 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 +161 -34
- package/src/__tests__/account-registry.test.ts +2 -1
- package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
- package/src/__tests__/app-bundler.test.ts +12 -33
- 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 +5 -8
- 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 +454 -0
- 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-state.test.ts +133 -0
- package/src/__tests__/call-store.test.ts +691 -0
- package/src/__tests__/cli-discover.test.ts +1 -1
- package/src/__tests__/commit-message-enrichment-service.test.ts +550 -0
- 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 +348 -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__/doordash-session.test.ts +9 -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 +96 -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 +17 -10
- 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 +222 -0
- package/src/__tests__/run-orchestrator.test.ts +7 -7
- package/src/__tests__/runtime-attachment-metadata.test.ts +19 -20
- package/src/__tests__/runtime-runs-http.test.ts +5 -23
- package/src/__tests__/runtime-runs.test.ts +11 -11
- 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 +89 -16
- 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 +273 -2
- 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 +403 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +141 -2
- package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
- package/src/bundler/app-bundler.ts +35 -14
- package/src/calls/call-bridge.ts +95 -0
- package/src/calls/call-constants.ts +48 -0
- package/src/calls/call-domain.ts +276 -0
- package/src/calls/call-orchestrator.ts +390 -0
- package/src/calls/call-recovery.ts +207 -0
- package/src/calls/call-state-machine.ts +68 -0
- package/src/calls/call-state.ts +64 -0
- package/src/calls/call-store.ts +416 -0
- package/src/calls/relay-server.ts +335 -0
- package/src/calls/speaker-identification.ts +213 -0
- package/src/calls/twilio-config.ts +34 -0
- package/src/calls/twilio-provider.ts +173 -0
- package/src/calls/twilio-routes.ts +250 -0
- package/src/calls/types.ts +37 -0
- package/src/calls/voice-provider.ts +14 -0
- package/src/cli/config-commands.ts +334 -0
- package/src/cli/core-commands.ts +776 -0
- package/src/cli/doordash.ts +256 -25
- 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 +163 -0
- 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.json +2 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -24
- 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 +44 -0
- package/src/config/loader.ts +4 -1
- package/src/config/schema.ts +218 -1
- package/src/config/system-prompt.ts +100 -6
- package/src/config/templates/IDENTITY.md +7 -0
- package/src/config/types.ts +5 -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 +192 -4
- 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 -271
- 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 +495 -39
- package/src/daemon/ipc-contract-inventory.json +40 -4
- package/src/daemon/ipc-contract.ts +185 -37
- package/src/daemon/ipc-protocol.ts +7 -2
- package/src/daemon/lifecycle.ts +48 -5
- package/src/daemon/main.ts +10 -4
- package/src/daemon/ride-shotgun-handler.ts +74 -10
- package/src/daemon/server.ts +144 -29
- 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 +222 -2
- package/src/daemon/session-usage.ts +0 -2
- package/src/daemon/session.ts +114 -1365
- 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 -1151
- package/src/media/gemini-image-service.ts +1 -1
- 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 +362 -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 +65 -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 +277 -25
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/routes/attachment-routes.ts +5 -6
- package/src/runtime/routes/call-routes.ts +140 -0
- package/src/runtime/routes/channel-routes.ts +12 -19
- package/src/runtime/routes/conversation-routes.ts +5 -9
- package/src/runtime/routes/run-routes.ts +4 -8
- package/src/runtime/run-orchestrator.ts +39 -6
- 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 +67 -0
- package/src/tools/calls/call-start.ts +73 -0
- package/src/tools/calls/call-status.ts +81 -0
- 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 +21 -5
- 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/registry.ts +2 -4
- 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 -6
- package/src/tools/tasks/task-delete.ts +69 -56
- package/src/tools/tasks/task-list.ts +31 -52
- package/src/tools/tasks/task-run.ts +74 -102
- package/src/tools/tasks/task-save.ts +33 -65
- package/src/tools/tasks/work-item-enqueue.ts +192 -134
- package/src/tools/tasks/work-item-list.ts +33 -78
- package/src/tools/tasks/work-item-remove.ts +60 -0
- package/src/tools/tasks/work-item-update.ts +114 -0
- package/src/tools/terminal/backends/native.ts +3 -1
- package/src/tools/tool-manifest.ts +20 -74
- package/src/tools/types.ts +6 -0
- package/src/tools/ui-surface/definitions.ts +6 -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 +236 -2
- package/src/workspace/commit-message-enrichment-service.ts +284 -0
- package/src/workspace/commit-message-provider.ts +95 -0
- package/src/workspace/git-service.ts +272 -52
- package/src/workspace/heartbeat-service.ts +70 -13
- package/src/workspace/provider-commit-message-generator.ts +242 -0
- package/src/workspace/turn-commit.ts +100 -51
- 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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, beforeEach, afterEach, mock } from 'bun:test';
|
|
2
|
-
import { mkdirSync, rmSync, existsSync } from 'node:fs';
|
|
2
|
+
import { mkdirSync, rmSync, existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
|
|
@@ -51,13 +51,24 @@ mock.module('../config/loader.js', () => ({
|
|
|
51
51
|
|
|
52
52
|
// ── Import after mocks ───────────────────────────────────────────────
|
|
53
53
|
const { buildSystemPrompt } = await import('../config/system-prompt.js');
|
|
54
|
-
const { taskListAddTool } = await import('../tools/tasks/work-item-enqueue.js');
|
|
55
|
-
const { reminderTool } = await import('../tools/reminder/reminder.js');
|
|
56
54
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
// Load task_list_add description from the bundled skill TOOLS.json
|
|
56
|
+
const tasksToolsJson = JSON.parse(
|
|
57
|
+
readFileSync(join(import.meta.dirname, '../config/bundled-skills/tasks/TOOLS.json'), 'utf-8'),
|
|
58
|
+
);
|
|
59
|
+
const taskListAddDef = tasksToolsJson.tools.find((t: { name: string }) => t.name === 'task_list_add');
|
|
60
|
+
|
|
61
|
+
// Load reminder_create description from the bundled skill TOOLS.json
|
|
62
|
+
const reminderToolsJson = JSON.parse(
|
|
63
|
+
readFileSync(join(import.meta.dirname, '../config/bundled-skills/reminder/TOOLS.json'), 'utf-8'),
|
|
64
|
+
);
|
|
65
|
+
const reminderCreateDef = reminderToolsJson.tools.find((t: { name: string }) => t.name === 'reminder_create');
|
|
66
|
+
|
|
67
|
+
// Load schedule_create description from the bundled skill TOOLS.json
|
|
68
|
+
const scheduleToolsJson = JSON.parse(
|
|
69
|
+
readFileSync(join(import.meta.dirname, '../config/bundled-skills/schedule/TOOLS.json'), 'utf-8'),
|
|
70
|
+
);
|
|
71
|
+
const scheduleCreateDef = scheduleToolsJson.tools.find((t: { name: string }) => t.name === 'schedule_create');
|
|
61
72
|
|
|
62
73
|
// =====================================================================
|
|
63
74
|
// 1. System prompt: buildTaskScheduleReminderRoutingSection
|
|
@@ -81,9 +92,9 @@ describe('Task/Schedule/Reminder routing section in system prompt', () => {
|
|
|
81
92
|
|
|
82
93
|
test('routing section explains all three subsystems', () => {
|
|
83
94
|
const prompt = buildSystemPrompt();
|
|
84
|
-
expect(prompt).toContain('### Task Queue (task_list_add / task_list_show)');
|
|
95
|
+
expect(prompt).toContain('### Task Queue (task_list_add / task_list_show / task_list_update / task_list_remove)');
|
|
85
96
|
expect(prompt).toContain('### Schedules (schedule_create / schedule_list / schedule_update / schedule_delete)');
|
|
86
|
-
expect(prompt).toContain('### Reminders (
|
|
97
|
+
expect(prompt).toContain('### Reminders (reminder_create / reminder_list / reminder_cancel)');
|
|
87
98
|
});
|
|
88
99
|
|
|
89
100
|
test('routing section contains key routing phrases for task queue', () => {
|
|
@@ -103,10 +114,30 @@ describe('Task/Schedule/Reminder routing section in system prompt', () => {
|
|
|
103
114
|
test('routing section clarifies schedules are for recurring automation only', () => {
|
|
104
115
|
const prompt = buildSystemPrompt();
|
|
105
116
|
expect(prompt).toContain('recurring automated jobs');
|
|
106
|
-
expect(prompt).toContain('cron
|
|
117
|
+
expect(prompt).toContain('recurrence schedule (cron or RRULE)');
|
|
107
118
|
expect(prompt).toContain('ONLY when the user explicitly wants');
|
|
108
119
|
});
|
|
109
120
|
|
|
121
|
+
test('routing section documents supported RRULE set constructs', () => {
|
|
122
|
+
const prompt = buildSystemPrompt();
|
|
123
|
+
expect(prompt).toContain('#### RRULE Set Constructs');
|
|
124
|
+
expect(prompt).toContain('**RDATE**');
|
|
125
|
+
expect(prompt).toContain('**EXDATE**');
|
|
126
|
+
expect(prompt).toContain('**EXRULE**');
|
|
127
|
+
expect(prompt).toContain('multiple RRULE lines form a union');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('routing section documents bounded recurrence patterns', () => {
|
|
131
|
+
const prompt = buildSystemPrompt();
|
|
132
|
+
expect(prompt).toContain('Bounded recurrence');
|
|
133
|
+
expect(prompt).toContain('COUNT or UNTIL');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('routing section states exclusion precedence', () => {
|
|
137
|
+
const prompt = buildSystemPrompt();
|
|
138
|
+
expect(prompt).toContain('Exclusions (EXDATE, EXRULE) take precedence over inclusions (RRULE, RDATE)');
|
|
139
|
+
});
|
|
140
|
+
|
|
110
141
|
test('routing section clarifies reminders are for time-triggered notifications', () => {
|
|
111
142
|
const prompt = buildSystemPrompt();
|
|
112
143
|
expect(prompt).toContain('one-time time-triggered notifications');
|
|
@@ -117,7 +148,7 @@ describe('Task/Schedule/Reminder routing section in system prompt', () => {
|
|
|
117
148
|
const prompt = buildSystemPrompt();
|
|
118
149
|
expect(prompt).toContain('### Common mistakes to avoid');
|
|
119
150
|
// The key mis-routing guard: "add this to my tasks" should go to task_list_add
|
|
120
|
-
expect(prompt).toContain('"Add this to my tasks" → task_list_add (NOT schedule_create or
|
|
151
|
+
expect(prompt).toContain('"Add this to my tasks" → task_list_add (NOT schedule_create or reminder_create)');
|
|
121
152
|
});
|
|
122
153
|
|
|
123
154
|
test('routing section distinguishes timed vs untimed "remind me"', () => {
|
|
@@ -125,7 +156,7 @@ describe('Task/Schedule/Reminder routing section in system prompt', () => {
|
|
|
125
156
|
// Without a time → task queue
|
|
126
157
|
expect(prompt).toContain('"Remind me to buy groceries" without a time → task_list_add');
|
|
127
158
|
// With a time → reminder
|
|
128
|
-
expect(prompt).toContain('"Remind me at 5pm to buy groceries" →
|
|
159
|
+
expect(prompt).toContain('"Remind me at 5pm to buy groceries" → reminder_create');
|
|
129
160
|
});
|
|
130
161
|
|
|
131
162
|
test('routing section appears after tool routing by content type', () => {
|
|
@@ -144,85 +175,70 @@ describe('Task/Schedule/Reminder routing section in system prompt', () => {
|
|
|
144
175
|
|
|
145
176
|
describe('task_list_add tool description', () => {
|
|
146
177
|
test('mentions "add to my tasks" routing phrase', () => {
|
|
147
|
-
const def =
|
|
178
|
+
const def = taskListAddDef;
|
|
148
179
|
expect(def.description).toContain('add to my tasks');
|
|
149
180
|
});
|
|
150
181
|
|
|
151
182
|
test('mentions "add to my queue" routing phrase', () => {
|
|
152
|
-
const def =
|
|
183
|
+
const def = taskListAddDef;
|
|
153
184
|
expect(def.description).toContain('add to my queue');
|
|
154
185
|
});
|
|
155
186
|
|
|
156
187
|
test('mentions "put this on my task list" routing phrase', () => {
|
|
157
|
-
const def =
|
|
188
|
+
const def = taskListAddDef;
|
|
158
189
|
expect(def.description).toContain('put this on my task list');
|
|
159
190
|
});
|
|
160
191
|
|
|
161
192
|
test('mentions ad-hoc title-only mode', () => {
|
|
162
|
-
const def =
|
|
193
|
+
const def = taskListAddDef;
|
|
163
194
|
expect(def.description).toContain('just a title');
|
|
164
195
|
});
|
|
165
196
|
|
|
166
197
|
test('explicitly warns NOT to use schedule_create or reminder for task requests', () => {
|
|
167
|
-
const def =
|
|
198
|
+
const def = taskListAddDef;
|
|
168
199
|
expect(def.description).toContain('Do NOT use schedule_create or reminder');
|
|
169
200
|
});
|
|
170
201
|
});
|
|
171
202
|
|
|
172
203
|
describe('schedule_create tool description', () => {
|
|
173
204
|
test('mentions recurring scheduled automation', () => {
|
|
174
|
-
|
|
175
|
-
expect(
|
|
176
|
-
const def = tool!.getDefinition();
|
|
177
|
-
expect(def.description).toContain('recurring');
|
|
205
|
+
expect(scheduleCreateDef).toBeDefined();
|
|
206
|
+
expect(scheduleCreateDef.description).toContain('recurring');
|
|
178
207
|
});
|
|
179
208
|
|
|
180
209
|
test('mentions cron interval', () => {
|
|
181
|
-
|
|
182
|
-
const def = tool!.getDefinition();
|
|
183
|
-
expect(def.description).toContain('cron');
|
|
210
|
+
expect(scheduleCreateDef.description).toContain('cron');
|
|
184
211
|
});
|
|
185
212
|
|
|
186
213
|
test('warns against using for "add to my tasks" requests', () => {
|
|
187
|
-
|
|
188
|
-
const def = tool!.getDefinition();
|
|
189
|
-
expect(def.description).toContain('Do NOT use this for "add to my tasks"');
|
|
214
|
+
expect(scheduleCreateDef.description).toContain('Do NOT use this for "add to my tasks"');
|
|
190
215
|
});
|
|
191
216
|
|
|
192
217
|
test('redirects to task_list_add for task queue items', () => {
|
|
193
|
-
|
|
194
|
-
const def = tool!.getDefinition();
|
|
195
|
-
expect(def.description).toContain('task_list_add');
|
|
218
|
+
expect(scheduleCreateDef.description).toContain('task_list_add');
|
|
196
219
|
});
|
|
197
220
|
|
|
198
221
|
test('does NOT suggest it handles task queue items', () => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// Should not claim to handle one-off task items
|
|
202
|
-
expect(def.description).not.toContain('task queue');
|
|
203
|
-
expect(def.description).not.toContain('one-off');
|
|
222
|
+
expect(scheduleCreateDef.description).not.toContain('task queue');
|
|
223
|
+
expect(scheduleCreateDef.description).not.toContain('one-off');
|
|
204
224
|
});
|
|
205
225
|
});
|
|
206
226
|
|
|
207
227
|
describe('reminder tool description', () => {
|
|
208
228
|
test('mentions time-based reminders', () => {
|
|
209
|
-
|
|
210
|
-
expect(def.description).toContain('time-based reminders');
|
|
229
|
+
expect(reminderCreateDef.description).toContain('time-based reminder');
|
|
211
230
|
});
|
|
212
231
|
|
|
213
232
|
test('scopes to time-triggered notifications only', () => {
|
|
214
|
-
|
|
215
|
-
expect(def.description).toContain('ONLY when the user wants a time-triggered notification');
|
|
233
|
+
expect(reminderCreateDef.description).toContain('ONLY when the user wants a time-triggered notification');
|
|
216
234
|
});
|
|
217
235
|
|
|
218
236
|
test('warns against using for "add to my tasks" requests', () => {
|
|
219
|
-
|
|
220
|
-
expect(def.description).toContain('Do NOT use this for "add to my tasks"');
|
|
237
|
+
expect(reminderCreateDef.description).toContain('Do NOT use this for "add to my tasks"');
|
|
221
238
|
});
|
|
222
239
|
|
|
223
240
|
test('redirects to task_list_add for task queue items', () => {
|
|
224
|
-
|
|
225
|
-
expect(def.description).toContain('task_list_add');
|
|
241
|
+
expect(reminderCreateDef.description).toContain('task_list_add');
|
|
226
242
|
});
|
|
227
243
|
});
|
|
228
244
|
|
|
@@ -232,24 +248,15 @@ describe('reminder tool description', () => {
|
|
|
232
248
|
|
|
233
249
|
describe('cross-tool routing consistency', () => {
|
|
234
250
|
test('all three tools reference task_list_add as the task-queue tool', () => {
|
|
235
|
-
const enqueueDef = taskListAddTool.getDefinition();
|
|
236
|
-
const scheduleTool = getTool('schedule_create')!;
|
|
237
|
-
const scheduleDef = scheduleTool.getDefinition();
|
|
238
|
-
const reminderDef = reminderTool.getDefinition();
|
|
239
|
-
|
|
240
251
|
// task_list_add is the canonical name in all three descriptions
|
|
241
|
-
expect(
|
|
242
|
-
expect(
|
|
243
|
-
expect(
|
|
252
|
+
expect(taskListAddDef.name).toBe('task_list_add');
|
|
253
|
+
expect(scheduleCreateDef.description).toContain('task_list_add');
|
|
254
|
+
expect(reminderCreateDef.description).toContain('task_list_add');
|
|
244
255
|
});
|
|
245
256
|
|
|
246
257
|
test('schedule_create and reminder both reject "add to my queue" usage', () => {
|
|
247
|
-
const scheduleTool = getTool('schedule_create')!;
|
|
248
|
-
const scheduleDef = scheduleTool.getDefinition();
|
|
249
|
-
const reminderDef = reminderTool.getDefinition();
|
|
250
|
-
|
|
251
258
|
// Both should redirect away from task-queue requests
|
|
252
|
-
expect(
|
|
253
|
-
expect(
|
|
259
|
+
expect(scheduleCreateDef.description).toContain('add to my queue');
|
|
260
|
+
expect(reminderCreateDef.description).toContain('add to my queue');
|
|
254
261
|
});
|
|
255
262
|
});
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPC Serialization/Parsing Benchmark
|
|
3
|
+
*
|
|
4
|
+
* Measures serialize + parse round-trip performance in isolation
|
|
5
|
+
* (no daemon required). Target ranges:
|
|
6
|
+
* - Small message p95: < 1ms (averaged over 1000 runs)
|
|
7
|
+
* - Large message (1MB): < 50ms
|
|
8
|
+
* - Rapid-fire: no message loss across 100 messages
|
|
9
|
+
* - Round-trip: content preserved exactly
|
|
10
|
+
*/
|
|
11
|
+
import { afterAll, beforeAll, describe, expect, mock, test } from 'bun:test';
|
|
12
|
+
import * as net from 'node:net';
|
|
13
|
+
import * as os from 'node:os';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import * as fs from 'node:fs';
|
|
16
|
+
|
|
17
|
+
mock.module('../util/logger.js', () => ({
|
|
18
|
+
getLogger: () =>
|
|
19
|
+
new Proxy({} as Record<string, unknown>, {
|
|
20
|
+
get: () => () => {},
|
|
21
|
+
}),
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
import { serialize, createMessageParser } from '../daemon/ipc-protocol.js';
|
|
25
|
+
import type { ClientMessage, ServerMessage } from '../daemon/ipc-contract.js';
|
|
26
|
+
|
|
27
|
+
function percentile(values: number[], p: number): number {
|
|
28
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
29
|
+
const idx = Math.ceil((p / 100) * sorted.length) - 1;
|
|
30
|
+
return sorted[Math.max(0, idx)];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('IPC round-trip benchmark', () => {
|
|
34
|
+
test('small message serialize + parse p95 < 1ms over 1000 runs', () => {
|
|
35
|
+
const msg: ClientMessage = { type: 'ping' };
|
|
36
|
+
const parser = createMessageParser();
|
|
37
|
+
const timings: number[] = [];
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < 1000; i++) {
|
|
40
|
+
const start = performance.now();
|
|
41
|
+
const serialized = serialize(msg);
|
|
42
|
+
const parsed = parser.feed(serialized);
|
|
43
|
+
const elapsed = performance.now() - start;
|
|
44
|
+
timings.push(elapsed);
|
|
45
|
+
|
|
46
|
+
// Sanity: each iteration should yield exactly one message
|
|
47
|
+
expect(parsed).toHaveLength(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const p95 = percentile(timings, 95);
|
|
51
|
+
expect(p95).toBeLessThan(1);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('large message (1MB) serialize + parse < 50ms', () => {
|
|
55
|
+
// Build a ~1MB payload using assistant_text_delta with a large text field
|
|
56
|
+
const largeText = 'x'.repeat(1024 * 1024);
|
|
57
|
+
const msg: ServerMessage = { type: 'assistant_text_delta', text: largeText };
|
|
58
|
+
const parser = createMessageParser();
|
|
59
|
+
const timings: number[] = [];
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < 10; i++) {
|
|
62
|
+
const start = performance.now();
|
|
63
|
+
const serialized = serialize(msg);
|
|
64
|
+
const parsed = parser.feed(serialized);
|
|
65
|
+
const elapsed = performance.now() - start;
|
|
66
|
+
timings.push(elapsed);
|
|
67
|
+
|
|
68
|
+
expect(parsed).toHaveLength(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const p95 = percentile(timings, 95);
|
|
72
|
+
expect(p95).toBeLessThan(50);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('no message loss under rapid-fire (100 messages)', () => {
|
|
76
|
+
const parser = createMessageParser();
|
|
77
|
+
const messages: ClientMessage[] = [];
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < 100; i++) {
|
|
80
|
+
messages.push({ type: 'session_list' } as ClientMessage);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Serialize all messages and concatenate into a single buffer
|
|
84
|
+
const combined = messages.map((m) => serialize(m)).join('');
|
|
85
|
+
|
|
86
|
+
// Feed the entire buffer at once
|
|
87
|
+
const parsed = parser.feed(combined);
|
|
88
|
+
|
|
89
|
+
expect(parsed).toHaveLength(100);
|
|
90
|
+
for (const p of parsed) {
|
|
91
|
+
expect(p).toHaveProperty('type', 'session_list');
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('serialize + parse round-trip preserves message content', () => {
|
|
96
|
+
const parser = createMessageParser();
|
|
97
|
+
|
|
98
|
+
const clientMsg: ClientMessage = {
|
|
99
|
+
type: 'user_message',
|
|
100
|
+
sessionId: 'sess-abc-123',
|
|
101
|
+
content: 'Hello, world! Special chars: \u00e9\u00e0\u00fc \ud83d\ude00 "quotes" & <angle>',
|
|
102
|
+
attachments: [
|
|
103
|
+
{
|
|
104
|
+
filename: 'test.txt',
|
|
105
|
+
mimeType: 'text/plain',
|
|
106
|
+
data: 'SGVsbG8gV29ybGQ=',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const serialized = serialize(clientMsg);
|
|
112
|
+
const parsed = parser.feed(serialized);
|
|
113
|
+
|
|
114
|
+
expect(parsed).toHaveLength(1);
|
|
115
|
+
const roundTripped = parsed[0] as ClientMessage;
|
|
116
|
+
expect(roundTripped).toEqual(clientMsg);
|
|
117
|
+
|
|
118
|
+
// Verify specific fields survived the round-trip
|
|
119
|
+
expect(roundTripped.type).toBe('user_message');
|
|
120
|
+
if (roundTripped.type === 'user_message') {
|
|
121
|
+
expect(roundTripped.sessionId).toBe('sess-abc-123');
|
|
122
|
+
expect(roundTripped.content).toContain('\ud83d\ude00');
|
|
123
|
+
expect(roundTripped.attachments).toHaveLength(1);
|
|
124
|
+
expect(roundTripped.attachments![0].filename).toBe('test.txt');
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('IPC Unix socket round-trip benchmark', () => {
|
|
130
|
+
let server: net.Server;
|
|
131
|
+
let client: net.Socket;
|
|
132
|
+
let tmpDir: string;
|
|
133
|
+
let socketPath: string;
|
|
134
|
+
|
|
135
|
+
beforeAll(async () => {
|
|
136
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ipc-bench-'));
|
|
137
|
+
socketPath = path.join(tmpDir, 'bench.sock');
|
|
138
|
+
|
|
139
|
+
// Server: parse incoming messages, echo back a session_list_response for each
|
|
140
|
+
server = net.createServer((socket) => {
|
|
141
|
+
const parser = createMessageParser();
|
|
142
|
+
socket.on('data', (data) => {
|
|
143
|
+
const msgs = parser.feed(data.toString());
|
|
144
|
+
for (const _msg of msgs) {
|
|
145
|
+
const response: ServerMessage = {
|
|
146
|
+
type: 'session_list_response',
|
|
147
|
+
sessions: [],
|
|
148
|
+
};
|
|
149
|
+
socket.write(serialize(response));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await new Promise<void>((resolve) => server.listen(socketPath, resolve));
|
|
155
|
+
|
|
156
|
+
client = net.createConnection(socketPath);
|
|
157
|
+
await new Promise<void>((resolve) => client.on('connect', resolve));
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
afterAll(async () => {
|
|
161
|
+
client?.destroy();
|
|
162
|
+
await new Promise<void>((resolve) => server?.close(() => resolve()));
|
|
163
|
+
try { fs.unlinkSync(socketPath); } catch { /* server.close() may already remove it */ }
|
|
164
|
+
try { fs.rmdirSync(tmpDir); } catch { /* best-effort */ }
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('session_list round-trip p50 < 5ms, p99 < 50ms', async () => {
|
|
168
|
+
const clientParser = createMessageParser();
|
|
169
|
+
const timings: number[] = [];
|
|
170
|
+
const iterations = 50;
|
|
171
|
+
|
|
172
|
+
for (let i = 0; i < iterations; i++) {
|
|
173
|
+
const start = performance.now();
|
|
174
|
+
|
|
175
|
+
const responsePromise = new Promise<ServerMessage>((resolve) => {
|
|
176
|
+
const handler = (data: Buffer) => {
|
|
177
|
+
const msgs = clientParser.feed(data.toString());
|
|
178
|
+
if (msgs.length > 0) {
|
|
179
|
+
client.removeListener('data', handler);
|
|
180
|
+
resolve(msgs[0] as ServerMessage);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
client.on('data', handler);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const request: ClientMessage = { type: 'session_list' };
|
|
187
|
+
client.write(serialize(request));
|
|
188
|
+
|
|
189
|
+
const response = await responsePromise;
|
|
190
|
+
const elapsed = performance.now() - start;
|
|
191
|
+
timings.push(elapsed);
|
|
192
|
+
|
|
193
|
+
expect(response.type).toBe('session_list_response');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const p50 = percentile(timings, 50);
|
|
197
|
+
const p99 = percentile(timings, 99);
|
|
198
|
+
expect(p50).toBeLessThan(5);
|
|
199
|
+
expect(p99).toBeLessThan(50);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('rapid-fire: 100 messages over socket without loss', async () => {
|
|
203
|
+
const clientParser = createMessageParser();
|
|
204
|
+
const messageCount = 100;
|
|
205
|
+
const received: ServerMessage[] = [];
|
|
206
|
+
|
|
207
|
+
const allReceived = new Promise<void>((resolve) => {
|
|
208
|
+
const handler = (data: Buffer) => {
|
|
209
|
+
const msgs = clientParser.feed(data.toString());
|
|
210
|
+
for (const msg of msgs) {
|
|
211
|
+
received.push(msg as ServerMessage);
|
|
212
|
+
}
|
|
213
|
+
if (received.length >= messageCount) {
|
|
214
|
+
client.removeListener('data', handler);
|
|
215
|
+
resolve();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
client.on('data', handler);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const start = performance.now();
|
|
222
|
+
for (let i = 0; i < messageCount; i++) {
|
|
223
|
+
const request: ClientMessage = { type: 'session_list' };
|
|
224
|
+
client.write(serialize(request));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
await allReceived;
|
|
228
|
+
const elapsed = performance.now() - start;
|
|
229
|
+
|
|
230
|
+
expect(received).toHaveLength(messageCount);
|
|
231
|
+
for (const msg of received) {
|
|
232
|
+
expect(msg.type).toBe('session_list_response');
|
|
233
|
+
}
|
|
234
|
+
// All 100 messages should complete well within 100ms on a local socket
|
|
235
|
+
expect(elapsed).toBeLessThan(100);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -70,6 +70,10 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
70
70
|
type: 'model_set',
|
|
71
71
|
model: 'claude-opus-4-6',
|
|
72
72
|
},
|
|
73
|
+
image_gen_model_set: {
|
|
74
|
+
type: 'image_gen_model_set',
|
|
75
|
+
model: 'gemini-2.5-flash-image',
|
|
76
|
+
},
|
|
73
77
|
history_request: {
|
|
74
78
|
type: 'history_request',
|
|
75
79
|
sessionId: 'sess-001',
|
|
@@ -339,6 +343,16 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
339
343
|
type: 'vercel_api_config',
|
|
340
344
|
action: 'get',
|
|
341
345
|
},
|
|
346
|
+
twitter_integration_config: {
|
|
347
|
+
type: 'twitter_integration_config',
|
|
348
|
+
action: 'get',
|
|
349
|
+
},
|
|
350
|
+
twitter_auth_start: {
|
|
351
|
+
type: 'twitter_auth_start',
|
|
352
|
+
},
|
|
353
|
+
twitter_auth_status: {
|
|
354
|
+
type: 'twitter_auth_status',
|
|
355
|
+
},
|
|
342
356
|
link_open_request: {
|
|
343
357
|
type: 'link_open_request',
|
|
344
358
|
url: 'https://example.com',
|
|
@@ -419,14 +433,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
419
433
|
type: 'work_item_get',
|
|
420
434
|
id: 'wi-001',
|
|
421
435
|
},
|
|
422
|
-
work_item_create: {
|
|
423
|
-
type: 'work_item_create',
|
|
424
|
-
taskId: 'task-001',
|
|
425
|
-
title: 'Process report',
|
|
426
|
-
notes: 'High priority',
|
|
427
|
-
priorityTier: 1,
|
|
428
|
-
sortIndex: 0,
|
|
429
|
-
},
|
|
430
436
|
work_item_update: {
|
|
431
437
|
type: 'work_item_update',
|
|
432
438
|
id: 'wi-001',
|
|
@@ -437,10 +443,31 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
437
443
|
type: 'work_item_complete',
|
|
438
444
|
id: 'wi-001',
|
|
439
445
|
},
|
|
446
|
+
work_item_delete: {
|
|
447
|
+
type: 'work_item_delete',
|
|
448
|
+
id: 'wi-001',
|
|
449
|
+
},
|
|
440
450
|
work_item_run_task: {
|
|
441
451
|
type: 'work_item_run_task',
|
|
442
452
|
id: 'wi-001',
|
|
443
453
|
},
|
|
454
|
+
work_item_output: {
|
|
455
|
+
type: 'work_item_output',
|
|
456
|
+
id: 'wi-001',
|
|
457
|
+
},
|
|
458
|
+
work_item_preflight: {
|
|
459
|
+
type: 'work_item_preflight',
|
|
460
|
+
id: 'wi-001',
|
|
461
|
+
},
|
|
462
|
+
work_item_approve_permissions: {
|
|
463
|
+
type: 'work_item_approve_permissions',
|
|
464
|
+
id: 'wi-001',
|
|
465
|
+
approvedTools: ['bash', 'file_write'],
|
|
466
|
+
},
|
|
467
|
+
work_item_cancel: {
|
|
468
|
+
type: 'work_item_cancel',
|
|
469
|
+
id: 'wi-001',
|
|
470
|
+
},
|
|
444
471
|
document_save: {
|
|
445
472
|
type: 'document_save',
|
|
446
473
|
surfaceId: 'doc-001',
|
|
@@ -464,7 +491,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
464
491
|
subagent_status: {
|
|
465
492
|
type: 'subagent_status',
|
|
466
493
|
subagentId: 'sub-001',
|
|
467
|
-
sessionId: 'sess-001',
|
|
468
494
|
},
|
|
469
495
|
subagent_message: {
|
|
470
496
|
type: 'subagent_message',
|
|
@@ -895,6 +921,8 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
895
921
|
id: 'sched-001',
|
|
896
922
|
name: 'Daily standup reminder',
|
|
897
923
|
enabled: true,
|
|
924
|
+
syntax: 'cron',
|
|
925
|
+
expression: '0 9 * * 1-5',
|
|
898
926
|
cronExpression: '0 9 * * 1-5',
|
|
899
927
|
timezone: 'America/Los_Angeles',
|
|
900
928
|
message: 'Remind me about the standup',
|
|
@@ -1102,6 +1130,25 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1102
1130
|
hasToken: true,
|
|
1103
1131
|
success: true,
|
|
1104
1132
|
},
|
|
1133
|
+
twitter_integration_config_response: {
|
|
1134
|
+
type: 'twitter_integration_config_response',
|
|
1135
|
+
success: true,
|
|
1136
|
+
mode: 'local_byo',
|
|
1137
|
+
managedAvailable: false,
|
|
1138
|
+
localClientConfigured: true,
|
|
1139
|
+
connected: false,
|
|
1140
|
+
},
|
|
1141
|
+
twitter_auth_result: {
|
|
1142
|
+
type: 'twitter_auth_result',
|
|
1143
|
+
success: true,
|
|
1144
|
+
accountInfo: '@vellum_test',
|
|
1145
|
+
},
|
|
1146
|
+
twitter_auth_status_response: {
|
|
1147
|
+
type: 'twitter_auth_status_response',
|
|
1148
|
+
connected: true,
|
|
1149
|
+
accountInfo: '@vellum_test',
|
|
1150
|
+
mode: 'local_byo',
|
|
1151
|
+
},
|
|
1105
1152
|
open_url: {
|
|
1106
1153
|
type: 'open_url',
|
|
1107
1154
|
url: 'https://example.com',
|
|
@@ -1271,25 +1318,6 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1271
1318
|
updatedAt: 1700000000,
|
|
1272
1319
|
},
|
|
1273
1320
|
},
|
|
1274
|
-
work_item_create_response: {
|
|
1275
|
-
type: 'work_item_create_response',
|
|
1276
|
-
item: {
|
|
1277
|
-
id: 'wi-001',
|
|
1278
|
-
taskId: 'task-001',
|
|
1279
|
-
title: 'Process report',
|
|
1280
|
-
notes: null,
|
|
1281
|
-
status: 'queued',
|
|
1282
|
-
priorityTier: 1,
|
|
1283
|
-
sortIndex: null,
|
|
1284
|
-
lastRunId: null,
|
|
1285
|
-
lastRunConversationId: null,
|
|
1286
|
-
lastRunStatus: null,
|
|
1287
|
-
sourceType: null,
|
|
1288
|
-
sourceId: null,
|
|
1289
|
-
createdAt: 1700000000,
|
|
1290
|
-
updatedAt: 1700000000,
|
|
1291
|
-
},
|
|
1292
|
-
},
|
|
1293
1321
|
work_item_update_response: {
|
|
1294
1322
|
type: 'work_item_update_response',
|
|
1295
1323
|
item: {
|
|
@@ -1309,12 +1337,49 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1309
1337
|
updatedAt: 1700001000,
|
|
1310
1338
|
},
|
|
1311
1339
|
},
|
|
1340
|
+
work_item_delete_response: {
|
|
1341
|
+
type: 'work_item_delete_response',
|
|
1342
|
+
id: 'wi-001',
|
|
1343
|
+
success: true,
|
|
1344
|
+
},
|
|
1312
1345
|
work_item_run_task_response: {
|
|
1313
1346
|
type: 'work_item_run_task_response',
|
|
1314
1347
|
id: 'wi-001',
|
|
1315
1348
|
lastRunId: 'run-001',
|
|
1316
1349
|
success: true,
|
|
1317
1350
|
},
|
|
1351
|
+
work_item_output_response: {
|
|
1352
|
+
type: 'work_item_output_response',
|
|
1353
|
+
id: 'wi-001',
|
|
1354
|
+
success: true,
|
|
1355
|
+
output: {
|
|
1356
|
+
title: 'Process report',
|
|
1357
|
+
status: 'completed',
|
|
1358
|
+
runId: 'run-001',
|
|
1359
|
+
conversationId: 'conv-001',
|
|
1360
|
+
completedAt: 1700002000,
|
|
1361
|
+
summary: 'Report processed successfully.',
|
|
1362
|
+
highlights: ['- Key finding 1', '- Key finding 2'],
|
|
1363
|
+
},
|
|
1364
|
+
},
|
|
1365
|
+
work_item_preflight_response: {
|
|
1366
|
+
type: 'work_item_preflight_response',
|
|
1367
|
+
id: 'wi-001',
|
|
1368
|
+
success: true,
|
|
1369
|
+
permissions: [
|
|
1370
|
+
{ tool: 'bash', description: 'Run shell commands', riskLevel: 'medium', currentDecision: 'prompt' },
|
|
1371
|
+
],
|
|
1372
|
+
},
|
|
1373
|
+
work_item_approve_permissions_response: {
|
|
1374
|
+
type: 'work_item_approve_permissions_response',
|
|
1375
|
+
id: 'wi-001',
|
|
1376
|
+
success: true,
|
|
1377
|
+
},
|
|
1378
|
+
work_item_cancel_response: {
|
|
1379
|
+
type: 'work_item_cancel_response',
|
|
1380
|
+
id: 'wi-001',
|
|
1381
|
+
success: true,
|
|
1382
|
+
},
|
|
1318
1383
|
work_item_status_changed: {
|
|
1319
1384
|
type: 'work_item_status_changed',
|
|
1320
1385
|
item: {
|
|
@@ -1328,6 +1393,9 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1328
1393
|
updatedAt: 1700001000,
|
|
1329
1394
|
},
|
|
1330
1395
|
},
|
|
1396
|
+
tasks_changed: {
|
|
1397
|
+
type: 'tasks_changed',
|
|
1398
|
+
},
|
|
1331
1399
|
open_tasks_window: {
|
|
1332
1400
|
type: 'open_tasks_window',
|
|
1333
1401
|
},
|