vellum 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/bun.lock +5 -2
- package/package.json +4 -2
- package/scripts/capture-x-graphql.ts +562 -0
- package/scripts/ipc/check-swift-decoder-drift.ts +2 -1
- package/scripts/test.sh +5 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +133 -34
- package/src/__tests__/account-registry.test.ts +2 -1
- package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
- package/src/__tests__/asset-materialize-tool.test.ts +16 -15
- package/src/__tests__/asset-search-tool.test.ts +23 -22
- package/src/__tests__/attachments-store.test.ts +56 -127
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +5 -4
- package/src/__tests__/browser-skill-endstate.test.ts +4 -3
- package/src/__tests__/call-bridge.test.ts +385 -0
- package/src/__tests__/call-constants.test.ts +40 -0
- package/src/__tests__/call-orchestrator.test.ts +130 -4
- package/src/__tests__/call-recovery.test.ts +518 -0
- package/src/__tests__/call-routes-http.test.ts +459 -0
- package/src/__tests__/call-state-machine.test.ts +143 -0
- package/src/__tests__/call-store.test.ts +216 -1
- package/src/__tests__/cli-discover.test.ts +1 -1
- package/src/__tests__/commit-message-enrichment-service.test.ts +148 -7
- package/src/__tests__/compaction.benchmark.test.ts +176 -0
- package/src/__tests__/computer-use-tools.test.ts +250 -0
- package/src/__tests__/config-schema.test.ts +299 -3
- package/src/__tests__/conflict-store.test.ts +2 -1
- package/src/__tests__/contacts-tools.test.ts +331 -0
- package/src/__tests__/conversation-store.test.ts +30 -32
- package/src/__tests__/credential-security-invariants.test.ts +4 -0
- package/src/__tests__/date-context.test.ts +373 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -3
- package/src/__tests__/followup-tools.test.ts +303 -0
- package/src/__tests__/handlers-twitter-config.test.ts +718 -0
- package/src/__tests__/intent-routing.test.ts +64 -57
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
- package/src/__tests__/ipc-snapshot.test.ts +62 -28
- package/src/__tests__/llm-usage-store.test.ts +3 -8
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -7
- package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
- package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
- package/src/__tests__/playbook-tools.test.ts +342 -0
- package/src/__tests__/profile-compiler.test.ts +2 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
- package/src/__tests__/recurrence-engine-rruleset.test.ts +78 -0
- package/src/__tests__/recurrence-engine.test.ts +69 -0
- package/src/__tests__/recurrence-types.test.ts +71 -0
- package/src/__tests__/registry.test.ts +5 -3
- package/src/__tests__/relay-server.test.ts +633 -0
- package/src/__tests__/reminder-store.test.ts +6 -3
- package/src/__tests__/reminder.test.ts +43 -77
- package/src/__tests__/run-orchestrator-assistant-events.test.ts +8 -4
- package/src/__tests__/run-orchestrator.test.ts +4 -4
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -6
- package/src/__tests__/runtime-runs-http.test.ts +4 -4
- package/src/__tests__/runtime-runs.test.ts +4 -4
- package/src/__tests__/schedule-store.test.ts +482 -0
- package/src/__tests__/schedule-tools.test.ts +700 -0
- package/src/__tests__/scheduler-recurrence.test.ts +329 -0
- package/src/__tests__/server-history-render.test.ts +14 -13
- package/src/__tests__/session-error.test.ts +28 -0
- package/src/__tests__/session-init.benchmark.test.ts +462 -0
- package/src/__tests__/session-queue.test.ts +71 -48
- package/src/__tests__/session-runtime-assembly.test.ts +161 -0
- package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
- package/src/__tests__/signup-e2e.test.ts +2 -1
- package/src/__tests__/skill-projection.benchmark.test.ts +328 -0
- package/src/__tests__/skill-script-runner.test.ts +159 -0
- package/src/__tests__/speaker-identification.test.ts +52 -0
- package/src/__tests__/subagent-manager-notify.test.ts +42 -10
- package/src/__tests__/subagent-tools.test.ts +141 -41
- package/src/__tests__/task-compiler.test.ts +2 -1
- package/src/__tests__/task-runner.test.ts +2 -1
- package/src/__tests__/task-scheduler.test.ts +2 -1
- package/src/__tests__/task-tools.test.ts +49 -56
- package/src/__tests__/tool-audit-listener.test.ts +1 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +2 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
- package/src/__tests__/tool-executor.test.ts +13 -17
- package/src/__tests__/turn-commit.test.ts +218 -3
- package/src/__tests__/twilio-provider.test.ts +143 -0
- package/src/__tests__/twilio-routes.test.ts +789 -0
- package/src/__tests__/twitter-auth-handler.test.ts +581 -0
- package/src/__tests__/view-image-tool.test.ts +217 -0
- package/src/__tests__/workspace-git-service.test.ts +186 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +13 -3
- package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
- package/src/bundler/app-bundler.ts +12 -8
- package/src/calls/call-bridge.ts +95 -0
- package/src/calls/call-constants.ts +43 -5
- package/src/calls/call-domain.ts +276 -0
- package/src/calls/call-orchestrator.ts +43 -17
- package/src/calls/call-recovery.ts +207 -0
- package/src/calls/call-state-machine.ts +68 -0
- package/src/calls/call-store.ts +192 -5
- package/src/calls/relay-server.ts +41 -4
- package/src/calls/speaker-identification.ts +213 -0
- package/src/calls/twilio-provider.ts +10 -6
- package/src/calls/twilio-routes.ts +90 -76
- package/src/calls/types.ts +1 -1
- package/src/cli/config-commands.ts +334 -0
- package/src/cli/core-commands.ts +776 -0
- package/src/cli/doordash.ts +251 -1
- package/src/cli/ipc-client.ts +82 -0
- package/src/cli/map.ts +246 -0
- package/src/cli/twitter.ts +575 -0
- package/src/cli.ts +7 -5
- package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
- package/src/commands/cc-command-registry.ts +209 -0
- package/src/config/bundled-skills/contacts/SKILL.md +39 -0
- package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +9 -0
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +9 -0
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +9 -0
- package/src/config/bundled-skills/document/SKILL.md +18 -0
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
- package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
- package/src/config/bundled-skills/doordash/SKILL.md +82 -23
- package/src/config/bundled-skills/followups/SKILL.md +32 -0
- package/src/config/bundled-skills/followups/TOOLS.json +100 -0
- package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -23
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -1
- package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
- package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +9 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +9 -0
- package/src/config/bundled-skills/reminder/SKILL.md +20 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
- package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
- package/src/config/bundled-skills/schedule/SKILL.md +74 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
- package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
- package/src/config/bundled-skills/subagent/SKILL.md +25 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
- package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
- package/src/config/bundled-skills/tasks/SKILL.md +28 -0
- package/src/config/bundled-skills/tasks/TOOLS.json +256 -0
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
- package/src/config/bundled-skills/twitter/SKILL.md +134 -0
- package/src/config/bundled-skills/watcher/SKILL.md +27 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
- package/src/config/defaults.ts +33 -0
- package/src/config/loader.ts +4 -1
- package/src/config/schema.ts +161 -1
- package/src/config/system-prompt.ts +61 -16
- package/src/config/templates/IDENTITY.md +7 -0
- package/src/config/types.ts +4 -0
- package/src/contacts/contact-store.ts +4 -4
- package/src/daemon/assistant-attachments.ts +10 -0
- package/src/daemon/classifier.ts +3 -1
- package/src/daemon/computer-use-session.ts +3 -1
- package/src/daemon/date-context.ts +136 -0
- package/src/daemon/handlers/apps.ts +16 -1
- package/src/daemon/handlers/browser.ts +54 -0
- package/src/daemon/handlers/computer-use.ts +7 -1
- package/src/daemon/handlers/config.ts +163 -5
- package/src/daemon/handlers/diagnostics.ts +5 -1
- package/src/daemon/handlers/documents.ts +18 -29
- package/src/daemon/handlers/home-base.ts +5 -1
- package/src/daemon/handlers/index.ts +40 -277
- package/src/daemon/handlers/misc.ts +9 -1
- package/src/daemon/handlers/publish.ts +6 -1
- package/src/daemon/handlers/sessions.ts +65 -12
- package/src/daemon/handlers/shared.ts +36 -1
- package/src/daemon/handlers/signing.ts +37 -0
- package/src/daemon/handlers/skills.ts +20 -6
- package/src/daemon/handlers/subagents.ts +8 -3
- package/src/daemon/handlers/twitter-auth.ts +169 -0
- package/src/daemon/handlers/work-items.ts +384 -68
- package/src/daemon/ipc-contract-inventory.json +28 -4
- package/src/daemon/ipc-contract.ts +133 -37
- package/src/daemon/ipc-protocol.ts +7 -2
- package/src/daemon/lifecycle.ts +21 -0
- package/src/daemon/main.ts +10 -4
- package/src/daemon/ride-shotgun-handler.ts +74 -10
- package/src/daemon/server.ts +143 -26
- package/src/daemon/session-agent-loop.ts +887 -0
- package/src/daemon/session-attachments.ts +28 -5
- package/src/daemon/session-error.ts +24 -3
- package/src/daemon/session-lifecycle.ts +147 -0
- package/src/daemon/session-media-retry.ts +147 -0
- package/src/daemon/session-messaging.ts +145 -0
- package/src/daemon/session-notifiers.ts +164 -0
- package/src/daemon/session-process.ts +2 -2
- package/src/daemon/session-queue-manager.ts +1 -0
- package/src/daemon/session-runtime-assembly.ts +52 -0
- package/src/daemon/session-skill-tools.ts +124 -5
- package/src/daemon/session-slash.ts +3 -0
- package/src/daemon/session-surfaces.ts +77 -2
- package/src/daemon/session-tool-setup.ts +216 -2
- package/src/daemon/session-usage.ts +0 -2
- package/src/daemon/session.ts +114 -1404
- package/src/daemon/video-thumbnail.ts +60 -0
- package/src/doordash/client.ts +121 -27
- package/src/doordash/queries.ts +1 -2
- package/src/export/formatter.ts +3 -1
- package/src/followups/followup-store.ts +4 -2
- package/src/followups/types.ts +6 -0
- package/src/hooks/templates.ts +1 -1
- package/src/index.ts +32 -1153
- package/src/memory/attachments-store.ts +28 -83
- package/src/memory/channel-delivery-store.ts +7 -21
- package/src/memory/clarification-resolver.ts +6 -5
- package/src/memory/contradiction-checker.ts +3 -2
- package/src/memory/conversation-key-store.ts +10 -29
- package/src/memory/conversation-store.ts +2 -1
- package/src/memory/db.ts +96 -2
- package/src/memory/entity-extractor.ts +6 -3
- package/src/memory/items-extractor.ts +5 -4
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/llm-usage-store.ts +1 -2
- package/src/memory/runs-store.ts +1 -2
- package/src/memory/schema.ts +23 -2
- package/src/messaging/style-analyzer.ts +3 -2
- package/src/messaging/thread-summarizer.ts +8 -12
- package/src/messaging/triage-engine.ts +4 -2
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/registry.ts +8 -0
- package/src/runtime/http-server.ts +108 -20
- package/src/runtime/routes/attachment-routes.ts +2 -3
- package/src/runtime/routes/call-routes.ts +140 -0
- package/src/runtime/routes/channel-routes.ts +5 -10
- package/src/runtime/routes/conversation-routes.ts +5 -5
- package/src/runtime/routes/run-routes.ts +2 -2
- package/src/runtime/run-orchestrator.ts +9 -3
- package/src/schedule/recurrence-engine.ts +138 -0
- package/src/schedule/recurrence-types.ts +67 -0
- package/src/schedule/schedule-store.ts +102 -57
- package/src/schedule/scheduler.ts +9 -6
- package/src/security/oauth2.ts +29 -4
- package/src/security/secret-allowlist.ts +46 -0
- package/src/skills/clawhub.ts +1 -1
- package/src/subagent/manager.ts +40 -8
- package/src/swarm/backend-claude-code.ts +64 -9
- package/src/swarm/worker-prompts.ts +2 -1
- package/src/tasks/SPEC.md +34 -28
- package/src/tasks/ephemeral-permissions.ts +16 -7
- package/src/tasks/task-compiler.ts +5 -4
- package/src/tasks/task-runner.ts +10 -5
- package/src/tasks/task-scheduler.ts +1 -1
- package/src/tasks/tool-sanitizer.ts +36 -0
- package/src/tools/assets/search.ts +4 -4
- package/src/tools/browser/api-map.ts +220 -0
- package/src/tools/browser/auto-navigate.ts +270 -0
- package/src/tools/browser/browser-execution.ts +2 -1
- package/src/tools/browser/browser-manager.ts +2 -2
- package/src/tools/browser/network-recorder.ts +5 -4
- package/src/tools/browser/x-auto-navigate.ts +207 -0
- package/src/tools/calls/call-end.ts +17 -67
- package/src/tools/calls/call-start.ts +24 -85
- package/src/tools/calls/call-status.ts +35 -51
- package/src/tools/claude-code/claude-code.ts +77 -11
- package/src/tools/contacts/contact-merge.ts +46 -78
- package/src/tools/contacts/contact-search.ts +35 -79
- package/src/tools/contacts/contact-upsert.ts +35 -108
- package/src/tools/credentials/vault.ts +20 -4
- package/src/tools/document/document-tool.ts +71 -144
- package/src/tools/executor.ts +129 -10
- package/src/tools/followups/followup_create.ts +46 -88
- package/src/tools/followups/followup_list.ts +34 -74
- package/src/tools/followups/followup_resolve.ts +31 -66
- package/src/tools/host-terminal/cli-discover.ts +2 -1
- package/src/tools/host-terminal/host-shell.ts +10 -0
- package/src/tools/memory/handlers.ts +5 -4
- package/src/tools/network/__tests__/web-search.test.ts +427 -0
- package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
- package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
- package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
- package/src/tools/network/web-fetch.ts +18 -6
- package/src/tools/playbooks/index.ts +4 -5
- package/src/tools/playbooks/playbook-create.ts +3 -47
- package/src/tools/playbooks/playbook-delete.ts +1 -25
- package/src/tools/playbooks/playbook-list.ts +1 -28
- package/src/tools/playbooks/playbook-update.ts +3 -51
- package/src/tools/reminder/reminder.ts +5 -78
- package/src/tools/schedule/create.ts +69 -74
- package/src/tools/schedule/delete.ts +21 -47
- package/src/tools/schedule/list.ts +55 -74
- package/src/tools/schedule/update.ts +77 -84
- package/src/tools/subagent/abort.ts +29 -58
- package/src/tools/subagent/message.ts +30 -63
- package/src/tools/subagent/read.ts +53 -84
- package/src/tools/subagent/spawn.ts +43 -82
- package/src/tools/subagent/status.ts +42 -71
- package/src/tools/swarm/delegate.ts +2 -1
- package/src/tools/tasks/index.ts +8 -8
- package/src/tools/tasks/task-delete.ts +60 -88
- package/src/tools/tasks/task-list.ts +31 -52
- package/src/tools/tasks/task-run.ts +72 -108
- package/src/tools/tasks/task-save.ts +33 -65
- package/src/tools/tasks/work-item-enqueue.ts +183 -215
- package/src/tools/tasks/work-item-list.ts +33 -63
- package/src/tools/tasks/work-item-remove.ts +45 -97
- package/src/tools/tasks/work-item-update.ts +91 -163
- package/src/tools/terminal/backends/native.ts +3 -1
- package/src/tools/tool-manifest.ts +0 -62
- package/src/tools/types.ts +6 -0
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/tools/watch/screen-watch.ts +3 -1
- package/src/tools/watcher/create.ts +52 -98
- package/src/tools/watcher/delete.ts +20 -46
- package/src/tools/watcher/digest.ts +36 -70
- package/src/tools/watcher/list.ts +49 -79
- package/src/tools/watcher/update.ts +45 -91
- package/src/twitter/client.ts +690 -0
- package/src/twitter/session.ts +91 -0
- package/src/usage/types.ts +0 -1
- package/src/util/truncate.ts +6 -0
- package/src/watcher/providers/slack.ts +2 -1
- package/src/watcher/watcher-store.ts +3 -2
- package/src/work-items/work-item-store.ts +27 -2
- package/src/workspace/commit-message-enrichment-service.ts +31 -7
- package/src/workspace/git-service.ts +87 -22
- package/src/workspace/provider-commit-message-generator.ts +242 -0
- package/src/workspace/turn-commit.ts +62 -3
- package/src/tools/contacts/index.ts +0 -4
- package/src/tools/document/index.ts +0 -5
- package/src/tools/followups/index.ts +0 -3
- package/src/tools/subagent/index.ts +0 -5
- /package/src/__tests__/{memory-context-benchmark.test.ts → memory-context-benchmark.benchmark.test.ts} +0 -0
|
@@ -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
|
+
});
|
|
@@ -343,6 +343,16 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
343
343
|
type: 'vercel_api_config',
|
|
344
344
|
action: 'get',
|
|
345
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
|
+
},
|
|
346
356
|
link_open_request: {
|
|
347
357
|
type: 'link_open_request',
|
|
348
358
|
url: 'https://example.com',
|
|
@@ -423,14 +433,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
423
433
|
type: 'work_item_get',
|
|
424
434
|
id: 'wi-001',
|
|
425
435
|
},
|
|
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
436
|
work_item_update: {
|
|
435
437
|
type: 'work_item_update',
|
|
436
438
|
id: 'wi-001',
|
|
@@ -453,6 +455,19 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
453
455
|
type: 'work_item_output',
|
|
454
456
|
id: 'wi-001',
|
|
455
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
|
+
},
|
|
456
471
|
document_save: {
|
|
457
472
|
type: 'document_save',
|
|
458
473
|
surfaceId: 'doc-001',
|
|
@@ -476,7 +491,6 @@ const clientMessages: Record<ClientMessageType, ClientMessage> = {
|
|
|
476
491
|
subagent_status: {
|
|
477
492
|
type: 'subagent_status',
|
|
478
493
|
subagentId: 'sub-001',
|
|
479
|
-
sessionId: 'sess-001',
|
|
480
494
|
},
|
|
481
495
|
subagent_message: {
|
|
482
496
|
type: 'subagent_message',
|
|
@@ -907,6 +921,8 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
907
921
|
id: 'sched-001',
|
|
908
922
|
name: 'Daily standup reminder',
|
|
909
923
|
enabled: true,
|
|
924
|
+
syntax: 'cron',
|
|
925
|
+
expression: '0 9 * * 1-5',
|
|
910
926
|
cronExpression: '0 9 * * 1-5',
|
|
911
927
|
timezone: 'America/Los_Angeles',
|
|
912
928
|
message: 'Remind me about the standup',
|
|
@@ -1114,6 +1130,25 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1114
1130
|
hasToken: true,
|
|
1115
1131
|
success: true,
|
|
1116
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
|
+
},
|
|
1117
1152
|
open_url: {
|
|
1118
1153
|
type: 'open_url',
|
|
1119
1154
|
url: 'https://example.com',
|
|
@@ -1283,25 +1318,6 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1283
1318
|
updatedAt: 1700000000,
|
|
1284
1319
|
},
|
|
1285
1320
|
},
|
|
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
1321
|
work_item_update_response: {
|
|
1306
1322
|
type: 'work_item_update_response',
|
|
1307
1323
|
item: {
|
|
@@ -1346,6 +1362,24 @@ const serverMessages: Record<ServerMessageType, ServerMessage> = {
|
|
|
1346
1362
|
highlights: ['- Key finding 1', '- Key finding 2'],
|
|
1347
1363
|
},
|
|
1348
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
|
+
},
|
|
1349
1383
|
work_item_status_changed: {
|
|
1350
1384
|
type: 'work_item_status_changed',
|
|
1351
1385
|
item: {
|
|
@@ -23,7 +23,7 @@ mock.module('../util/logger.js', () => ({
|
|
|
23
23
|
}),
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
|
-
import { initializeDb, getDb } from '../memory/db.js';
|
|
26
|
+
import { initializeDb, getDb, resetDb } from '../memory/db.js';
|
|
27
27
|
import { recordUsageEvent, listUsageEvents } from '../memory/llm-usage-store.js';
|
|
28
28
|
import type { UsageEventInput, PricingResult } from '../usage/types.js';
|
|
29
29
|
|
|
@@ -31,6 +31,7 @@ import type { UsageEventInput, PricingResult } from '../usage/types.js';
|
|
|
31
31
|
initializeDb();
|
|
32
32
|
|
|
33
33
|
afterAll(() => {
|
|
34
|
+
resetDb();
|
|
34
35
|
try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
|
|
35
36
|
});
|
|
36
37
|
|
|
@@ -43,7 +44,6 @@ function makeInput(overrides?: Partial<UsageEventInput>): UsageEventInput {
|
|
|
43
44
|
cacheCreationInputTokens: null,
|
|
44
45
|
cacheReadInputTokens: null,
|
|
45
46
|
actor: 'main_agent',
|
|
46
|
-
assistantId: null,
|
|
47
47
|
conversationId: null,
|
|
48
48
|
runId: null,
|
|
49
49
|
requestId: null,
|
|
@@ -86,7 +86,7 @@ describe('recordUsageEvent', () => {
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
test('persists a priced event that can be retrieved', () => {
|
|
89
|
-
const input = makeInput({
|
|
89
|
+
const input = makeInput({ conversationId: 'c1' });
|
|
90
90
|
const event = recordUsageEvent(input, pricedResult);
|
|
91
91
|
|
|
92
92
|
const events = listUsageEvents();
|
|
@@ -94,7 +94,6 @@ describe('recordUsageEvent', () => {
|
|
|
94
94
|
expect(events[0].id).toBe(event.id);
|
|
95
95
|
expect(events[0].estimatedCostUsd).toBe(0.0045);
|
|
96
96
|
expect(events[0].pricingStatus).toBe('priced');
|
|
97
|
-
expect(events[0].assistantId).toBe('a1');
|
|
98
97
|
expect(events[0].conversationId).toBe('c1');
|
|
99
98
|
});
|
|
100
99
|
|
|
@@ -113,7 +112,6 @@ describe('recordUsageEvent', () => {
|
|
|
113
112
|
|
|
114
113
|
test('handles null optional fields', () => {
|
|
115
114
|
const input = makeInput({
|
|
116
|
-
assistantId: null,
|
|
117
115
|
conversationId: null,
|
|
118
116
|
runId: null,
|
|
119
117
|
requestId: null,
|
|
@@ -124,7 +122,6 @@ describe('recordUsageEvent', () => {
|
|
|
124
122
|
|
|
125
123
|
const events = listUsageEvents();
|
|
126
124
|
expect(events).toHaveLength(1);
|
|
127
|
-
expect(events[0].assistantId).toBeNull();
|
|
128
125
|
expect(events[0].conversationId).toBeNull();
|
|
129
126
|
expect(events[0].runId).toBeNull();
|
|
130
127
|
expect(events[0].requestId).toBeNull();
|
|
@@ -134,7 +131,6 @@ describe('recordUsageEvent', () => {
|
|
|
134
131
|
|
|
135
132
|
test('handles populated optional fields', () => {
|
|
136
133
|
const input = makeInput({
|
|
137
|
-
assistantId: 'assistant-1',
|
|
138
134
|
conversationId: 'conv-1',
|
|
139
135
|
runId: 'run-1',
|
|
140
136
|
requestId: 'req-1',
|
|
@@ -145,7 +141,6 @@ describe('recordUsageEvent', () => {
|
|
|
145
141
|
|
|
146
142
|
const events = listUsageEvents();
|
|
147
143
|
expect(events).toHaveLength(1);
|
|
148
|
-
expect(events[0].assistantId).toBe('assistant-1');
|
|
149
144
|
expect(events[0].conversationId).toBe('conv-1');
|
|
150
145
|
expect(events[0].runId).toBe('run-1');
|
|
151
146
|
expect(events[0].requestId).toBe('req-1');
|