@vellumai/assistant 0.5.16 → 0.6.1
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/AGENTS.md +4 -0
- package/ARCHITECTURE.md +69 -16
- package/Dockerfile +2 -5
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +32 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/knip.json +2 -1
- package/openapi.yaml +1198 -83
- package/package.json +5 -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 +217 -98
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- 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__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +63 -9
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/config-schema.test.ts +6 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -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 +13 -6
- package/src/__tests__/conversation-agent-loop.test.ts +13 -51
- 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 +6 -1
- 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 +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +13 -414
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- 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 +2 -0
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- 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 +192 -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 +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +178 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +293 -0
- 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 +17 -28
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +103 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +74 -111
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +134 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/onboarding-template-contract.test.ts +62 -14
- 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 +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +3 -3
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- 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-host-parity.test.ts +5 -4
- 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__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +422 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +44 -9
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- 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 +23 -11
- package/src/__tests__/skill-memory.test.ts +2 -741
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +185 -241
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/terminal-tools.test.ts +17 -27
- package/src/__tests__/test-preload.ts +7 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-executor.test.ts +4 -26
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- 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 +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/__tests__/run-assistant-command.ts +29 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +37 -84
- package/src/cli/commands/notifications.ts +7 -2
- 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__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +25 -11
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +218 -36
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +1 -120
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
- 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 +4 -12
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +17 -18
- 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/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/slack/SKILL.md +3 -7
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +78 -8
- package/src/config/feature-flag-registry.json +38 -125
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +14 -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 +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +79 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
- package/src/daemon/conversation-agent-loop.ts +236 -108
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +36 -9
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +13 -7
- package/src/daemon/conversation-runtime-assembly.ts +305 -306
- package/src/daemon/conversation-tool-setup.ts +44 -14
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +59 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +4 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +85 -17
- package/src/daemon/handlers/skills.ts +416 -209
- package/src/daemon/lifecycle.ts +212 -131
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +29 -7
- package/src/daemon/message-types/messages.ts +12 -2
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +6 -0
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +100 -11
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +50 -8
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +97 -7
- 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/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +42 -75
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +3 -1
- package/src/memory/conversation-crud.ts +211 -288
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +61 -13
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +194 -361
- 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 +521 -0
- package/src/memory/graph/capability-seed.ts +449 -0
- package/src/memory/graph/consolidation.ts +725 -0
- package/src/memory/graph/conversation-graph-memory.ts +659 -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 +74 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1297 -0
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +280 -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 +469 -0
- package/src/memory/graph/inspect.ts +543 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1111 -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 +1098 -0
- package/src/memory/graph/store.ts +838 -0
- package/src/memory/graph/tool-handlers.ts +301 -0
- package/src/memory/graph/tools.ts +97 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +295 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +32 -42
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- 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 +21 -31
- package/src/memory/jobs-worker.ts +180 -129
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -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/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +154 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +58 -61
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +95 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +36 -4
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/workspace-policy.ts +10 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +62 -36
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +70 -165
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +25 -4
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +136 -220
- 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/route-policy.ts +30 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +55 -5
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +22 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
- package/src/runtime/routes/conversation-management-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +264 -44
- 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/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- 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/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export-routes.ts +23 -275
- package/src/runtime/routes/memory-item-routes.test.ts +170 -247
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +28 -11
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +52 -18
- package/src/security/oauth2.ts +1 -1
- 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 +25 -16
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +29 -18
- package/src/skills/skill-memory.ts +12 -229
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +7 -5
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +85 -1
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +17 -1
- package/src/tools/tool-manifest.ts +9 -3
- package/src/tools/types.ts +2 -0
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- 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/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +84 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -372
- package/src/__tests__/clipboard.test.ts +0 -88
- 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/cli/cli-memory.ts +0 -176
- 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 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- 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 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- 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 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
- package/src/util/clipboard.ts +0 -34
|
@@ -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
|
};
|
|
@@ -78,3 +78,20 @@ export interface EditOutput {
|
|
|
78
78
|
export type EditResult =
|
|
79
79
|
| { ok: true; value: EditOutput }
|
|
80
80
|
| { ok: false; error: FsError };
|
|
81
|
+
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// List
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
export interface ListInput {
|
|
87
|
+
path: string;
|
|
88
|
+
glob?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface ListOutput {
|
|
92
|
+
listing: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type ListResult =
|
|
96
|
+
| { ok: true; value: ListOutput }
|
|
97
|
+
| { ok: false; error: FsError };
|
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
export const MAX_OUTPUT_LENGTH = 20_000;
|
|
7
|
+
|
|
8
|
+
/** Tracks temp files created for truncated shell output so they can be cleaned up on shutdown. */
|
|
9
|
+
const trackedTempFiles = new Set<string>();
|
|
10
|
+
|
|
11
|
+
/** Remove all tracked truncated-output temp files. Safe to call multiple times. */
|
|
12
|
+
export function cleanupShellOutputTempFiles(): void {
|
|
13
|
+
for (const filePath of trackedTempFiles) {
|
|
14
|
+
try {
|
|
15
|
+
unlinkSync(filePath);
|
|
16
|
+
} catch {
|
|
17
|
+
// File may already be gone — ignore.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
trackedTempFiles.clear();
|
|
21
|
+
}
|
|
2
22
|
|
|
3
23
|
export interface ShellOutputResult {
|
|
4
24
|
content: string;
|
|
@@ -33,7 +53,16 @@ export function formatShellOutput(
|
|
|
33
53
|
}
|
|
34
54
|
|
|
35
55
|
if (output.length > MAX_OUTPUT_LENGTH) {
|
|
36
|
-
|
|
56
|
+
let fullOutputPath: string | undefined;
|
|
57
|
+
try {
|
|
58
|
+
fullOutputPath = join(tmpdir(), `vellum-shell-output-${randomUUID()}.txt`);
|
|
59
|
+
writeFileSync(fullOutputPath, output, { encoding: "utf-8", mode: 0o600 });
|
|
60
|
+
trackedTempFiles.add(fullOutputPath);
|
|
61
|
+
} catch {
|
|
62
|
+
fullOutputPath = undefined;
|
|
63
|
+
}
|
|
64
|
+
const fileAttr = fullOutputPath ? ` file="${fullOutputPath}"` : "";
|
|
65
|
+
const msg = `<output_truncated limit="20K"${fileAttr} />`;
|
|
37
66
|
output = output.slice(0, MAX_OUTPUT_LENGTH) + `\n${msg}`;
|
|
38
67
|
statusParts.push(msg);
|
|
39
68
|
}
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
2
2
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
3
|
+
import { resolveSubagentId } from "./resolve.js";
|
|
3
4
|
|
|
4
5
|
export async function executeSubagentAbort(
|
|
5
6
|
input: Record<string, unknown>,
|
|
6
7
|
context: ToolContext,
|
|
7
8
|
): Promise<ToolExecutionResult> {
|
|
8
|
-
const subagentId = input
|
|
9
|
+
const subagentId = resolveSubagentId(input, context);
|
|
10
|
+
if (!subagentId && input.label) {
|
|
11
|
+
return {
|
|
12
|
+
content: `No subagent found with label "${input.label as string}".`,
|
|
13
|
+
isError: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
9
16
|
if (!subagentId) {
|
|
10
|
-
return {
|
|
17
|
+
return {
|
|
18
|
+
content: '"subagent_id" or "label" is required.',
|
|
19
|
+
isError: true,
|
|
20
|
+
};
|
|
11
21
|
}
|
|
12
22
|
|
|
13
23
|
const manager = getSubagentManager();
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
2
2
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
3
|
+
import { resolveSubagentId } from "./resolve.js";
|
|
3
4
|
|
|
4
5
|
export async function executeSubagentMessage(
|
|
5
6
|
input: Record<string, unknown>,
|
|
6
7
|
context: ToolContext,
|
|
7
8
|
): Promise<ToolExecutionResult> {
|
|
8
|
-
const subagentId = input
|
|
9
|
+
const subagentId = resolveSubagentId(input, context);
|
|
9
10
|
const content = input.content as string;
|
|
10
11
|
|
|
12
|
+
if (!subagentId && input.label) {
|
|
13
|
+
return {
|
|
14
|
+
content: `No subagent found with label "${input.label as string}".`,
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
11
18
|
if (!subagentId || !content) {
|
|
12
19
|
return {
|
|
13
|
-
content: '
|
|
20
|
+
content: '"subagent_id" or "label", and "content" are required.',
|
|
14
21
|
isError: true,
|
|
15
22
|
};
|
|
16
23
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { RiskLevel } from "../../permissions/types.js";
|
|
2
|
+
import type { ToolDefinition } from "../../providers/types.js";
|
|
3
|
+
import { getSubagentManager } from "../../subagent/index.js";
|
|
4
|
+
import { registerTool } from "../registry.js";
|
|
5
|
+
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
6
|
+
|
|
7
|
+
export async function executeSubagentNotifyParent(
|
|
8
|
+
input: Record<string, unknown>,
|
|
9
|
+
context: ToolContext,
|
|
10
|
+
): Promise<ToolExecutionResult> {
|
|
11
|
+
const message = input.message as string;
|
|
12
|
+
const urgency = (input.urgency as string) || "info";
|
|
13
|
+
|
|
14
|
+
if (!message) {
|
|
15
|
+
return { content: '"message" is required.', isError: true };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const manager = getSubagentManager();
|
|
19
|
+
const sent = manager.notifyParent(context.conversationId, message, urgency);
|
|
20
|
+
|
|
21
|
+
if (!sent) {
|
|
22
|
+
return {
|
|
23
|
+
content:
|
|
24
|
+
"Could not notify parent. This tool is only available to subagents.",
|
|
25
|
+
isError: true,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
content: JSON.stringify({ sent: true, urgency }),
|
|
31
|
+
isError: false,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class NotifyParentTool implements Tool {
|
|
36
|
+
name = "notify_parent";
|
|
37
|
+
description =
|
|
38
|
+
"Send a notification to the parent conversation. Use this for important findings, when you're blocked, or when you have preliminary results the parent should know about. Do not overuse — notify for significant findings, not after every tool call.";
|
|
39
|
+
category = "orchestration";
|
|
40
|
+
defaultRiskLevel = RiskLevel.Low;
|
|
41
|
+
|
|
42
|
+
getDefinition(): ToolDefinition {
|
|
43
|
+
return {
|
|
44
|
+
name: this.name,
|
|
45
|
+
description: this.description,
|
|
46
|
+
input_schema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
message: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "The notification content for the parent.",
|
|
52
|
+
},
|
|
53
|
+
urgency: {
|
|
54
|
+
type: "string",
|
|
55
|
+
enum: ["info", "important", "blocked"],
|
|
56
|
+
description:
|
|
57
|
+
"'info' for progress updates, 'important' for key findings, 'blocked' when you need guidance.",
|
|
58
|
+
},
|
|
59
|
+
activity: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description:
|
|
62
|
+
"Brief non-technical explanation of what you are doing and why, shown to the user as a status update.",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ["message", "activity"],
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async execute(
|
|
71
|
+
input: Record<string, unknown>,
|
|
72
|
+
context: ToolContext,
|
|
73
|
+
): Promise<ToolExecutionResult> {
|
|
74
|
+
return executeSubagentNotifyParent(input, context);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const notifyParentTool = new NotifyParentTool();
|
|
79
|
+
registerTool(notifyParentTool);
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { getMessages } from "../../memory/conversation-crud.js";
|
|
2
2
|
import { getSubagentManager, TERMINAL_STATUSES } from "../../subagent/index.js";
|
|
3
3
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
4
|
+
import { resolveSubagentId } from "./resolve.js";
|
|
4
5
|
|
|
5
6
|
export async function executeSubagentRead(
|
|
6
7
|
input: Record<string, unknown>,
|
|
7
8
|
context: ToolContext,
|
|
8
9
|
): Promise<ToolExecutionResult> {
|
|
9
|
-
const subagentId = input
|
|
10
|
+
const subagentId = resolveSubagentId(input, context);
|
|
11
|
+
if (!subagentId && input.label) {
|
|
12
|
+
return {
|
|
13
|
+
content: `No subagent found with label "${input.label as string}".`,
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
10
17
|
if (!subagentId) {
|
|
11
|
-
return {
|
|
18
|
+
return {
|
|
19
|
+
content: '"subagent_id" or "label" is required.',
|
|
20
|
+
isError: true,
|
|
21
|
+
};
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
const manager = getSubagentManager();
|
|
@@ -45,32 +55,43 @@ export async function executeSubagentRead(
|
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
// Extract assistant messages only - that's the subagent's output.
|
|
48
|
-
|
|
58
|
+
// Group text blocks by message so last_n slices messages, not blocks.
|
|
59
|
+
const messageTexts: string[] = [];
|
|
49
60
|
for (const msg of dbMessages) {
|
|
50
61
|
if (msg.role !== "assistant") continue;
|
|
62
|
+
const blocks: string[] = [];
|
|
51
63
|
try {
|
|
52
64
|
const content = JSON.parse(msg.content);
|
|
53
65
|
if (Array.isArray(content)) {
|
|
54
66
|
for (const block of content) {
|
|
55
67
|
if (block.type === "text" && typeof block.text === "string") {
|
|
56
|
-
|
|
68
|
+
blocks.push(block.text);
|
|
57
69
|
}
|
|
58
70
|
}
|
|
59
71
|
} else if (typeof content === "string") {
|
|
60
|
-
|
|
72
|
+
blocks.push(content);
|
|
61
73
|
}
|
|
62
74
|
} catch {
|
|
63
75
|
// Content might be plain text.
|
|
64
|
-
|
|
76
|
+
blocks.push(msg.content);
|
|
77
|
+
}
|
|
78
|
+
if (blocks.length > 0) {
|
|
79
|
+
messageTexts.push(blocks.join("\n\n"));
|
|
65
80
|
}
|
|
66
81
|
}
|
|
67
82
|
|
|
68
|
-
if (
|
|
83
|
+
if (messageTexts.length === 0) {
|
|
69
84
|
return { content: "Subagent produced no text output.", isError: false };
|
|
70
85
|
}
|
|
71
86
|
|
|
87
|
+
const lastN =
|
|
88
|
+
typeof input.last_n === "number" && input.last_n > 0
|
|
89
|
+
? input.last_n
|
|
90
|
+
: undefined;
|
|
91
|
+
const sliced = lastN ? messageTexts.slice(-lastN) : messageTexts;
|
|
92
|
+
|
|
72
93
|
return {
|
|
73
|
-
content:
|
|
94
|
+
content: sliced.join("\n\n"),
|
|
74
95
|
isError: false,
|
|
75
96
|
};
|
|
76
97
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getSubagentManager } from "../../subagent/index.js";
|
|
2
|
+
import type { ToolContext } from "../types.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a subagent ID from tool input.
|
|
6
|
+
* Accepts either `subagent_id` (direct UUID) or `label` (case-insensitive lookup).
|
|
7
|
+
*/
|
|
8
|
+
export function resolveSubagentId(
|
|
9
|
+
input: Record<string, unknown>,
|
|
10
|
+
context: ToolContext,
|
|
11
|
+
): string | undefined {
|
|
12
|
+
if (input.subagent_id) return input.subagent_id as string;
|
|
13
|
+
if (input.label) {
|
|
14
|
+
const state = getSubagentManager().getByLabel(
|
|
15
|
+
input.label as string,
|
|
16
|
+
context.conversationId,
|
|
17
|
+
);
|
|
18
|
+
return state?.config.id;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
@@ -9,6 +9,7 @@ export async function executeSubagentSpawn(
|
|
|
9
9
|
const objective = input.objective as string;
|
|
10
10
|
const extraContext = input.context as string | undefined;
|
|
11
11
|
const sendResultToUser = input.send_result_to_user !== false;
|
|
12
|
+
const role = (input.role as string | undefined) ?? undefined;
|
|
12
13
|
|
|
13
14
|
if (!label || !objective) {
|
|
14
15
|
return {
|
|
@@ -36,6 +37,7 @@ export async function executeSubagentSpawn(
|
|
|
36
37
|
objective,
|
|
37
38
|
context: extraContext,
|
|
38
39
|
sendResultToUser,
|
|
40
|
+
...(role ? { role: role as import("../../subagent/types.js").SubagentRole } : {}),
|
|
39
41
|
},
|
|
40
42
|
sendToClient as (msg: unknown) => void,
|
|
41
43
|
);
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
2
2
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
3
|
+
import { resolveSubagentId } from "./resolve.js";
|
|
3
4
|
|
|
4
5
|
export async function executeSubagentStatus(
|
|
5
6
|
input: Record<string, unknown>,
|
|
6
7
|
context: ToolContext,
|
|
7
8
|
): Promise<ToolExecutionResult> {
|
|
8
|
-
const subagentId = input
|
|
9
|
+
const subagentId = resolveSubagentId(input, context);
|
|
9
10
|
const manager = getSubagentManager();
|
|
10
11
|
|
|
12
|
+
// If a label was provided but didn't resolve, that's an error — don't fall
|
|
13
|
+
// through to the "list all" path.
|
|
14
|
+
if (!subagentId && input.label) {
|
|
15
|
+
return {
|
|
16
|
+
content: `No subagent found with label "${input.label as string}".`,
|
|
17
|
+
isError: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
if (subagentId) {
|
|
12
22
|
const state = manager.getState(subagentId);
|
|
13
23
|
if (
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { generateAvatar } from "../../media/avatar-router.js";
|
|
6
6
|
import { mapGeminiError } from "../../media/gemini-image-service.js";
|
|
7
7
|
import { getLogger } from "../../util/logger.js";
|
|
8
|
-
import {
|
|
8
|
+
import { getAvatarImagePath } from "../../util/platform.js";
|
|
9
9
|
|
|
10
10
|
const log = getLogger("avatar-generator");
|
|
11
11
|
|
|
12
12
|
/** Canonical path where the custom avatar PNG is stored. */
|
|
13
13
|
function getAvatarPath(): string {
|
|
14
|
-
return
|
|
14
|
+
return getAvatarImagePath();
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface AvatarGenerationResult {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers feature-flag-gated system tools with the daemon's tool registry.
|
|
3
|
+
*
|
|
4
|
+
* Called once at daemon startup via initializeTools(). Tools that are always
|
|
5
|
+
* registered (e.g. request_system_permission) are handled via the tool
|
|
6
|
+
* manifest's explicit tools list; this module handles conditional registration.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
10
|
+
import { getConfig } from "../../config/loader.js";
|
|
11
|
+
import { registerTool } from "../registry.js";
|
|
12
|
+
import { setPermissionModeTool } from "./set-permission-mode.js";
|
|
13
|
+
|
|
14
|
+
export function registerSystemTools(): void {
|
|
15
|
+
try {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
if (isAssistantFeatureFlagEnabled("permission-controls-v2", config)) {
|
|
18
|
+
registerTool(setPermissionModeTool);
|
|
19
|
+
}
|
|
20
|
+
} catch {
|
|
21
|
+
// Config not yet loaded (e.g. during test setup) — permission mode tool stays off.
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System tool: set_permission_mode
|
|
3
|
+
*
|
|
4
|
+
* Allows the LLM to deterministically switch permission mode axes via the
|
|
5
|
+
* PermissionModeStore rather than relying on model-generated text.
|
|
6
|
+
*
|
|
7
|
+
* This tool is always available (no permission check required) when the
|
|
8
|
+
* `permission-controls-v2` feature flag is enabled — it IS the permission
|
|
9
|
+
* mechanism.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
getMode,
|
|
14
|
+
setAskBeforeActing,
|
|
15
|
+
setHostAccess,
|
|
16
|
+
} from "../../permissions/permission-mode-store.js";
|
|
17
|
+
import { RiskLevel } from "../../permissions/types.js";
|
|
18
|
+
import type { ToolDefinition } from "../../providers/types.js";
|
|
19
|
+
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
20
|
+
|
|
21
|
+
class SetPermissionModeTool implements Tool {
|
|
22
|
+
name = "set_permission_mode";
|
|
23
|
+
description =
|
|
24
|
+
"Change the assistant's permission mode. Supports partial updates — " +
|
|
25
|
+
"only the provided fields are changed. Use this to toggle whether the " +
|
|
26
|
+
"assistant asks before acting or whether host access is enabled.";
|
|
27
|
+
category = "system";
|
|
28
|
+
defaultRiskLevel = RiskLevel.Low;
|
|
29
|
+
|
|
30
|
+
getDefinition(): ToolDefinition {
|
|
31
|
+
return {
|
|
32
|
+
name: this.name,
|
|
33
|
+
description: this.description,
|
|
34
|
+
input_schema: {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
askBeforeActing: {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
description:
|
|
40
|
+
"When true, the assistant checks in with the user before taking actions.",
|
|
41
|
+
},
|
|
42
|
+
hostAccess: {
|
|
43
|
+
type: "boolean",
|
|
44
|
+
description:
|
|
45
|
+
"When true, the assistant can execute commands on the host machine without prompting.",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async execute(
|
|
53
|
+
input: Record<string, unknown>,
|
|
54
|
+
_context: ToolContext,
|
|
55
|
+
): Promise<ToolExecutionResult> {
|
|
56
|
+
const { askBeforeActing, hostAccess } = input;
|
|
57
|
+
|
|
58
|
+
// Validate that at least one field is provided
|
|
59
|
+
if (askBeforeActing === undefined && hostAccess === undefined) {
|
|
60
|
+
return {
|
|
61
|
+
content:
|
|
62
|
+
"Error: at least one of askBeforeActing or hostAccess must be provided.",
|
|
63
|
+
isError: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate types of provided fields
|
|
68
|
+
if (askBeforeActing !== undefined && typeof askBeforeActing !== "boolean") {
|
|
69
|
+
return {
|
|
70
|
+
content: `Error: askBeforeActing must be a boolean, got ${typeof askBeforeActing}.`,
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (hostAccess !== undefined && typeof hostAccess !== "boolean") {
|
|
75
|
+
return {
|
|
76
|
+
content: `Error: hostAccess must be a boolean, got ${typeof hostAccess}.`,
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Apply changes for provided fields
|
|
82
|
+
if (typeof askBeforeActing === "boolean") {
|
|
83
|
+
setAskBeforeActing(askBeforeActing);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (typeof hostAccess === "boolean") {
|
|
87
|
+
setHostAccess(hostAccess);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Return confirmation with the new state
|
|
91
|
+
const mode = getMode();
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
"Permission mode updated.",
|
|
95
|
+
` askBeforeActing: ${mode.askBeforeActing}`,
|
|
96
|
+
` hostAccess: ${mode.hostAccess}`,
|
|
97
|
+
].join("\n"),
|
|
98
|
+
isError: false,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const setPermissionModeTool = new SetPermissionModeTool();
|