@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
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the set_permission_mode system tool.
|
|
3
|
+
*
|
|
4
|
+
* Verifies:
|
|
5
|
+
* - Mode transitions via askBeforeActing and hostAccess
|
|
6
|
+
* - Partial updates (only provided fields change)
|
|
7
|
+
* - Idempotent calls (setting same value is safe)
|
|
8
|
+
* - Error when no fields provided
|
|
9
|
+
* - Tool is not registered when permission-controls-v2 flag is off
|
|
10
|
+
* - Tool is registered when permission-controls-v2 flag is on
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import {
|
|
16
|
+
afterAll,
|
|
17
|
+
afterEach,
|
|
18
|
+
beforeEach,
|
|
19
|
+
describe,
|
|
20
|
+
expect,
|
|
21
|
+
mock,
|
|
22
|
+
test,
|
|
23
|
+
} from "bun:test";
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Mocks — declared before imports that depend on platform/logger
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
30
|
+
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
31
|
+
|
|
32
|
+
function ensureTestDir(): void {
|
|
33
|
+
const dirs = [
|
|
34
|
+
WORKSPACE_DIR,
|
|
35
|
+
join(WORKSPACE_DIR, "data"),
|
|
36
|
+
join(WORKSPACE_DIR, "data", "logs"),
|
|
37
|
+
];
|
|
38
|
+
for (const dir of dirs) {
|
|
39
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function makeLoggerStub(): Record<string, unknown> {
|
|
44
|
+
const stub: Record<string, unknown> = {};
|
|
45
|
+
for (const m of [
|
|
46
|
+
"info",
|
|
47
|
+
"warn",
|
|
48
|
+
"error",
|
|
49
|
+
"debug",
|
|
50
|
+
"trace",
|
|
51
|
+
"fatal",
|
|
52
|
+
"silent",
|
|
53
|
+
"child",
|
|
54
|
+
]) {
|
|
55
|
+
stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
|
|
56
|
+
}
|
|
57
|
+
return stub;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
mock.module("../util/logger.js", () => ({
|
|
61
|
+
getLogger: () => makeLoggerStub(),
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
afterAll(() => {
|
|
65
|
+
mock.restore();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
69
|
+
import { invalidateConfigCache } from "../config/loader.js";
|
|
70
|
+
import {
|
|
71
|
+
getMode,
|
|
72
|
+
resetForTesting,
|
|
73
|
+
} from "../permissions/permission-mode-store.js";
|
|
74
|
+
import { __clearRegistryForTesting, getTool } from "../tools/registry.js";
|
|
75
|
+
import { registerSystemTools } from "../tools/system/register.js";
|
|
76
|
+
import { setPermissionModeTool } from "../tools/system/set-permission-mode.js";
|
|
77
|
+
import type { ToolContext } from "../tools/types.js";
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Helpers
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
function writeConfig(obj: unknown): void {
|
|
84
|
+
ensureTestDir();
|
|
85
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(obj, null, 2) + "\n");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function makeContext(): ToolContext {
|
|
89
|
+
return {
|
|
90
|
+
workingDir: WORKSPACE_DIR,
|
|
91
|
+
conversationId: "test-conversation",
|
|
92
|
+
trustClass: "guardian",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Setup / teardown
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
beforeEach(() => {
|
|
101
|
+
ensureTestDir();
|
|
102
|
+
resetForTesting();
|
|
103
|
+
invalidateConfigCache();
|
|
104
|
+
_setOverridesForTesting({});
|
|
105
|
+
__clearRegistryForTesting();
|
|
106
|
+
// Write a minimal config so the store initializes cleanly
|
|
107
|
+
writeConfig({});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
afterEach(() => {
|
|
111
|
+
resetForTesting();
|
|
112
|
+
invalidateConfigCache();
|
|
113
|
+
_setOverridesForTesting({});
|
|
114
|
+
__clearRegistryForTesting();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Tests — tool execution
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
describe("set_permission_mode tool", () => {
|
|
122
|
+
describe("mode transitions", () => {
|
|
123
|
+
test("sets askBeforeActing to false", async () => {
|
|
124
|
+
const result = await setPermissionModeTool.execute(
|
|
125
|
+
{ askBeforeActing: false },
|
|
126
|
+
makeContext(),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(result.isError).toBe(false);
|
|
130
|
+
expect(result.content).toContain("askBeforeActing: false");
|
|
131
|
+
|
|
132
|
+
const mode = getMode();
|
|
133
|
+
expect(mode.askBeforeActing).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("sets hostAccess to true", async () => {
|
|
137
|
+
const result = await setPermissionModeTool.execute(
|
|
138
|
+
{ hostAccess: true },
|
|
139
|
+
makeContext(),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
expect(result.isError).toBe(false);
|
|
143
|
+
expect(result.content).toContain("hostAccess: true");
|
|
144
|
+
|
|
145
|
+
const mode = getMode();
|
|
146
|
+
expect(mode.hostAccess).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("sets both fields at once", async () => {
|
|
150
|
+
const result = await setPermissionModeTool.execute(
|
|
151
|
+
{ askBeforeActing: false, hostAccess: true },
|
|
152
|
+
makeContext(),
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
expect(result.isError).toBe(false);
|
|
156
|
+
expect(result.content).toContain("askBeforeActing: false");
|
|
157
|
+
expect(result.content).toContain("hostAccess: true");
|
|
158
|
+
|
|
159
|
+
const mode = getMode();
|
|
160
|
+
expect(mode.askBeforeActing).toBe(false);
|
|
161
|
+
expect(mode.hostAccess).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe("partial updates", () => {
|
|
166
|
+
test("only askBeforeActing changes, hostAccess unchanged", async () => {
|
|
167
|
+
await setPermissionModeTool.execute(
|
|
168
|
+
{ askBeforeActing: false },
|
|
169
|
+
makeContext(),
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const mode = getMode();
|
|
173
|
+
expect(mode.askBeforeActing).toBe(false);
|
|
174
|
+
// hostAccess should remain at default (false)
|
|
175
|
+
expect(mode.hostAccess).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("only hostAccess changes, askBeforeActing unchanged", async () => {
|
|
179
|
+
await setPermissionModeTool.execute({ hostAccess: true }, makeContext());
|
|
180
|
+
|
|
181
|
+
const mode = getMode();
|
|
182
|
+
// askBeforeActing should remain at default (true)
|
|
183
|
+
expect(mode.askBeforeActing).toBe(true);
|
|
184
|
+
expect(mode.hostAccess).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe("idempotent calls", () => {
|
|
189
|
+
test("setting askBeforeActing to current value is safe", async () => {
|
|
190
|
+
// Default is true
|
|
191
|
+
const result = await setPermissionModeTool.execute(
|
|
192
|
+
{ askBeforeActing: true },
|
|
193
|
+
makeContext(),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
expect(result.isError).toBe(false);
|
|
197
|
+
expect(getMode().askBeforeActing).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("setting hostAccess to current value is safe", async () => {
|
|
201
|
+
// Default is false
|
|
202
|
+
const result = await setPermissionModeTool.execute(
|
|
203
|
+
{ hostAccess: false },
|
|
204
|
+
makeContext(),
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
expect(result.isError).toBe(false);
|
|
208
|
+
expect(getMode().hostAccess).toBe(false);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("repeated calls produce same result", async () => {
|
|
212
|
+
await setPermissionModeTool.execute(
|
|
213
|
+
{ askBeforeActing: false, hostAccess: true },
|
|
214
|
+
makeContext(),
|
|
215
|
+
);
|
|
216
|
+
const result = await setPermissionModeTool.execute(
|
|
217
|
+
{ askBeforeActing: false, hostAccess: true },
|
|
218
|
+
makeContext(),
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(result.isError).toBe(false);
|
|
222
|
+
const mode = getMode();
|
|
223
|
+
expect(mode.askBeforeActing).toBe(false);
|
|
224
|
+
expect(mode.hostAccess).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
describe("validation", () => {
|
|
229
|
+
test("returns error when no fields provided", async () => {
|
|
230
|
+
const result = await setPermissionModeTool.execute({}, makeContext());
|
|
231
|
+
|
|
232
|
+
expect(result.isError).toBe(true);
|
|
233
|
+
expect(result.content).toContain("at least one");
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe("tool definition", () => {
|
|
238
|
+
test("has correct name", () => {
|
|
239
|
+
expect(setPermissionModeTool.name).toBe("set_permission_mode");
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("has correct category", () => {
|
|
243
|
+
expect(setPermissionModeTool.category).toBe("system");
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("definition includes both properties", () => {
|
|
247
|
+
const def = setPermissionModeTool.getDefinition();
|
|
248
|
+
const schema = def.input_schema as { properties?: Record<string, unknown> };
|
|
249
|
+
const props = schema.properties as Record<string, unknown>;
|
|
250
|
+
expect(props).toHaveProperty("askBeforeActing");
|
|
251
|
+
expect(props).toHaveProperty("hostAccess");
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// Tests — feature flag gating
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
|
|
260
|
+
describe("set_permission_mode registration", () => {
|
|
261
|
+
test("tool is NOT registered when permission-controls-v2 flag is off", () => {
|
|
262
|
+
_setOverridesForTesting({ "permission-controls-v2": false });
|
|
263
|
+
registerSystemTools();
|
|
264
|
+
|
|
265
|
+
expect(getTool("set_permission_mode")).toBeUndefined();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("tool IS registered when permission-controls-v2 flag is on", () => {
|
|
269
|
+
_setOverridesForTesting({ "permission-controls-v2": true });
|
|
270
|
+
registerSystemTools();
|
|
271
|
+
|
|
272
|
+
expect(getTool("set_permission_mode")).toBeDefined();
|
|
273
|
+
});
|
|
274
|
+
});
|
|
@@ -28,16 +28,16 @@ import { parseFrontmatterFields } from "../skills/frontmatter.js";
|
|
|
28
28
|
// Fixtures
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
|
|
31
|
-
/** A SKILL.md with `feature-flag:
|
|
31
|
+
/** A SKILL.md with `feature-flag: email-channel` declared in its vellum metadata. */
|
|
32
32
|
const SKILL_MD_WITH_FLAG = `---
|
|
33
|
-
name: "
|
|
34
|
-
description: "
|
|
33
|
+
name: "Email Setup"
|
|
34
|
+
description: "Set up email integration"
|
|
35
35
|
metadata:
|
|
36
36
|
vellum:
|
|
37
|
-
feature-flag:
|
|
37
|
+
feature-flag: email-channel
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
-
Instructions for the
|
|
40
|
+
Instructions for the email setup skill.
|
|
41
41
|
`;
|
|
42
42
|
|
|
43
43
|
/** A SKILL.md with no feature-flag field at all. */
|
|
@@ -128,16 +128,16 @@ describe("frontmatter feature-flag integration", () => {
|
|
|
128
128
|
expect(metadataObj).toBeTruthy();
|
|
129
129
|
|
|
130
130
|
const vellum = metadataObj.vellum as Record<string, unknown>;
|
|
131
|
-
expect(vellum["feature-flag"]).toBe("
|
|
131
|
+
expect(vellum["feature-flag"]).toBe("email-channel");
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
test("skillFlagKey returns correct key for parsed skill", () => {
|
|
135
|
-
const skill = buildSkillSummary("
|
|
135
|
+
const skill = buildSkillSummary("email-setup", SKILL_MD_WITH_FLAG);
|
|
136
136
|
expect(skill).not.toBeNull();
|
|
137
|
-
expect(skill!.featureFlag).toBe("
|
|
137
|
+
expect(skill!.featureFlag).toBe("email-channel");
|
|
138
138
|
|
|
139
139
|
const key = skillFlagKey(skill!);
|
|
140
|
-
expect(key).toBe("
|
|
140
|
+
expect(key).toBe("email-channel");
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
test("skillFlagKey returns undefined for skill without feature-flag", () => {
|
|
@@ -149,27 +149,26 @@ describe("frontmatter feature-flag integration", () => {
|
|
|
149
149
|
expect(key).toBeUndefined();
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
test("resolveSkillStates includes skill with featureFlag when flag
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
test("resolveSkillStates includes skill with featureFlag when flag is ON", () => {
|
|
153
|
+
_setOverridesForTesting({
|
|
154
|
+
"email-channel": true,
|
|
155
|
+
});
|
|
156
|
+
const skill = buildSkillSummary("email-setup", SKILL_MD_WITH_FLAG)!;
|
|
155
157
|
const config = makeConfig();
|
|
156
158
|
|
|
157
159
|
const resolved = resolveSkillStates([skill], config);
|
|
158
|
-
// Flag defaults to true → skill passes through
|
|
159
160
|
expect(resolved.length).toBe(1);
|
|
160
|
-
expect(resolved[0].summary.id).toBe("
|
|
161
|
+
expect(resolved[0].summary.id).toBe("email-setup");
|
|
161
162
|
});
|
|
162
163
|
|
|
163
|
-
test("resolveSkillStates
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
});
|
|
167
|
-
const skill = buildSkillSummary("contacts", SKILL_MD_WITH_FLAG)!;
|
|
164
|
+
test("resolveSkillStates excludes skill with featureFlag when flag defaults to OFF", () => {
|
|
165
|
+
const skill = buildSkillSummary("email-setup", SKILL_MD_WITH_FLAG)!;
|
|
166
|
+
// "email-channel" is in the registry with defaultEnabled: false
|
|
168
167
|
const config = makeConfig();
|
|
169
168
|
|
|
170
169
|
const resolved = resolveSkillStates([skill], config);
|
|
171
|
-
|
|
172
|
-
expect(resolved
|
|
170
|
+
// Flag defaults to false → skill is filtered out
|
|
171
|
+
expect(resolved.length).toBe(0);
|
|
173
172
|
});
|
|
174
173
|
|
|
175
174
|
test("resolveSkillStates never gates skill without featureFlag", () => {
|
|
@@ -192,26 +191,34 @@ describe("frontmatter feature-flag integration", () => {
|
|
|
192
191
|
const metadataObj = parsed!.fields.metadata as Record<string, unknown>;
|
|
193
192
|
const vellum = metadataObj.vellum as Record<string, unknown>;
|
|
194
193
|
const flagId = vellum["feature-flag"];
|
|
195
|
-
expect(flagId).toBe("
|
|
194
|
+
expect(flagId).toBe("email-channel");
|
|
196
195
|
|
|
197
196
|
// Step 2: Build SkillSummary (as the catalog loader would)
|
|
198
|
-
const skill = buildSkillSummary("
|
|
199
|
-
expect(skill.featureFlag).toBe("
|
|
197
|
+
const skill = buildSkillSummary("email-setup", SKILL_MD_WITH_FLAG)!;
|
|
198
|
+
expect(skill.featureFlag).toBe("email-channel");
|
|
200
199
|
|
|
201
200
|
// Step 3: Derive the flag key
|
|
202
201
|
const key = skillFlagKey(skill);
|
|
203
|
-
expect(key).toBe("
|
|
202
|
+
expect(key).toBe("email-channel");
|
|
204
203
|
|
|
205
|
-
// Step 4: Check flag state — "
|
|
204
|
+
// Step 4: Check flag state — "email-channel" has defaultEnabled: false in registry
|
|
206
205
|
const configDefault = makeConfig();
|
|
207
|
-
expect(isAssistantFeatureFlagEnabled(key!, configDefault)).toBe(
|
|
206
|
+
expect(isAssistantFeatureFlagEnabled(key!, configDefault)).toBe(false);
|
|
208
207
|
|
|
209
|
-
// Step 5: resolveSkillStates
|
|
208
|
+
// Step 5: resolveSkillStates excludes it by default (flag is off)
|
|
210
209
|
const resolvedDefault = resolveSkillStates([skill], configDefault);
|
|
211
|
-
expect(resolvedDefault.length).toBe(
|
|
212
|
-
|
|
210
|
+
expect(resolvedDefault.length).toBe(0);
|
|
211
|
+
|
|
212
|
+
// Step 6: With override enabled, skill passes through
|
|
213
|
+
_setOverridesForTesting({ [key!]: true });
|
|
214
|
+
const configOn = makeConfig();
|
|
215
|
+
expect(isAssistantFeatureFlagEnabled(key!, configOn)).toBe(true);
|
|
216
|
+
|
|
217
|
+
const resolvedOn = resolveSkillStates([skill], configOn);
|
|
218
|
+
expect(resolvedOn.length).toBe(1);
|
|
219
|
+
expect(resolvedOn[0].summary.id).toBe("email-setup");
|
|
213
220
|
|
|
214
|
-
// Step
|
|
221
|
+
// Step 7: With override disabled, skill is filtered out
|
|
215
222
|
_setOverridesForTesting({ [key!]: false });
|
|
216
223
|
const configOff = makeConfig();
|
|
217
224
|
expect(isAssistantFeatureFlagEnabled(key!, configOff)).toBe(false);
|
|
@@ -16,9 +16,9 @@ afterEach(() => {
|
|
|
16
16
|
_setOverridesForTesting({});
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
const DECLARED_FLAG_ID = "
|
|
19
|
+
const DECLARED_FLAG_ID = "sounds";
|
|
20
20
|
const DECLARED_FLAG_KEY = DECLARED_FLAG_ID;
|
|
21
|
-
const DECLARED_SKILL_ID = "
|
|
21
|
+
const DECLARED_SKILL_ID = "sounds";
|
|
22
22
|
const APP_BUILDER_MULTIFILE_FLAG_KEY = "app-builder-multifile";
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
// Helpers
|
|
@@ -144,7 +144,7 @@ describe("isAssistantFeatureFlagEnabled", () => {
|
|
|
144
144
|
|
|
145
145
|
test("falls back to registry default when no override", () => {
|
|
146
146
|
const config = makeConfig();
|
|
147
|
-
//
|
|
147
|
+
// sounds defaults to true in the registry
|
|
148
148
|
expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(true);
|
|
149
149
|
});
|
|
150
150
|
|
|
@@ -214,7 +214,7 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
214
214
|
const config = makeConfig();
|
|
215
215
|
|
|
216
216
|
const resolved = resolveSkillStates(catalog, config);
|
|
217
|
-
//
|
|
217
|
+
// sounds registry default is true, so it passes through
|
|
218
218
|
expect(resolved.length).toBe(1);
|
|
219
219
|
expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
|
|
220
220
|
});
|
|
@@ -272,7 +272,7 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
272
272
|
const resolved = resolveSkillStates(catalog, config);
|
|
273
273
|
const ids = resolved.map((r) => r.summary.id);
|
|
274
274
|
|
|
275
|
-
//
|
|
275
|
+
// sounds and deploy explicitly false; browser explicitly true
|
|
276
276
|
expect(ids).toEqual(["browser"]);
|
|
277
277
|
});
|
|
278
278
|
});
|
|
@@ -283,7 +283,7 @@ describe("resolveSkillStates with feature flags", () => {
|
|
|
283
283
|
|
|
284
284
|
describe("resolveSkillStates with frontmatter featureFlag", () => {
|
|
285
285
|
test("skill with featureFlag (defaultEnabled: true) is included when no config override", () => {
|
|
286
|
-
//
|
|
286
|
+
// sounds has defaultEnabled: true in the registry
|
|
287
287
|
const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
|
|
288
288
|
const config = makeConfig();
|
|
289
289
|
|
|
@@ -12,8 +12,8 @@ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
|
12
12
|
|
|
13
13
|
let currentConfig: Record<string, unknown> = {};
|
|
14
14
|
|
|
15
|
-
const DECLARED_SKILL_ID = "
|
|
16
|
-
const DECLARED_FLAG_KEY = "
|
|
15
|
+
const DECLARED_SKILL_ID = "sounds";
|
|
16
|
+
const DECLARED_FLAG_KEY = "sounds";
|
|
17
17
|
|
|
18
18
|
const noopLogger = new Proxy({} as Record<string, unknown>, {
|
|
19
19
|
get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
|
|
@@ -39,6 +39,18 @@ mock.module("../config/loader.js", () => ({
|
|
|
39
39
|
invalidateConfigCache: () => {},
|
|
40
40
|
getNestedValue: () => undefined,
|
|
41
41
|
setNestedValue: () => {},
|
|
42
|
+
deepMergeOverwrite: (a: unknown) => a,
|
|
43
|
+
mergeDefaultWorkspaceConfig: () => {},
|
|
44
|
+
API_KEY_PROVIDERS: [
|
|
45
|
+
"anthropic",
|
|
46
|
+
"openai",
|
|
47
|
+
"gemini",
|
|
48
|
+
"ollama",
|
|
49
|
+
"fireworks",
|
|
50
|
+
"openrouter",
|
|
51
|
+
"brave",
|
|
52
|
+
"perplexity",
|
|
53
|
+
],
|
|
42
54
|
}));
|
|
43
55
|
|
|
44
56
|
await import("../tools/skills/load.js");
|
|
@@ -86,8 +98,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
86
98
|
test("returns deterministic error for flag OFF skill", async () => {
|
|
87
99
|
writeSkill(
|
|
88
100
|
DECLARED_SKILL_ID,
|
|
89
|
-
"
|
|
90
|
-
"Toggle
|
|
101
|
+
"Sounds",
|
|
102
|
+
"Toggle sounds behavior",
|
|
91
103
|
"Use the feature.",
|
|
92
104
|
);
|
|
93
105
|
writeFileSync(
|
|
@@ -107,8 +119,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
107
119
|
test("loads skill normally when flag is ON", async () => {
|
|
108
120
|
writeSkill(
|
|
109
121
|
DECLARED_SKILL_ID,
|
|
110
|
-
"
|
|
111
|
-
"Toggle
|
|
122
|
+
"Sounds",
|
|
123
|
+
"Toggle sounds behavior",
|
|
112
124
|
"Use the feature.",
|
|
113
125
|
);
|
|
114
126
|
writeFileSync(
|
|
@@ -121,14 +133,14 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
121
133
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
122
134
|
|
|
123
135
|
expect(result.isError).toBe(false);
|
|
124
|
-
expect(result.content).toContain("Skill:
|
|
136
|
+
expect(result.content).toContain("Skill: Sounds");
|
|
125
137
|
});
|
|
126
138
|
|
|
127
139
|
test("loads skill when flag key is absent (registry defaults to enabled)", async () => {
|
|
128
140
|
writeSkill(
|
|
129
141
|
DECLARED_SKILL_ID,
|
|
130
|
-
"
|
|
131
|
-
"Toggle
|
|
142
|
+
"Sounds",
|
|
143
|
+
"Toggle sounds behavior",
|
|
132
144
|
"Use the feature.",
|
|
133
145
|
);
|
|
134
146
|
writeFileSync(
|
|
@@ -140,8 +152,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
140
152
|
|
|
141
153
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
142
154
|
|
|
143
|
-
//
|
|
155
|
+
// sounds is declared in the registry with defaultEnabled: true
|
|
144
156
|
expect(result.isError).toBe(false);
|
|
145
|
-
expect(result.content).toContain("Skill:
|
|
157
|
+
expect(result.content).toContain("Skill: Sounds");
|
|
146
158
|
});
|
|
147
159
|
});
|