@vellumai/assistant 0.4.44 → 0.4.45
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/.prettierignore +4 -0
- package/ARCHITECTURE.md +34 -31
- package/README.md +4 -4
- package/bun.lock +10 -35
- package/docs/architecture/integrations.md +102 -197
- package/docs/architecture/keychain-broker.md +1 -1
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/scheduling.md +1 -1
- package/docs/architecture/security.md +11 -11
- package/docs/error-handling.md +1 -1
- package/docs/trusted-contact-access.md +3 -3
- package/drizzle/meta/0000_snapshot.json +34 -100
- package/drizzle/meta/_journal.json +1 -1
- package/drizzle.config.ts +4 -4
- package/package.json +3 -2
- package/scripts/capture-x-graphql.ts +237 -141
- package/scripts/generate-bundled-tool-registry.ts +223 -0
- package/src/__tests__/access-request-decision.test.ts +0 -1
- package/src/__tests__/actor-token-service.test.ts +23 -24
- package/src/__tests__/agent-loop.test.ts +0 -131
- package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
- package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +11 -1
- package/src/__tests__/asset-materialize-tool.test.ts +0 -1
- package/src/__tests__/asset-search-tool.test.ts +0 -1
- package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
- package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
- package/src/__tests__/attachments-store.test.ts +0 -1
- package/src/__tests__/avatar-e2e.test.ts +74 -115
- package/src/__tests__/avatar-router.test.ts +25 -62
- package/src/__tests__/browser-manager.test.ts +24 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
- package/src/__tests__/browser-skill-endstate.test.ts +8 -11
- package/src/__tests__/btw-routes.test.ts +326 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-conversation-messages.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +0 -1
- package/src/__tests__/call-pointer-messages.test.ts +0 -1
- package/src/__tests__/call-recovery.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/call-store.test.ts +0 -1
- package/src/__tests__/canonical-guardian-store.test.ts +0 -1
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/channel-delivery-store.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +5 -7
- package/src/__tests__/channel-retry-sweep.test.ts +0 -1
- package/src/__tests__/checker.test.ts +4 -11
- package/src/__tests__/compaction.benchmark.test.ts +16 -14
- package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
- package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
- package/src/__tests__/computer-use-tools.test.ts +35 -31
- package/src/__tests__/config-schema.test.ts +11 -15
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conflict-store.test.ts +0 -1
- package/src/__tests__/connection-policy.test.ts +4 -7
- package/src/__tests__/contacts-tools.test.ts +0 -1
- package/src/__tests__/context-memory-e2e.test.ts +2 -4
- package/src/__tests__/context-overflow-reducer.test.ts +2 -4
- package/src/__tests__/context-window-manager.test.ts +147 -60
- package/src/__tests__/contradiction-checker.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +25 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
- package/src/__tests__/conversation-store.test.ts +0 -1
- package/src/__tests__/conversation-unread-route.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +7 -8
- package/src/__tests__/cross-provider-web-search.test.ts +353 -0
- package/src/__tests__/daemon-assistant-events.test.ts +6 -7
- package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
- package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
- package/src/__tests__/diagnostics-export.test.ts +189 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/entity-extractor.test.ts +0 -1
- package/src/__tests__/entity-search.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +2 -4
- package/src/__tests__/file-read-tool.test.ts +86 -0
- package/src/__tests__/followup-tools.test.ts +0 -1
- package/src/__tests__/frontmatter.test.ts +77 -34
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/gateway-only-guard.test.ts +1 -1
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
- package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
- package/src/__tests__/guardian-action-store.test.ts +0 -1
- package/src/__tests__/guardian-action-sweep.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-outbound-http.test.ts +0 -1
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
- package/src/__tests__/host-bash-proxy.test.ts +335 -0
- package/src/__tests__/host-file-proxy.test.ts +374 -0
- package/src/__tests__/host-shell-tool.test.ts +147 -1
- package/src/__tests__/http-user-message-parity.test.ts +361 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
- package/src/__tests__/integration-status.test.ts +3 -8
- package/src/__tests__/intent-routing.test.ts +7 -46
- package/src/__tests__/invite-redemption-service.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +0 -1
- package/src/__tests__/llm-usage-store.test.ts +0 -1
- package/src/__tests__/managed-avatar-client.test.ts +101 -55
- package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
- package/src/__tests__/managed-store.test.ts +94 -21
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
- package/src/__tests__/memory-recall-quality.test.ts +0 -1
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
- package/src/__tests__/memory-regressions.test.ts +0 -1
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
- package/src/__tests__/messaging-send-tool.test.ts +35 -0
- package/src/__tests__/messaging-skill-split.test.ts +138 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
- package/src/__tests__/migration-export-http.test.ts +2 -3
- package/src/__tests__/migration-import-commit-http.test.ts +1 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
- package/src/__tests__/migration-validate-http.test.ts +1 -2
- package/src/__tests__/native-web-search.test.ts +475 -0
- package/src/__tests__/navigate-settings-tab.test.ts +84 -0
- package/src/__tests__/non-member-access-request.test.ts +0 -1
- package/src/__tests__/notification-broadcaster.test.ts +15 -15
- package/src/__tests__/notification-decision-strategy.test.ts +6 -6
- package/src/__tests__/notification-deep-link.test.ts +7 -7
- package/src/__tests__/notification-guardian-path.test.ts +2 -3
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
- package/src/__tests__/notification-thread-candidates.test.ts +4 -4
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/playbook-execution.test.ts +0 -1
- package/src/__tests__/playbook-tools.test.ts +0 -1
- package/src/__tests__/profile-compiler.test.ts +0 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
- package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
- package/src/__tests__/recording-handler.test.ts +30 -94
- package/src/__tests__/registry.test.ts +28 -35
- package/src/__tests__/relay-server.test.ts +0 -1
- package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +0 -1
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
- package/src/__tests__/schedule-store.test.ts +441 -1
- package/src/__tests__/schedule-tools.test.ts +468 -7
- package/src/__tests__/scheduler-recurrence.test.ts +196 -23
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
- package/src/__tests__/secret-response-routing.test.ts +4 -1
- package/src/__tests__/send-endpoint-busy.test.ts +14 -2
- package/src/__tests__/send-notification-tool.test.ts +0 -7
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/server-history-render.test.ts +1 -2
- package/src/__tests__/session-abort-tool-results.test.ts +0 -1
- package/src/__tests__/session-agent-loop.test.ts +46 -6
- package/src/__tests__/session-confirmation-signals.test.ts +0 -1
- package/src/__tests__/session-conflict-gate.test.ts +2 -6
- package/src/__tests__/session-error.test.ts +5 -14
- package/src/__tests__/session-init.benchmark.test.ts +3 -5
- package/src/__tests__/session-load-history-repair.test.ts +0 -1
- package/src/__tests__/session-media-retry.test.ts +12 -74
- package/src/__tests__/session-pre-run-repair.test.ts +0 -1
- package/src/__tests__/session-profile-injection.test.ts +2 -6
- package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
- package/src/__tests__/session-queue.test.ts +94 -139
- package/src/__tests__/session-skill-tools.test.ts +115 -115
- package/src/__tests__/session-slash-known.test.ts +0 -1
- package/src/__tests__/session-slash-queue.test.ts +0 -1
- package/src/__tests__/session-slash-unknown.test.ts +0 -1
- package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
- package/src/__tests__/session-usage.test.ts +0 -1
- package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
- package/src/__tests__/session-workspace-injection.test.ts +2 -6
- package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
- package/src/__tests__/skill-feature-flags.test.ts +125 -18
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
- package/src/__tests__/skill-load-tool.test.ts +194 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
- package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
- package/src/__tests__/skills.test.ts +14 -53
- package/src/__tests__/slack-channel-config.test.ts +0 -1
- package/src/__tests__/slack-inbound-verification.test.ts +0 -1
- package/src/__tests__/slack-skill.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +4 -3
- package/src/__tests__/task-compiler.test.ts +0 -1
- package/src/__tests__/task-management-tools.test.ts +0 -1
- package/src/__tests__/task-memory-cleanup.test.ts +0 -1
- package/src/__tests__/task-runner.test.ts +0 -1
- package/src/__tests__/task-scheduler.test.ts +0 -1
- package/src/__tests__/terminal-tools.test.ts +0 -1
- package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
- package/src/__tests__/thread-seed-composer.test.ts +5 -5
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +8 -86
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/tool-notification-listener.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
- package/src/__tests__/trust-store.test.ts +80 -4
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/trusted-contact-verification.test.ts +0 -1
- package/src/__tests__/twilio-provider.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +0 -1
- package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
- package/src/__tests__/update-bulletin.test.ts +0 -1
- package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
- package/src/__tests__/usage-routes.test.ts +0 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
- package/src/__tests__/voice-invite-redemption.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/__tests__/voice-session-bridge.test.ts +9 -1
- package/src/__tests__/web-fetch.test.ts +57 -0
- package/src/__tests__/workspace-git-service.test.ts +5 -14
- package/src/__tests__/workspace-policy.test.ts +0 -1
- package/src/agent/loop.ts +22 -34
- package/src/bundler/bundle-signer.ts +4 -4
- package/src/calls/call-controller.ts +1 -1
- package/src/calls/relay-server.ts +1 -1
- package/src/calls/twilio-rest.ts +1 -1
- package/src/calls/voice-session-bridge.ts +3 -1
- package/src/cli/__tests__/notifications.test.ts +3 -4
- package/src/cli/commands/map.ts +2 -6
- package/src/cli/commands/mcp.ts +73 -15
- package/src/cli/commands/notifications.ts +4 -4
- package/src/cli/commands/sessions.ts +9 -1
- package/src/cli/commands/skills.ts +6 -10
- package/src/cli/http-client.ts +2 -3
- package/src/cli/main-screen.tsx +10 -10
- package/src/cli/program.ts +0 -4
- package/src/cli/reference.ts +0 -2
- package/src/cli.ts +15 -9
- package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +6 -1
- package/src/config/bundled-skills/browser/SKILL.md +6 -1
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
- package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
- package/src/config/bundled-skills/contacts/SKILL.md +10 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
- package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -1
- package/src/config/bundled-skills/doordash/SKILL.md +8 -1
- package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
- package/src/config/bundled-skills/followups/SKILL.md +4 -1
- package/src/config/bundled-skills/gmail/SKILL.md +180 -0
- package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
- package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
- package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
- package/src/config/bundled-skills/messaging/SKILL.md +23 -139
- package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
- package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
- package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
- package/src/config/bundled-skills/notifications/SKILL.md +5 -1
- package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
- package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
- package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → orchestration/tools/swarm-delegate.ts} +3 -3
- package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
- package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
- package/src/config/bundled-skills/schedule/SKILL.md +70 -9
- package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
- package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
- package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
- package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
- package/src/config/bundled-skills/sequences/SKILL.md +47 -0
- package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
- package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
- package/src/config/bundled-skills/settings/SKILL.md +12 -0
- package/src/config/bundled-skills/settings/TOOLS.json +112 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
- package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
- package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
- package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
- package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
- package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
- package/src/config/bundled-skills/slack/SKILL.md +5 -1
- package/src/config/bundled-skills/subagent/SKILL.md +4 -1
- package/src/config/bundled-skills/tasks/SKILL.md +5 -2
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
- package/src/config/bundled-skills/watcher/SKILL.md +4 -1
- package/src/config/bundled-tool-registry.ts +118 -107
- package/src/config/env.ts +5 -2
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/loader.ts +10 -2
- package/src/config/schema.ts +19 -16
- package/src/config/schemas/inference.ts +12 -22
- package/src/config/schemas/memory-storage.ts +19 -1
- package/src/config/schemas/platform.ts +0 -16
- package/src/config/skill-state.ts +11 -8
- package/src/config/skills.ts +83 -32
- package/src/context/token-estimator.ts +11 -0
- package/src/context/window-manager.ts +180 -151
- package/src/daemon/computer-use-session.ts +11 -43
- package/src/daemon/daemon-control.ts +4 -1
- package/src/daemon/handlers/config-channels.ts +5 -9
- package/src/daemon/handlers/config-ingress.ts +0 -4
- package/src/daemon/handlers/config-model.ts +7 -13
- package/src/daemon/handlers/config-telegram.ts +4 -8
- package/src/daemon/handlers/config-voice.ts +2 -5
- package/src/daemon/handlers/dictation.ts +2 -12
- package/src/daemon/handlers/identity.ts +0 -105
- package/src/daemon/handlers/recording.ts +3 -23
- package/src/daemon/handlers/session-history.ts +1 -1
- package/src/daemon/handlers/sessions.ts +53 -72
- package/src/daemon/handlers/shared.ts +7 -28
- package/src/daemon/handlers/skills.ts +31 -27
- package/src/daemon/host-bash-proxy.ts +148 -0
- package/src/daemon/host-file-proxy.ts +135 -0
- package/src/daemon/lifecycle.ts +49 -24
- package/src/daemon/mcp-reload-service.ts +123 -0
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/browser.ts +1 -1
- package/src/daemon/message-types/computer-use.ts +1 -4
- package/src/daemon/message-types/guardian-actions.ts +1 -1
- package/src/daemon/message-types/host-bash.ts +18 -0
- package/src/daemon/message-types/host-file.ts +44 -0
- package/src/daemon/message-types/integrations.ts +1 -67
- package/src/daemon/message-types/messages.ts +15 -0
- package/src/daemon/message-types/schedules.ts +11 -27
- package/src/daemon/message-types/sessions.ts +2 -1
- package/src/daemon/message-types/settings.ts +1 -1
- package/src/daemon/message-types/shared.ts +1 -1
- package/src/daemon/ride-shotgun-handler.ts +2 -42
- package/src/daemon/server.ts +43 -10
- package/src/daemon/session-agent-loop-handlers.ts +48 -7
- package/src/daemon/session-agent-loop.ts +97 -66
- package/src/daemon/session-attachments.ts +1 -1
- package/src/daemon/session-error.ts +17 -16
- package/src/daemon/session-lifecycle.ts +20 -1
- package/src/daemon/session-media-retry.ts +1 -15
- package/src/daemon/session-messaging.ts +14 -6
- package/src/daemon/session-process.ts +36 -7
- package/src/daemon/session-queue-manager.ts +62 -103
- package/src/daemon/session-runtime-assembly.ts +27 -0
- package/src/daemon/session-skill-tools.ts +12 -11
- package/src/daemon/session-slash.ts +7 -0
- package/src/daemon/session-surfaces.ts +19 -97
- package/src/daemon/session-tool-setup.ts +146 -6
- package/src/daemon/session.ts +77 -13
- package/src/errors.ts +0 -2
- package/src/export/formatter.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +1 -3
- package/src/media/avatar-router.ts +20 -28
- package/src/media/avatar-types.ts +7 -14
- package/src/media/managed-avatar-client.ts +70 -34
- package/src/memory/conversation-title-service.ts +1 -2
- package/src/memory/db-init.ts +16 -0
- package/src/memory/embedding-backend.ts +129 -27
- package/src/memory/embedding-gemini.test.ts +256 -0
- package/src/memory/embedding-gemini.ts +47 -13
- package/src/memory/embedding-local.ts +14 -2
- package/src/memory/embedding-ollama.ts +15 -2
- package/src/memory/embedding-openai.ts +15 -2
- package/src/memory/embedding-types.test.ts +116 -0
- package/src/memory/embedding-types.ts +61 -0
- package/src/memory/fingerprint.ts +1 -1
- package/src/memory/indexer.ts +25 -1
- package/src/memory/job-handlers/embedding.test.ts +258 -0
- package/src/memory/job-handlers/embedding.ts +81 -1
- package/src/memory/job-handlers/index-maintenance.ts +35 -1
- package/src/memory/job-handlers/media-processing.ts +11 -1
- package/src/memory/job-utils.ts +21 -6
- package/src/memory/jobs-store.ts +5 -1
- package/src/memory/jobs-worker.ts +8 -0
- package/src/memory/message-content.ts +66 -0
- package/src/memory/migrations/100-core-tables.ts +1 -31
- package/src/memory/migrations/104-core-indexes.ts +0 -11
- package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
- package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/migrations/registry.ts +19 -0
- package/src/memory/qdrant-client.ts +158 -43
- package/src/memory/retriever.test.ts +0 -1
- package/src/memory/retriever.ts +12 -2
- package/src/memory/schema/infrastructure.ts +5 -29
- package/src/memory/search/formatting.ts +34 -9
- package/src/memory/search/semantic.ts +57 -2
- package/src/memory/search/types.ts +2 -1
- package/src/notifications/AGENTS.md +2 -2
- package/src/notifications/README.md +59 -58
- package/src/notifications/adapters/macos.ts +1 -1
- package/src/notifications/broadcaster.ts +5 -5
- package/src/notifications/copy-composer.ts +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/destination-resolver.ts +2 -2
- package/src/notifications/emit-signal.ts +8 -8
- package/src/notifications/signal.ts +1 -1
- package/src/notifications/thread-seed-composer.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +1 -1
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +12 -1
- package/src/permissions/defaults.ts +10 -14
- package/src/permissions/trust-store.ts +37 -0
- package/src/permissions/workspace-policy.ts +0 -1
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
- package/src/prompts/computer-use-prompt.ts +1 -1
- package/src/prompts/system-prompt.ts +29 -30
- package/src/prompts/templates/SOUL.md +1 -2
- package/src/prompts/templates/UPDATES.md +16 -7
- package/src/providers/anthropic/client.ts +87 -33
- package/src/providers/gemini/client.ts +6 -0
- package/src/providers/managed-proxy/constants.ts +5 -0
- package/src/providers/openai/client.ts +15 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/types.ts +24 -2
- package/src/runtime/AGENTS.md +18 -0
- package/src/runtime/assistant-event-hub.ts +2 -3
- package/src/runtime/assistant-event.ts +4 -4
- package/src/runtime/auth/__tests__/context.test.ts +5 -5
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -2
- package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
- package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
- package/src/runtime/auth/__tests__/scopes.test.ts +7 -7
- package/src/runtime/auth/__tests__/subject.test.ts +8 -8
- package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
- package/src/runtime/auth/route-policy.ts +8 -4
- package/src/runtime/auth/scopes.ts +1 -1
- package/src/runtime/auth/subject.ts +4 -4
- package/src/runtime/auth/token-service.ts +0 -23
- package/src/runtime/auth/types.ts +3 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-action-grant-minter.ts +1 -1
- package/src/runtime/guardian-action-service.ts +3 -3
- package/src/runtime/http-server.ts +15 -2
- package/src/runtime/invite-service.ts +3 -3
- package/src/runtime/local-actor-identity.ts +17 -22
- package/src/runtime/pending-interactions.ts +21 -9
- package/src/runtime/routes/app-management-routes.ts +2 -3
- package/src/runtime/routes/approval-routes.ts +1 -3
- package/src/runtime/routes/btw-routes.ts +155 -0
- package/src/runtime/routes/computer-use-routes.ts +77 -31
- package/src/runtime/routes/conversation-routes.ts +230 -46
- package/src/runtime/routes/diagnostics-routes.ts +63 -29
- package/src/runtime/routes/documents-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/host-bash-routes.ts +83 -0
- package/src/runtime/routes/host-file-routes.ts +79 -0
- package/src/runtime/routes/integrations/slack/share.ts +1 -1
- package/src/runtime/routes/log-export-routes.ts +120 -0
- package/src/runtime/routes/mcp-routes.ts +20 -0
- package/src/runtime/routes/migration-routes.ts +3 -3
- package/src/runtime/routes/pairing-routes.ts +1 -1
- package/src/runtime/routes/recording-routes.ts +6 -4
- package/src/runtime/routes/schedule-routes.ts +31 -5
- package/src/runtime/routes/session-management-routes.ts +2 -6
- package/src/runtime/routes/session-query-routes.ts +18 -15
- package/src/runtime/routes/settings-routes.ts +7 -261
- package/src/runtime/routes/skills-routes.ts +7 -6
- package/src/runtime/routes/subagents-routes.ts +4 -10
- package/src/runtime/routes/surface-action-routes.ts +3 -14
- package/src/runtime/routes/surface-content-routes.ts +22 -5
- package/src/runtime/routes/work-items-routes.ts +21 -25
- package/src/runtime/routes/workspace-routes.test.ts +3 -3
- package/src/runtime/routes/workspace-utils.ts +1 -1
- package/src/runtime/telegram-streaming-delivery.ts +3 -0
- package/src/runtime/verification-outbound-actions.ts +2 -2
- package/src/schedule/integration-status.ts +0 -6
- package/src/schedule/schedule-store.ts +234 -43
- package/src/schedule/scheduler.ts +73 -74
- package/src/security/oauth2.ts +1 -1
- package/src/sequence/store.ts +12 -2
- package/src/skills/frontmatter.ts +19 -77
- package/src/skills/managed-store.ts +11 -2
- package/src/subagent/manager.ts +5 -3
- package/src/tasks/ephemeral-permissions.ts +3 -5
- package/src/tools/AGENTS.md +0 -1
- package/src/tools/browser/browser-manager.ts +17 -11
- package/src/tools/browser/jit-auth.ts +4 -1
- package/src/tools/claude-code/claude-code.ts +1 -1
- package/src/tools/computer-use/definitions.ts +48 -60
- package/src/tools/document/document-tool.ts +6 -6
- package/src/tools/filesystem/edit.ts +2 -1
- package/src/tools/filesystem/read.ts +20 -2
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +17 -1
- package/src/tools/host-filesystem/read.ts +16 -1
- package/src/tools/host-filesystem/write.ts +15 -1
- package/src/tools/host-terminal/host-shell.ts +24 -0
- package/src/tools/memory/definitions.ts +45 -81
- package/src/tools/memory/handlers.test.ts +0 -1
- package/src/tools/memory/handlers.ts +1 -1
- package/src/tools/memory/register.ts +26 -60
- package/src/tools/network/script-proxy/session-manager.ts +6 -8
- package/src/tools/network/web-fetch.ts +7 -1
- package/src/tools/network/web-search.ts +2 -1
- package/src/tools/registry.ts +23 -0
- package/src/tools/schedule/create.ts +113 -5
- package/src/tools/schedule/list.ts +57 -15
- package/src/tools/schedule/update.ts +73 -3
- package/src/tools/shared/filesystem/image-read.ts +192 -0
- package/src/tools/side-effects.ts +1 -7
- package/src/tools/skills/delete-managed.ts +27 -64
- package/src/tools/skills/execute.ts +54 -0
- package/src/tools/skills/load.ts +127 -5
- package/src/tools/skills/scaffold-managed.ts +93 -172
- package/src/tools/subagent/message.ts +0 -7
- package/src/tools/subagent/spawn.ts +1 -1
- package/src/tools/swarm/delegate.ts +0 -3
- package/src/tools/system/avatar-generator.ts +13 -19
- package/src/tools/system/request-permission.ts +2 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +41 -47
- package/src/tools/types.ts +6 -2
- package/src/tools/ui-surface/definitions.ts +0 -55
- package/src/util/errors.ts +0 -10
- package/src/workspace/git-service.ts +0 -2
- package/src/__tests__/account-registry.test.ts +0 -258
- package/src/__tests__/email-classifier.test.ts +0 -25
- package/src/__tests__/gmail-integration.test.ts +0 -97
- package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
- package/src/__tests__/managed-twitter-guardrails.test.ts +0 -357
- package/src/__tests__/recording-intent-fallback.test.ts +0 -199
- package/src/__tests__/recording-intent.test.ts +0 -985
- package/src/__tests__/recording-state-machine.test.ts +0 -1574
- package/src/__tests__/reminder-store.test.ts +0 -350
- package/src/__tests__/reminder.test.ts +0 -337
- package/src/__tests__/scan-result-store.test.ts +0 -121
- package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -475
- package/src/__tests__/view-image-tool.test.ts +0 -241
- package/src/cli/commands/amazon/cart.ts +0 -513
- package/src/cli/commands/amazon/checkout.ts +0 -394
- package/src/cli/commands/amazon/client.ts +0 -513
- package/src/cli/commands/amazon/index.ts +0 -885
- package/src/cli/commands/amazon/product-details.ts +0 -145
- package/src/cli/commands/amazon/request-extractor.ts +0 -187
- package/src/cli/commands/amazon/search.ts +0 -76
- package/src/cli/commands/amazon/session.ts +0 -108
- package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -345
- package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -252
- package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -151
- package/src/cli/commands/twitter/index.ts +0 -420
- package/src/cli/commands/twitter/oauth-client.ts +0 -60
- package/src/cli/commands/twitter/router.ts +0 -351
- package/src/cli/commands/twitter/types.ts +0 -30
- package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
- package/src/config/bundled-skills/agentmail/icon.svg +0 -21
- package/src/config/bundled-skills/amazon/SKILL.md +0 -136
- package/src/config/bundled-skills/amazon/icon.svg +0 -13
- package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
- package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
- package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
- package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
- package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
- package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
- package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
- package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
- package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
- package/src/config/bundled-skills/influencer/SKILL.md +0 -144
- package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
- package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
- package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
- package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
- package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
- package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
- package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
- package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
- package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
- package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
- package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
- package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
- package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
- package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
- package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
- package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
- package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
- package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
- package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
- package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
- package/src/config/bundled-skills/notion/SKILL.md +0 -240
- package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
- package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
- package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
- package/src/config/bundled-skills/reminder/SKILL.md +0 -79
- package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
- package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
- package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
- package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
- package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
- package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
- package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
- package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
- package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
- package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
- package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
- package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
- package/src/config/bundled-skills/twitter/SKILL.md +0 -206
- package/src/config/bundled-skills/twitter/icon.svg +0 -14
- package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
- package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
- package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
- package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
- package/src/daemon/handlers/pairing.ts +0 -119
- package/src/daemon/handlers/session-user-message.ts +0 -961
- package/src/daemon/recording-executor.ts +0 -180
- package/src/daemon/recording-intent-fallback.ts +0 -162
- package/src/daemon/recording-intent.ts +0 -493
- package/src/memory/account-store.ts +0 -117
- package/src/messaging/activity-analyzer.ts +0 -76
- package/src/messaging/email-classifier.ts +0 -208
- package/src/messaging/index.ts +0 -2
- package/src/messaging/outreach-classifier.ts +0 -185
- package/src/messaging/thread-summarizer.ts +0 -346
- package/src/messaging/types.ts +0 -17
- package/src/tools/browser/x-auto-navigate.ts +0 -254
- package/src/tools/credentials/account-registry.ts +0 -144
- package/src/tools/filesystem/view-image.ts +0 -244
- package/src/tools/reminder/reminder-store.ts +0 -194
- package/src/tools/reminder/reminder.ts +0 -158
- package/src/tools/system/navigate-settings.ts +0 -74
- package/src/tools/system/open-system-settings.ts +0 -85
- package/src/tools/system/version.ts +0 -54
- package/src/twitter/platform-proxy-client.ts +0 -408
- /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
|
@@ -7,7 +7,7 @@ Signal-driven notification architecture where producers emit free-form events an
|
|
|
7
7
|
```
|
|
8
8
|
Producer → NotificationSignal → Candidate Generation → Decision Engine (LLM) → Deterministic Checks → Broadcaster → Conversation Pairing → Adapters → Delivery
|
|
9
9
|
↑ ↓
|
|
10
|
-
Preference Summary notification_thread_created
|
|
10
|
+
Preference Summary notification_thread_created SSE event
|
|
11
11
|
Thread Candidates (creation-only — not emitted on reuse)
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -71,7 +71,7 @@ Hard invariants that the LLM cannot override:
|
|
|
71
71
|
|
|
72
72
|
### 6. Broadcast, Conversation Pairing, and Delivery
|
|
73
73
|
|
|
74
|
-
The broadcaster (`broadcaster.ts`) iterates over selected channels (vellum first for fast
|
|
74
|
+
The broadcaster (`broadcaster.ts`) iterates over selected channels (vellum first for fast SSE push), resolves destinations via `destination-resolver.ts`, pairs each delivery with a conversation via `conversation-pairing.ts`, pulls rendered copy from the decision (falling back to `copy-composer.ts` templates), and dispatches through channel adapters. Each delivery attempt is recorded in `notification_deliveries` with `conversation_id`, `message_id`, and `conversation_strategy` columns.
|
|
75
75
|
|
|
76
76
|
## Channel Policy Registry
|
|
77
77
|
|
|
@@ -183,27 +183,27 @@ Take out the trash
|
|
|
183
183
|
Reminder. Take out the trash. Action required.
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
## Thread Surfacing via `notification_thread_created`
|
|
186
|
+
## Thread Surfacing via `notification_thread_created` Event (Creation-Only)
|
|
187
187
|
|
|
188
|
-
The `notification_thread_created`
|
|
188
|
+
The `notification_thread_created` SSE event is emitted **only when a brand-new conversation is actually created** by the broadcaster. Reused threads do not trigger this event — the macOS/iOS client already knows about the conversation from the original creation.
|
|
189
189
|
|
|
190
|
-
This is enforced in `broadcaster.ts` by gating the
|
|
190
|
+
This is enforced in `broadcaster.ts` by gating the event emission on `pairing.createdNewConversation === true`:
|
|
191
191
|
|
|
192
192
|
```ts
|
|
193
193
|
// Emit notification_thread_created only when a NEW conversation was
|
|
194
|
-
// actually created. Reusing an existing thread should not fire the
|
|
194
|
+
// actually created. Reusing an existing thread should not fire the SSE
|
|
195
195
|
// event — the client already knows about the conversation.
|
|
196
196
|
if (
|
|
197
197
|
pairing.createdNewConversation &&
|
|
198
198
|
pairing.strategy === "start_new_conversation"
|
|
199
199
|
) {
|
|
200
|
-
// ... emit
|
|
200
|
+
// ... emit SSE event
|
|
201
201
|
}
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
When a vellum notification thread **is** newly created (strategy `start_new_conversation`), the broadcaster emits the
|
|
204
|
+
When a vellum notification thread **is** newly created (strategy `start_new_conversation`), the broadcaster emits the SSE event **immediately**, before waiting for slower channel deliveries (e.g. Telegram). This avoids a race where a slow Telegram delivery delays the broadcast past the macOS deep-link retry window.
|
|
205
205
|
|
|
206
|
-
The
|
|
206
|
+
The SSE event payload:
|
|
207
207
|
|
|
208
208
|
```ts
|
|
209
209
|
{
|
|
@@ -223,39 +223,40 @@ The macOS/iOS client listens for this event and surfaces the thread in the sideb
|
|
|
223
223
|
**Important distinction between the two callbacks:**
|
|
224
224
|
|
|
225
225
|
- **Per-dispatch `options.onThreadCreated`**: Fires for **both** new and reused vellum conversation pairings. Callers like `dispatchGuardianQuestion` rely on this to create delivery bookkeeping rows before `emitNotificationSignal()` returns, regardless of whether the conversation was newly created or reused.
|
|
226
|
-
- **Class-level `this.onThreadCreated` (
|
|
226
|
+
- **Class-level `this.onThreadCreated` (SSE broadcast)**: Fires **only** when a brand-new conversation is created (`createdNewConversation === true && strategy === 'start_new_conversation'`). This emits the `notification_thread_created` SSE event so macOS/iOS clients surface the new thread in the sidebar. Reused threads do not trigger this event because the client already knows about the conversation.
|
|
227
227
|
|
|
228
|
-
##
|
|
228
|
+
## Schedule Routing Metadata and Trigger-Time Enforcement
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
Schedules (both recurring and one-shot) carry optional routing metadata that controls how notifications fan out across channels when the schedule fires in `notify` mode. This enables a single schedule to produce multi-channel delivery without requiring the user to create duplicate schedules per channel.
|
|
231
231
|
|
|
232
232
|
### Routing Intent Model
|
|
233
233
|
|
|
234
|
-
The `routing_intent` field on each
|
|
234
|
+
The `routing_intent` field on each `schedule_jobs` row specifies the desired channel coverage:
|
|
235
235
|
|
|
236
|
-
| Intent | Behavior | When to use
|
|
237
|
-
| ---------------- | ----------------------------------------------------- |
|
|
238
|
-
| `single_channel` | Default LLM-driven routing (no override) | Standard
|
|
239
|
-
| `multi_channel` | Ensures delivery on 2+ channels when 2+ are connected | Important
|
|
240
|
-
| `all_channels` | Forces delivery on every connected channel | Critical
|
|
236
|
+
| Intent | Behavior | When to use |
|
|
237
|
+
| ---------------- | ----------------------------------------------------- | -------------------------------------------------------------------- |
|
|
238
|
+
| `single_channel` | Default LLM-driven routing (no override) | Standard schedules where the decision engine picks the best channel |
|
|
239
|
+
| `multi_channel` | Ensures delivery on 2+ channels when 2+ are connected | Important schedules the user wants on both desktop and phone |
|
|
240
|
+
| `all_channels` | Forces delivery on every connected channel | Critical schedules that must reach the user everywhere |
|
|
241
241
|
|
|
242
|
-
The default is `
|
|
242
|
+
The default is `all_channels`. Routing intent is persisted in the `schedule_jobs` table (`routing_intent` column) and carried through the notification signal as `routingIntent`.
|
|
243
243
|
|
|
244
244
|
### Routing Hints
|
|
245
245
|
|
|
246
|
-
The `
|
|
246
|
+
The `routing_hints_json` field is free-form JSON metadata passed alongside the routing intent. It flows through the signal as `routingHints` and is included in the decision engine prompt, allowing producers to communicate channel preferences or contextual hints without requiring schema changes.
|
|
247
247
|
|
|
248
248
|
### Trigger-Time Enforcement Flow
|
|
249
249
|
|
|
250
|
-
When a
|
|
250
|
+
When a schedule fires in `notify` mode, the routing metadata flows through the notification pipeline with a post-decision enforcement step:
|
|
251
251
|
|
|
252
252
|
```
|
|
253
|
-
|
|
254
|
-
→
|
|
255
|
-
→
|
|
256
|
-
→
|
|
257
|
-
→
|
|
258
|
-
→
|
|
253
|
+
Schedule fires (scheduler.ts: notify mode)
|
|
254
|
+
→ notifyScheduleOneShot callback (lifecycle.ts)
|
|
255
|
+
→ emitNotificationSignal({ routingIntent, routingHints })
|
|
256
|
+
→ Decision Engine (LLM selects channels)
|
|
257
|
+
→ enforceRoutingIntent() (post-decision guard)
|
|
258
|
+
→ Deterministic Checks
|
|
259
|
+
→ Broadcaster → Adapters → Delivery
|
|
259
260
|
```
|
|
260
261
|
|
|
261
262
|
The `enforceRoutingIntent()` function in `decision-engine.ts` runs after the LLM produces its channel selection but before deterministic checks. It overrides the decision's `selectedChannels` based on the routing intent:
|
|
@@ -266,16 +267,16 @@ The `enforceRoutingIntent()` function in `decision-engine.ts` runs after the LLM
|
|
|
266
267
|
|
|
267
268
|
When enforcement changes the decision, the updated channel selection is re-persisted to the `notification_decisions` table so the stored decision matches what was actually dispatched. The `reasoningSummary` is annotated with the enforcement action (e.g. `[routing_intent=all_channels enforced: vellum, telegram]`).
|
|
268
269
|
|
|
269
|
-
### Single-
|
|
270
|
+
### Single-Schedule Fanout
|
|
270
271
|
|
|
271
|
-
A key design principle: **one
|
|
272
|
+
A key design principle: **one schedule produces one notification signal that fans out to multiple channels**. The user never needs to create separate schedules for each channel. The routing intent metadata on the single schedule controls the fanout behavior, and the notification pipeline handles per-channel copy rendering, conversation pairing, and delivery through the existing adapter infrastructure.
|
|
272
273
|
|
|
273
274
|
### Data Flow
|
|
274
275
|
|
|
275
276
|
```
|
|
276
|
-
|
|
277
|
-
→ scheduler.ts:
|
|
278
|
-
→ lifecycle.ts:
|
|
277
|
+
schedule_jobs table (routing_intent, routing_hints_json)
|
|
278
|
+
→ scheduler.ts: claimDueSchedules() reads routing metadata
|
|
279
|
+
→ lifecycle.ts: notifyScheduleOneShot({ routingIntent, routingHints })
|
|
279
280
|
→ emitNotificationSignal({ routingIntent, routingHints })
|
|
280
281
|
→ signal.ts: NotificationSignal.routingIntent / routingHints
|
|
281
282
|
→ decision-engine.ts: evaluateSignal() → enforceRoutingIntent()
|
|
@@ -288,7 +289,7 @@ The notification system delivers to three channel types:
|
|
|
288
289
|
|
|
289
290
|
### Vellum (always connected)
|
|
290
291
|
|
|
291
|
-
Local
|
|
292
|
+
Local SSE via the daemon's broadcast mechanism. The `VellumAdapter` emits a `notification_intent` message containing:
|
|
292
293
|
|
|
293
294
|
- `sourceEventName` -- the event that triggered the notification
|
|
294
295
|
- `title` and `body` -- rendered notification copy
|
|
@@ -304,7 +305,7 @@ HTTP POST to the gateway's `/deliver/telegram` endpoint. The `TelegramAdapter` s
|
|
|
304
305
|
|
|
305
306
|
Connected channels are resolved at signal emission time by `getConnectedChannels()` in `emit-signal.ts`:
|
|
306
307
|
|
|
307
|
-
- **Vellum** is always considered connected (
|
|
308
|
+
- **Vellum** is always considered connected (HTTP transport is always available when the daemon is running)
|
|
308
309
|
- **Telegram** is considered connected only when an active guardian binding exists for the assistant (checked via `getActiveBinding()`)
|
|
309
310
|
|
|
310
311
|
## Conversation Materialization
|
|
@@ -319,7 +320,7 @@ Guardian dispatch follows this same path and uses the optional `onThreadCreated`
|
|
|
319
320
|
|
|
320
321
|
### Conversation Pairing Invariant
|
|
321
322
|
|
|
322
|
-
For notification flows that create conversations, the conversation must be created **before** the
|
|
323
|
+
For notification flows that create conversations, the conversation must be created **before** the SSE event is emitted. This ensures the macOS client can immediately fetch the conversation contents when it receives the thread-created event.
|
|
323
324
|
|
|
324
325
|
## Thread Decision Audit Trail
|
|
325
326
|
|
|
@@ -405,29 +406,29 @@ All disambiguation messages are generated through `composeGuardianActionMessageG
|
|
|
405
406
|
|
|
406
407
|
## Key Files
|
|
407
408
|
|
|
408
|
-
| File | Purpose
|
|
409
|
-
| ------------------------- |
|
|
410
|
-
| `../channels/config.ts` | Channel policy registry -- single source of truth for per-channel notification behavior
|
|
411
|
-
| `emit-signal.ts` | Single entry point for producers; orchestrates the full pipeline
|
|
412
|
-
| `signal.ts` | `NotificationSignal` and `AttentionHints` type definitions
|
|
413
|
-
| `types.ts` | Channel adapter interfaces, delivery types, decision output contract, `ThreadAction` union
|
|
414
|
-
| `thread-candidates.ts` | Builds per-channel candidate set of recent notification conversations for the decision engine
|
|
415
|
-
| `conversation-pairing.ts` | Materializes conversation + message per delivery based on channel strategy
|
|
416
|
-
| `decision-engine.ts` | LLM-based routing with forced tool_choice; deterministic fallback
|
|
417
|
-
| `deterministic-checks.ts` | Pre-send gate checks (dedupe, source-active, channel availability)
|
|
418
|
-
| `runtime-dispatch.ts` | Dispatch gating (no-op decisions, empty channels)
|
|
409
|
+
| File | Purpose |
|
|
410
|
+
| ------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
411
|
+
| `../channels/config.ts` | Channel policy registry -- single source of truth for per-channel notification behavior |
|
|
412
|
+
| `emit-signal.ts` | Single entry point for producers; orchestrates the full pipeline |
|
|
413
|
+
| `signal.ts` | `NotificationSignal` and `AttentionHints` type definitions |
|
|
414
|
+
| `types.ts` | Channel adapter interfaces, delivery types, decision output contract, `ThreadAction` union |
|
|
415
|
+
| `thread-candidates.ts` | Builds per-channel candidate set of recent notification conversations for the decision engine |
|
|
416
|
+
| `conversation-pairing.ts` | Materializes conversation + message per delivery based on channel strategy |
|
|
417
|
+
| `decision-engine.ts` | LLM-based routing with forced tool_choice; deterministic fallback |
|
|
418
|
+
| `deterministic-checks.ts` | Pre-send gate checks (dedupe, source-active, channel availability) |
|
|
419
|
+
| `runtime-dispatch.ts` | Dispatch gating (no-op decisions, empty channels) |
|
|
419
420
|
| `broadcaster.ts` | Fan-out to channel adapters with delivery audit trail; emits `notification_thread_created` SSE event |
|
|
420
|
-
| `copy-composer.ts` | Template-based fallback notification copy when LLM copy is unavailable
|
|
421
|
-
| `thread-seed-composer.ts` | Surface-aware thread seed generation (richer than notification copy)
|
|
422
|
-
| `destination-resolver.ts` | Resolves per-channel endpoints (vellum SSE, Telegram chat ID)
|
|
423
|
-
| `adapters/macos.ts` | Vellum adapter -- broadcasts `notification_intent` via SSE with deep-link metadata
|
|
424
|
-
| `adapters/telegram.ts` | Telegram adapter -- POSTs to gateway `/deliver/telegram`
|
|
425
|
-
| `preference-extractor.ts` | Detects notification preferences in conversation messages
|
|
426
|
-
| `preference-summary.ts` | Builds preference context string for the decision engine prompt
|
|
427
|
-
| `preferences-store.ts` | CRUD for `notification_preferences` table
|
|
428
|
-
| `events-store.ts` | CRUD for `notification_events` table
|
|
429
|
-
| `decisions-store.ts` | CRUD for `notification_decisions` table
|
|
430
|
-
| `deliveries-store.ts` | CRUD for `notification_deliveries` table
|
|
421
|
+
| `copy-composer.ts` | Template-based fallback notification copy when LLM copy is unavailable |
|
|
422
|
+
| `thread-seed-composer.ts` | Surface-aware thread seed generation (richer than notification copy) |
|
|
423
|
+
| `destination-resolver.ts` | Resolves per-channel endpoints (vellum SSE, Telegram chat ID) |
|
|
424
|
+
| `adapters/macos.ts` | Vellum adapter -- broadcasts `notification_intent` via SSE with deep-link metadata |
|
|
425
|
+
| `adapters/telegram.ts` | Telegram adapter -- POSTs to gateway `/deliver/telegram` |
|
|
426
|
+
| `preference-extractor.ts` | Detects notification preferences in conversation messages |
|
|
427
|
+
| `preference-summary.ts` | Builds preference context string for the decision engine prompt |
|
|
428
|
+
| `preferences-store.ts` | CRUD for `notification_preferences` table |
|
|
429
|
+
| `events-store.ts` | CRUD for `notification_events` table |
|
|
430
|
+
| `decisions-store.ts` | CRUD for `notification_decisions` table |
|
|
431
|
+
| `deliveries-store.ts` | CRUD for `notification_deliveries` table |
|
|
431
432
|
|
|
432
433
|
## How to Add a New Notification Producer
|
|
433
434
|
|
|
@@ -479,7 +480,7 @@ Three SQLite tables form the audit chain:
|
|
|
479
480
|
|
|
480
481
|
### Client Delivery Ack
|
|
481
482
|
|
|
482
|
-
For vellum (macOS/iOS) deliveries, the audit trail now extends past the
|
|
483
|
+
For vellum (macOS/iOS) deliveries, the audit trail now extends past the SSE broadcast to the actual OS notification post. The `notification_intent` message carries an optional `deliveryId` that the client echoes back in a `notification_intent_result` ack after `UNUserNotificationCenter.add()` completes (or fails).
|
|
483
484
|
|
|
484
485
|
The ack populates three columns on `notification_deliveries`:
|
|
485
486
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vellum channel adapter — delivers notifications to connected desktop
|
|
3
|
-
* and mobile clients via the daemon's
|
|
3
|
+
* and mobile clients via the daemon's event broadcast mechanism.
|
|
4
4
|
*
|
|
5
5
|
* The adapter broadcasts a `notification_intent` message that the Vellum
|
|
6
6
|
* client can use to display a native notification (e.g. NSUserNotification
|
|
@@ -79,8 +79,8 @@ export class NotificationBroadcaster {
|
|
|
79
79
|
): Promise<NotificationDeliveryResult[]> {
|
|
80
80
|
const destinations = resolveDestinations(decision.selectedChannels);
|
|
81
81
|
|
|
82
|
-
// Ensure vellum is processed first so the notification_thread_created
|
|
83
|
-
//
|
|
82
|
+
// Ensure vellum is processed first so the notification_thread_created
|
|
83
|
+
// event fires immediately, before slower channel sends (e.g. Telegram 30s
|
|
84
84
|
// timeout) can delay it past the macOS deep-link retry window.
|
|
85
85
|
const orderedChannels = [...decision.selectedChannels].sort((a, b) => {
|
|
86
86
|
if (a === "vellum") return -1;
|
|
@@ -242,10 +242,10 @@ export class NotificationBroadcaster {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
// Emit notification_thread_created
|
|
245
|
+
// Emit notification_thread_created event only when a NEW
|
|
246
246
|
// conversation was actually created. Reusing an existing thread
|
|
247
|
-
// should not fire the
|
|
248
|
-
//
|
|
247
|
+
// should not fire the event — the client already knows about the
|
|
248
|
+
// conversation.
|
|
249
249
|
if (
|
|
250
250
|
pairing.createdNewConversation &&
|
|
251
251
|
pairing.strategy === "start_new_conversation"
|
|
@@ -233,7 +233,7 @@ export function buildAccessRequestContractText(
|
|
|
233
233
|
|
|
234
234
|
// Templates keyed by dot-separated sourceEventName strings matching producers.
|
|
235
235
|
const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
|
|
236
|
-
"
|
|
236
|
+
"schedule.notify": (payload) => ({
|
|
237
237
|
title: "Reminder",
|
|
238
238
|
body: str(payload.message, str(payload.label, "A reminder has fired")),
|
|
239
239
|
}),
|
|
@@ -293,7 +293,7 @@ function buildFallbackDecision(
|
|
|
293
293
|
signal.attentionHints.urgency === "high" &&
|
|
294
294
|
signal.attentionHints.requiresAction;
|
|
295
295
|
|
|
296
|
-
// Always include the vellum channel in the fallback — it's a local
|
|
296
|
+
// Always include the vellum channel in the fallback — it's a local
|
|
297
297
|
// broadcast with no cost, so desktop notifications should never be lost
|
|
298
298
|
// when the LLM is unavailable. External channels (e.g. Telegram) are
|
|
299
299
|
// only included for high-urgency actionable signals.
|
|
@@ -320,7 +320,7 @@ function buildFallbackDecision(
|
|
|
320
320
|
selectedChannels,
|
|
321
321
|
reasoningSummary: isHighUrgencyAction
|
|
322
322
|
? "Fallback: high urgency + requires action — all channels"
|
|
323
|
-
: "Fallback: vellum-only (local
|
|
323
|
+
: "Fallback: vellum-only (local, always delivered)",
|
|
324
324
|
renderedCopy: copy,
|
|
325
325
|
dedupeKey: `fallback:${signal.sourceEventName}:${signal.sourceSessionId}:${signal.createdAt}`,
|
|
326
326
|
confidence: 0.3,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Reads guardian delivery info from the contacts table.
|
|
5
5
|
*
|
|
6
|
-
* - Vellum: no external endpoint needed — delivery goes through the
|
|
6
|
+
* - Vellum: no external endpoint needed — delivery goes through the event
|
|
7
7
|
* broadcast mechanism to connected desktop/mobile clients. The
|
|
8
8
|
* guardianPrincipalId is included in metadata so downstream adapters
|
|
9
9
|
* can scope guardian-sensitive notifications to bound guardian devices.
|
|
@@ -40,7 +40,7 @@ export function resolveDestinations(
|
|
|
40
40
|
// guard, so we narrow with a switch over known deliverable values.
|
|
41
41
|
switch (channel as NotificationChannel) {
|
|
42
42
|
case "vellum": {
|
|
43
|
-
// Vellum delivery is local
|
|
43
|
+
// Vellum delivery is local — no external endpoint required.
|
|
44
44
|
// Include the guardianPrincipalId so the adapter can annotate
|
|
45
45
|
// guardian-sensitive notifications for scoped delivery.
|
|
46
46
|
const guardianResult = findGuardianForChannel("vellum");
|
|
@@ -49,9 +49,9 @@ let broadcasterInstance: NotificationBroadcaster | null = null;
|
|
|
49
49
|
let registeredBroadcastFn: BroadcastFn | null = null;
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* Register the
|
|
53
|
-
* notifications
|
|
54
|
-
*
|
|
52
|
+
* Register the broadcast function so the vellum adapter can deliver
|
|
53
|
+
* notifications to connected clients. Must be called once during
|
|
54
|
+
* daemon startup (before any signals are emitted).
|
|
55
55
|
*/
|
|
56
56
|
export function registerBroadcastFn(fn: BroadcastFn): void {
|
|
57
57
|
registeredBroadcastFn = fn;
|
|
@@ -69,7 +69,7 @@ function getBroadcaster(): NotificationBroadcaster {
|
|
|
69
69
|
|
|
70
70
|
// Wire the thread-created callback so the macOS client is notified
|
|
71
71
|
// immediately when a vellum notification thread is paired — before
|
|
72
|
-
// slower channel deliveries (e.g. Telegram) delay the
|
|
72
|
+
// slower channel deliveries (e.g. Telegram) delay the push.
|
|
73
73
|
if (registeredBroadcastFn) {
|
|
74
74
|
const broadcastFn = registeredBroadcastFn;
|
|
75
75
|
broadcasterInstance.setOnThreadCreated((info) => {
|
|
@@ -104,8 +104,8 @@ function getConnectedChannels(): NotificationChannel[] {
|
|
|
104
104
|
for (const channel of getDeliverableChannels()) {
|
|
105
105
|
switch (channel) {
|
|
106
106
|
case "vellum":
|
|
107
|
-
// Vellum is always considered connected (
|
|
108
|
-
// available when the daemon is running).
|
|
107
|
+
// Vellum is always considered connected (the local transport is
|
|
108
|
+
// always available when the daemon is running).
|
|
109
109
|
channels.push(channel);
|
|
110
110
|
break;
|
|
111
111
|
case "telegram": {
|
|
@@ -144,7 +144,7 @@ function getConnectedChannels(): NotificationChannel[] {
|
|
|
144
144
|
// ── Public API ─────────────────────────────────────────────────────────
|
|
145
145
|
|
|
146
146
|
export interface EmitSignalParams<TEventName extends string = string> {
|
|
147
|
-
/** Free-form event name, e.g. '
|
|
147
|
+
/** Free-form event name, e.g. 'schedule.notify', 'schedule.complete'. */
|
|
148
148
|
sourceEventName: TEventName;
|
|
149
149
|
/** Source channel that produced the event — must be a registered channel. */
|
|
150
150
|
sourceChannel: NotificationSourceChannel;
|
|
@@ -320,7 +320,7 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
// Step 4: Dispatch through the broadcaster
|
|
323
|
-
// Note: notification_thread_created
|
|
323
|
+
// Note: notification_thread_created events are emitted eagerly inside
|
|
324
324
|
// the broadcaster as soon as vellum conversation pairing succeeds, rather
|
|
325
325
|
// than after all channel deliveries complete. This avoids a race where
|
|
326
326
|
// slow Telegram delivery delays the push past the macOS deep-link retry.
|
|
@@ -37,7 +37,7 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
37
37
|
id: "user.send_notification",
|
|
38
38
|
description: "User-initiated notification via assistant tool",
|
|
39
39
|
},
|
|
40
|
-
{ id: "
|
|
40
|
+
{ id: "schedule.notify", description: "Scheduled notification triggered (one-shot or recurring)" },
|
|
41
41
|
{ id: "schedule.complete", description: "Scheduled task finished running" },
|
|
42
42
|
{
|
|
43
43
|
id: "guardian.question",
|
|
@@ -73,7 +73,7 @@ export function isThreadSeedSane(value: unknown): value is string {
|
|
|
73
73
|
/**
|
|
74
74
|
* Build a human-readable label from a dot-delimited event name.
|
|
75
75
|
*
|
|
76
|
-
* e.g. "
|
|
76
|
+
* e.g. "schedule.notify" → "Schedule notify", "guardian.question" → "Guardian question"
|
|
77
77
|
*/
|
|
78
78
|
function humanizeEventName(eventName: string): string {
|
|
79
79
|
const words = eventName.replace(/[._]/g, " ").trim();
|
|
@@ -47,7 +47,7 @@ export interface OAuthConnectOptions {
|
|
|
47
47
|
isInteractive: boolean;
|
|
48
48
|
/** Open a URL in the user's browser (interactive path). */
|
|
49
49
|
openUrl?: (url: string) => void;
|
|
50
|
-
/** Send a message to the client (e.g. open_url
|
|
50
|
+
/** Send a message to the client (e.g. open_url). */
|
|
51
51
|
sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
|
|
52
52
|
/** Tools allowed to use the resulting credential. */
|
|
53
53
|
allowedTools?: string[];
|
|
@@ -37,7 +37,7 @@ export interface StoreOAuth2TokensParams {
|
|
|
37
37
|
userinfoUrl?: string;
|
|
38
38
|
allowedTools?: string[];
|
|
39
39
|
wellKnownInjectionTemplates?: CredentialInjectionTemplate[];
|
|
40
|
-
/** Fallback account info from an identity verifier (e.g.
|
|
40
|
+
/** Fallback account info from an identity verifier (e.g. @username, email). */
|
|
41
41
|
identityAccountInfo?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -540,6 +540,17 @@ async function classifyRiskUncached(
|
|
|
540
540
|
if (toolName === "network_request") return RiskLevel.Medium;
|
|
541
541
|
if (toolName === "skill_load") return RiskLevel.Low;
|
|
542
542
|
|
|
543
|
+
// Skill mutation tools are always High risk — they write or delete persistent
|
|
544
|
+
// skill source code. These tools moved from core tool registry to bundled
|
|
545
|
+
// skills, but their security classification must remain High regardless of
|
|
546
|
+
// whether they appear in the tool registry.
|
|
547
|
+
if (
|
|
548
|
+
toolName === "scaffold_managed_skill" ||
|
|
549
|
+
toolName === "delete_managed_skill"
|
|
550
|
+
) {
|
|
551
|
+
return RiskLevel.High;
|
|
552
|
+
}
|
|
553
|
+
|
|
543
554
|
// Escalate host file mutations targeting skill source paths to High risk.
|
|
544
555
|
// The host variants fall through to the tool registry (Medium) by default,
|
|
545
556
|
// but writing to skill source code is a privilege-escalation vector.
|
|
@@ -576,7 +587,7 @@ async function classifyRiskUncached(
|
|
|
576
587
|
|
|
577
588
|
if (prog === "rm") {
|
|
578
589
|
// Only downgrade rm of known safe workspace files for sandboxed bash.
|
|
579
|
-
// host_bash has a global
|
|
590
|
+
// host_bash has a global ask rule that would prompt Medium-risk
|
|
580
591
|
// commands, so rm on the host must always require explicit approval.
|
|
581
592
|
if (toolName === "bash" && isRmOfKnownSafeFile(seg.args)) {
|
|
582
593
|
maxRisk = RiskLevel.Medium;
|
|
@@ -21,8 +21,6 @@ const HOST_FILE_TOOLS = [
|
|
|
21
21
|
] as const;
|
|
22
22
|
const COMPUTER_USE_TOOLS = [
|
|
23
23
|
"computer_use_click",
|
|
24
|
-
"computer_use_double_click",
|
|
25
|
-
"computer_use_right_click",
|
|
26
24
|
"computer_use_type_text",
|
|
27
25
|
"computer_use_key",
|
|
28
26
|
"computer_use_scroll",
|
|
@@ -209,6 +207,15 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
209
207
|
priority: 100,
|
|
210
208
|
};
|
|
211
209
|
|
|
210
|
+
const skillExecuteRule: DefaultRuleTemplate = {
|
|
211
|
+
id: "default:allow-skill_execute-global",
|
|
212
|
+
tool: "skill_execute",
|
|
213
|
+
pattern: "skill_execute:*",
|
|
214
|
+
scope: "everywhere",
|
|
215
|
+
decision: "allow",
|
|
216
|
+
priority: 100,
|
|
217
|
+
};
|
|
218
|
+
|
|
212
219
|
// Browser tools were previously core-registered with RiskLevel.Low (auto-allowed).
|
|
213
220
|
// After migration to skill-provided tools, default allow rules preserve the
|
|
214
221
|
// same frictionless UX so they don't trigger permission prompts.
|
|
@@ -267,17 +274,6 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
267
274
|
}),
|
|
268
275
|
);
|
|
269
276
|
|
|
270
|
-
// view_image is a read-only sandbox tool — always allow without prompting.
|
|
271
|
-
// Candidates contain "/" (absolute paths), so use "/**" globstar.
|
|
272
|
-
const viewImageRule: DefaultRuleTemplate = {
|
|
273
|
-
id: "default:allow-view_image-global",
|
|
274
|
-
tool: "view_image",
|
|
275
|
-
pattern: "view_image:/**",
|
|
276
|
-
scope: "everywhere",
|
|
277
|
-
decision: "allow",
|
|
278
|
-
priority: 100,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
277
|
// memory_recall is a read-only tool — always allow without prompting.
|
|
282
278
|
const memoryRecallRule: DefaultRuleTemplate = {
|
|
283
279
|
id: "default:allow-memory_recall-global",
|
|
@@ -299,10 +295,10 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
299
295
|
updatesDeleteRule,
|
|
300
296
|
...skillSourceMutationRules,
|
|
301
297
|
skillLoadRule,
|
|
298
|
+
skillExecuteRule,
|
|
302
299
|
browserNavigateRule,
|
|
303
300
|
...browserToolRules,
|
|
304
301
|
...uiSurfaceRules,
|
|
305
|
-
viewImageRule,
|
|
306
302
|
memoryRecallRule,
|
|
307
303
|
];
|
|
308
304
|
}
|
|
@@ -217,11 +217,48 @@ function backfillDefaults(rules: TrustRule[]): boolean {
|
|
|
217
217
|
return changed;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
function getLegacyTrustPath(): string {
|
|
221
|
+
return join(getRootDir(), "trust.json");
|
|
222
|
+
}
|
|
223
|
+
|
|
220
224
|
function loadFromDisk(): TrustRule[] {
|
|
221
225
|
const path = getTrustPath();
|
|
222
226
|
let rules: TrustRule[] = [];
|
|
223
227
|
let needsSave = false;
|
|
224
228
|
|
|
229
|
+
// Migrate legacy trust file from root dir to protected subdir.
|
|
230
|
+
// Only migrate when the protected path does not yet exist.
|
|
231
|
+
if (!existsSync(path)) {
|
|
232
|
+
const legacyPath = getLegacyTrustPath();
|
|
233
|
+
if (existsSync(legacyPath)) {
|
|
234
|
+
try {
|
|
235
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
236
|
+
renameSync(legacyPath, path);
|
|
237
|
+
chmodSync(path, 0o600);
|
|
238
|
+
log.info(
|
|
239
|
+
{ from: legacyPath, to: path },
|
|
240
|
+
"Migrated legacy trust file to protected path",
|
|
241
|
+
);
|
|
242
|
+
} catch (err) {
|
|
243
|
+
log.warn(
|
|
244
|
+
{ err },
|
|
245
|
+
"Failed to migrate legacy trust file; reading from legacy path",
|
|
246
|
+
);
|
|
247
|
+
// Fall back: copy content so the normal read path picks it up.
|
|
248
|
+
try {
|
|
249
|
+
const content = readFileSync(legacyPath, "utf-8");
|
|
250
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
251
|
+
writeFileSync(path, content, { mode: 0o600 });
|
|
252
|
+
} catch (copyErr) {
|
|
253
|
+
log.warn(
|
|
254
|
+
{ copyErr },
|
|
255
|
+
"Failed to copy legacy trust file to protected path",
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
225
262
|
if (existsSync(path)) {
|
|
226
263
|
try {
|
|
227
264
|
const raw = readFileSync(path, "utf-8");
|
|
@@ -32,6 +32,17 @@ describe("buildCliReferenceSection", () => {
|
|
|
32
32
|
expect(result).toContain("available via `bash`");
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
test("routes account and auth work through documented assistant CLI commands", () => {
|
|
36
|
+
const result = buildCliReferenceSection();
|
|
37
|
+
expect(result).toContain(
|
|
38
|
+
"prefer real `assistant` CLI workflows over any legacy account-record abstraction",
|
|
39
|
+
);
|
|
40
|
+
expect(result).toContain("assistant credentials");
|
|
41
|
+
expect(result).toContain("assistant oauth token <service>");
|
|
42
|
+
expect(result).toContain("assistant mcp auth <name>");
|
|
43
|
+
expect(result).toContain("assistant platform status");
|
|
44
|
+
});
|
|
45
|
+
|
|
35
46
|
test("result is cached — calling twice returns the same string", () => {
|
|
36
47
|
const first = buildCliReferenceSection();
|
|
37
48
|
const second = buildCliReferenceSection();
|
|
@@ -36,7 +36,7 @@ Before every action, ask yourself: "Can I do this with AppleScript or a direct r
|
|
|
36
36
|
|
|
37
37
|
You will receive the current screen state as an accessibility tree. Each interactive element has an [ID] number like [3] or [17]. Use these IDs with element_id to target elements \u2014 this is much more reliable than pixel coordinates.
|
|
38
38
|
|
|
39
|
-
YOUR AVAILABLE TOOLS ARE: computer_use_click
|
|
39
|
+
YOUR AVAILABLE TOOLS ARE: computer_use_click (with click_type: "single" | "double" | "right"), computer_use_type_text, computer_use_key, computer_use_scroll, computer_use_drag, computer_use_wait, computer_use_open_app, computer_use_run_applescript, computer_use_done, computer_use_respond, ui_show, ui_update, ui_dismiss.
|
|
40
40
|
You MUST only call one tool per turn.
|
|
41
41
|
|
|
42
42
|
UI SURFACES: When the user asks you to build, create, or display something (an app, dashboard, tracker, etc.), use ui_show with surface_type "dynamic_page" to render custom HTML directly instead of trying to build it with computer-use tools. This is your primary way to create visual applications for the user. After calling ui_show, call computer_use_done immediately — the surface is already displayed to the user.
|