vellum 0.2.1 → 0.2.7
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 +71 -100
- package/package.json +5 -3
- 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 +305 -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-twilio-config.test.ts +221 -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 +71 -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-regressions.test.ts +100 -2
- 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-commit-message-generator.test.ts +303 -0
- 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-conflict-gate.test.ts +28 -25
- 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/__tests__/twilio-webhook-urls.test.ts +162 -0
- 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-config.ts +8 -8
- package/src/calls/twilio-provider.ts +13 -9
- package/src/calls/twilio-routes.ts +90 -76
- package/src/calls/twilio-webhook-urls.ts +50 -0
- 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 +270 -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 +34 -0
- package/src/config/loader.ts +4 -1
- package/src/config/schema.ts +165 -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/config/vellum-skills/telegram-setup/SKILL.md +1 -5
- 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 +205 -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 +32 -4
- package/src/daemon/ipc-contract.ts +156 -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 +75 -10
- package/src/daemon/server.ts +143 -26
- package/src/daemon/session-agent-loop.ts +922 -0
- package/src/daemon/session-attachments.ts +28 -5
- package/src/daemon/session-conflict-gate.ts +18 -109
- 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/conflict-intent.ts +114 -0
- 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/job-handlers/conflict.ts +23 -1
- 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/gateway-client.ts +36 -0
- package/src/runtime/http-server.ts +166 -22
- 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 +125 -88
- 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 +293 -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 +207 -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 +269 -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
|
@@ -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
|
+
});
|
|
@@ -339,10 +339,24 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
339
339
|
type: 'slack_webhook_config',
|
|
340
340
|
action: 'get',
|
|
341
341
|
},
|
|
342
|
+
twilio_webhook_config: {
|
|
343
|
+
type: 'twilio_webhook_config',
|
|
344
|
+
action: 'get',
|
|
345
|
+
},
|
|
342
346
|
vercel_api_config: {
|
|
343
347
|
type: 'vercel_api_config',
|
|
344
348
|
action: 'get',
|
|
345
349
|
},
|
|
350
|
+
twitter_integration_config: {
|
|
351
|
+
type: 'twitter_integration_config',
|
|
352
|
+
action: 'get',
|
|
353
|
+
},
|
|
354
|
+
twitter_auth_start: {
|
|
355
|
+
type: 'twitter_auth_start',
|
|
356
|
+
},
|
|
357
|
+
twitter_auth_status: {
|
|
358
|
+
type: 'twitter_auth_status',
|
|
359
|
+
},
|
|
346
360
|
link_open_request: {
|
|
347
361
|
type: 'link_open_request',
|
|
348
362
|
url: 'https://example.com',
|
|
@@ -423,14 +437,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
423
437
|
type: 'work_item_get',
|
|
424
438
|
id: 'wi-001',
|
|
425
439
|
},
|
|
426
|
-
work_item_create: {
|
|
427
|
-
type: 'work_item_create',
|
|
428
|
-
taskId: 'task-001',
|
|
429
|
-
title: 'Process report',
|
|
430
|
-
notes: 'High priority',
|
|
431
|
-
priorityTier: 1,
|
|
432
|
-
sortIndex: 0,
|
|
433
|
-
},
|
|
434
440
|
work_item_update: {
|
|
435
441
|
type: 'work_item_update',
|
|
436
442
|
id: 'wi-001',
|
|
@@ -453,6 +459,19 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
453
459
|
type: 'work_item_output',
|
|
454
460
|
id: 'wi-001',
|
|
455
461
|
},
|
|
462
|
+
work_item_preflight: {
|
|
463
|
+
type: 'work_item_preflight',
|
|
464
|
+
id: 'wi-001',
|
|
465
|
+
},
|
|
466
|
+
work_item_approve_permissions: {
|
|
467
|
+
type: 'work_item_approve_permissions',
|
|
468
|
+
id: 'wi-001',
|
|
469
|
+
approvedTools: ['bash', 'file_write'],
|
|
470
|
+
},
|
|
471
|
+
work_item_cancel: {
|
|
472
|
+
type: 'work_item_cancel',
|
|
473
|
+
id: 'wi-001',
|
|
474
|
+
},
|
|
456
475
|
document_save: {
|
|
457
476
|
type: 'document_save',
|
|
458
477
|
surfaceId: 'doc-001',
|
|
@@ -476,7 +495,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
476
495
|
subagent_status: {
|
|
477
496
|
type: 'subagent_status',
|
|
478
497
|
subagentId: 'sub-001',
|
|
479
|
-
sessionId: 'sess-001',
|
|
480
498
|
},
|
|
481
499
|
subagent_message: {
|
|
482
500
|
type: 'subagent_message',
|
|
@@ -907,6 +925,8 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
907
925
|
id: 'sched-001',
|
|
908
926
|
name: 'Daily standup reminder',
|
|
909
927
|
enabled: true,
|
|
928
|
+
syntax: 'cron',
|
|
929
|
+
expression: '0 9 * * 1-5',
|
|
910
930
|
cronExpression: '0 9 * * 1-5',
|
|
911
931
|
timezone: 'America/Los_Angeles',
|
|
912
932
|
message: 'Remind me about the standup',
|
|
@@ -1109,11 +1129,35 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1109
1129
|
webhookUrl: 'https://hooks.slack.com/services/T00/B00/xxx',
|
|
1110
1130
|
success: true,
|
|
1111
1131
|
},
|
|
1132
|
+
twilio_webhook_config_response: {
|
|
1133
|
+
type: 'twilio_webhook_config_response',
|
|
1134
|
+
webhookBaseUrl: 'https://example.com/twilio',
|
|
1135
|
+
success: true,
|
|
1136
|
+
},
|
|
1112
1137
|
vercel_api_config_response: {
|
|
1113
1138
|
type: 'vercel_api_config_response',
|
|
1114
1139
|
hasToken: true,
|
|
1115
1140
|
success: true,
|
|
1116
1141
|
},
|
|
1142
|
+
twitter_integration_config_response: {
|
|
1143
|
+
type: 'twitter_integration_config_response',
|
|
1144
|
+
success: true,
|
|
1145
|
+
mode: 'local_byo',
|
|
1146
|
+
managedAvailable: false,
|
|
1147
|
+
localClientConfigured: true,
|
|
1148
|
+
connected: false,
|
|
1149
|
+
},
|
|
1150
|
+
twitter_auth_result: {
|
|
1151
|
+
type: 'twitter_auth_result',
|
|
1152
|
+
success: true,
|
|
1153
|
+
accountInfo: '@vellum_test',
|
|
1154
|
+
},
|
|
1155
|
+
twitter_auth_status_response: {
|
|
1156
|
+
type: 'twitter_auth_status_response',
|
|
1157
|
+
connected: true,
|
|
1158
|
+
accountInfo: '@vellum_test',
|
|
1159
|
+
mode: 'local_byo',
|
|
1160
|
+
},
|
|
1117
1161
|
open_url: {
|
|
1118
1162
|
type: 'open_url',
|
|
1119
1163
|
url: 'https://example.com',
|
|
@@ -1283,25 +1327,6 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1283
1327
|
updatedAt: 1700000000,
|
|
1284
1328
|
},
|
|
1285
1329
|
},
|
|
1286
|
-
work_item_create_response: {
|
|
1287
|
-
type: 'work_item_create_response',
|
|
1288
|
-
item: {
|
|
1289
|
-
id: 'wi-001',
|
|
1290
|
-
taskId: 'task-001',
|
|
1291
|
-
title: 'Process report',
|
|
1292
|
-
notes: null,
|
|
1293
|
-
status: 'queued',
|
|
1294
|
-
priorityTier: 1,
|
|
1295
|
-
sortIndex: null,
|
|
1296
|
-
lastRunId: null,
|
|
1297
|
-
lastRunConversationId: null,
|
|
1298
|
-
lastRunStatus: null,
|
|
1299
|
-
sourceType: null,
|
|
1300
|
-
sourceId: null,
|
|
1301
|
-
createdAt: 1700000000,
|
|
1302
|
-
updatedAt: 1700000000,
|
|
1303
|
-
},
|
|
1304
|
-
},
|
|
1305
1330
|
work_item_update_response: {
|
|
1306
1331
|
type: 'work_item_update_response',
|
|
1307
1332
|
item: {
|
|
@@ -1346,6 +1371,24 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1346
1371
|
highlights: ['- Key finding 1', '- Key finding 2'],
|
|
1347
1372
|
},
|
|
1348
1373
|
},
|
|
1374
|
+
work_item_preflight_response: {
|
|
1375
|
+
type: 'work_item_preflight_response',
|
|
1376
|
+
id: 'wi-001',
|
|
1377
|
+
success: true,
|
|
1378
|
+
permissions: [
|
|
1379
|
+
{ tool: 'bash', description: 'Run shell commands', riskLevel: 'medium', currentDecision: 'prompt' },
|
|
1380
|
+
],
|
|
1381
|
+
},
|
|
1382
|
+
work_item_approve_permissions_response: {
|
|
1383
|
+
type: 'work_item_approve_permissions_response',
|
|
1384
|
+
id: 'wi-001',
|
|
1385
|
+
success: true,
|
|
1386
|
+
},
|
|
1387
|
+
work_item_cancel_response: {
|
|
1388
|
+
type: 'work_item_cancel_response',
|
|
1389
|
+
id: 'wi-001',
|
|
1390
|
+
success: true,
|
|
1391
|
+
},
|
|
1349
1392
|
work_item_status_changed: {
|
|
1350
1393
|
type: 'work_item_status_changed',
|
|
1351
1394
|
item: {
|