@vellumai/assistant 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +163 -54
- package/docs/architecture/integrations.md +62 -67
- package/docs/credential-execution-service.md +3 -3
- package/docs/skills.md +100 -0
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +111 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
- package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
- package/src/__tests__/app-dir-path-guard.test.ts +78 -0
- package/src/__tests__/app-executors.test.ts +1 -291
- package/src/__tests__/app-git-history.test.ts +4 -4
- package/src/__tests__/app-routes-csp.test.ts +1 -0
- package/src/__tests__/app-store-dir-names.test.ts +426 -0
- package/src/__tests__/attachments-store.test.ts +169 -21
- package/src/__tests__/attachments.test.ts +115 -1
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/canonical-guardian-store.test.ts +38 -0
- package/src/__tests__/channel-reply-delivery.test.ts +55 -0
- package/src/__tests__/checker.test.ts +54 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/config-schema-cmd.test.ts +68 -21
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +156 -5
- package/src/__tests__/conversation-agent-loop.test.ts +297 -2
- package/src/__tests__/conversation-attachments.test.ts +17 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
- package/src/__tests__/conversation-disk-view.test.ts +810 -0
- package/src/__tests__/conversation-error.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +551 -0
- package/src/__tests__/conversation-fork-route.test.ts +386 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
- package/src/__tests__/conversation-media-retry.test.ts +8 -2
- package/src/__tests__/conversation-memory-dirty-tail.test.ts +150 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +7 -0
- package/src/__tests__/conversation-queue.test.ts +36 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
- package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
- package/src/__tests__/conversation-skill-tools.test.ts +4 -9
- package/src/__tests__/conversation-slash-commands.test.ts +149 -0
- package/src/__tests__/conversation-store.test.ts +24 -21
- package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
- package/src/__tests__/conversation-title-service.test.ts +137 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
- package/src/__tests__/conversation-wipe.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-vault-unit.test.ts +5 -10
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
- package/src/__tests__/db-memory-archive-migration.test.ts +372 -0
- package/src/__tests__/db-memory-brief-state-migration.test.ts +213 -0
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +273 -0
- package/src/__tests__/diagnostics-export.test.ts +70 -1
- package/src/__tests__/first-greeting.test.ts +80 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
- package/src/__tests__/history-repair.test.ts +32 -10
- package/src/__tests__/http-conversation-lineage.test.ts +251 -0
- package/src/__tests__/image-source-path-reinject.test.ts +136 -0
- package/src/__tests__/inline-command-runner.test.ts +311 -0
- package/src/__tests__/inline-skill-authoring-guard.test.ts +220 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +435 -0
- package/src/__tests__/list-messages-attachments.test.ts +96 -0
- package/src/__tests__/llm-context-normalization.test.ts +1116 -0
- package/src/__tests__/llm-context-route-provider.test.ts +217 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
- package/src/__tests__/media-generate-image.test.ts +47 -94
- package/src/__tests__/memory-brief-open-loops.test.ts +530 -0
- package/src/__tests__/memory-brief-time.test.ts +285 -0
- package/src/__tests__/memory-brief-wrapper.test.ts +311 -0
- package/src/__tests__/memory-chunk-archive.test.ts +400 -0
- package/src/__tests__/memory-chunk-dual-write.test.ts +453 -0
- package/src/__tests__/memory-episode-archive.test.ts +370 -0
- package/src/__tests__/memory-episode-dual-write.test.ts +626 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
- package/src/__tests__/memory-observation-archive.test.ts +375 -0
- package/src/__tests__/memory-observation-dual-write.test.ts +318 -0
- package/src/__tests__/memory-recall-quality.test.ts +7 -7
- package/src/__tests__/memory-reducer-store.test.ts +728 -0
- package/src/__tests__/memory-reducer-types.test.ts +699 -0
- package/src/__tests__/memory-reducer.test.ts +698 -0
- package/src/__tests__/memory-regressions.test.ts +6 -4
- package/src/__tests__/memory-simplified-config.test.ts +281 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
- package/src/__tests__/migration-export-http.test.ts +3 -1
- package/src/__tests__/migration-import-commit-http.test.ts +18 -4
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
- package/src/__tests__/mime-builder.test.ts +3 -2
- package/src/__tests__/non-member-access-request.test.ts +12 -1
- package/src/__tests__/notification-decision-identity.test.ts +52 -0
- package/src/__tests__/oauth-apps-routes.test.ts +103 -0
- package/src/__tests__/oauth-store.test.ts +115 -0
- package/src/__tests__/parse-identity-fields.test.ts +129 -0
- package/src/__tests__/provider-error-scenarios.test.ts +1 -3
- package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
- package/src/__tests__/recording-handler.test.ts +17 -0
- package/src/__tests__/registry.test.ts +3 -8
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
- package/src/__tests__/schema-transforms.test.ts +165 -5
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/skill-load-inline-command.test.ts +598 -0
- package/src/__tests__/skill-load-inline-includes.test.ts +644 -0
- package/src/__tests__/skills-inline-command-expansions.test.ts +301 -0
- package/src/__tests__/skills-transitive-hash.test.ts +333 -0
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -2
- package/src/__tests__/starter-task-flow.test.ts +1 -0
- package/src/__tests__/suggestion-routes.test.ts +443 -0
- package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
- package/src/__tests__/swarm-recursion.test.ts +1 -0
- package/src/__tests__/swarm-tool.test.ts +1 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
- package/src/__tests__/top-level-renderer.test.ts +22 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +320 -0
- package/src/__tests__/web-fetch.test.ts +6 -2
- package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
- package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
- package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
- package/src/agent/attachments.ts +27 -1
- package/src/agent/loop.ts +29 -1
- package/src/avatar/traits-png-sync.ts +80 -25
- package/src/bundler/app-bundler.ts +4 -4
- package/src/calls/call-domain.ts +1 -0
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/commands/auth.ts +92 -0
- package/src/cli/commands/avatar.ts +7 -6
- package/src/cli/commands/config.ts +2 -0
- package/src/cli/commands/oauth/providers.ts +29 -0
- package/src/cli/program.ts +12 -0
- package/src/cli.ts +15 -48
- package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
- package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
- package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
- package/src/config/bundled-tool-registry.ts +2 -14
- package/src/config/feature-flag-registry.json +24 -0
- package/src/config/loader.ts +65 -0
- package/src/config/raw-config-utils.ts +58 -0
- package/src/config/schema-utils.ts +28 -7
- package/src/config/schema.ts +20 -0
- package/src/config/schemas/elevenlabs.ts +18 -0
- package/src/config/schemas/memory-lifecycle.ts +4 -2
- package/src/config/schemas/memory-simplified.ts +101 -0
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +8 -6
- package/src/config/skills.ts +50 -4
- package/src/contacts/contact-store.ts +13 -6
- package/src/contacts/contacts-write.ts +0 -1
- package/src/context/window-manager.ts +13 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +54 -8
- package/src/daemon/conversation-agent-loop.ts +127 -20
- package/src/daemon/conversation-attachments.ts +18 -36
- package/src/daemon/conversation-error.ts +2 -1
- package/src/daemon/conversation-history.ts +18 -4
- package/src/daemon/conversation-lifecycle.ts +50 -16
- package/src/daemon/conversation-messaging.ts +70 -26
- package/src/daemon/conversation-process.ts +58 -34
- package/src/daemon/conversation-runtime-assembly.ts +22 -38
- package/src/daemon/conversation-slash.ts +121 -256
- package/src/daemon/conversation-surfaces.ts +170 -24
- package/src/daemon/conversation-tool-setup.ts +0 -6
- package/src/daemon/conversation-workspace.ts +21 -1
- package/src/daemon/conversation.ts +69 -30
- package/src/daemon/first-greeting.ts +35 -0
- package/src/daemon/handlers/config-embeddings.ts +156 -0
- package/src/daemon/handlers/config-model.ts +62 -26
- package/src/daemon/handlers/conversations.ts +0 -23
- package/src/daemon/handlers/identity.ts +12 -1
- package/src/daemon/handlers/recording.ts +26 -21
- package/src/daemon/host-cu-proxy.ts +2 -2
- package/src/daemon/lifecycle.ts +115 -65
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +18 -0
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/shared.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/upgrades.ts +23 -0
- package/src/daemon/server.ts +83 -12
- package/src/daemon/shutdown-handlers.ts +8 -5
- package/src/daemon/startup-error.ts +9 -0
- package/src/daemon/tool-side-effects.ts +11 -28
- package/src/events/tool-permission-telemetry-listener.ts +1 -3
- package/src/followups/followup-store.ts +47 -1
- package/src/instrument.ts +0 -4
- package/src/media/app-icon-generator.ts +2 -2
- package/src/memory/app-git-service.ts +28 -16
- package/src/memory/app-store.ts +230 -41
- package/src/memory/archive-store.ts +400 -0
- package/src/memory/attachments-store.ts +558 -130
- package/src/memory/brief-formatting.ts +33 -0
- package/src/memory/brief-open-loops.ts +266 -0
- package/src/memory/brief-time.ts +161 -0
- package/src/memory/brief.ts +75 -0
- package/src/memory/conversation-attention-store.ts +70 -0
- package/src/memory/conversation-crud.ts +591 -8
- package/src/memory/conversation-directories.ts +125 -0
- package/src/memory/conversation-disk-view.ts +390 -0
- package/src/memory/conversation-key-store.ts +17 -5
- package/src/memory/conversation-queries.ts +5 -1
- package/src/memory/conversation-title-service.ts +21 -49
- package/src/memory/db-init.ts +40 -0
- package/src/memory/embedding-backend.ts +42 -53
- package/src/memory/embedding-gemini.test.ts +4 -4
- package/src/memory/embedding-local.ts +1 -3
- package/src/memory/embedding-ollama.ts +1 -3
- package/src/memory/embedding-openai.ts +1 -3
- package/src/memory/indexer.ts +114 -21
- package/src/memory/items-extractor.ts +42 -13
- package/src/memory/job-handlers/conversation-starters.ts +6 -1
- package/src/memory/job-handlers/embedding.test.ts +2 -4
- package/src/memory/job-handlers/embedding.ts +83 -0
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +6 -0
- package/src/memory/jobs-worker.ts +12 -0
- package/src/memory/llm-request-log-store.ts +100 -1
- package/src/memory/migrations/102-alter-table-columns.ts +5 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
- package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
- package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
- package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
- package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
- package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
- package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
- package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
- package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
- package/src/memory/migrations/185-memory-brief-state.ts +52 -0
- package/src/memory/migrations/186-memory-archive.ts +109 -0
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +19 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/qdrant-client.ts +23 -4
- package/src/memory/reducer-store.ts +271 -0
- package/src/memory/reducer-types.ts +99 -0
- package/src/memory/reducer.ts +453 -0
- package/src/memory/retriever.test.ts +601 -2
- package/src/memory/retriever.ts +85 -9
- package/src/memory/schema/conversations.ts +9 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/infrastructure.ts +13 -7
- package/src/memory/schema/memory-archive.ts +121 -0
- package/src/memory/schema/memory-brief.ts +55 -0
- package/src/memory/schema/oauth.ts +6 -0
- package/src/memory/search/semantic.ts +17 -4
- package/src/messaging/providers/gmail/mime-builder.ts +3 -1
- package/src/notifications/copy-composer.ts +26 -0
- package/src/notifications/decision-engine.ts +14 -1
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +36 -0
- package/src/oauth/byo-connection.test.ts +1 -45
- package/src/oauth/byo-connection.ts +2 -8
- package/src/oauth/connect-orchestrator.ts +15 -11
- package/src/oauth/connection-resolver.test.ts +191 -0
- package/src/oauth/connection-resolver.ts +66 -38
- package/src/oauth/connection.ts +0 -1
- package/src/oauth/oauth-store.ts +99 -47
- package/src/oauth/platform-connection.test.ts +0 -1
- package/src/oauth/platform-connection.ts +11 -3
- package/src/oauth/seed-providers.ts +78 -3
- package/src/oauth/token-persistence.ts +16 -10
- package/src/permissions/checker.ts +160 -14
- package/src/permissions/defaults.ts +14 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -0
- package/src/providers/anthropic/client.ts +8 -1
- package/src/providers/failover.ts +4 -1
- package/src/providers/gemini/client.ts +50 -0
- package/src/providers/model-catalog.ts +92 -0
- package/src/providers/model-intents.ts +29 -20
- package/src/providers/openai/client.ts +49 -0
- package/src/providers/types.ts +2 -0
- package/src/runtime/access-request-helper.ts +16 -7
- package/src/runtime/auth/credential-service.ts +3 -1
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/btw-sidechain.ts +101 -0
- package/src/runtime/channel-reply-delivery.ts +17 -1
- package/src/runtime/http-router.ts +3 -1
- package/src/runtime/http-server.ts +196 -141
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/migrations/vbundle-builder.ts +5 -1
- package/src/runtime/routes/access-request-decision.ts +41 -0
- package/src/runtime/routes/app-management-routes.ts +6 -3
- package/src/runtime/routes/app-routes.ts +7 -3
- package/src/runtime/routes/approval-routes.ts +1 -0
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
- package/src/runtime/routes/attachment-routes.ts +45 -15
- package/src/runtime/routes/btw-routes.ts +21 -61
- package/src/runtime/routes/conversation-management-routes.ts +74 -0
- package/src/runtime/routes/conversation-query-routes.ts +187 -10
- package/src/runtime/routes/conversation-routes.ts +269 -28
- package/src/runtime/routes/conversation-starter-routes.ts +9 -11
- package/src/runtime/routes/diagnostics-routes.ts +1 -0
- package/src/runtime/routes/identity-routes.ts +2 -35
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
- package/src/runtime/routes/llm-context-normalization.ts +1212 -0
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/memory-item-routes.test.ts +34 -0
- package/src/runtime/routes/memory-item-routes.ts +94 -5
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/oauth-apps.ts +291 -0
- package/src/runtime/routes/secret-routes.ts +30 -1
- package/src/runtime/routes/settings-routes.ts +14 -0
- package/src/runtime/routes/surface-action-routes.ts +68 -1
- package/src/runtime/routes/trace-event-routes.ts +4 -1
- package/src/schedule/schedule-store.ts +30 -21
- package/src/security/secure-keys.ts +21 -0
- package/src/signals/bash.ts +1 -1
- package/src/skills/inline-command-expansions.ts +204 -0
- package/src/skills/inline-command-render.ts +127 -0
- package/src/skills/inline-command-runner.ts +242 -0
- package/src/skills/transitive-version-hash.ts +88 -0
- package/src/swarm/backend-claude-code.ts +3 -6
- package/src/tasks/task-store.ts +43 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +3 -1
- package/src/tools/AGENTS.md +6 -10
- package/src/tools/apps/executors.ts +17 -232
- package/src/tools/claude-code/claude-code.ts +2 -3
- package/src/tools/credentials/vault.ts +7 -12
- package/src/tools/host-filesystem/read.ts +13 -10
- package/src/tools/network/__tests__/web-search.test.ts +4 -2
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/schedule/list.ts +2 -7
- package/src/tools/schema-transforms.ts +5 -0
- package/src/tools/shared/filesystem/format-diff.ts +2 -7
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +140 -6
- package/src/tools/tool-manifest.ts +0 -6
- package/src/tools/ui-surface/definitions.ts +2 -2
- package/src/util/device-id.ts +28 -5
- package/src/util/platform.ts +24 -0
- package/src/util/pricing.ts +1 -0
- package/src/util/retry.ts +1 -3
- package/src/workspace/migrations/003-seed-device-id.ts +3 -4
- package/src/workspace/migrations/006-services-config.ts +5 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
- package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts} +24 -13
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
- package/src/workspace/migrations/registry.ts +11 -1
- package/src/workspace/top-level-renderer.ts +12 -0
- package/src/__tests__/asset-materialize-tool.test.ts +0 -523
- package/src/__tests__/asset-search-tool.test.ts +0 -536
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
- package/src/__tests__/media-visibility-policy.test.ts +0 -190
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
- package/src/daemon/media-visibility-policy.ts +0 -59
- package/src/tools/assets/materialize.ts +0 -248
- package/src/tools/assets/search.ts +0 -400
|
@@ -28,3 +28,61 @@ export function setServiceField(
|
|
|
28
28
|
services[service] = svc;
|
|
29
29
|
raw.services = services;
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Safely set a nested field on a raw config object's `memory.embeddings` map.
|
|
34
|
+
*
|
|
35
|
+
* Ensures the `memory` and `embeddings` objects exist before writing,
|
|
36
|
+
* so callers don't need to guard against undefined intermediate keys.
|
|
37
|
+
*
|
|
38
|
+
* Example: `setMemoryEmbeddingField(raw, "provider", "openai")`
|
|
39
|
+
* produces `raw.memory.embeddings.provider = "openai"`.
|
|
40
|
+
*/
|
|
41
|
+
export function setMemoryEmbeddingField(
|
|
42
|
+
raw: Record<string, unknown>,
|
|
43
|
+
field: string,
|
|
44
|
+
value: unknown,
|
|
45
|
+
): void {
|
|
46
|
+
const memory: Record<string, unknown> =
|
|
47
|
+
raw.memory != null &&
|
|
48
|
+
typeof raw.memory === "object" &&
|
|
49
|
+
!Array.isArray(raw.memory)
|
|
50
|
+
? (raw.memory as Record<string, unknown>)
|
|
51
|
+
: {};
|
|
52
|
+
const existing = memory.embeddings;
|
|
53
|
+
const embeddings: Record<string, unknown> =
|
|
54
|
+
existing != null && typeof existing === "object" && !Array.isArray(existing)
|
|
55
|
+
? (existing as Record<string, unknown>)
|
|
56
|
+
: {};
|
|
57
|
+
embeddings[field] = value;
|
|
58
|
+
memory.embeddings = embeddings;
|
|
59
|
+
raw.memory = memory;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Safely delete a nested field from a raw config object's `memory.embeddings`
|
|
64
|
+
* map, allowing Zod schema defaults to take effect on the next config reload.
|
|
65
|
+
*/
|
|
66
|
+
export function deleteMemoryEmbeddingField(
|
|
67
|
+
raw: Record<string, unknown>,
|
|
68
|
+
field: string,
|
|
69
|
+
): void {
|
|
70
|
+
if (
|
|
71
|
+
raw.memory == null ||
|
|
72
|
+
typeof raw.memory !== "object" ||
|
|
73
|
+
Array.isArray(raw.memory)
|
|
74
|
+
) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const memory = raw.memory as Record<string, unknown>;
|
|
78
|
+
const existing = memory.embeddings;
|
|
79
|
+
if (
|
|
80
|
+
existing == null ||
|
|
81
|
+
typeof existing !== "object" ||
|
|
82
|
+
Array.isArray(existing)
|
|
83
|
+
) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const embeddings = existing as Record<string, unknown>;
|
|
87
|
+
delete embeddings[field];
|
|
88
|
+
}
|
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Unwrap a Zod schema to reach its inner object shape, handling:
|
|
5
|
+
* - default/optional/nullable wrappers (innerType)
|
|
6
|
+
* - pipe/transform wrappers (in — the input side)
|
|
7
|
+
*/
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
function unwrapToShape(schema: any): any {
|
|
10
|
+
let current = schema;
|
|
11
|
+
while (current && !current.shape) {
|
|
12
|
+
const def = current._zod?.def;
|
|
13
|
+
if (!def) break;
|
|
14
|
+
// Pipe/transform: follow the input side to get the pre-transform schema
|
|
15
|
+
if (def.type === "pipe" && def.in) {
|
|
16
|
+
current = def.in;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
// Default/optional/nullable: follow innerType
|
|
20
|
+
if (def.innerType) {
|
|
21
|
+
current = def.innerType;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
return current;
|
|
27
|
+
}
|
|
28
|
+
|
|
3
29
|
/**
|
|
4
30
|
* Navigate a Zod schema by dotted path, unwrapping wrapper types
|
|
5
|
-
* (default, optional, nullable) to reach inner object shapes.
|
|
31
|
+
* (default, optional, nullable, pipe/transform) to reach inner object shapes.
|
|
6
32
|
* Returns the Zod schema at the given path, or null if the path is invalid.
|
|
7
33
|
*/
|
|
8
34
|
export function getSchemaAtPath(
|
|
@@ -13,12 +39,7 @@ export function getSchemaAtPath(
|
|
|
13
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
40
|
let current: any = schema;
|
|
15
41
|
for (const key of keys) {
|
|
16
|
-
|
|
17
|
-
while (current && !current.shape) {
|
|
18
|
-
const inner = current._zod?.def?.innerType;
|
|
19
|
-
if (!inner) break;
|
|
20
|
-
current = inner;
|
|
21
|
-
}
|
|
42
|
+
current = unwrapToShape(current);
|
|
22
43
|
if (!current || !current.shape) return null;
|
|
23
44
|
current = current.shape[key];
|
|
24
45
|
if (!current) return null;
|
package/src/config/schema.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type { ElevenLabsConfig } from "./schemas/elevenlabs.js";
|
|
|
38
38
|
export {
|
|
39
39
|
DEFAULT_ELEVENLABS_VOICE_ID,
|
|
40
40
|
ElevenLabsConfigSchema,
|
|
41
|
+
VALID_CONVERSATION_TIMEOUTS,
|
|
41
42
|
} from "./schemas/elevenlabs.js";
|
|
42
43
|
export type { HeartbeatConfig } from "./schemas/heartbeat.js";
|
|
43
44
|
export { HeartbeatConfigSchema } from "./schemas/heartbeat.js";
|
|
@@ -105,6 +106,18 @@ export {
|
|
|
105
106
|
MemoryDynamicBudgetConfigSchema,
|
|
106
107
|
MemoryRetrievalConfigSchema,
|
|
107
108
|
} from "./schemas/memory-retrieval.js";
|
|
109
|
+
export type {
|
|
110
|
+
MemorySimplifiedArchiveRecallConfig,
|
|
111
|
+
MemorySimplifiedBriefConfig,
|
|
112
|
+
MemorySimplifiedConfig,
|
|
113
|
+
MemorySimplifiedReducerConfig,
|
|
114
|
+
} from "./schemas/memory-simplified.js";
|
|
115
|
+
export {
|
|
116
|
+
MemorySimplifiedArchiveRecallConfigSchema,
|
|
117
|
+
MemorySimplifiedBriefConfigSchema,
|
|
118
|
+
MemorySimplifiedConfigSchema,
|
|
119
|
+
MemorySimplifiedReducerConfigSchema,
|
|
120
|
+
} from "./schemas/memory-simplified.js";
|
|
108
121
|
export type {
|
|
109
122
|
MemoryEmbeddingsConfig,
|
|
110
123
|
MemorySegmentationConfig,
|
|
@@ -321,6 +334,13 @@ export const AssistantConfigSchema = z
|
|
|
321
334
|
.boolean()
|
|
322
335
|
.default(true)
|
|
323
336
|
.describe("Whether to send diagnostic/crash reports"),
|
|
337
|
+
maxStepsPerSession: z
|
|
338
|
+
.number({ error: "maxStepsPerSession must be a number" })
|
|
339
|
+
.int("maxStepsPerSession must be an integer")
|
|
340
|
+
.min(1, "maxStepsPerSession must be >= 1")
|
|
341
|
+
.max(200, "maxStepsPerSession must be <= 200")
|
|
342
|
+
.default(50)
|
|
343
|
+
.describe("Maximum number of computer-use steps per session"),
|
|
324
344
|
})
|
|
325
345
|
.superRefine((config, ctx) => {
|
|
326
346
|
if (
|
|
@@ -5,6 +5,9 @@ import { z } from "zod";
|
|
|
5
5
|
// Mirrored in: clients/macos/.../OpenAIVoiceService.swift (defaultVoiceId)
|
|
6
6
|
export const DEFAULT_ELEVENLABS_VOICE_ID = "ZF6FPAbjXT4488VcRRnw";
|
|
7
7
|
|
|
8
|
+
/** Valid conversation timeout values (seconds). Shared with voice-config-update tool. */
|
|
9
|
+
export const VALID_CONVERSATION_TIMEOUTS = [5, 10, 15, 30, 60] as const;
|
|
10
|
+
|
|
8
11
|
export const ElevenLabsConfigSchema = z
|
|
9
12
|
.object({
|
|
10
13
|
voiceId: z
|
|
@@ -42,6 +45,21 @@ export const ElevenLabsConfigSchema = z
|
|
|
42
45
|
.describe(
|
|
43
46
|
"How closely the output matches the original voice — higher values increase similarity",
|
|
44
47
|
),
|
|
48
|
+
conversationTimeoutSeconds: z
|
|
49
|
+
.number({
|
|
50
|
+
error: "elevenlabs.conversationTimeoutSeconds must be a number",
|
|
51
|
+
})
|
|
52
|
+
.refine(
|
|
53
|
+
(v) =>
|
|
54
|
+
VALID_CONVERSATION_TIMEOUTS.includes(
|
|
55
|
+
v as (typeof VALID_CONVERSATION_TIMEOUTS)[number],
|
|
56
|
+
),
|
|
57
|
+
{
|
|
58
|
+
message: `elevenlabs.conversationTimeoutSeconds must be one of: ${VALID_CONVERSATION_TIMEOUTS.join(", ")}`,
|
|
59
|
+
},
|
|
60
|
+
)
|
|
61
|
+
.default(30)
|
|
62
|
+
.describe("Seconds of silence before voice conversation auto-ends"),
|
|
45
63
|
})
|
|
46
64
|
.describe("ElevenLabs text-to-speech configuration");
|
|
47
65
|
|
|
@@ -68,8 +68,10 @@ export const MemoryCleanupConfigSchema = z
|
|
|
68
68
|
.nonnegative(
|
|
69
69
|
"memory.cleanup.conversationRetentionDays must be non-negative",
|
|
70
70
|
)
|
|
71
|
-
.default(
|
|
72
|
-
.describe(
|
|
71
|
+
.default(0)
|
|
72
|
+
.describe(
|
|
73
|
+
"Number of days to retain conversation data before cleanup (0 disables pruning)",
|
|
74
|
+
),
|
|
73
75
|
})
|
|
74
76
|
.describe("Automatic memory cleanup and garbage collection settings");
|
|
75
77
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const MemorySimplifiedBriefConfigSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
maxTokens: z
|
|
6
|
+
.number({
|
|
7
|
+
error: "memory.simplified.brief.maxTokens must be a number",
|
|
8
|
+
})
|
|
9
|
+
.int("memory.simplified.brief.maxTokens must be an integer")
|
|
10
|
+
.positive("memory.simplified.brief.maxTokens must be a positive integer")
|
|
11
|
+
.default(4000)
|
|
12
|
+
.describe(
|
|
13
|
+
"Maximum token budget for the memory brief injected into conversation context",
|
|
14
|
+
),
|
|
15
|
+
})
|
|
16
|
+
.describe("Controls the memory brief that is injected into conversations");
|
|
17
|
+
|
|
18
|
+
export const MemorySimplifiedReducerConfigSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
idleDelayMs: z
|
|
21
|
+
.number({
|
|
22
|
+
error: "memory.simplified.reducer.idleDelayMs must be a number",
|
|
23
|
+
})
|
|
24
|
+
.int("memory.simplified.reducer.idleDelayMs must be an integer")
|
|
25
|
+
.positive(
|
|
26
|
+
"memory.simplified.reducer.idleDelayMs must be a positive integer",
|
|
27
|
+
)
|
|
28
|
+
.default(30_000)
|
|
29
|
+
.describe(
|
|
30
|
+
"Milliseconds of idle time before the reducer processes new conversation turns into memory",
|
|
31
|
+
),
|
|
32
|
+
switchWaitMs: z
|
|
33
|
+
.number({
|
|
34
|
+
error: "memory.simplified.reducer.switchWaitMs must be a number",
|
|
35
|
+
})
|
|
36
|
+
.int("memory.simplified.reducer.switchWaitMs must be an integer")
|
|
37
|
+
.positive(
|
|
38
|
+
"memory.simplified.reducer.switchWaitMs must be a positive integer",
|
|
39
|
+
)
|
|
40
|
+
.default(5_000)
|
|
41
|
+
.describe(
|
|
42
|
+
"Milliseconds to wait after a conversation switch before running the reducer",
|
|
43
|
+
),
|
|
44
|
+
})
|
|
45
|
+
.describe(
|
|
46
|
+
"Controls when the memory reducer runs to process conversation turns into persistent memory",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const MemorySimplifiedArchiveRecallConfigSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
maxSnippets: z
|
|
52
|
+
.number({
|
|
53
|
+
error: "memory.simplified.archiveRecall.maxSnippets must be a number",
|
|
54
|
+
})
|
|
55
|
+
.int("memory.simplified.archiveRecall.maxSnippets must be an integer")
|
|
56
|
+
.positive(
|
|
57
|
+
"memory.simplified.archiveRecall.maxSnippets must be a positive integer",
|
|
58
|
+
)
|
|
59
|
+
.default(10)
|
|
60
|
+
.describe(
|
|
61
|
+
"Maximum number of archive snippets to recall when supplementing the brief with semantic search",
|
|
62
|
+
),
|
|
63
|
+
})
|
|
64
|
+
.describe(
|
|
65
|
+
"Controls how archived memory snippets are recalled via semantic search",
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
export const MemorySimplifiedConfigSchema = z
|
|
69
|
+
.object({
|
|
70
|
+
enabled: z
|
|
71
|
+
.boolean({
|
|
72
|
+
error: "memory.simplified.enabled must be a boolean",
|
|
73
|
+
})
|
|
74
|
+
.default(false)
|
|
75
|
+
.describe("Whether the simplified memory system is enabled"),
|
|
76
|
+
brief: MemorySimplifiedBriefConfigSchema.default(
|
|
77
|
+
MemorySimplifiedBriefConfigSchema.parse({}),
|
|
78
|
+
),
|
|
79
|
+
reducer: MemorySimplifiedReducerConfigSchema.default(
|
|
80
|
+
MemorySimplifiedReducerConfigSchema.parse({}),
|
|
81
|
+
),
|
|
82
|
+
archiveRecall: MemorySimplifiedArchiveRecallConfigSchema.default(
|
|
83
|
+
MemorySimplifiedArchiveRecallConfigSchema.parse({}),
|
|
84
|
+
),
|
|
85
|
+
})
|
|
86
|
+
.describe(
|
|
87
|
+
"Simplified two-layer memory system — a brief plus archive recall, replacing the legacy item/tier/staleness model",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
export type MemorySimplifiedConfig = z.infer<
|
|
91
|
+
typeof MemorySimplifiedConfigSchema
|
|
92
|
+
>;
|
|
93
|
+
export type MemorySimplifiedBriefConfig = z.infer<
|
|
94
|
+
typeof MemorySimplifiedBriefConfigSchema
|
|
95
|
+
>;
|
|
96
|
+
export type MemorySimplifiedReducerConfig = z.infer<
|
|
97
|
+
typeof MemorySimplifiedReducerConfigSchema
|
|
98
|
+
>;
|
|
99
|
+
export type MemorySimplifiedArchiveRecallConfig = z.infer<
|
|
100
|
+
typeof MemorySimplifiedArchiveRecallConfigSchema
|
|
101
|
+
>;
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
MemorySummarizationConfigSchema,
|
|
11
11
|
} from "./memory-processing.js";
|
|
12
12
|
import { MemoryRetrievalConfigSchema } from "./memory-retrieval.js";
|
|
13
|
+
import { MemorySimplifiedConfigSchema } from "./memory-simplified.js";
|
|
13
14
|
import {
|
|
14
15
|
MemoryEmbeddingsConfigSchema,
|
|
15
16
|
MemorySegmentationConfigSchema,
|
|
@@ -45,6 +46,9 @@ export const MemoryConfigSchema = z
|
|
|
45
46
|
summarization: MemorySummarizationConfigSchema.default(
|
|
46
47
|
MemorySummarizationConfigSchema.parse({}),
|
|
47
48
|
),
|
|
49
|
+
simplified: MemorySimplifiedConfigSchema.default(
|
|
50
|
+
MemorySimplifiedConfigSchema.parse({}),
|
|
51
|
+
),
|
|
48
52
|
})
|
|
49
53
|
.describe(
|
|
50
54
|
"Long-term memory system — stores, retrieves, and manages persistent knowledge across conversations",
|
|
@@ -20,15 +20,18 @@ export const VALID_WEB_SEARCH_PROVIDERS = [
|
|
|
20
20
|
"inference-provider-native",
|
|
21
21
|
] as const;
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const BaseServiceSchema = z.object({
|
|
24
24
|
mode: ServiceModeSchema.default("your-own"),
|
|
25
|
+
});
|
|
26
|
+
export type BaseService = z.infer<typeof BaseServiceSchema>;
|
|
27
|
+
|
|
28
|
+
export const InferenceServiceSchema = BaseServiceSchema.extend({
|
|
25
29
|
provider: z.enum(VALID_INFERENCE_PROVIDERS).default("anthropic"),
|
|
26
30
|
model: z.string().default("claude-opus-4-6"),
|
|
27
31
|
});
|
|
28
32
|
export type InferenceService = z.infer<typeof InferenceServiceSchema>;
|
|
29
33
|
|
|
30
|
-
export const ImageGenerationServiceSchema =
|
|
31
|
-
mode: ServiceModeSchema.default("your-own"),
|
|
34
|
+
export const ImageGenerationServiceSchema = BaseServiceSchema.extend({
|
|
32
35
|
provider: z.enum(VALID_IMAGE_GEN_PROVIDERS).default("gemini"),
|
|
33
36
|
model: z.string().default("gemini-3.1-flash-image-preview"),
|
|
34
37
|
});
|
|
@@ -36,15 +39,14 @@ export type ImageGenerationService = z.infer<
|
|
|
36
39
|
typeof ImageGenerationServiceSchema
|
|
37
40
|
>;
|
|
38
41
|
|
|
39
|
-
export const WebSearchServiceSchema =
|
|
40
|
-
mode: ServiceModeSchema.default("your-own"),
|
|
42
|
+
export const WebSearchServiceSchema = BaseServiceSchema.extend({
|
|
41
43
|
provider: z
|
|
42
44
|
.enum(VALID_WEB_SEARCH_PROVIDERS)
|
|
43
45
|
.default("inference-provider-native"),
|
|
44
46
|
});
|
|
45
47
|
export type WebSearchService = z.infer<typeof WebSearchServiceSchema>;
|
|
46
48
|
|
|
47
|
-
export const GoogleOAuthServiceSchema =
|
|
49
|
+
export const GoogleOAuthServiceSchema = BaseServiceSchema.extend({
|
|
48
50
|
mode: ServiceModeSchema.default("managed"),
|
|
49
51
|
});
|
|
50
52
|
export type GoogleOAuthService = z.infer<typeof GoogleOAuthServiceSchema>;
|
package/src/config/skills.ts
CHANGED
|
@@ -25,10 +25,15 @@ import {
|
|
|
25
25
|
userMessage,
|
|
26
26
|
} from "../providers/provider-send-message.js";
|
|
27
27
|
import { parseFrontmatterFields } from "../skills/frontmatter.js";
|
|
28
|
+
import type { InlineCommandExpansion } from "../skills/inline-command-expansions.js";
|
|
29
|
+
import { parseInlineCommandExpansions } from "../skills/inline-command-expansions.js";
|
|
28
30
|
import { parseToolManifestFile } from "../skills/tool-manifest.js";
|
|
29
31
|
import { computeSkillVersionHash } from "../skills/version-hash.js";
|
|
30
32
|
import { getLogger } from "../util/logger.js";
|
|
31
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
getWorkspaceDirDisplay,
|
|
35
|
+
getWorkspaceSkillsDir,
|
|
36
|
+
} from "../util/platform.js";
|
|
32
37
|
import { isAssistantFeatureFlagEnabled } from "./assistant-feature-flags.js";
|
|
33
38
|
import { getConfig } from "./loader.js";
|
|
34
39
|
|
|
@@ -80,6 +85,8 @@ export interface SkillSummary {
|
|
|
80
85
|
activationHints?: string[];
|
|
81
86
|
/** Conditions under which this skill should NOT be loaded. */
|
|
82
87
|
avoidWhen?: string[];
|
|
88
|
+
/** Parsed inline command expansion descriptors (`!\`command\``) found in the skill body. */
|
|
89
|
+
inlineCommandExpansions?: InlineCommandExpansion[];
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
export interface SkillDefinition extends SkillSummary {
|
|
@@ -198,6 +205,7 @@ interface ParsedFrontmatter {
|
|
|
198
205
|
featureFlag?: string;
|
|
199
206
|
activationHints?: string[];
|
|
200
207
|
avoidWhen?: string[];
|
|
208
|
+
inlineCommandExpansions?: InlineCommandExpansion[];
|
|
201
209
|
}
|
|
202
210
|
|
|
203
211
|
function normalizeStringArray(raw: unknown): string[] | undefined {
|
|
@@ -302,16 +310,29 @@ function parseFrontmatter(
|
|
|
302
310
|
const activationHints = normalizeStringArray(vellum?.["activation-hints"]);
|
|
303
311
|
const avoidWhen = normalizeStringArray(vellum?.["avoid-when"]);
|
|
304
312
|
|
|
313
|
+
const strippedBody = stripCommentLines(body);
|
|
314
|
+
|
|
315
|
+
// Parse inline command expansions from the body (after frontmatter/comment stripping)
|
|
316
|
+
const expansionResult = parseInlineCommandExpansions(strippedBody);
|
|
317
|
+
const inlineCommandExpansions =
|
|
318
|
+
expansionResult.expansions.length > 0
|
|
319
|
+
? expansionResult.expansions
|
|
320
|
+
: undefined;
|
|
321
|
+
|
|
322
|
+
// Fail closed: if there are malformed tokens, log and exclude from parsed expansions
|
|
323
|
+
// (errors are already logged inside parseInlineCommandExpansions)
|
|
324
|
+
|
|
305
325
|
return {
|
|
306
326
|
name,
|
|
307
327
|
displayName,
|
|
308
328
|
description,
|
|
309
|
-
body:
|
|
329
|
+
body: strippedBody,
|
|
310
330
|
emoji,
|
|
311
331
|
includes,
|
|
312
332
|
featureFlag,
|
|
313
333
|
activationHints,
|
|
314
334
|
avoidWhen,
|
|
335
|
+
inlineCommandExpansions,
|
|
315
336
|
};
|
|
316
337
|
}
|
|
317
338
|
|
|
@@ -466,6 +487,7 @@ function readSkillFromDirectory(
|
|
|
466
487
|
featureFlag: parsed.featureFlag,
|
|
467
488
|
activationHints: parsed.activationHints,
|
|
468
489
|
avoidWhen: parsed.avoidWhen,
|
|
490
|
+
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
469
491
|
};
|
|
470
492
|
} catch (err) {
|
|
471
493
|
log.warn({ err, skillFilePath }, "Failed to read skill file");
|
|
@@ -516,6 +538,7 @@ function readBundledSkillFromDirectory(
|
|
|
516
538
|
featureFlag: parsed.featureFlag,
|
|
517
539
|
activationHints: parsed.activationHints,
|
|
518
540
|
avoidWhen: parsed.avoidWhen,
|
|
541
|
+
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
519
542
|
};
|
|
520
543
|
} catch (err) {
|
|
521
544
|
log.warn({ err, skillFilePath }, "Failed to read bundled skill file");
|
|
@@ -574,6 +597,7 @@ function loadBundledSkills(): SkillSummary[] {
|
|
|
574
597
|
featureFlag: skill.featureFlag,
|
|
575
598
|
activationHints: skill.activationHints,
|
|
576
599
|
avoidWhen: skill.avoidWhen,
|
|
600
|
+
inlineCommandExpansions: skill.inlineCommandExpansions,
|
|
577
601
|
});
|
|
578
602
|
}
|
|
579
603
|
|
|
@@ -710,6 +734,7 @@ function skillSummaryFromDefinition(
|
|
|
710
734
|
featureFlag: skill.featureFlag,
|
|
711
735
|
activationHints: skill.activationHints,
|
|
712
736
|
avoidWhen: skill.avoidWhen,
|
|
737
|
+
inlineCommandExpansions: skill.inlineCommandExpansions,
|
|
713
738
|
};
|
|
714
739
|
}
|
|
715
740
|
|
|
@@ -760,6 +785,7 @@ export function loadSkillCatalog(
|
|
|
760
785
|
toolManifest: detectToolManifest(directory),
|
|
761
786
|
includes: parsed.includes,
|
|
762
787
|
featureFlag: parsed.featureFlag,
|
|
788
|
+
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
763
789
|
});
|
|
764
790
|
} catch (err) {
|
|
765
791
|
log.warn({ err, directory }, "Failed to read skill from extraDirs");
|
|
@@ -854,6 +880,7 @@ export function loadSkillCatalog(
|
|
|
854
880
|
toolManifest: detectToolManifest(directory),
|
|
855
881
|
includes: parsed.includes,
|
|
856
882
|
featureFlag: parsed.featureFlag,
|
|
883
|
+
inlineCommandExpansions: parsed.inlineCommandExpansions,
|
|
857
884
|
};
|
|
858
885
|
|
|
859
886
|
if (seenIds.has(id)) {
|
|
@@ -1001,8 +1028,28 @@ function loadSkillDefinition(skill: SkillSummary): SkillLookupResult {
|
|
|
1001
1028
|
}
|
|
1002
1029
|
// Replace {baseDir} placeholders with the actual skill directory path
|
|
1003
1030
|
loaded.body = loaded.body.replaceAll("{baseDir}", loaded.directoryPath);
|
|
1031
|
+
// Replace {workspaceDir} placeholders with the runtime workspace display path
|
|
1032
|
+
loaded.body = loaded.body.replaceAll(
|
|
1033
|
+
"{workspaceDir}",
|
|
1034
|
+
getWorkspaceDirDisplay(),
|
|
1035
|
+
);
|
|
1004
1036
|
// Strip feature-gated sections based on assistant feature flags
|
|
1005
1037
|
loaded.body = applyFeatureGatedSections(loaded.body);
|
|
1038
|
+
|
|
1039
|
+
// Re-parse inline command expansions after placeholder substitution.
|
|
1040
|
+
// The initial parse (during SKILL.md parsing) produces byte offsets against
|
|
1041
|
+
// the pre-substitution body. Since {baseDir} and {workspaceDir} replacements
|
|
1042
|
+
// change the body length, those offsets become stale. Re-parsing ensures the
|
|
1043
|
+
// offsets match the final body that renderInlineCommands will operate on.
|
|
1044
|
+
if (
|
|
1045
|
+
loaded.inlineCommandExpansions &&
|
|
1046
|
+
loaded.inlineCommandExpansions.length > 0
|
|
1047
|
+
) {
|
|
1048
|
+
const reparse = parseInlineCommandExpansions(loaded.body);
|
|
1049
|
+
loaded.inlineCommandExpansions =
|
|
1050
|
+
reparse.expansions.length > 0 ? reparse.expansions : undefined;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1006
1053
|
return { skill: loaded };
|
|
1007
1054
|
}
|
|
1008
1055
|
|
|
@@ -1021,8 +1068,7 @@ export function resolveSkillSelector(
|
|
|
1021
1068
|
const catalog = loadSkillCatalog(workspaceSkillsDir);
|
|
1022
1069
|
if (catalog.length === 0) {
|
|
1023
1070
|
return {
|
|
1024
|
-
error:
|
|
1025
|
-
"No skills are available. Configure ~/.vellum/workspace/skills/SKILLS.md or add skill directories.",
|
|
1071
|
+
error: `No skills are available. Configure ${getWorkspaceDirDisplay()}/skills/SKILLS.md or add skill directories.`,
|
|
1026
1072
|
errorCode: "empty_catalog",
|
|
1027
1073
|
};
|
|
1028
1074
|
}
|
|
@@ -295,21 +295,28 @@ function syncChannels(
|
|
|
295
295
|
.get();
|
|
296
296
|
|
|
297
297
|
if (existing) {
|
|
298
|
+
// Preserve guardian blocks: if the channel is blocked, do not overwrite
|
|
299
|
+
// its status/policy — mirrors the guard in the cross-contact reassignment
|
|
300
|
+
// path so a blocked channel cannot be unblocked via a same-contact sync.
|
|
301
|
+
const isBlocked = existing.status === "blocked";
|
|
302
|
+
|
|
298
303
|
const updateSet: Record<string, unknown> = {};
|
|
299
304
|
if (ch.isPrimary !== undefined) updateSet.isPrimary = ch.isPrimary;
|
|
300
305
|
if (ch.externalUserId !== undefined)
|
|
301
306
|
updateSet.externalUserId = ch.externalUserId;
|
|
302
307
|
if (ch.externalChatId !== undefined)
|
|
303
308
|
updateSet.externalChatId = ch.externalChatId;
|
|
304
|
-
if (
|
|
305
|
-
|
|
309
|
+
if (!isBlocked) {
|
|
310
|
+
if (ch.status !== undefined) updateSet.status = ch.status;
|
|
311
|
+
if (ch.policy !== undefined) updateSet.policy = ch.policy;
|
|
312
|
+
if (ch.revokedReason !== undefined)
|
|
313
|
+
updateSet.revokedReason = ch.revokedReason;
|
|
314
|
+
if (ch.blockedReason !== undefined)
|
|
315
|
+
updateSet.blockedReason = ch.blockedReason;
|
|
316
|
+
}
|
|
306
317
|
if (ch.verifiedAt !== undefined) updateSet.verifiedAt = ch.verifiedAt;
|
|
307
318
|
if (ch.verifiedVia !== undefined) updateSet.verifiedVia = ch.verifiedVia;
|
|
308
319
|
if (ch.inviteId !== undefined) updateSet.inviteId = ch.inviteId;
|
|
309
|
-
if (ch.revokedReason !== undefined)
|
|
310
|
-
updateSet.revokedReason = ch.revokedReason;
|
|
311
|
-
if (ch.blockedReason !== undefined)
|
|
312
|
-
updateSet.blockedReason = ch.blockedReason;
|
|
313
320
|
|
|
314
321
|
if (Object.keys(updateSet).length > 0) {
|
|
315
322
|
updateSet.updatedAt = now;
|
|
@@ -681,13 +681,24 @@ function countPersistedMessages(messages: Message[]): number {
|
|
|
681
681
|
}).length;
|
|
682
682
|
}
|
|
683
683
|
|
|
684
|
-
|
|
684
|
+
function isSystemNoticeBlock(block: ContentBlock): boolean {
|
|
685
|
+
if (block.type !== "text") return false;
|
|
686
|
+
const text = (block as { text?: string }).text ?? "";
|
|
687
|
+
return (
|
|
688
|
+
text.startsWith("<system_notice>") && text.endsWith("</system_notice>")
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/** A user message that contains ONLY tool_result blocks (no text or other content).
|
|
693
|
+
* System notice text blocks (retry nudges, progress checks) do not count as user content. */
|
|
685
694
|
function isToolResultOnly(message: Message): boolean {
|
|
686
695
|
return (
|
|
687
696
|
message.content.length > 0 &&
|
|
688
697
|
message.content.every(
|
|
689
698
|
(block) =>
|
|
690
|
-
block.type === "tool_result" ||
|
|
699
|
+
block.type === "tool_result" ||
|
|
700
|
+
block.type === "web_search_tool_result" ||
|
|
701
|
+
isSystemNoticeBlock(block),
|
|
691
702
|
)
|
|
692
703
|
);
|
|
693
704
|
}
|