@vellumai/assistant 0.5.15 → 0.6.0
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/ARCHITECTURE.md +3 -3
- package/Dockerfile +0 -3
- package/docs/architecture/integrations.md +15 -14
- package/knip.json +4 -1
- package/openapi.yaml +670 -122
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +57 -3
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +5 -377
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/ces-rpc-credential-backend.test.ts +4 -1
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +84 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +108 -6
- package/src/__tests__/cli-memory.test.ts +377 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -2
- package/src/__tests__/config-schema.test.ts +1 -3
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/config-watcher-feature-flags.test.ts +211 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +9 -0
- package/src/__tests__/conversation-agent-loop.test.ts +9 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +5 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +2 -6
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +3 -6
- package/src/__tests__/conversation-wipe.test.ts +11 -408
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +6 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +7 -73
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -7
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +343 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/heartbeat-service.test.ts +1 -3
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +154 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +292 -0
- package/src/__tests__/intent-routing.test.ts +6 -18
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -14
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/llm-context-route-provider.test.ts +2 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +4 -34
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -37
- package/src/__tests__/managed-store.test.ts +40 -21
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +2 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/messaging-send-tool.test.ts +6 -6
- package/src/__tests__/migration-cross-version-compatibility.test.ts +1 -29
- package/src/__tests__/migration-export-http.test.ts +3 -34
- package/src/__tests__/migration-import-commit-http.test.ts +1 -29
- package/src/__tests__/migration-import-preflight-http.test.ts +3 -34
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +2 -1
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-apps-routes.test.ts +120 -10
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth-connect-orchestrator.test.ts +709 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +2 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +149 -0
- package/src/__tests__/oauth-providers-routes.test.ts +5 -2
- package/src/__tests__/oauth-store.test.ts +0 -5
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +1071 -0
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/path-policy.test.ts +2 -17
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/platform-callback-registration.test.ts +7 -11
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +21 -2
- package/src/__tests__/qdrant-manager.test.ts +68 -21
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/require-fresh-approval.test.ts +64 -3
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/sandbox-diagnostics.test.ts +20 -29
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +2 -10
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/search-skills-unified.test.ts +421 -0
- package/src/__tests__/secret-allowlist.test.ts +20 -35
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +2 -6
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/shell-credential-ref.test.ts +0 -5
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -54
- package/src/__tests__/skill-load-inline-command.test.ts +3 -65
- package/src/__tests__/skill-load-inline-includes.test.ts +3 -65
- package/src/__tests__/skill-load-tool.test.ts +3 -67
- package/src/__tests__/skill-memory.test.ts +480 -195
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +23 -50
- package/src/__tests__/slack-channel-config.test.ts +2 -21
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/starter-bundle.test.ts +2 -8
- package/src/__tests__/stt-hints.test.ts +7 -2
- package/src/__tests__/system-prompt.test.ts +25 -45
- package/src/__tests__/task-compiler.test.ts +2 -27
- package/src/__tests__/task-management-tools.test.ts +2 -27
- package/src/__tests__/task-memory-cleanup.test.ts +173 -250
- package/src/__tests__/task-runner.test.ts +2 -27
- package/src/__tests__/task-scheduler.test.ts +2 -27
- package/src/__tests__/terminal-tools.test.ts +1 -17
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +0 -79
- package/src/__tests__/tool-approval-handler.test.ts +4 -27
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +2 -11
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -25
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +4 -27
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -20
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- package/src/__tests__/trust-store.test.ts +10 -42
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -30
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +3 -27
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -28
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -28
- package/src/__tests__/trusted-contact-verification.test.ts +2 -28
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -34
- package/src/__tests__/twilio-provider.test.ts +0 -16
- package/src/__tests__/twilio-routes-twiml.test.ts +7 -12
- package/src/__tests__/twilio-routes.test.ts +0 -24
- package/src/__tests__/update-bulletin.test.ts +17 -89
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -26
- package/src/__tests__/usage-routes.test.ts +2 -27
- package/src/__tests__/user-reference.test.ts +1 -5
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +4 -34
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -53
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -27
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -30
- package/src/__tests__/voice-session-bridge.test.ts +2 -27
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -29
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +2 -2
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +4 -29
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +0 -6
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +1 -15
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -24
- package/src/cli/cli-memory.ts +179 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/memory.ts +41 -55
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +26 -6
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/providers.ts +49 -42
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -55
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/skills.ts +88 -16
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +7 -7
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +2 -10
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +26 -19
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +1 -7
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +15 -8
- package/src/config/feature-flag-registry.json +29 -116
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +8 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +32 -9
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/config-watcher.ts +51 -0
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
- package/src/daemon/conversation-agent-loop.ts +99 -63
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-lifecycle.ts +33 -0
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +1 -0
- package/src/daemon/conversation-runtime-assembly.ts +5 -0
- package/src/daemon/conversation-usage.ts +1 -0
- package/src/daemon/conversation.ts +41 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/handlers/shared.ts +22 -12
- package/src/daemon/handlers/skills.ts +423 -201
- package/src/daemon/lifecycle.ts +52 -4
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +5 -1
- package/src/daemon/message-types/messages.ts +3 -1
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/providers-setup.ts +7 -0
- package/src/daemon/server.ts +35 -22
- package/src/daemon/tool-side-effects.ts +27 -5
- package/src/events/domain-events.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/memory/admin.ts +11 -45
- package/src/memory/conversation-bootstrap.ts +2 -0
- package/src/memory/conversation-crud.ts +242 -348
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +4 -2
- package/src/memory/db-init.ts +39 -3
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +512 -0
- package/src/memory/graph/capability-seed.ts +297 -0
- package/src/memory/graph/consolidation.ts +691 -0
- package/src/memory/graph/conversation-graph-memory.ts +630 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +69 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1254 -0
- package/src/memory/graph/graph-search.ts +266 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +439 -0
- package/src/memory/graph/inspect.ts +534 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1008 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1050 -0
- package/src/memory/graph/store.ts +699 -0
- package/src/memory/graph/tool-handlers.ts +426 -0
- package/src/memory/graph/tools.ts +141 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +271 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +0 -53
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.test.ts +3 -27
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +50 -70
- package/src/memory/jobs-worker.ts +147 -112
- package/src/memory/llm-usage-store.ts +35 -2
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/201-oauth-providers-feature-flag.ts +11 -0
- package/src/memory/migrations/202-drop-callback-transport-column.ts +13 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/qdrant-manager.ts +26 -5
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/schema/oauth.ts +1 -1
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/slack-thread-store.ts +17 -0
- package/src/memory/task-memory-cleanup.ts +28 -50
- package/src/messaging/providers/outlook/adapter.ts +200 -0
- package/src/messaging/providers/outlook/client.ts +610 -0
- package/src/messaging/providers/outlook/types.ts +201 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/adapters/slack.ts +1 -1
- package/src/notifications/copy-composer.ts +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +10 -3
- package/src/oauth/oauth-store.ts +10 -11
- package/src/oauth/provider-serializer.ts +3 -0
- package/src/oauth/provider-visibility.ts +16 -0
- package/src/oauth/seed-providers.ts +50 -17
- package/src/permissions/checker.ts +62 -9
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/types.ts +2 -4
- package/src/permissions/workspace-policy.ts +1 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +6 -93
- package/src/prompts/templates/UPDATES.md +6 -0
- package/src/providers/anthropic/client.ts +47 -19
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/__tests__/credential-service.test.ts +1 -27
- package/src/runtime/auth/__tests__/token-service.test.ts +1 -25
- package/src/runtime/auth/route-policy.ts +7 -4
- package/src/runtime/guardian-reply-router.ts +10 -2
- package/src/runtime/http-server.ts +23 -3
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +8 -0
- package/src/runtime/routes/conversation-management-routes.ts +2 -0
- package/src/runtime/routes/conversation-query-routes.ts +2 -58
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +43 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/memory-item-routes.test.ts +2 -31
- package/src/runtime/routes/memory-item-routes.ts +385 -341
- package/src/runtime/routes/oauth-apps.ts +18 -1
- package/src/runtime/routes/oauth-providers.ts +13 -1
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/settings-routes.ts +1 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/usage-routes.ts +19 -2
- package/src/runtime/routes/work-items-routes.test.ts +2 -27
- package/src/runtime/routes/workspace-routes.test.ts +3 -27
- package/src/schedule/scheduler.ts +8 -1
- package/src/security/oauth2.ts +1 -1
- package/src/security/secret-allowlist.ts +4 -4
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +15 -14
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +27 -16
- package/src/skills/skill-memory.ts +210 -96
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/tasks/task-runner.ts +3 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +7 -19
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/skills/skill-script-runner.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +3 -3
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/device-id.ts +3 -65
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/git-service.ts +27 -6
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -741
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -383
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1590
- package/src/memory/retriever.ts +0 -1323
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -136
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -156
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -590
- package/src/tools/memory/handlers.ts +0 -434
|
@@ -1,67 +1,56 @@
|
|
|
1
1
|
import { getConfig } from "../../config/loader.js";
|
|
2
|
+
import {
|
|
3
|
+
handleRecall,
|
|
4
|
+
handleRemember,
|
|
5
|
+
type RecallInput,
|
|
6
|
+
type RememberInput,
|
|
7
|
+
} from "../../memory/graph/tool-handlers.js";
|
|
8
|
+
import {
|
|
9
|
+
graphRecallDefinition,
|
|
10
|
+
graphRememberDefinition,
|
|
11
|
+
} from "../../memory/graph/tools.js";
|
|
2
12
|
import { RiskLevel } from "../../permissions/types.js";
|
|
3
13
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
4
14
|
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
5
|
-
import {
|
|
6
|
-
memoryManageDefinition,
|
|
7
|
-
memoryRecallDefinition,
|
|
8
|
-
} from "./definitions.js";
|
|
9
|
-
import {
|
|
10
|
-
handleMemoryDelete,
|
|
11
|
-
handleMemoryRecall,
|
|
12
|
-
handleMemorySave,
|
|
13
|
-
handleMemoryUpdate,
|
|
14
|
-
} from "./handlers.js";
|
|
15
15
|
|
|
16
|
-
// ──
|
|
16
|
+
// ── remember ────────────────────────────────────────────────────────
|
|
17
17
|
|
|
18
|
-
class
|
|
19
|
-
name = "
|
|
20
|
-
description =
|
|
18
|
+
class RememberTool implements Tool {
|
|
19
|
+
name = "remember";
|
|
20
|
+
description = graphRememberDefinition.description;
|
|
21
21
|
category = "memory";
|
|
22
22
|
defaultRiskLevel = RiskLevel.Low;
|
|
23
23
|
|
|
24
24
|
getDefinition(): ToolDefinition {
|
|
25
|
-
return
|
|
25
|
+
return graphRememberDefinition;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async execute(
|
|
29
29
|
input: Record<string, unknown>,
|
|
30
30
|
context: ToolContext,
|
|
31
31
|
): Promise<ToolExecutionResult> {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
case "update":
|
|
43
|
-
return handleMemoryUpdate(input, config, context.memoryScopeId);
|
|
44
|
-
case "delete":
|
|
45
|
-
return handleMemoryDelete(input, config, context.memoryScopeId);
|
|
46
|
-
default:
|
|
47
|
-
return {
|
|
48
|
-
content: `Error: unknown op "${input.op}". Must be one of: save, update, delete`,
|
|
49
|
-
isError: true,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
32
|
+
const result = handleRemember(
|
|
33
|
+
input as unknown as RememberInput,
|
|
34
|
+
context.conversationId,
|
|
35
|
+
context.memoryScopeId ?? "default",
|
|
36
|
+
);
|
|
37
|
+
return {
|
|
38
|
+
content: result.message,
|
|
39
|
+
isError: !result.success,
|
|
40
|
+
};
|
|
52
41
|
}
|
|
53
42
|
}
|
|
54
43
|
|
|
55
|
-
// ──
|
|
44
|
+
// ── recall ──────────────────────────────────────────────────────────
|
|
56
45
|
|
|
57
|
-
class
|
|
58
|
-
name = "
|
|
59
|
-
description =
|
|
46
|
+
class RecallTool implements Tool {
|
|
47
|
+
name = "recall";
|
|
48
|
+
description = graphRecallDefinition.description;
|
|
60
49
|
category = "memory";
|
|
61
50
|
defaultRiskLevel = RiskLevel.Low;
|
|
62
51
|
|
|
63
52
|
getDefinition(): ToolDefinition {
|
|
64
|
-
return
|
|
53
|
+
return graphRecallDefinition;
|
|
65
54
|
}
|
|
66
55
|
|
|
67
56
|
async execute(
|
|
@@ -69,16 +58,44 @@ class MemoryRecallTool implements Tool {
|
|
|
69
58
|
context: ToolContext,
|
|
70
59
|
): Promise<ToolExecutionResult> {
|
|
71
60
|
const config = getConfig();
|
|
72
|
-
|
|
73
|
-
input,
|
|
61
|
+
const result = await handleRecall(
|
|
62
|
+
input as unknown as RecallInput,
|
|
74
63
|
config,
|
|
75
|
-
context.memoryScopeId,
|
|
76
|
-
context.conversationId,
|
|
64
|
+
context.memoryScopeId ?? "default",
|
|
77
65
|
);
|
|
66
|
+
|
|
67
|
+
if (result.results.length === 0) {
|
|
68
|
+
return { content: "No results found.", isError: false };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const formatted = result.results
|
|
72
|
+
.map((r) => {
|
|
73
|
+
const ts = formatTimestamp(r.created);
|
|
74
|
+
const meta =
|
|
75
|
+
result.mode === "memory"
|
|
76
|
+
? `[${r.type}] ${ts} (confidence: ${r.confidence.toFixed(2)}, score: ${r.score.toFixed(3)})`
|
|
77
|
+
: `[archive] ${ts}`;
|
|
78
|
+
return `${meta}\n${r.content}`;
|
|
79
|
+
})
|
|
80
|
+
.join("\n\n---\n\n");
|
|
81
|
+
|
|
82
|
+
return { content: formatted, isError: false };
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
|
|
86
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
function formatTimestamp(epochMs: number): string {
|
|
89
|
+
const d = new Date(epochMs);
|
|
90
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
91
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
92
|
+
const yy = String(d.getFullYear()).slice(-2);
|
|
93
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
94
|
+
const min = String(d.getMinutes()).padStart(2, "0");
|
|
95
|
+
return `${mm}/${dd}/${yy} ${hh}:${min}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
81
98
|
// ── Exported tool instances ──────────────────────────────────────────
|
|
82
99
|
|
|
83
|
-
export const
|
|
84
|
-
export const
|
|
100
|
+
export const rememberTool = new RememberTool();
|
|
101
|
+
export const recallTool = new RecallTool();
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "../permissions/checker.js";
|
|
9
9
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
10
10
|
import { addRule } from "../permissions/trust-store.js";
|
|
11
|
+
import { RiskLevel } from "../permissions/types.js";
|
|
11
12
|
import {
|
|
12
13
|
getEffectiveMode,
|
|
13
14
|
setConversationMode,
|
|
@@ -137,24 +138,6 @@ export class PermissionChecker {
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
if (result.decision === "prompt") {
|
|
140
|
-
// dangerouslySkipPermissions: when enabled, auto-approve all prompts
|
|
141
|
-
// without user interaction. Deny rules are still respected (they
|
|
142
|
-
// return before reaching this block).
|
|
143
|
-
//
|
|
144
|
-
// Note: unlike guardian auto-approve and temporary overrides below,
|
|
145
|
-
// this intentionally does NOT check `context.requireFreshApproval`.
|
|
146
|
-
// The setting is designed to skip ALL interactive prompts
|
|
147
|
-
// unconditionally — it is an explicit operator opt-out from the
|
|
148
|
-
// permission system, so requireFreshApproval does not apply.
|
|
149
|
-
const cfg = getConfig();
|
|
150
|
-
if (cfg.permissions.dangerouslySkipPermissions) {
|
|
151
|
-
log.info(
|
|
152
|
-
{ toolName: name, riskLevel },
|
|
153
|
-
"dangerouslySkipPermissions active — auto-approving without prompt",
|
|
154
|
-
);
|
|
155
|
-
return { allowed: true, decision: "dangerously_skip_permissions", riskLevel };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
141
|
// Guardian-trust sessions (e.g. scheduled jobs, reminders) should be
|
|
159
142
|
// able to use bundled tools without interactive approval. The guardian
|
|
160
143
|
// is the owner - prompting makes no sense when there is no client.
|
|
@@ -163,6 +146,10 @@ export class PermissionChecker {
|
|
|
163
146
|
// Exception: inline-command skill loads (skill_load_dynamic:*) must
|
|
164
147
|
// never be silently auto-approved — they execute embedded commands
|
|
165
148
|
// and require explicit human review or a pinned trust rule.
|
|
149
|
+
// Exception: high-risk tools (e.g. destructive shell commands, writes
|
|
150
|
+
// to sensitive paths) are denied — unattended sessions must not
|
|
151
|
+
// auto-approve operations that could cause significant damage if
|
|
152
|
+
// triggered by prompt injection from untrusted content.
|
|
166
153
|
const isDynamicSkillLoad =
|
|
167
154
|
result.matchedRule?.pattern.startsWith("skill_load_dynamic:") ===
|
|
168
155
|
true;
|
|
@@ -170,7 +157,8 @@ export class PermissionChecker {
|
|
|
170
157
|
context.isInteractive === false &&
|
|
171
158
|
context.trustClass === "guardian" &&
|
|
172
159
|
!context.requireFreshApproval &&
|
|
173
|
-
!isDynamicSkillLoad
|
|
160
|
+
!isDynamicSkillLoad &&
|
|
161
|
+
riskLevel !== RiskLevel.High
|
|
174
162
|
) {
|
|
175
163
|
log.info(
|
|
176
164
|
{ toolName: name, riskLevel },
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readFileSync, statSync, unlinkSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
5
2
|
|
|
3
|
+
import { optimizeImageForTransport } from "../../../agent/image-optimize.js";
|
|
6
4
|
import type { ImageContent } from "../../../providers/types.js";
|
|
7
5
|
import type { ToolExecutionResult } from "../../types.js";
|
|
8
6
|
|
|
@@ -17,12 +15,6 @@ export const IMAGE_EXTENSIONS = new Set([
|
|
|
17
15
|
const MAX_SIZE_BYTES = 20 * 1024 * 1024; // 20 MB — LLM API transport limit (post-optimization)
|
|
18
16
|
const MAX_SOURCE_SIZE_BYTES = 100 * 1024 * 1024; // 100 MB — pre-optimization guard
|
|
19
17
|
|
|
20
|
-
// Images above this threshold get auto-optimized via sips (macOS) to avoid
|
|
21
|
-
// sending multi-MB base64 payloads to the LLM API.
|
|
22
|
-
const OPTIMIZE_THRESHOLD_BYTES = 1 * 1024 * 1024; // 1 MB
|
|
23
|
-
const OPTIMIZE_MAX_DIMENSION = 1568; // Anthropic's recommended max
|
|
24
|
-
const OPTIMIZE_JPEG_QUALITY = 80;
|
|
25
|
-
|
|
26
18
|
/**
|
|
27
19
|
* Detect the actual image format from the first bytes of the buffer.
|
|
28
20
|
* Returns the MIME type, or null if unrecognised.
|
|
@@ -69,36 +61,6 @@ function detectMediaType(buf: Buffer): string | null {
|
|
|
69
61
|
return null;
|
|
70
62
|
}
|
|
71
63
|
|
|
72
|
-
/**
|
|
73
|
-
* Use macOS `sips` to resize and convert an image to JPEG.
|
|
74
|
-
* Returns the path to the optimized temp file, or null if sips is unavailable.
|
|
75
|
-
*/
|
|
76
|
-
function optimizeWithSips(srcPath: string): string | null {
|
|
77
|
-
const tmpPath = join(tmpdir(), `vellum-view-image-${Date.now()}.jpg`);
|
|
78
|
-
try {
|
|
79
|
-
execFileSync(
|
|
80
|
-
"sips",
|
|
81
|
-
[
|
|
82
|
-
"--resampleHeightWidthMax",
|
|
83
|
-
String(OPTIMIZE_MAX_DIMENSION),
|
|
84
|
-
"-s",
|
|
85
|
-
"format",
|
|
86
|
-
"jpeg",
|
|
87
|
-
"-s",
|
|
88
|
-
"formatOptions",
|
|
89
|
-
String(OPTIMIZE_JPEG_QUALITY),
|
|
90
|
-
srcPath,
|
|
91
|
-
"--out",
|
|
92
|
-
tmpPath,
|
|
93
|
-
],
|
|
94
|
-
{ stdio: "pipe", timeout: 15_000 },
|
|
95
|
-
);
|
|
96
|
-
return tmpPath;
|
|
97
|
-
} catch {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
64
|
/**
|
|
103
65
|
* Read an image file from disk, optionally optimize it, and return a
|
|
104
66
|
* ToolExecutionResult with base64-encoded image content blocks.
|
|
@@ -130,51 +92,11 @@ export function readImageFile(resolvedPath: string): ToolExecutionResult {
|
|
|
130
92
|
}
|
|
131
93
|
|
|
132
94
|
let buffer: Buffer;
|
|
133
|
-
let optimized = false;
|
|
134
|
-
let tmpPath: string | null = null;
|
|
135
|
-
|
|
136
95
|
try {
|
|
137
|
-
|
|
138
|
-
tmpPath = optimizeWithSips(resolvedPath);
|
|
139
|
-
if (tmpPath) {
|
|
140
|
-
buffer = readFileSync(tmpPath) as Buffer;
|
|
141
|
-
optimized = true;
|
|
142
|
-
} else {
|
|
143
|
-
// sips unavailable — fast-fail if original file exceeds the transport limit
|
|
144
|
-
if (stat.size > MAX_SIZE_BYTES) {
|
|
145
|
-
const sizeMB = (stat.size / (1024 * 1024)).toFixed(1);
|
|
146
|
-
return {
|
|
147
|
-
content: `Error: image too large (${sizeMB} MB). Maximum is 20 MB. Image optimization (sips) is unavailable on this platform.`,
|
|
148
|
-
isError: true,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
buffer = readFileSync(resolvedPath) as Buffer;
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
buffer = readFileSync(resolvedPath) as Buffer;
|
|
155
|
-
}
|
|
96
|
+
buffer = readFileSync(resolvedPath) as Buffer;
|
|
156
97
|
} catch (err) {
|
|
157
98
|
const msg = err instanceof Error ? err.message : String(err);
|
|
158
99
|
return { content: `Error reading file: ${msg}`, isError: true };
|
|
159
|
-
} finally {
|
|
160
|
-
if (tmpPath) {
|
|
161
|
-
try {
|
|
162
|
-
unlinkSync(tmpPath);
|
|
163
|
-
} catch {
|
|
164
|
-
/* ignore cleanup errors */
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (buffer.length > MAX_SIZE_BYTES) {
|
|
170
|
-
const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
|
|
171
|
-
const msg = optimized
|
|
172
|
-
? `Error: image too large after optimization (${sizeMB} MB). Maximum is 20 MB.`
|
|
173
|
-
: `Error: image too large (${sizeMB} MB). Maximum is 20 MB.`;
|
|
174
|
-
return {
|
|
175
|
-
content: msg,
|
|
176
|
-
isError: true,
|
|
177
|
-
};
|
|
178
100
|
}
|
|
179
101
|
|
|
180
102
|
// Detect actual format from magic bytes - never trust the file extension
|
|
@@ -187,25 +109,40 @@ export function readImageFile(resolvedPath: string): ToolExecutionResult {
|
|
|
187
109
|
};
|
|
188
110
|
}
|
|
189
111
|
|
|
190
|
-
|
|
112
|
+
// Optimize before size-checking — oversized images may compress under the limit.
|
|
113
|
+
const rawBase64 = buffer.toString("base64");
|
|
114
|
+
const { data: base64Data, mediaType: finalType } =
|
|
115
|
+
optimizeImageForTransport(rawBase64, detectedType);
|
|
116
|
+
const optimized = base64Data !== rawBase64;
|
|
117
|
+
|
|
118
|
+
const optimizedBytes = optimized
|
|
119
|
+
? Math.ceil((base64Data.length * 3) / 4)
|
|
120
|
+
: buffer.length;
|
|
121
|
+
if (optimizedBytes > MAX_SIZE_BYTES) {
|
|
122
|
+
const sizeMB = (optimizedBytes / (1024 * 1024)).toFixed(1);
|
|
123
|
+
return {
|
|
124
|
+
content: `Error: image too large (${sizeMB} MB). Maximum is 20 MB even after optimization.`,
|
|
125
|
+
isError: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
191
128
|
|
|
192
129
|
const imageBlock: ImageContent = {
|
|
193
130
|
type: "image" as const,
|
|
194
131
|
source: {
|
|
195
132
|
type: "base64" as const,
|
|
196
|
-
media_type:
|
|
133
|
+
media_type: finalType,
|
|
197
134
|
data: base64Data,
|
|
198
135
|
},
|
|
199
136
|
};
|
|
200
137
|
|
|
201
138
|
const sizeSuffix = optimized
|
|
202
139
|
? ` (optimized from ${(stat.size / 1024).toFixed(0)} KB to ${(
|
|
203
|
-
|
|
140
|
+
optimizedBytes / 1024
|
|
204
141
|
).toFixed(0)} KB)`
|
|
205
142
|
: "";
|
|
206
143
|
|
|
207
144
|
return {
|
|
208
|
-
content: `Image loaded: ${resolvedPath} (${
|
|
145
|
+
content: `Image loaded: ${resolvedPath} (${optimizedBytes} bytes, ${finalType})${sizeSuffix}`,
|
|
209
146
|
isError: false,
|
|
210
147
|
contentBlocks: [imageBlock],
|
|
211
148
|
};
|
|
@@ -40,7 +40,7 @@ export async function runSkillToolScript(
|
|
|
40
40
|
context: ToolContext,
|
|
41
41
|
options?: RunSkillToolScriptOptions,
|
|
42
42
|
): Promise<ToolExecutionResult> {
|
|
43
|
-
if (options?.target === "sandbox") {
|
|
43
|
+
if (options?.target === "sandbox" && !options?.bundled) {
|
|
44
44
|
return runSkillToolScriptSandbox(skillDir, executorPath, input, context, {
|
|
45
45
|
timeoutMs: options.timeoutMs,
|
|
46
46
|
expectedSkillVersionHash: options.expectedSkillVersionHash,
|
|
@@ -18,7 +18,7 @@ import { credentialStoreTool } from "./credentials/vault.js";
|
|
|
18
18
|
import { fileEditTool } from "./filesystem/edit.js";
|
|
19
19
|
import { fileReadTool } from "./filesystem/read.js";
|
|
20
20
|
import { fileWriteTool } from "./filesystem/write.js";
|
|
21
|
-
import {
|
|
21
|
+
import { recallTool, rememberTool } from "./memory/register.js";
|
|
22
22
|
import { webFetchTool } from "./network/web-fetch.js";
|
|
23
23
|
import { webSearchTool } from "./network/web-search.js";
|
|
24
24
|
import { skillExecuteTool } from "./skills/execute.js";
|
|
@@ -82,8 +82,8 @@ export const explicitTools: Tool[] = [
|
|
|
82
82
|
skillLoadTool,
|
|
83
83
|
requestSystemPermissionTool,
|
|
84
84
|
// Always-explicit tools
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
rememberTool,
|
|
86
|
+
recallTool,
|
|
87
87
|
credentialStoreTool,
|
|
88
88
|
];
|
|
89
89
|
|
package/src/util/browser.ts
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { getLogger } from "./logger.js";
|
|
5
|
+
import { getSignalsDir } from "./platform.js";
|
|
6
|
+
|
|
7
|
+
const log = getLogger("browser");
|
|
2
8
|
|
|
3
9
|
/**
|
|
4
|
-
* Open a URL
|
|
5
|
-
*
|
|
10
|
+
* Open a URL on the user's host machine.
|
|
11
|
+
*
|
|
12
|
+
* Writes an `open_url` event to the `signals/emit-event` file so that the
|
|
13
|
+
* daemon's ConfigWatcher picks it up and publishes it to connected clients
|
|
14
|
+
* (e.g. the Swift macOS app) via the assistant event hub.
|
|
6
15
|
*/
|
|
7
|
-
export function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
export async function openInHostBrowser(url: string): Promise<void> {
|
|
17
|
+
try {
|
|
18
|
+
const signalsDir = getSignalsDir();
|
|
19
|
+
mkdirSync(signalsDir, { recursive: true });
|
|
20
|
+
writeFileSync(
|
|
21
|
+
join(signalsDir, "emit-event"),
|
|
22
|
+
JSON.stringify({ type: "open_url", url }),
|
|
23
|
+
);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
log.warn(
|
|
26
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
27
|
+
"Failed to write open_url signal",
|
|
28
|
+
);
|
|
14
29
|
}
|
|
15
30
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for locating or JIT-installing a standalone `bun` binary.
|
|
3
|
+
*
|
|
4
|
+
* Several subsystems (package resolver, hook runner, browser runtime,
|
|
5
|
+
* credential execution, embedding runtime) need to spawn `bun` as a child
|
|
6
|
+
* process. Inside a `bun build --compile` binary, `process.execPath` is the
|
|
7
|
+
* compiled app — not the bun CLI — and the user may not have bun on PATH.
|
|
8
|
+
*
|
|
9
|
+
* This module checks well-known locations first, and if none is found it
|
|
10
|
+
* downloads a pinned release from GitHub into $VELLUM_WORKSPACE_DIR/bin/.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
chmodSync,
|
|
15
|
+
existsSync,
|
|
16
|
+
mkdirSync,
|
|
17
|
+
renameSync,
|
|
18
|
+
rmSync,
|
|
19
|
+
writeFileSync,
|
|
20
|
+
} from "node:fs";
|
|
21
|
+
import { arch, homedir, platform } from "node:os";
|
|
22
|
+
import { basename, join } from "node:path";
|
|
23
|
+
|
|
24
|
+
import { getLogger } from "./logger.js";
|
|
25
|
+
import { getBinDir } from "./platform.js";
|
|
26
|
+
|
|
27
|
+
const log = getLogger("bun-runtime");
|
|
28
|
+
|
|
29
|
+
/** Pinned bun version to download when no system bun is available. */
|
|
30
|
+
const BUN_VERSION = "1.2.0";
|
|
31
|
+
|
|
32
|
+
/** Module-level cache so we only resolve/download once per process. */
|
|
33
|
+
let cachedBunPath: string | undefined;
|
|
34
|
+
|
|
35
|
+
/** In-flight download promise to deduplicate concurrent callers. */
|
|
36
|
+
let inflightDownload: Promise<string> | undefined;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Return a path to a usable `bun` binary, downloading one if necessary.
|
|
40
|
+
*
|
|
41
|
+
* Resolution order:
|
|
42
|
+
* 1. `process.execPath` if it IS the bun CLI (dev mode)
|
|
43
|
+
* 2. Previously downloaded copy at $VELLUM_WORKSPACE_DIR/bin/bun
|
|
44
|
+
* 3. Common install locations (~/.bun/bin/bun, /opt/homebrew/bin/bun, etc.)
|
|
45
|
+
* 4. `Bun.which("bun")` (PATH lookup)
|
|
46
|
+
* 5. Download from GitHub releases into $VELLUM_WORKSPACE_DIR/bin/
|
|
47
|
+
*/
|
|
48
|
+
export async function ensureBun(): Promise<string> {
|
|
49
|
+
if (cachedBunPath && existsSync(cachedBunPath)) {
|
|
50
|
+
return cachedBunPath;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const found = findBun();
|
|
54
|
+
if (found) {
|
|
55
|
+
cachedBunPath = found;
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// No bun found anywhere — download it.
|
|
60
|
+
// Use an in-flight promise to deduplicate concurrent callers.
|
|
61
|
+
if (!inflightDownload) {
|
|
62
|
+
log.info("No bun binary found, downloading…");
|
|
63
|
+
const binDir = getBinDir();
|
|
64
|
+
inflightDownload = downloadBun(binDir).finally(() => {
|
|
65
|
+
inflightDownload = undefined;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const downloaded = await inflightDownload;
|
|
69
|
+
cachedBunPath = downloaded;
|
|
70
|
+
return downloaded;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Synchronous check for an already-available bun binary.
|
|
75
|
+
* Returns the path if found, undefined otherwise. Does NOT download.
|
|
76
|
+
*/
|
|
77
|
+
export function findBun(): string | undefined {
|
|
78
|
+
// 1. process.execPath if it is the bun CLI itself (dev mode)
|
|
79
|
+
const execBase = basename(process.execPath);
|
|
80
|
+
if (execBase === "bun" || execBase === "bun.exe") {
|
|
81
|
+
return process.execPath;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 2. Previously downloaded copy
|
|
85
|
+
const downloaded = join(getBinDir(), "bun");
|
|
86
|
+
if (existsSync(downloaded)) return downloaded;
|
|
87
|
+
|
|
88
|
+
// 3. Common install locations
|
|
89
|
+
const home = homedir();
|
|
90
|
+
for (const p of [
|
|
91
|
+
join(home, ".bun", "bin", "bun"),
|
|
92
|
+
"/opt/homebrew/bin/bun",
|
|
93
|
+
"/usr/local/bin/bun",
|
|
94
|
+
]) {
|
|
95
|
+
if (existsSync(p)) return p;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 4. PATH lookup
|
|
99
|
+
const which = Bun.which("bun");
|
|
100
|
+
if (which) return which;
|
|
101
|
+
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Download a pinned bun release into the given directory.
|
|
107
|
+
* Returns the absolute path to the downloaded binary.
|
|
108
|
+
*/
|
|
109
|
+
async function downloadBun(installDir: string): Promise<string> {
|
|
110
|
+
const os = platform();
|
|
111
|
+
const cpu = arch() === "arm64" ? "aarch64" : arch();
|
|
112
|
+
const target = `${os}-${cpu}`;
|
|
113
|
+
const url = `https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-${target}.zip`;
|
|
114
|
+
|
|
115
|
+
log.info({ url, target, bunVersion: BUN_VERSION }, "Downloading bun binary");
|
|
116
|
+
|
|
117
|
+
const response = await fetch(url, { redirect: "follow" });
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Failed to download bun: ${response.status} ${response.statusText}`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const zipData = await response.arrayBuffer();
|
|
125
|
+
mkdirSync(installDir, { recursive: true });
|
|
126
|
+
|
|
127
|
+
const tmpZip = join(installDir, `bun-download-${Date.now()}.zip`);
|
|
128
|
+
writeFileSync(tmpZip, Buffer.from(zipData));
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const proc = Bun.spawn({
|
|
132
|
+
cmd: ["unzip", "-o", tmpZip, "-d", installDir],
|
|
133
|
+
stdout: "ignore",
|
|
134
|
+
stderr: "pipe",
|
|
135
|
+
});
|
|
136
|
+
await proc.exited;
|
|
137
|
+
if (proc.exitCode !== 0) {
|
|
138
|
+
const stderr = await new Response(proc.stderr).text();
|
|
139
|
+
throw new Error(`Failed to extract bun zip: ${stderr}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Move binary from bun-{target}/bun to installDir/bun
|
|
143
|
+
const extractedBun = join(installDir, `bun-${target}`, "bun");
|
|
144
|
+
const finalPath = join(installDir, "bun");
|
|
145
|
+
if (existsSync(extractedBun)) {
|
|
146
|
+
// Remove old binary first to avoid "Text file busy" on some systems
|
|
147
|
+
if (existsSync(finalPath)) {
|
|
148
|
+
rmSync(finalPath);
|
|
149
|
+
}
|
|
150
|
+
renameSync(extractedBun, finalPath);
|
|
151
|
+
rmSync(join(installDir, `bun-${target}`), {
|
|
152
|
+
recursive: true,
|
|
153
|
+
force: true,
|
|
154
|
+
});
|
|
155
|
+
} else if (!existsSync(finalPath)) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`Bun binary not found at expected path after extraction: ${extractedBun}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
chmodSync(finalPath, 0o755);
|
|
162
|
+
|
|
163
|
+
log.info({ path: finalPath }, "Bun binary downloaded successfully");
|
|
164
|
+
return finalPath;
|
|
165
|
+
} finally {
|
|
166
|
+
try {
|
|
167
|
+
rmSync(tmpZip);
|
|
168
|
+
} catch {
|
|
169
|
+
/* ignore cleanup failure */
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|