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
|
@@ -5,7 +5,7 @@ import { ComputerUseSession } from '../computer-use-session.js';
|
|
|
5
5
|
import { getLogger } from '../../util/logger.js';
|
|
6
6
|
import { execSync } from 'node:child_process';
|
|
7
7
|
import { estimateBase64Bytes } from '../assistant-attachments.js';
|
|
8
|
-
import type { CuSessionCreate, ServerMessage, SessionTransportMetadata } from '../ipc-protocol.js';
|
|
8
|
+
import type { ClientMessage, CuSessionCreate, ServerMessage, SessionTransportMetadata } from '../ipc-protocol.js';
|
|
9
9
|
import type { SecretPromptResult } from '../../permissions/secret-prompter.js';
|
|
10
10
|
import { getConfig } from '../../config/loader.js';
|
|
11
11
|
|
|
@@ -13,6 +13,9 @@ const log = getLogger('handlers');
|
|
|
13
13
|
|
|
14
14
|
export { log };
|
|
15
15
|
|
|
16
|
+
/** Debounce window for suppressing file-watcher config reloads after programmatic saves. */
|
|
17
|
+
export const CONFIG_RELOAD_DEBOUNCE_MS = 300;
|
|
18
|
+
|
|
16
19
|
const HISTORY_ATTACHMENT_TEXT_LIMIT = 500;
|
|
17
20
|
|
|
18
21
|
export const FALLBACK_SCREEN = { width: 1920, height: 1080 };
|
|
@@ -67,6 +70,13 @@ export interface RenderedHistoryContent {
|
|
|
67
70
|
surfaces: HistorySurface[];
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
export interface SubagentNotificationData {
|
|
74
|
+
subagentId: string;
|
|
75
|
+
label: string;
|
|
76
|
+
status: 'completed' | 'failed' | 'aborted';
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
export interface ParsedHistoryMessage {
|
|
71
81
|
id?: string;
|
|
72
82
|
role: string;
|
|
@@ -77,6 +87,7 @@ export interface ParsedHistoryMessage {
|
|
|
77
87
|
textSegments: string[];
|
|
78
88
|
contentOrder: string[];
|
|
79
89
|
surfaces: HistorySurface[];
|
|
90
|
+
subagentNotification?: SubagentNotificationData;
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
/**
|
|
@@ -120,6 +131,30 @@ export interface HandlerContext {
|
|
|
120
131
|
touchSession(sessionId: string): void;
|
|
121
132
|
}
|
|
122
133
|
|
|
134
|
+
// ─── Typed dispatch ──────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
type MessageType = ClientMessage['type'];
|
|
137
|
+
// 'auth' is handled at the transport layer (server.ts) and never reaches dispatch.
|
|
138
|
+
export type DispatchableType = Exclude<MessageType, 'auth'>;
|
|
139
|
+
type MessageOfType<T extends MessageType> = Extract<ClientMessage, { type: T }>;
|
|
140
|
+
type MessageHandler<T extends MessageType> = (
|
|
141
|
+
msg: MessageOfType<T>,
|
|
142
|
+
socket: net.Socket,
|
|
143
|
+
ctx: HandlerContext,
|
|
144
|
+
) => void | Promise<void>;
|
|
145
|
+
export type DispatchMap = { [T in DispatchableType]: MessageHandler<T> };
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Type-safe handler group definition. Preserves exact key types so the
|
|
149
|
+
* combined spread in index.ts can be checked for exhaustiveness via
|
|
150
|
+
* `satisfies DispatchMap` instead of an unsafe `as DispatchMap` cast.
|
|
151
|
+
*/
|
|
152
|
+
export function defineHandlers<K extends DispatchableType>(
|
|
153
|
+
handlers: Pick<DispatchMap, K>,
|
|
154
|
+
): Pick<DispatchMap, K> {
|
|
155
|
+
return handlers;
|
|
156
|
+
}
|
|
157
|
+
|
|
123
158
|
/**
|
|
124
159
|
* Query the main display dimensions via CoreGraphics.
|
|
125
160
|
* Cached after the first successful call; falls back to 1920x1080.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { log, pendingSignBundlePayload, pendingSigningIdentity, defineHandlers } from './shared.js';
|
|
2
|
+
|
|
3
|
+
export const signingHandlers = defineHandlers({
|
|
4
|
+
sign_bundle_payload_response: (msg) => {
|
|
5
|
+
const pending = pendingSignBundlePayload.get(msg.requestId);
|
|
6
|
+
if (pending) {
|
|
7
|
+
clearTimeout(pending.timer);
|
|
8
|
+
pendingSignBundlePayload.delete(msg.requestId);
|
|
9
|
+
if (msg.error) {
|
|
10
|
+
pending.reject(new Error(msg.error));
|
|
11
|
+
} else if (msg.signature && msg.keyId && msg.publicKey) {
|
|
12
|
+
pending.resolve({ signature: msg.signature, keyId: msg.keyId, publicKey: msg.publicKey });
|
|
13
|
+
} else {
|
|
14
|
+
pending.reject(new Error('Missing required fields in sign_bundle_payload_response'));
|
|
15
|
+
}
|
|
16
|
+
} else {
|
|
17
|
+
log.warn({ requestId: msg.requestId }, 'Received sign_bundle_payload_response with no pending request');
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
get_signing_identity_response: (msg) => {
|
|
22
|
+
const pending = pendingSigningIdentity.get(msg.requestId);
|
|
23
|
+
if (pending) {
|
|
24
|
+
clearTimeout(pending.timer);
|
|
25
|
+
pendingSigningIdentity.delete(msg.requestId);
|
|
26
|
+
if (msg.error) {
|
|
27
|
+
pending.reject(new Error(msg.error));
|
|
28
|
+
} else if (msg.keyId && msg.publicKey) {
|
|
29
|
+
pending.resolve({ keyId: msg.keyId, publicKey: msg.publicKey });
|
|
30
|
+
} else {
|
|
31
|
+
pending.reject(new Error('Missing required fields in get_signing_identity_response'));
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
log.warn({ requestId: msg.requestId }, 'Received get_signing_identity_response with no pending request');
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -19,7 +19,7 @@ import type {
|
|
|
19
19
|
SkillsSearchRequest,
|
|
20
20
|
SkillsInspectRequest,
|
|
21
21
|
} from '../ipc-protocol.js';
|
|
22
|
-
import { log, ensureSkillEntry, type HandlerContext } from './shared.js';
|
|
22
|
+
import { log, CONFIG_RELOAD_DEBOUNCE_MS, ensureSkillEntry, defineHandlers, type HandlerContext } from './shared.js';
|
|
23
23
|
|
|
24
24
|
export function handleSkillsList(socket: net.Socket, ctx: HandlerContext): void {
|
|
25
25
|
const config = getConfig();
|
|
@@ -63,7 +63,7 @@ export function handleSkillsEnable(
|
|
|
63
63
|
|
|
64
64
|
const existingSuppressTimer = ctx.debounceTimers.get('__suppress_reset__');
|
|
65
65
|
if (existingSuppressTimer) clearTimeout(existingSuppressTimer);
|
|
66
|
-
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); },
|
|
66
|
+
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); }, CONFIG_RELOAD_DEBOUNCE_MS);
|
|
67
67
|
ctx.debounceTimers.set('__suppress_reset__', resetTimer);
|
|
68
68
|
|
|
69
69
|
ctx.updateConfigFingerprint();
|
|
@@ -110,7 +110,7 @@ export function handleSkillsDisable(
|
|
|
110
110
|
|
|
111
111
|
const existingSuppressTimer = ctx.debounceTimers.get('__suppress_reset__');
|
|
112
112
|
if (existingSuppressTimer) clearTimeout(existingSuppressTimer);
|
|
113
|
-
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); },
|
|
113
|
+
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); }, CONFIG_RELOAD_DEBOUNCE_MS);
|
|
114
114
|
ctx.debounceTimers.set('__suppress_reset__', resetTimer);
|
|
115
115
|
|
|
116
116
|
ctx.updateConfigFingerprint();
|
|
@@ -167,7 +167,7 @@ export function handleSkillsConfigure(
|
|
|
167
167
|
|
|
168
168
|
const existingSuppressTimer = ctx.debounceTimers.get('__suppress_reset__');
|
|
169
169
|
if (existingSuppressTimer) clearTimeout(existingSuppressTimer);
|
|
170
|
-
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); },
|
|
170
|
+
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); }, CONFIG_RELOAD_DEBOUNCE_MS);
|
|
171
171
|
ctx.debounceTimers.set('__suppress_reset__', resetTimer);
|
|
172
172
|
|
|
173
173
|
ctx.updateConfigFingerprint();
|
|
@@ -228,7 +228,7 @@ export async function handleSkillsInstall(
|
|
|
228
228
|
invalidateConfigCache();
|
|
229
229
|
const existingSuppressTimer = ctx.debounceTimers.get('__suppress_reset__');
|
|
230
230
|
if (existingSuppressTimer) clearTimeout(existingSuppressTimer);
|
|
231
|
-
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); },
|
|
231
|
+
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); }, CONFIG_RELOAD_DEBOUNCE_MS);
|
|
232
232
|
ctx.debounceTimers.set('__suppress_reset__', resetTimer);
|
|
233
233
|
ctx.updateConfigFingerprint();
|
|
234
234
|
} catch (err) {
|
|
@@ -323,7 +323,7 @@ export async function handleSkillsUninstall(
|
|
|
323
323
|
|
|
324
324
|
const existingSuppressTimer = ctx.debounceTimers.get('__suppress_reset__');
|
|
325
325
|
if (existingSuppressTimer) clearTimeout(existingSuppressTimer);
|
|
326
|
-
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); },
|
|
326
|
+
const resetTimer = setTimeout(() => { ctx.setSuppressConfigReload(false); }, CONFIG_RELOAD_DEBOUNCE_MS);
|
|
327
327
|
ctx.debounceTimers.set('__suppress_reset__', resetTimer);
|
|
328
328
|
|
|
329
329
|
ctx.updateConfigFingerprint();
|
|
@@ -485,3 +485,17 @@ export async function handleSkillDetail(
|
|
|
485
485
|
});
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
|
+
|
|
489
|
+
export const skillHandlers = defineHandlers({
|
|
490
|
+
skills_list: (_msg, socket, ctx) => handleSkillsList(socket, ctx),
|
|
491
|
+
skill_detail: handleSkillDetail,
|
|
492
|
+
skills_enable: handleSkillsEnable,
|
|
493
|
+
skills_disable: handleSkillsDisable,
|
|
494
|
+
skills_configure: handleSkillsConfigure,
|
|
495
|
+
skills_install: handleSkillsInstall,
|
|
496
|
+
skills_uninstall: handleSkillsUninstall,
|
|
497
|
+
skills_update: handleSkillsUpdate,
|
|
498
|
+
skills_check_updates: handleSkillsCheckUpdates,
|
|
499
|
+
skills_search: handleSkillsSearch,
|
|
500
|
+
skills_inspect: handleSkillsInspect,
|
|
501
|
+
});
|
|
@@ -6,7 +6,7 @@ import * as net from 'node:net';
|
|
|
6
6
|
import type { SubagentAbortRequest, SubagentStatusRequest, SubagentMessageRequest } from '../ipc-protocol.js';
|
|
7
7
|
import type { HandlerContext } from './shared.js';
|
|
8
8
|
import { getSubagentManager } from '../../subagent/index.js';
|
|
9
|
-
import { log } from './shared.js';
|
|
9
|
+
import { log, defineHandlers } from './shared.js';
|
|
10
10
|
|
|
11
11
|
export function handleSubagentAbort(
|
|
12
12
|
msg: SubagentAbortRequest,
|
|
@@ -66,8 +66,7 @@ export function handleSubagentStatus(
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Return all subagents for the caller's session.
|
|
69
|
-
const
|
|
70
|
-
const children = manager.getChildrenOf(sessionId);
|
|
69
|
+
const children = manager.getChildrenOf(callerSessionId);
|
|
71
70
|
for (const child of children) {
|
|
72
71
|
ctx.send(socket, {
|
|
73
72
|
type: 'subagent_status_changed',
|
|
@@ -120,3 +119,9 @@ export function handleSubagentMessage(
|
|
|
120
119
|
});
|
|
121
120
|
}
|
|
122
121
|
}
|
|
122
|
+
|
|
123
|
+
export const subagentHandlers = defineHandlers({
|
|
124
|
+
subagent_abort: handleSubagentAbort,
|
|
125
|
+
subagent_status: handleSubagentStatus,
|
|
126
|
+
subagent_message: handleSubagentMessage,
|
|
127
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as net from 'node:net';
|
|
2
|
+
import { loadRawConfig } from '../../config/loader.js';
|
|
3
|
+
import { getSecureKey, setSecureKey, deleteSecureKey } from '../../security/secure-keys.js';
|
|
4
|
+
import { startOAuth2Flow } from '../../security/oauth2.js';
|
|
5
|
+
import { upsertCredentialMetadata, getCredentialMetadata } from '../../tools/credentials/metadata-store.js';
|
|
6
|
+
import type { TwitterAuthStartRequest, TwitterAuthStatusRequest } from '../ipc-protocol.js';
|
|
7
|
+
import { log, defineHandlers, type HandlerContext } from './shared.js';
|
|
8
|
+
import type { OAuth2Config } from '../../security/oauth2.js';
|
|
9
|
+
|
|
10
|
+
export async function handleTwitterAuthStart(
|
|
11
|
+
_msg: TwitterAuthStartRequest,
|
|
12
|
+
socket: net.Socket,
|
|
13
|
+
ctx: HandlerContext,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
try {
|
|
16
|
+
const raw = loadRawConfig();
|
|
17
|
+
const mode = (raw.twitterIntegrationMode as string | undefined) ?? 'local_byo';
|
|
18
|
+
if (mode !== 'local_byo') {
|
|
19
|
+
ctx.send(socket, {
|
|
20
|
+
type: 'twitter_auth_result',
|
|
21
|
+
success: false,
|
|
22
|
+
error: 'Twitter integration mode must be "local_byo" to use this flow.',
|
|
23
|
+
});
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const clientId = getSecureKey('credential:integration:twitter:oauth_client_id');
|
|
28
|
+
if (!clientId) {
|
|
29
|
+
ctx.send(socket, {
|
|
30
|
+
type: 'twitter_auth_result',
|
|
31
|
+
success: false,
|
|
32
|
+
error: 'No Twitter client credentials configured. Please set up your Client ID first.',
|
|
33
|
+
});
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const clientSecret = getSecureKey('credential:integration:twitter:oauth_client_secret') || undefined;
|
|
38
|
+
|
|
39
|
+
const oauthConfig: OAuth2Config = {
|
|
40
|
+
authUrl: 'https://twitter.com/i/oauth2/authorize',
|
|
41
|
+
tokenUrl: 'https://api.x.com/2/oauth2/token',
|
|
42
|
+
scopes: ['tweet.read', 'tweet.write', 'users.read', 'offline.access'],
|
|
43
|
+
clientId,
|
|
44
|
+
clientSecret,
|
|
45
|
+
extraParams: {},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const result = await startOAuth2Flow(oauthConfig, {
|
|
49
|
+
openUrl: (url: string) => {
|
|
50
|
+
ctx.send(socket, { type: 'open_url', url });
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Verify identity via Twitter API before persisting any tokens
|
|
55
|
+
let accountInfo: string;
|
|
56
|
+
try {
|
|
57
|
+
const userResp = await fetch('https://api.x.com/2/users/me', {
|
|
58
|
+
headers: { Authorization: `Bearer ${result.tokens.accessToken}` },
|
|
59
|
+
});
|
|
60
|
+
if (!userResp.ok) {
|
|
61
|
+
log.error({ status: userResp.status }, 'Twitter identity verification returned non-2xx');
|
|
62
|
+
ctx.send(socket, {
|
|
63
|
+
type: 'twitter_auth_result',
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Failed to verify Twitter identity. Please try again.',
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const userData = (await userResp.json()) as { data?: { username?: string } };
|
|
70
|
+
if (!userData.data?.username) {
|
|
71
|
+
log.error({ userData }, 'Twitter identity verification returned no username');
|
|
72
|
+
ctx.send(socket, {
|
|
73
|
+
type: 'twitter_auth_result',
|
|
74
|
+
success: false,
|
|
75
|
+
error: 'Failed to verify Twitter identity. Please try again.',
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
accountInfo = `@${userData.data.username}`;
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.error({ err }, 'Twitter identity verification fetch failed');
|
|
82
|
+
ctx.send(socket, {
|
|
83
|
+
type: 'twitter_auth_result',
|
|
84
|
+
success: false,
|
|
85
|
+
error: 'Failed to verify Twitter identity. Please try again.',
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Persist tokens only after successful verification
|
|
91
|
+
setSecureKey('credential:integration:twitter:access_token', result.tokens.accessToken);
|
|
92
|
+
if (result.tokens.refreshToken) {
|
|
93
|
+
setSecureKey('credential:integration:twitter:refresh_token', result.tokens.refreshToken);
|
|
94
|
+
} else {
|
|
95
|
+
deleteSecureKey('credential:integration:twitter:refresh_token');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
upsertCredentialMetadata('integration:twitter', 'access_token', {
|
|
99
|
+
accountInfo,
|
|
100
|
+
allowedTools: ['twitter_post'],
|
|
101
|
+
allowedDomains: [],
|
|
102
|
+
oauth2TokenUrl: 'https://api.x.com/2/oauth2/token',
|
|
103
|
+
oauth2ClientId: clientId,
|
|
104
|
+
oauth2ClientSecret: clientSecret ?? null,
|
|
105
|
+
grantedScopes: result.grantedScopes,
|
|
106
|
+
expiresAt: result.tokens.expiresIn ? Date.now() + result.tokens.expiresIn * 1000 : null,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
ctx.send(socket, {
|
|
110
|
+
type: 'twitter_auth_result',
|
|
111
|
+
success: true,
|
|
112
|
+
accountInfo,
|
|
113
|
+
});
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
116
|
+
log.error({ err }, 'Twitter OAuth flow failed');
|
|
117
|
+
|
|
118
|
+
let userError: string;
|
|
119
|
+
const lower = message.toLowerCase();
|
|
120
|
+
if (lower.includes('timed out')) {
|
|
121
|
+
userError = 'Twitter authentication timed out. Please try again.';
|
|
122
|
+
} else if (lower.includes('user_cancelled') || lower.includes('cancelled')) {
|
|
123
|
+
userError = 'Twitter authentication was cancelled.';
|
|
124
|
+
} else if (lower.includes('denied') || lower.includes('invalid_grant')) {
|
|
125
|
+
userError = 'Twitter denied the authorization request. Please try again.';
|
|
126
|
+
} else {
|
|
127
|
+
userError = 'Twitter authentication failed. Please try again.';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
ctx.send(socket, {
|
|
131
|
+
type: 'twitter_auth_result',
|
|
132
|
+
success: false,
|
|
133
|
+
error: userError,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function handleTwitterAuthStatus(
|
|
139
|
+
_msg: TwitterAuthStatusRequest,
|
|
140
|
+
socket: net.Socket,
|
|
141
|
+
ctx: HandlerContext,
|
|
142
|
+
): void {
|
|
143
|
+
try {
|
|
144
|
+
const accessToken = getSecureKey('credential:integration:twitter:access_token');
|
|
145
|
+
const raw = loadRawConfig();
|
|
146
|
+
const mode = (raw.twitterIntegrationMode as 'local_byo' | 'managed' | undefined) ?? 'local_byo';
|
|
147
|
+
const meta = getCredentialMetadata('integration:twitter', 'access_token');
|
|
148
|
+
|
|
149
|
+
ctx.send(socket, {
|
|
150
|
+
type: 'twitter_auth_status_response',
|
|
151
|
+
connected: !!accessToken,
|
|
152
|
+
accountInfo: meta?.accountInfo ?? undefined,
|
|
153
|
+
mode,
|
|
154
|
+
});
|
|
155
|
+
} catch (err) {
|
|
156
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
157
|
+
log.error({ err }, 'Failed to get Twitter auth status');
|
|
158
|
+
ctx.send(socket, {
|
|
159
|
+
type: 'twitter_auth_status_response',
|
|
160
|
+
connected: false,
|
|
161
|
+
error: message,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const twitterAuthHandlers = defineHandlers({
|
|
167
|
+
twitter_auth_start: handleTwitterAuthStart,
|
|
168
|
+
twitter_auth_status: handleTwitterAuthStatus,
|
|
169
|
+
});
|