@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
|
@@ -10,11 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
import { compileApp } from "../../bundler/app-compiler.js";
|
|
12
12
|
import { generateAppIcon } from "../../media/app-icon-generator.js";
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
EditEngineResult,
|
|
16
|
-
} from "../../memory/app-store.js";
|
|
17
|
-
import { getAppsDir, isMultifileApp } from "../../memory/app-store.js";
|
|
13
|
+
import type { AppDefinition } from "../../memory/app-store.js";
|
|
14
|
+
import { getAppDirPath } from "../../memory/app-store.js";
|
|
18
15
|
|
|
19
16
|
// ---------------------------------------------------------------------------
|
|
20
17
|
// Shared result type
|
|
@@ -35,9 +32,6 @@ export interface ExecutorResult {
|
|
|
35
32
|
export interface AppStoreReader {
|
|
36
33
|
getApp(id: string): AppDefinition | null;
|
|
37
34
|
listApps(): AppDefinition[];
|
|
38
|
-
queryAppRecords(appId: string): unknown[];
|
|
39
|
-
listAppFiles(appId: string): string[];
|
|
40
|
-
readAppFile(appId: string, path: string): string;
|
|
41
35
|
}
|
|
42
36
|
|
|
43
37
|
export interface AppStoreWriter {
|
|
@@ -61,13 +55,6 @@ export interface AppStoreWriter {
|
|
|
61
55
|
): AppDefinition;
|
|
62
56
|
deleteApp(id: string): void;
|
|
63
57
|
writeAppFile(appId: string, path: string, content: string): void;
|
|
64
|
-
editAppFile(
|
|
65
|
-
appId: string,
|
|
66
|
-
path: string,
|
|
67
|
-
oldString: string,
|
|
68
|
-
newString: string,
|
|
69
|
-
replaceAll?: boolean,
|
|
70
|
-
): EditEngineResult;
|
|
71
58
|
}
|
|
72
59
|
|
|
73
60
|
export type AppStore = AppStoreReader & AppStoreWriter;
|
|
@@ -81,28 +68,6 @@ export type ProxyResolver = (
|
|
|
81
68
|
input: Record<string, unknown>,
|
|
82
69
|
) => Promise<ExecutorResult>;
|
|
83
70
|
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
// Path resolution - multifile apps default to src/ for file operations
|
|
86
|
-
// ---------------------------------------------------------------------------
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* For multifile (formatVersion 2) apps, prepend `src/` to paths that don't
|
|
90
|
-
* already target a known top-level directory (src/, dist/, records/).
|
|
91
|
-
* Legacy apps pass through unchanged.
|
|
92
|
-
*/
|
|
93
|
-
export function resolveAppFilePath(app: AppDefinition, path: string): string {
|
|
94
|
-
if (!isMultifileApp(app)) return path;
|
|
95
|
-
const normalized = path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
96
|
-
if (
|
|
97
|
-
normalized.startsWith("src/") ||
|
|
98
|
-
normalized.startsWith("dist/") ||
|
|
99
|
-
normalized.startsWith("records/")
|
|
100
|
-
) {
|
|
101
|
-
return normalized;
|
|
102
|
-
}
|
|
103
|
-
return `src/${normalized}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
71
|
// ---------------------------------------------------------------------------
|
|
107
72
|
// app_create
|
|
108
73
|
// ---------------------------------------------------------------------------
|
|
@@ -222,8 +187,7 @@ render(<App />, document.getElementById('app')!);
|
|
|
222
187
|
store.writeAppFile(app.id, "src/main.tsx", mainTsx);
|
|
223
188
|
|
|
224
189
|
// Compile src/ → dist/
|
|
225
|
-
const
|
|
226
|
-
const appDir = join(getAppsDir(), app.id);
|
|
190
|
+
const appDir = getAppDirPath(app.id);
|
|
227
191
|
const compileResult = await compileApp(appDir);
|
|
228
192
|
if (!compileResult.ok) {
|
|
229
193
|
return {
|
|
@@ -286,72 +250,6 @@ render(<App />, document.getElementById('app')!);
|
|
|
286
250
|
return { content: JSON.stringify(app), isError: false };
|
|
287
251
|
}
|
|
288
252
|
|
|
289
|
-
// ---------------------------------------------------------------------------
|
|
290
|
-
// app_list
|
|
291
|
-
// ---------------------------------------------------------------------------
|
|
292
|
-
|
|
293
|
-
export function executeAppList(store: AppStoreReader): ExecutorResult {
|
|
294
|
-
const apps = store.listApps().map((a) => ({
|
|
295
|
-
id: a.id,
|
|
296
|
-
name: a.name,
|
|
297
|
-
description: a.description,
|
|
298
|
-
updatedAt: a.updatedAt,
|
|
299
|
-
}));
|
|
300
|
-
return { content: JSON.stringify(apps), isError: false };
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// ---------------------------------------------------------------------------
|
|
304
|
-
// app_query
|
|
305
|
-
// ---------------------------------------------------------------------------
|
|
306
|
-
|
|
307
|
-
export interface AppQueryInput {
|
|
308
|
-
app_id: string;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
export function executeAppQuery(
|
|
312
|
-
input: AppQueryInput,
|
|
313
|
-
store: AppStoreReader,
|
|
314
|
-
): ExecutorResult {
|
|
315
|
-
const records = store.queryAppRecords(input.app_id);
|
|
316
|
-
return { content: JSON.stringify(records), isError: false };
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// ---------------------------------------------------------------------------
|
|
320
|
-
// app_update
|
|
321
|
-
// ---------------------------------------------------------------------------
|
|
322
|
-
|
|
323
|
-
export interface AppUpdateInput {
|
|
324
|
-
app_id: string;
|
|
325
|
-
name?: string;
|
|
326
|
-
description?: string;
|
|
327
|
-
schema_json?: string;
|
|
328
|
-
html?: string;
|
|
329
|
-
pages?: Record<string, string>;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
export function executeAppUpdate(
|
|
333
|
-
input: AppUpdateInput,
|
|
334
|
-
store: AppStore,
|
|
335
|
-
): ExecutorResult {
|
|
336
|
-
const updates: Partial<
|
|
337
|
-
Pick<
|
|
338
|
-
AppDefinition,
|
|
339
|
-
"name" | "description" | "schemaJson" | "htmlDefinition" | "pages"
|
|
340
|
-
>
|
|
341
|
-
> = {};
|
|
342
|
-
if (typeof input.name === "string") updates.name = input.name;
|
|
343
|
-
if (typeof input.description === "string")
|
|
344
|
-
updates.description = input.description;
|
|
345
|
-
if (typeof input.schema_json === "string")
|
|
346
|
-
updates.schemaJson = input.schema_json;
|
|
347
|
-
if (typeof input.html === "string") updates.htmlDefinition = input.html;
|
|
348
|
-
if (input.pages && typeof input.pages === "object")
|
|
349
|
-
updates.pages = input.pages;
|
|
350
|
-
|
|
351
|
-
const app = store.updateApp(input.app_id, updates);
|
|
352
|
-
return { content: JSON.stringify(app), isError: false };
|
|
353
|
-
}
|
|
354
|
-
|
|
355
253
|
// ---------------------------------------------------------------------------
|
|
356
254
|
// app_delete
|
|
357
255
|
// ---------------------------------------------------------------------------
|
|
@@ -372,131 +270,15 @@ export function executeAppDelete(
|
|
|
372
270
|
}
|
|
373
271
|
|
|
374
272
|
// ---------------------------------------------------------------------------
|
|
375
|
-
//
|
|
376
|
-
// ---------------------------------------------------------------------------
|
|
377
|
-
|
|
378
|
-
export interface AppFileListInput {
|
|
379
|
-
app_id: string;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
export function executeAppFileList(
|
|
383
|
-
input: AppFileListInput,
|
|
384
|
-
store: AppStoreReader,
|
|
385
|
-
): ExecutorResult {
|
|
386
|
-
const files = store.listAppFiles(input.app_id);
|
|
387
|
-
const app = store.getApp(input.app_id);
|
|
388
|
-
|
|
389
|
-
if (app && isMultifileApp(app)) {
|
|
390
|
-
// Separate build output paths from source paths without mutating the
|
|
391
|
-
// file path strings - consumers need clean paths for subsequent tool calls.
|
|
392
|
-
const buildOutputPaths = files.filter((f) =>
|
|
393
|
-
f.replace(/\\/g, "/").startsWith("dist/"),
|
|
394
|
-
);
|
|
395
|
-
return {
|
|
396
|
-
content: JSON.stringify({
|
|
397
|
-
files,
|
|
398
|
-
buildOutput: buildOutputPaths,
|
|
399
|
-
}),
|
|
400
|
-
isError: false,
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return { content: JSON.stringify(files), isError: false };
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// ---------------------------------------------------------------------------
|
|
408
|
-
// app_file_read
|
|
409
|
-
// ---------------------------------------------------------------------------
|
|
410
|
-
|
|
411
|
-
export interface AppFileReadInput {
|
|
412
|
-
app_id: string;
|
|
413
|
-
path: string;
|
|
414
|
-
offset?: number;
|
|
415
|
-
limit?: number;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
export function executeAppFileRead(
|
|
419
|
-
input: AppFileReadInput,
|
|
420
|
-
store: AppStoreReader,
|
|
421
|
-
): ExecutorResult {
|
|
422
|
-
const offset = input.offset ?? 1;
|
|
423
|
-
const limit = input.limit;
|
|
424
|
-
|
|
425
|
-
const app = store.getApp(input.app_id);
|
|
426
|
-
const resolvedPath = app ? resolveAppFilePath(app, input.path) : input.path;
|
|
427
|
-
const raw = store.readAppFile(input.app_id, resolvedPath);
|
|
428
|
-
const allLines = raw.split("\n");
|
|
429
|
-
const startIndex = Math.max(0, offset - 1);
|
|
430
|
-
const sliced =
|
|
431
|
-
limit != null
|
|
432
|
-
? allLines.slice(startIndex, startIndex + limit)
|
|
433
|
-
: allLines.slice(startIndex);
|
|
434
|
-
|
|
435
|
-
const formatted = sliced
|
|
436
|
-
.map((line, i) => {
|
|
437
|
-
const lineNum = startIndex + i + 1;
|
|
438
|
-
return `${String(lineNum).padStart(6)}\t${line}`;
|
|
439
|
-
})
|
|
440
|
-
.join("\n");
|
|
441
|
-
|
|
442
|
-
return { content: formatted, isError: false };
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// ---------------------------------------------------------------------------
|
|
446
|
-
// app_file_edit
|
|
447
|
-
// ---------------------------------------------------------------------------
|
|
448
|
-
|
|
449
|
-
export interface AppFileEditInput {
|
|
450
|
-
app_id: string;
|
|
451
|
-
path: string;
|
|
452
|
-
old_string: string;
|
|
453
|
-
new_string: string;
|
|
454
|
-
replace_all?: boolean;
|
|
455
|
-
status?: string;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
export function executeAppFileEdit(
|
|
459
|
-
input: AppFileEditInput,
|
|
460
|
-
store: AppStore,
|
|
461
|
-
): ExecutorResult {
|
|
462
|
-
if (!input.old_string) {
|
|
463
|
-
return {
|
|
464
|
-
content: JSON.stringify({ error: "old_string must not be empty" }),
|
|
465
|
-
isError: true,
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const app = store.getApp(input.app_id);
|
|
470
|
-
const resolvedPath = app ? resolveAppFilePath(app, input.path) : input.path;
|
|
471
|
-
|
|
472
|
-
const replaceAll = input.replace_all ?? false;
|
|
473
|
-
const result = store.editAppFile(
|
|
474
|
-
input.app_id,
|
|
475
|
-
resolvedPath,
|
|
476
|
-
input.old_string,
|
|
477
|
-
input.new_string,
|
|
478
|
-
replaceAll,
|
|
479
|
-
);
|
|
480
|
-
return {
|
|
481
|
-
content: JSON.stringify(result),
|
|
482
|
-
isError: false,
|
|
483
|
-
status: input.status,
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// ---------------------------------------------------------------------------
|
|
488
|
-
// app_file_write
|
|
273
|
+
// app_refresh
|
|
489
274
|
// ---------------------------------------------------------------------------
|
|
490
275
|
|
|
491
|
-
export interface
|
|
276
|
+
export interface AppRefreshInput {
|
|
492
277
|
app_id: string;
|
|
493
|
-
path: string;
|
|
494
|
-
content: string;
|
|
495
|
-
status?: string;
|
|
496
278
|
}
|
|
497
279
|
|
|
498
|
-
export function
|
|
499
|
-
input:
|
|
280
|
+
export function executeAppRefresh(
|
|
281
|
+
input: AppRefreshInput,
|
|
500
282
|
store: AppStore,
|
|
501
283
|
): ExecutorResult {
|
|
502
284
|
const app = store.getApp(input.app_id);
|
|
@@ -507,12 +289,16 @@ export function executeAppFileWrite(
|
|
|
507
289
|
};
|
|
508
290
|
}
|
|
509
291
|
|
|
510
|
-
|
|
511
|
-
|
|
292
|
+
// Empty update bumps updatedAt timestamp, triggering recompilation and
|
|
293
|
+
// surface refresh on the client side.
|
|
294
|
+
const updated = store.updateApp(input.app_id, {});
|
|
512
295
|
return {
|
|
513
|
-
content: JSON.stringify({
|
|
296
|
+
content: JSON.stringify({
|
|
297
|
+
refreshed: true,
|
|
298
|
+
appId: updated.id,
|
|
299
|
+
name: updated.name,
|
|
300
|
+
}),
|
|
514
301
|
isError: false,
|
|
515
|
-
status: input.status,
|
|
516
302
|
};
|
|
517
303
|
}
|
|
518
304
|
|
|
@@ -541,9 +327,8 @@ export async function executeAppGenerateIcon(
|
|
|
541
327
|
// destroying an existing icon if generation fails.
|
|
542
328
|
const { existsSync, renameSync, unlinkSync } = await import("node:fs");
|
|
543
329
|
const { join } = await import("node:path");
|
|
544
|
-
const
|
|
545
|
-
const
|
|
546
|
-
const tempPath = join(getAppsDir(), input.app_id, "icon.tmp.png");
|
|
330
|
+
const iconPath = join(getAppDirPath(input.app_id), "icon.png");
|
|
331
|
+
const tempPath = join(getAppDirPath(input.app_id), "icon.tmp.png");
|
|
547
332
|
|
|
548
333
|
// Temporarily move existing icon aside so generateAppIcon doesn't skip
|
|
549
334
|
if (existsSync(iconPath)) {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../../commands/cc-command-registry.js";
|
|
5
5
|
import { RiskLevel } from "../../permissions/types.js";
|
|
6
6
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
7
|
-
import {
|
|
7
|
+
import { getProviderKeyAsync } from "../../security/secure-keys.js";
|
|
8
8
|
import type { WorkerProfile } from "../../swarm/worker-backend.js";
|
|
9
9
|
import { getProfilePolicy } from "../../swarm/worker-backend.js";
|
|
10
10
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -203,8 +203,7 @@ export const claudeCodeTool: Tool = {
|
|
|
203
203
|
const profilePolicy = getProfilePolicy(profileName);
|
|
204
204
|
|
|
205
205
|
// Validate API key
|
|
206
|
-
const apiKey =
|
|
207
|
-
(await getSecureKeyAsync("anthropic")) ?? process.env.ANTHROPIC_API_KEY;
|
|
206
|
+
const apiKey = await getProviderKeyAsync("anthropic");
|
|
208
207
|
if (!apiKey) {
|
|
209
208
|
return {
|
|
210
209
|
content:
|
|
@@ -7,8 +7,8 @@ import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
|
|
|
7
7
|
import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
|
|
8
8
|
import {
|
|
9
9
|
disconnectOAuthProvider,
|
|
10
|
+
getActiveConnection,
|
|
10
11
|
getAppByProviderAndClientId,
|
|
11
|
-
getConnectionByProviderAndAccount,
|
|
12
12
|
getMostRecentAppByProvider,
|
|
13
13
|
getProvider,
|
|
14
14
|
} from "../../oauth/oauth-store.js";
|
|
@@ -66,9 +66,7 @@ async function storeSlackChannelCredential(
|
|
|
66
66
|
: setSlackChannelConfig(undefined, value);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
function formatSlackChannelStatus(
|
|
70
|
-
result: SlackChannelConfigResult,
|
|
71
|
-
): string {
|
|
69
|
+
function formatSlackChannelStatus(result: SlackChannelConfigResult): string {
|
|
72
70
|
if (result.connected) {
|
|
73
71
|
const teamLabel = result.teamName ?? "Slack";
|
|
74
72
|
const botLabel = result.botUsername ? ` (@${result.botUsername})` : "";
|
|
@@ -366,8 +364,7 @@ class CredentialStoreTool implements Tool {
|
|
|
366
364
|
if (!slackChannelResult.success) {
|
|
367
365
|
return {
|
|
368
366
|
content: `Error: ${
|
|
369
|
-
slackChannelResult.error ??
|
|
370
|
-
"failed to configure Slack channel"
|
|
367
|
+
slackChannelResult.error ?? "failed to configure Slack channel"
|
|
371
368
|
}`,
|
|
372
369
|
isError: true,
|
|
373
370
|
};
|
|
@@ -523,10 +520,9 @@ class CredentialStoreTool implements Tool {
|
|
|
523
520
|
const accountHint = input.account as string | undefined;
|
|
524
521
|
let oauthResult: "disconnected" | "not-found" | "error";
|
|
525
522
|
if (accountHint) {
|
|
526
|
-
const targetConn =
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
);
|
|
523
|
+
const targetConn = getActiveConnection(service, {
|
|
524
|
+
account: accountHint,
|
|
525
|
+
});
|
|
530
526
|
oauthResult = targetConn
|
|
531
527
|
? await disconnectOAuthProvider(service, undefined, targetConn.id)
|
|
532
528
|
: "not-found";
|
|
@@ -778,8 +774,7 @@ class CredentialStoreTool implements Tool {
|
|
|
778
774
|
if (!slackChannelResult.success) {
|
|
779
775
|
return {
|
|
780
776
|
content: `Error: ${
|
|
781
|
-
slackChannelResult.error ??
|
|
782
|
-
"failed to configure Slack channel"
|
|
777
|
+
slackChannelResult.error ?? "failed to configure Slack channel"
|
|
783
778
|
}`,
|
|
784
779
|
isError: true,
|
|
785
780
|
};
|
|
@@ -54,6 +54,19 @@ class HostFileReadTool implements Tool {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// Image files must be handled locally — the host-file proxy protocol
|
|
58
|
+
// only carries {content, isError} and cannot transport contentBlocks
|
|
59
|
+
// (base64 image data). Check for image extensions before the proxy
|
|
60
|
+
// short-circuit so image reads work in managed/macOS+iOS sessions.
|
|
61
|
+
const ext = extname(rawPath).toLowerCase();
|
|
62
|
+
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
63
|
+
const pathCheck = hostPolicy(rawPath);
|
|
64
|
+
if (!pathCheck.ok) {
|
|
65
|
+
return { content: `Error: ${pathCheck.error}`, isError: true };
|
|
66
|
+
}
|
|
67
|
+
return readImageFile(pathCheck.resolved);
|
|
68
|
+
}
|
|
69
|
+
|
|
57
70
|
// Proxy to connected client for execution on the user's machine
|
|
58
71
|
// when a capable client is available (managed/cloud-hosted mode).
|
|
59
72
|
if (context.hostFileProxy?.isAvailable()) {
|
|
@@ -69,16 +82,6 @@ class HostFileReadTool implements Tool {
|
|
|
69
82
|
);
|
|
70
83
|
}
|
|
71
84
|
|
|
72
|
-
// For image files, delegate to the shared image reader.
|
|
73
|
-
const ext = extname(rawPath).toLowerCase();
|
|
74
|
-
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
75
|
-
const pathCheck = hostPolicy(rawPath);
|
|
76
|
-
if (!pathCheck.ok) {
|
|
77
|
-
return { content: `Error: ${pathCheck.error}`, isError: true };
|
|
78
|
-
}
|
|
79
|
-
return readImageFile(pathCheck.resolved);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
85
|
const ops = new FileSystemOps(hostPolicy);
|
|
83
86
|
|
|
84
87
|
const result = ops.readFileSafe({
|
|
@@ -16,12 +16,14 @@ mock.module("../../registry.js", () => ({
|
|
|
16
16
|
|
|
17
17
|
mock.module("../../../config/loader.js", () => ({
|
|
18
18
|
getConfig: () => ({
|
|
19
|
-
|
|
19
|
+
services: {
|
|
20
|
+
"web-search": { provider: mockWebSearchProvider },
|
|
21
|
+
},
|
|
20
22
|
}),
|
|
21
23
|
}));
|
|
22
24
|
|
|
23
25
|
mock.module("../../../security/secure-keys.js", () => ({
|
|
24
|
-
|
|
26
|
+
getProviderKeyAsync: async (provider: string) => {
|
|
25
27
|
if (provider === "brave") return mockBraveSecureKey;
|
|
26
28
|
if (provider === "perplexity") return mockPerplexitySecureKey;
|
|
27
29
|
return undefined;
|
|
@@ -142,10 +142,17 @@ export class PermissionChecker {
|
|
|
142
142
|
// is the owner - prompting makes no sense when there is no client.
|
|
143
143
|
// Exception: requireFreshApproval tools cannot be auto-approved -
|
|
144
144
|
// without a human present, bundle installation must be denied.
|
|
145
|
+
// Exception: inline-command skill loads (skill_load_dynamic:*) must
|
|
146
|
+
// never be silently auto-approved — they execute embedded commands
|
|
147
|
+
// and require explicit human review or a pinned trust rule.
|
|
148
|
+
const isDynamicSkillLoad =
|
|
149
|
+
result.matchedRule?.pattern.startsWith("skill_load_dynamic:") ===
|
|
150
|
+
true;
|
|
145
151
|
if (
|
|
146
152
|
context.isInteractive === false &&
|
|
147
153
|
context.trustClass === "guardian" &&
|
|
148
|
-
!context.requireFreshApproval
|
|
154
|
+
!context.requireFreshApproval &&
|
|
155
|
+
!isDynamicSkillLoad
|
|
149
156
|
) {
|
|
150
157
|
log.info(
|
|
151
158
|
{ toolName: name, riskLevel },
|
|
@@ -62,15 +62,10 @@ export async function executeScheduleList(
|
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
lines.push(
|
|
66
|
-
` Enabled: ${job.enabled}`,
|
|
67
|
-
` Message: ${job.message}`,
|
|
68
|
-
);
|
|
65
|
+
lines.push(` Enabled: ${job.enabled}`, ` Message: ${job.message}`);
|
|
69
66
|
|
|
70
67
|
if (!oneShot) {
|
|
71
|
-
lines.push(
|
|
72
|
-
` Next run: ${formatLocalDate(job.nextRunAt)}`,
|
|
73
|
-
);
|
|
68
|
+
lines.push(` Next run: ${formatLocalDate(job.nextRunAt)}`);
|
|
74
69
|
}
|
|
75
70
|
|
|
76
71
|
lines.push(
|
|
@@ -29,7 +29,12 @@ export function injectActivityField(
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const properties = schema.properties as Record<string, unknown>;
|
|
32
|
+
|
|
32
33
|
if (schemaDefinesProperty(schema, "activity")) {
|
|
34
|
+
// Activity is already defined somewhere in the schema (top-level properties
|
|
35
|
+
// or composite sub-schemas). Don't modify schemas we don't own — MCP tools
|
|
36
|
+
// may define activity as intentionally optional or with server-specific
|
|
37
|
+
// semantics.
|
|
33
38
|
return def;
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -4,13 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export function formatEditDiff(oldString: string, newString: string): string {
|
|
6
6
|
const removed =
|
|
7
|
-
oldString.length > 0
|
|
8
|
-
? oldString.split("\n").map((l) => `- ${l}`)
|
|
9
|
-
: [];
|
|
7
|
+
oldString.length > 0 ? oldString.split("\n").map((l) => `- ${l}`) : [];
|
|
10
8
|
const added =
|
|
11
|
-
newString.length > 0
|
|
12
|
-
? newString.split("\n").map((l) => `+ ${l}`)
|
|
13
|
-
: [];
|
|
9
|
+
newString.length > 0 ? newString.split("\n").map((l) => `+ ${l}`) : [];
|
|
14
10
|
|
|
15
11
|
return [...removed, ...added].join("\n");
|
|
16
12
|
}
|
|
@@ -30,4 +26,3 @@ export function formatWriteSummary(
|
|
|
30
26
|
const oldLineCount = oldContent.split("\n").length;
|
|
31
27
|
return `(${oldLineCount} → ${newLineCount} lines)`;
|
|
32
28
|
}
|
|
33
|
-
|