@vellumai/assistant 0.4.56 → 0.4.57
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 +10 -10
- package/Dockerfile +3 -0
- package/README.md +11 -11
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/memory.md +3 -4
- package/docs/credential-execution-service.md +13 -20
- package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +7 -7
- package/src/__tests__/anthropic-provider.test.ts +172 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
- package/src/__tests__/approval-cascade.test.ts +2 -2
- package/src/__tests__/approval-routes-http.test.ts +3 -4
- package/src/__tests__/asset-materialize-tool.test.ts +5 -5
- package/src/__tests__/asset-search-tool.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +5 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
- package/src/__tests__/attachments-store.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +5 -3
- package/src/__tests__/browser-skill-endstate.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +2 -2
- package/src/__tests__/callback-handoff-copy.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +31 -32
- package/src/__tests__/chrome-cdp.test.ts +47 -18
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +9 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop.test.ts +11 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +33 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +23 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
- package/src/__tests__/conversation-seed-composer.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +4 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
- package/src/__tests__/conversation-starter-routes.test.ts +291 -0
- package/src/__tests__/conversation-wipe.test.ts +438 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
- package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
- package/src/__tests__/credential-security-e2e.test.ts +20 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +227 -0
- package/src/__tests__/credentials-cli.test.ts +3 -0
- package/src/__tests__/date-context.test.ts +59 -377
- package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/encrypted-store.test.ts +237 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +4 -4
- package/src/__tests__/gemini-provider.test.ts +6 -9
- package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/intent-routing.test.ts +51 -99
- package/src/__tests__/invite-routes-http.test.ts +5 -0
- package/src/__tests__/list-messages-attachments.test.ts +1 -1
- package/src/__tests__/managed-proxy-context.test.ts +2 -5
- package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
- package/src/__tests__/media-generate-image.test.ts +32 -15
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
- package/src/__tests__/memory-recall-quality.test.ts +4 -3
- package/src/__tests__/memory-regressions.test.ts +86 -90
- package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
- package/src/__tests__/migration-export-http.test.ts +26 -27
- package/src/__tests__/migration-import-commit-http.test.ts +165 -37
- package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
- package/src/__tests__/migration-validate-http.test.ts +16 -16
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/notification-broadcaster.test.ts +1 -1
- package/src/__tests__/notification-decision-fallback.test.ts +2 -2
- package/src/__tests__/notification-decision-identity.test.ts +8 -9
- package/src/__tests__/notification-decision-strategy.test.ts +1 -1
- package/src/__tests__/notification-deep-link.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
- package/src/__tests__/onboarding-template-contract.test.ts +23 -59
- package/src/__tests__/provider-error-scenarios.test.ts +154 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
- package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
- package/src/__tests__/provider-registry-ollama.test.ts +5 -2
- package/src/__tests__/qdrant-manager.test.ts +7 -7
- package/src/__tests__/ratelimit.test.ts +0 -74
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +46 -2
- package/src/__tests__/schema-transforms.test.ts +114 -54
- package/src/__tests__/secret-onetime-send.test.ts +20 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
- package/src/__tests__/secret-scanner-executor.test.ts +1 -2
- package/src/__tests__/send-endpoint-busy.test.ts +63 -4
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/shell-credential-ref.test.ts +0 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
- package/src/__tests__/skill-memory.test.ts +547 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
- package/src/__tests__/slack-channel-config.test.ts +109 -94
- package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
- package/src/__tests__/swarm-recursion.test.ts +2 -2
- package/src/__tests__/swarm-tool.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +19 -66
- package/src/__tests__/telegram-config.test.ts +121 -0
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trace-emitter.test.ts +8 -1
- package/src/__tests__/trust-store.test.ts +7 -8
- package/src/__tests__/twilio-routes.test.ts +1 -18
- package/src/__tests__/user-reference.test.ts +82 -2
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +3 -3
- package/src/avatar/ascii-renderer.ts +2 -2
- package/src/avatar/png-renderer.ts +2 -2
- package/src/avatar/resvg-lazy.ts +21 -0
- package/src/calls/guardian-dispatch.ts +1 -1
- package/src/calls/relay-access-wait.ts +2 -2
- package/src/calls/twilio-rest.ts +0 -248
- package/src/cli/AGENTS.md +5 -8
- package/src/cli/__tests__/notifications.test.ts +5 -5
- package/src/cli/commands/avatar.ts +64 -2
- package/src/cli/commands/conversations.ts +131 -1
- package/src/cli/commands/credentials.ts +2 -0
- package/src/cli/commands/notifications.ts +3 -3
- package/src/cli.ts +10 -0
- package/src/config/bundled-skills/acp/SKILL.md +5 -5
- package/src/config/bundled-skills/acp/TOOLS.json +6 -6
- package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
- package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
- package/src/config/bundled-skills/browser/SKILL.md +15 -15
- package/src/config/bundled-skills/browser/TOOLS.json +14 -14
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
- package/src/config/bundled-skills/contacts/SKILL.md +3 -3
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
- package/src/config/bundled-skills/document/SKILL.md +4 -4
- package/src/config/bundled-skills/document/TOOLS.json +2 -2
- package/src/config/bundled-skills/followups/TOOLS.json +3 -3
- package/src/config/bundled-skills/gmail/SKILL.md +32 -32
- package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
- package/src/config/bundled-skills/google-calendar/types.ts +1 -1
- package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
- package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
- package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +29 -25
- package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +3 -3
- package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
- package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
- package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
- package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
- package/src/config/bundled-skills/schedule/SKILL.md +26 -26
- package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
- package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
- package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +2 -2
- package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
- package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
- package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
- package/src/config/bundled-skills/slack/SKILL.md +2 -2
- package/src/config/bundled-skills/slack/TOOLS.json +8 -8
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
- package/src/config/bundled-skills/tasks/SKILL.md +1 -1
- package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
- package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
- package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
- package/src/config/bundled-skills/watcher/SKILL.md +4 -4
- package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/schemas/sandbox.ts +1 -1
- package/src/config/schemas/services.ts +13 -3
- package/src/config/schemas/timeouts.ts +0 -10
- package/src/contacts/contact-store.ts +63 -0
- package/src/contacts/contacts-write.ts +1 -1
- package/src/daemon/assistant-attachments.ts +2 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
- package/src/daemon/conversation-agent-loop.ts +7 -30
- package/src/daemon/conversation-error.ts +24 -0
- package/src/daemon/conversation-memory.ts +8 -7
- package/src/daemon/conversation-runtime-assembly.ts +139 -274
- package/src/daemon/conversation-slash.ts +7 -26
- package/src/daemon/conversation-surfaces.ts +14 -0
- package/src/daemon/conversation-tool-setup.ts +9 -8
- package/src/daemon/conversation.ts +2 -0
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +10 -83
- package/src/daemon/handlers/config-channels.ts +12 -2
- package/src/daemon/handlers/config-slack-channel.ts +7 -1
- package/src/daemon/handlers/config-telegram.ts +6 -1
- package/src/daemon/handlers/conversations.ts +2 -2
- package/src/daemon/handlers/skills.ts +4 -0
- package/src/daemon/lifecycle.ts +28 -4
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +1 -5
- package/src/daemon/shutdown-handlers.ts +9 -3
- package/src/daemon/tool-side-effects.ts +40 -0
- package/src/daemon/trace-emitter.ts +25 -2
- package/src/events/domain-events.ts +1 -1
- package/src/events/tool-permission-telemetry-listener.ts +46 -0
- package/src/inbound/platform-callback-registration.ts +0 -18
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +15 -8
- package/src/media/gemini-image-service.ts +125 -21
- package/src/memory/attachments-store.ts +3 -3
- package/src/memory/channel-verification-sessions.ts +6 -6
- package/src/memory/conversation-crud.ts +196 -1
- package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
- package/src/memory/conversation-title-service.ts +2 -3
- package/src/memory/db-init.ts +25 -1
- package/src/memory/invite-store.ts +4 -4
- package/src/memory/items-extractor.ts +4 -4
- package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/jobs-worker.ts +7 -5
- package/src/memory/lifecycle-events-store.ts +63 -0
- package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
- package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
- package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
- package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
- package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
- package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +223 -96
- package/src/memory/retriever.ts +115 -138
- package/src/memory/schema/calls.ts +1 -1
- package/src/memory/schema/contacts.ts +1 -1
- package/src/memory/schema/infrastructure.ts +29 -0
- package/src/memory/schema/memory-core.ts +7 -17
- package/src/memory/schema/notifications.ts +1 -1
- package/src/memory/search/formatting.ts +23 -6
- package/src/memory/search/lexical.ts +2 -0
- package/src/memory/search/semantic.ts +2 -0
- package/src/memory/search/staleness.ts +1 -0
- package/src/memory/search/types.ts +4 -0
- package/src/memory/task-memory-cleanup.ts +96 -6
- package/src/memory/trace-event-store.ts +148 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/emit-signal.ts +4 -4
- package/src/notifications/events-store.ts +4 -4
- package/src/notifications/signal.ts +1 -1
- package/src/oauth/manual-token-connection.ts +49 -25
- package/src/permissions/checker.ts +6 -5
- package/src/permissions/defaults.ts +4 -4
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
- package/src/prompts/cache-boundary.ts +8 -0
- package/src/prompts/system-prompt.ts +105 -634
- package/src/prompts/templates/BOOTSTRAP.md +166 -33
- package/src/prompts/templates/IDENTITY.md +8 -23
- package/src/prompts/templates/SOUL.md +20 -41
- package/src/prompts/templates/USER.md +3 -19
- package/src/prompts/user-reference.ts +14 -16
- package/src/providers/anthropic/client.ts +46 -2
- package/src/providers/gemini/client.ts +6 -9
- package/src/providers/managed-proxy/constants.ts +1 -7
- package/src/providers/managed-proxy/context.ts +0 -1
- package/src/providers/model-intents.ts +5 -5
- package/src/providers/openai/client.ts +10 -1
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/ratelimit.ts +0 -35
- package/src/providers/registry.ts +3 -5
- package/src/providers/retry.ts +18 -1
- package/src/runtime/access-request-helper.ts +1 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/channel-verification-service.ts +1 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/guardian-vellum-migration.ts +63 -1
- package/src/runtime/http-server.ts +8 -4
- package/src/runtime/migrations/vbundle-builder.ts +212 -32
- package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
- package/src/runtime/migrations/vbundle-importer.ts +66 -1
- package/src/runtime/migrations/vbundle-validator.ts +17 -3
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
- package/src/runtime/routes/attachment-routes.ts +2 -2
- package/src/runtime/routes/btw-routes.ts +9 -0
- package/src/runtime/routes/channel-verification-routes.ts +19 -2
- package/src/runtime/routes/conversation-management-routes.ts +55 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +49 -5
- package/src/runtime/routes/conversation-starter-routes.ts +207 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +25 -13
- package/src/runtime/routes/secret-routes.ts +18 -0
- package/src/runtime/routes/settings-routes.ts +8 -8
- package/src/runtime/routes/telemetry-routes.ts +53 -0
- package/src/runtime/routes/trace-event-routes.ts +62 -0
- package/src/runtime/tool-grant-request-helper.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +47 -31
- package/src/security/encrypted-store.ts +263 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +220 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/telemetry/usage-telemetry-reporter.ts +51 -4
- package/src/tools/AGENTS.md +11 -11
- package/src/tools/acp/spawn.ts +1 -1
- package/src/tools/apps/executors.ts +8 -8
- package/src/tools/apps/registry.ts +1 -1
- package/src/tools/assets/materialize.ts +6 -6
- package/src/tools/assets/search.ts +10 -10
- package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
- package/src/tools/browser/auth-detector.ts +6 -6
- package/src/tools/browser/browser-execution.ts +13 -13
- package/src/tools/browser/browser-manager.ts +3 -3
- package/src/tools/browser/chrome-cdp.ts +5 -5
- package/src/tools/browser/jit-auth.ts +2 -2
- package/src/tools/browser/network-recorder.test.ts +2 -2
- package/src/tools/browser/network-recorder.ts +3 -3
- package/src/tools/browser/runtime-check.ts +3 -3
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/computer-use/definitions.ts +18 -18
- package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
- package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
- package/src/tools/credentials/broker-types.ts +5 -5
- package/src/tools/credentials/broker.ts +15 -15
- package/src/tools/credentials/metadata-store.ts +2 -2
- package/src/tools/credentials/resolve.ts +1 -1
- package/src/tools/credentials/selection.ts +1 -1
- package/src/tools/credentials/tool-policy.ts +1 -1
- package/src/tools/credentials/vault.ts +115 -25
- package/src/tools/execution-target.ts +2 -2
- package/src/tools/executor.ts +7 -7
- package/src/tools/filesystem/edit.ts +2 -2
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -1
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +9 -8
- package/src/tools/mcp/mcp-tool-factory.ts +7 -6
- package/src/tools/memory/definitions.ts +6 -5
- package/src/tools/memory/handlers.test.ts +1 -1
- package/src/tools/network/__tests__/web-search.test.ts +3 -3
- package/src/tools/network/domain-normalize.ts +2 -2
- package/src/tools/network/script-proxy/session-manager.ts +10 -10
- package/src/tools/network/web-fetch.ts +1 -1
- package/src/tools/network/web-search.ts +3 -3
- package/src/tools/permission-checker.ts +8 -8
- package/src/tools/registry.ts +7 -7
- package/src/tools/schedule/list.ts +2 -2
- package/src/tools/schema-transforms.ts +31 -21
- package/src/tools/secret-detection-handler.ts +1 -1
- package/src/tools/sensitive-output-placeholders.ts +1 -1
- package/src/tools/shared/filesystem/edit-engine.ts +1 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
- package/src/tools/shared/filesystem/image-read.ts +25 -5
- package/src/tools/shared/filesystem/path-policy.ts +2 -2
- package/src/tools/shared/shell-output.ts +1 -1
- package/src/tools/side-effects.ts +1 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +3 -3
- package/src/tools/skills/sandbox-runner.ts +3 -3
- package/src/tools/subagent/read.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -2
- package/src/tools/swarm/delegate.ts +3 -3
- package/src/tools/system/request-permission.ts +5 -4
- package/src/tools/terminal/backends/native.ts +4 -4
- package/src/tools/terminal/parser.ts +6 -6
- package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
- package/src/tools/terminal/shell.ts +16 -16
- package/src/tools/tool-approval-handler.ts +21 -12
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +3 -3
- package/src/tools/ui-surface/definitions.ts +9 -37
- package/src/tools/watcher/list.ts +1 -1
- package/src/util/logger.ts +7 -2
- package/src/util/retry.ts +29 -1
- package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
- package/src/cli/reference.ts +0 -38
- package/src/memory/job-handlers/capability-cards.ts +0 -420
- package/src/runtime/routes/thread-starter-routes.ts +0 -294
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { describe, expect, it, mock } from "bun:test";
|
|
2
2
|
|
|
3
|
+
// Mock the persistence layer so tests are isolated from the database.
|
|
4
|
+
// getMaxSequence returning -1 means "no persisted events" → sequence starts at 0.
|
|
5
|
+
mock.module("../memory/trace-event-store.js", () => ({
|
|
6
|
+
getMaxSequence: () => -1,
|
|
7
|
+
persistTraceEvent: () => {},
|
|
8
|
+
}));
|
|
9
|
+
|
|
3
10
|
import type { ServerMessage, TraceEvent } from "../daemon/message-protocol.js";
|
|
4
11
|
import { TraceEmitter } from "../daemon/trace-emitter.js";
|
|
5
12
|
|
|
@@ -169,6 +176,6 @@ describe("TraceEmitter", () => {
|
|
|
169
176
|
expect(newSent).toHaveLength(1);
|
|
170
177
|
expect(newSent[0].summary).toBe("after");
|
|
171
178
|
// Sequence continues from where it left off
|
|
172
|
-
expect(newSent[0].sequence).toBe(1);
|
|
179
|
+
expect(newSent[0].sequence).toBe(sent[0].sequence + 1);
|
|
173
180
|
});
|
|
174
181
|
});
|
|
@@ -790,6 +790,7 @@ describe("Trust Store", () => {
|
|
|
790
790
|
"skill_execute",
|
|
791
791
|
"skill_load",
|
|
792
792
|
"ui_dismiss",
|
|
793
|
+
"ui_show",
|
|
793
794
|
"ui_update",
|
|
794
795
|
]);
|
|
795
796
|
});
|
|
@@ -922,16 +923,14 @@ describe("Trust Store", () => {
|
|
|
922
923
|
expect(match!.id).toBe("default:allow-bash-rm-bootstrap");
|
|
923
924
|
expect(match!.decision).toBe("allow");
|
|
924
925
|
expect(match!.allowHighRisk).toBe(true);
|
|
925
|
-
// Outside workspace, the bootstrap rule doesn't match —
|
|
926
|
-
// default
|
|
926
|
+
// Outside workspace, the bootstrap rule doesn't match — with sandbox
|
|
927
|
+
// disabled (the default), there is no catch-all bash allow rule either.
|
|
927
928
|
const other = findHighestPriorityRule(
|
|
928
929
|
"bash",
|
|
929
930
|
["rm BOOTSTRAP.md"],
|
|
930
931
|
"/tmp/other-project",
|
|
931
932
|
);
|
|
932
|
-
expect(other).
|
|
933
|
-
expect(other!.id).not.toBe("default:allow-bash-rm-bootstrap");
|
|
934
|
-
expect(other!.id).toBe("default:allow-bash-global");
|
|
933
|
+
expect(other).toBeNull();
|
|
935
934
|
});
|
|
936
935
|
|
|
937
936
|
test("updates delete rule matches only when workingDir is the workspace dir", () => {
|
|
@@ -945,14 +944,14 @@ describe("Trust Store", () => {
|
|
|
945
944
|
expect(match!.id).toBe("default:allow-bash-rm-updates");
|
|
946
945
|
expect(match!.decision).toBe("allow");
|
|
947
946
|
expect(match!.allowHighRisk).toBe(true);
|
|
948
|
-
// Outside workspace, should NOT match the updates rule
|
|
947
|
+
// Outside workspace, should NOT match the updates rule — with sandbox
|
|
948
|
+
// disabled (the default), there is no catch-all bash allow rule either.
|
|
949
949
|
const other = findHighestPriorityRule(
|
|
950
950
|
"bash",
|
|
951
951
|
["rm UPDATES.md"],
|
|
952
952
|
"/tmp/other-project",
|
|
953
953
|
);
|
|
954
|
-
expect(other).
|
|
955
|
-
expect(other!.id).not.toBe("default:allow-bash-rm-updates");
|
|
954
|
+
expect(other).toBeNull();
|
|
956
955
|
});
|
|
957
956
|
|
|
958
957
|
test("default ask does not affect files outside protected directory", () => {
|
|
@@ -121,7 +121,7 @@ const mockConfigObj = {
|
|
|
121
121
|
model: "test",
|
|
122
122
|
provider: "test",
|
|
123
123
|
memory: { enabled: false },
|
|
124
|
-
rateLimit: { maxRequestsPerMinute: 0
|
|
124
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
125
125
|
secretDetection: { enabled: false },
|
|
126
126
|
elevenlabs: { voiceId: DEFAULT_ELEVENLABS_VOICE_ID },
|
|
127
127
|
calls: {
|
|
@@ -183,11 +183,8 @@ mock.module("../calls/twilio-config.js", () => ({
|
|
|
183
183
|
}));
|
|
184
184
|
|
|
185
185
|
mock.module("../calls/twilio-rest.js", () => ({
|
|
186
|
-
deleteTollFreeVerification: async () => {},
|
|
187
186
|
fetchMessageStatus: async () => ({ status: "delivered" }),
|
|
188
187
|
getPhoneNumberSid: async () => "PN_test",
|
|
189
|
-
getTollFreeVerificationBySid: async () => null,
|
|
190
|
-
getTollFreeVerificationStatus: async () => null,
|
|
191
188
|
getTwilioCredentials: () => ({
|
|
192
189
|
accountSid: readMockTwilioAccountSid() ?? "",
|
|
193
190
|
authToken: readMockTwilioAuthToken() ?? "",
|
|
@@ -205,20 +202,6 @@ mock.module("../calls/twilio-rest.js", () => ({
|
|
|
205
202
|
}),
|
|
206
203
|
releasePhoneNumber: async () => {},
|
|
207
204
|
searchAvailableNumbers: async () => mockAvailableNumbers,
|
|
208
|
-
submitTollFreeVerification: async () => ({
|
|
209
|
-
sid: "VF_test",
|
|
210
|
-
status: "PENDING_REVIEW",
|
|
211
|
-
}),
|
|
212
|
-
updateTollFreeVerification: async (
|
|
213
|
-
_accountSid: string,
|
|
214
|
-
_authToken: string,
|
|
215
|
-
verificationSid: string,
|
|
216
|
-
) => ({
|
|
217
|
-
sid: verificationSid,
|
|
218
|
-
status: "PENDING_REVIEW",
|
|
219
|
-
editAllowed: true,
|
|
220
|
-
editExpiration: undefined,
|
|
221
|
-
}),
|
|
222
205
|
updatePhoneNumberWebhooks: async (
|
|
223
206
|
accountSid: string,
|
|
224
207
|
authToken: string,
|
|
@@ -26,8 +26,12 @@ mock.module("node:fs", () => ({
|
|
|
26
26
|
}));
|
|
27
27
|
|
|
28
28
|
// Import after mocks are in place
|
|
29
|
-
const {
|
|
30
|
-
|
|
29
|
+
const {
|
|
30
|
+
resolveUserReference,
|
|
31
|
+
resolveUserPronouns,
|
|
32
|
+
resolveGuardianName,
|
|
33
|
+
DEFAULT_USER_REFERENCE,
|
|
34
|
+
} = await import("../prompts/user-reference.js");
|
|
31
35
|
|
|
32
36
|
describe("resolveUserReference", () => {
|
|
33
37
|
beforeEach(() => {
|
|
@@ -71,6 +75,82 @@ describe("resolveUserReference", () => {
|
|
|
71
75
|
});
|
|
72
76
|
});
|
|
73
77
|
|
|
78
|
+
describe("resolveUserPronouns", () => {
|
|
79
|
+
beforeEach(() => {
|
|
80
|
+
mockFileExists = false;
|
|
81
|
+
mockFileContent = "";
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("returns null when USER.md does not exist", () => {
|
|
85
|
+
mockFileExists = false;
|
|
86
|
+
expect(resolveUserPronouns()).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("returns pronouns from flat USER.md (no Onboarding Snapshot)", () => {
|
|
90
|
+
mockFileExists = true;
|
|
91
|
+
mockFileContent = [
|
|
92
|
+
"# USER.md",
|
|
93
|
+
"",
|
|
94
|
+
"- Preferred name/reference: Alice",
|
|
95
|
+
"- Pronouns: she/her",
|
|
96
|
+
"- Locale: en-US",
|
|
97
|
+
].join("\n");
|
|
98
|
+
expect(resolveUserPronouns()).toBe("she/her");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("returns null when pronouns field is empty in flat format", () => {
|
|
102
|
+
mockFileExists = true;
|
|
103
|
+
mockFileContent = [
|
|
104
|
+
"# USER.md",
|
|
105
|
+
"",
|
|
106
|
+
"- Preferred name/reference: Alice",
|
|
107
|
+
"- Pronouns:",
|
|
108
|
+
"- Locale: en-US",
|
|
109
|
+
].join("\n");
|
|
110
|
+
expect(resolveUserPronouns()).toBeNull();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("returns pronouns from legacy Onboarding Snapshot section", () => {
|
|
114
|
+
mockFileExists = true;
|
|
115
|
+
mockFileContent = [
|
|
116
|
+
"## Onboarding Snapshot",
|
|
117
|
+
"",
|
|
118
|
+
"- Pronouns: they/them",
|
|
119
|
+
].join("\n");
|
|
120
|
+
expect(resolveUserPronouns()).toBe("they/them");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("prefers pronouns above Onboarding Snapshot over inside it", () => {
|
|
124
|
+
mockFileExists = true;
|
|
125
|
+
mockFileContent = [
|
|
126
|
+
"Pronouns: he/him",
|
|
127
|
+
"",
|
|
128
|
+
"## Onboarding Snapshot",
|
|
129
|
+
"",
|
|
130
|
+
"- Pronouns: she/her",
|
|
131
|
+
].join("\n");
|
|
132
|
+
expect(resolveUserPronouns()).toBe("he/him");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("returns null for declined_by_user", () => {
|
|
136
|
+
mockFileExists = true;
|
|
137
|
+
mockFileContent = [
|
|
138
|
+
"- Preferred name/reference: Alice",
|
|
139
|
+
"- Pronouns: declined_by_user",
|
|
140
|
+
].join("\n");
|
|
141
|
+
expect(resolveUserPronouns()).toBeNull();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("strips inferred: prefix", () => {
|
|
145
|
+
mockFileExists = true;
|
|
146
|
+
mockFileContent = [
|
|
147
|
+
"- Preferred name/reference: Alice",
|
|
148
|
+
"- Pronouns: inferred: she/her",
|
|
149
|
+
].join("\n");
|
|
150
|
+
expect(resolveUserPronouns()).toBe("she/her");
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
74
154
|
describe("resolveGuardianName", () => {
|
|
75
155
|
beforeEach(() => {
|
|
76
156
|
mockFileExists = false;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for PAX extended header round-trip and symlinked skills directory
|
|
3
|
+
* handling in the vbundle builder/validator.
|
|
4
|
+
*
|
|
5
|
+
* Covers:
|
|
6
|
+
* - Builder emits PAX headers for paths >100 bytes; validator parses them
|
|
7
|
+
* - buildExportVBundle follows symlinks when checking skillsDir
|
|
8
|
+
*/
|
|
9
|
+
import {
|
|
10
|
+
mkdirSync,
|
|
11
|
+
mkdtempSync,
|
|
12
|
+
realpathSync,
|
|
13
|
+
rmSync,
|
|
14
|
+
symlinkSync,
|
|
15
|
+
writeFileSync,
|
|
16
|
+
} from "node:fs";
|
|
17
|
+
import { tmpdir } from "node:os";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { afterAll, describe, expect, mock, test } from "bun:test";
|
|
20
|
+
|
|
21
|
+
const testDir = realpathSync(
|
|
22
|
+
mkdtempSync(join(tmpdir(), "vbundle-pax-symlink-test-")),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
mock.module("../util/platform.js", () => ({
|
|
26
|
+
getRootDir: () => testDir,
|
|
27
|
+
getDataDir: () => testDir,
|
|
28
|
+
isMacOS: () => process.platform === "darwin",
|
|
29
|
+
isLinux: () => process.platform === "linux",
|
|
30
|
+
isWindows: () => process.platform === "win32",
|
|
31
|
+
getPidPath: () => join(testDir, "test.pid"),
|
|
32
|
+
getDbPath: () => join(testDir, "test.db"),
|
|
33
|
+
getLogPath: () => join(testDir, "test.log"),
|
|
34
|
+
ensureDataDir: () => {},
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
mock.module("../util/logger.js", () => ({
|
|
38
|
+
getLogger: () =>
|
|
39
|
+
new Proxy({} as Record<string, unknown>, {
|
|
40
|
+
get: () => () => {},
|
|
41
|
+
}),
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
mock.module("../config/loader.js", () => ({
|
|
45
|
+
getConfig: () => ({
|
|
46
|
+
ui: {},
|
|
47
|
+
model: "test",
|
|
48
|
+
provider: "test",
|
|
49
|
+
memory: { enabled: false },
|
|
50
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
51
|
+
secretDetection: { enabled: false },
|
|
52
|
+
}),
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
mock.module("../config/env.js", () => ({
|
|
56
|
+
isHttpAuthDisabled: () => true,
|
|
57
|
+
hasUngatedHttpAuthDisabled: () => false,
|
|
58
|
+
getGatewayInternalBaseUrl: () => "http://127.0.0.1:7830",
|
|
59
|
+
getGatewayPort: () => 7830,
|
|
60
|
+
getRuntimeHttpPort: () => 7821,
|
|
61
|
+
getRuntimeHttpHost: () => "127.0.0.1",
|
|
62
|
+
getRuntimeGatewayOriginSecret: () => undefined,
|
|
63
|
+
getIngressPublicBaseUrl: () => undefined,
|
|
64
|
+
setIngressPublicBaseUrl: () => {},
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
import {
|
|
68
|
+
buildExportVBundle,
|
|
69
|
+
buildVBundle,
|
|
70
|
+
} from "../runtime/migrations/vbundle-builder.js";
|
|
71
|
+
import { validateVBundle } from "../runtime/migrations/vbundle-validator.js";
|
|
72
|
+
|
|
73
|
+
afterAll(() => {
|
|
74
|
+
try {
|
|
75
|
+
rmSync(testDir, { recursive: true });
|
|
76
|
+
} catch {
|
|
77
|
+
/* best effort */
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// PAX header round-trip
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
describe("PAX extended header round-trip", () => {
|
|
86
|
+
test("builder + validator round-trip for paths >100 bytes", () => {
|
|
87
|
+
// Create a path that exceeds the 100-byte ustar limit
|
|
88
|
+
const longPath =
|
|
89
|
+
"skills/" +
|
|
90
|
+
"a".repeat(50) +
|
|
91
|
+
"/" +
|
|
92
|
+
"b".repeat(50) +
|
|
93
|
+
"/very-long-skill-name-that-exceeds-limit.md";
|
|
94
|
+
expect(new TextEncoder().encode(longPath).length).toBeGreaterThan(100);
|
|
95
|
+
|
|
96
|
+
const fileData = new TextEncoder().encode("# Long path skill content");
|
|
97
|
+
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
98
|
+
|
|
99
|
+
const { archive } = buildVBundle({
|
|
100
|
+
files: [
|
|
101
|
+
{ path: "data/db/assistant.db", data: dbData },
|
|
102
|
+
{ path: longPath, data: fileData },
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Validate: should succeed — validator must parse the PAX header
|
|
107
|
+
const result = validateVBundle(archive);
|
|
108
|
+
expect(result.errors).toEqual([]);
|
|
109
|
+
expect(result.is_valid).toBe(true);
|
|
110
|
+
expect(result.manifest).toBeDefined();
|
|
111
|
+
|
|
112
|
+
// The long-path file should appear in the entry map with its full name
|
|
113
|
+
expect(result.entries?.has(longPath)).toBe(true);
|
|
114
|
+
const entry = result.entries?.get(longPath);
|
|
115
|
+
expect(entry?.size).toBe(fileData.length);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("validator rejects long-path file with wrong checksum", () => {
|
|
119
|
+
const longPath =
|
|
120
|
+
"skills/" + "x".repeat(60) + "/" + "y".repeat(60) + "/skill.md";
|
|
121
|
+
expect(new TextEncoder().encode(longPath).length).toBeGreaterThan(100);
|
|
122
|
+
|
|
123
|
+
const fileData = new TextEncoder().encode("content");
|
|
124
|
+
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
125
|
+
|
|
126
|
+
// Build archive, then re-validate — should pass first
|
|
127
|
+
const { archive } = buildVBundle({
|
|
128
|
+
files: [
|
|
129
|
+
{ path: "data/db/assistant.db", data: dbData },
|
|
130
|
+
{ path: longPath, data: fileData },
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const result = validateVBundle(archive);
|
|
135
|
+
expect(result.is_valid).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("short paths (<= 100 bytes) do not emit PAX headers", () => {
|
|
139
|
+
const shortPath = "config/settings.json";
|
|
140
|
+
expect(new TextEncoder().encode(shortPath).length).toBeLessThanOrEqual(100);
|
|
141
|
+
|
|
142
|
+
const fileData = new TextEncoder().encode("{}");
|
|
143
|
+
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
144
|
+
|
|
145
|
+
const { archive } = buildVBundle({
|
|
146
|
+
files: [
|
|
147
|
+
{ path: "data/db/assistant.db", data: dbData },
|
|
148
|
+
{ path: shortPath, data: fileData },
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const result = validateVBundle(archive);
|
|
153
|
+
expect(result.is_valid).toBe(true);
|
|
154
|
+
expect(result.entries?.has(shortPath)).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Symlinked skills directory
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
describe("buildExportVBundle with symlinked skills directory", () => {
|
|
163
|
+
test("skips symlinked directory inside workspace", () => {
|
|
164
|
+
// Set up: workspace with a real skills dir and a symlinked dir
|
|
165
|
+
const wsDir = join(testDir, "export-workspace");
|
|
166
|
+
const realSkillsDir = join(testDir, "real-skills");
|
|
167
|
+
mkdirSync(realSkillsDir, { recursive: true });
|
|
168
|
+
writeFileSync(join(realSkillsDir, "my-skill.md"), "# Skill");
|
|
169
|
+
|
|
170
|
+
// Create workspace with a symlink to the skills dir — walkDirectory
|
|
171
|
+
// skips symlinks, so the symlinked dir should not appear in the archive.
|
|
172
|
+
mkdirSync(join(wsDir, "skills"), { recursive: true });
|
|
173
|
+
writeFileSync(join(wsDir, "skills", "real-skill.md"), "# Real");
|
|
174
|
+
symlinkSync(realSkillsDir, join(wsDir, "linked-skills"));
|
|
175
|
+
|
|
176
|
+
const { archive, manifest } = buildExportVBundle({
|
|
177
|
+
workspaceDir: wsDir,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Validate archive
|
|
181
|
+
const result = validateVBundle(archive);
|
|
182
|
+
expect(result.is_valid).toBe(true);
|
|
183
|
+
|
|
184
|
+
// Real skill file is in the manifest under workspace/ prefix
|
|
185
|
+
const realSkill = manifest.files.find(
|
|
186
|
+
(f) => f.path === "workspace/skills/real-skill.md",
|
|
187
|
+
);
|
|
188
|
+
expect(realSkill).toBeDefined();
|
|
189
|
+
|
|
190
|
+
// Symlinked directory is skipped
|
|
191
|
+
const linkedSkill = manifest.files.find(
|
|
192
|
+
(f) => f.path === "workspace/linked-skills/my-skill.md",
|
|
193
|
+
);
|
|
194
|
+
expect(linkedSkill).toBeUndefined();
|
|
195
|
+
});
|
|
196
|
+
});
|
|
@@ -399,7 +399,7 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
399
399
|
void emitNotificationSignal({
|
|
400
400
|
sourceEventName: "ingress.trusted_contact.guardian_decision",
|
|
401
401
|
sourceChannel: channel,
|
|
402
|
-
|
|
402
|
+
sourceContextId: request.conversationId ?? "",
|
|
403
403
|
attentionHints: {
|
|
404
404
|
requiresAction: false,
|
|
405
405
|
urgency: "medium",
|
|
@@ -413,7 +413,7 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
413
413
|
void emitNotificationSignal({
|
|
414
414
|
sourceEventName: "ingress.trusted_contact.denied",
|
|
415
415
|
sourceChannel: channel,
|
|
416
|
-
|
|
416
|
+
sourceContextId: request.conversationId ?? "",
|
|
417
417
|
attentionHints: {
|
|
418
418
|
requiresAction: false,
|
|
419
419
|
urgency: "low",
|
|
@@ -590,7 +590,7 @@ const accessRequestResolver: GuardianRequestResolver = {
|
|
|
590
590
|
void emitNotificationSignal({
|
|
591
591
|
sourceEventName: "ingress.trusted_contact.verification_sent",
|
|
592
592
|
sourceChannel: channel,
|
|
593
|
-
|
|
593
|
+
sourceContextId: request.conversationId ?? "",
|
|
594
594
|
attentionHints: {
|
|
595
595
|
requiresAction: false,
|
|
596
596
|
urgency: "low",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { getResvg } from "./resvg-lazy.js";
|
|
3
2
|
import { composeSvg } from "./svg-compositor.js";
|
|
4
3
|
|
|
5
4
|
const RAMP = " .·:;+=xX$&@";
|
|
@@ -25,6 +24,7 @@ export function renderCharacterAscii(
|
|
|
25
24
|
): string {
|
|
26
25
|
const renderSize = width * 2;
|
|
27
26
|
const svg = composeSvg(bodyShapeId, eyeStyleId, colorId, renderSize);
|
|
27
|
+
const Resvg = getResvg();
|
|
28
28
|
const resvg = new Resvg(svg, {
|
|
29
29
|
fitTo: { mode: "width", value: renderSize },
|
|
30
30
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { getResvg } from "./resvg-lazy.js";
|
|
3
2
|
import { composeSvg } from "./svg-compositor.js";
|
|
4
3
|
|
|
5
4
|
export function renderCharacterPng(
|
|
@@ -9,6 +8,7 @@ export function renderCharacterPng(
|
|
|
9
8
|
size = 512,
|
|
10
9
|
): Buffer {
|
|
11
10
|
const svg = composeSvg(bodyShapeId, eyeStyleId, colorId, size);
|
|
11
|
+
const Resvg = getResvg();
|
|
12
12
|
const resvg = new Resvg(svg, {
|
|
13
13
|
fitTo: { mode: "width", value: size },
|
|
14
14
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Resvg as ResvgType } from "@resvg/resvg-js";
|
|
2
|
+
|
|
3
|
+
let ResvgClass: typeof ResvgType | undefined;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the Resvg constructor, loading the native module on first call.
|
|
7
|
+
* Defers the native-addon require so the daemon can start even when the
|
|
8
|
+
* platform-specific binary is unavailable (e.g. inside a bun --compile
|
|
9
|
+
* single-file executable).
|
|
10
|
+
*/
|
|
11
|
+
export function getResvg(): typeof ResvgType {
|
|
12
|
+
if (!ResvgClass) {
|
|
13
|
+
// Inline require is necessary here: @resvg/resvg-js loads a platform-specific
|
|
14
|
+
// native .node addon at import time. A top-level import would crash the daemon
|
|
15
|
+
// on startup inside bun --compile binaries where native addons are unavailable.
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
+
const mod = require("@resvg/resvg-js") as typeof import("@resvg/resvg-js");
|
|
18
|
+
ResvgClass = mod.Resvg;
|
|
19
|
+
}
|
|
20
|
+
return ResvgClass;
|
|
21
|
+
}
|
|
@@ -204,7 +204,7 @@ async function dispatchGuardianQuestionInner(
|
|
|
204
204
|
const signalResult = await emitNotificationSignal({
|
|
205
205
|
sourceEventName: "guardian.question",
|
|
206
206
|
sourceChannel: "phone",
|
|
207
|
-
|
|
207
|
+
sourceContextId: callSessionId,
|
|
208
208
|
attentionHints: {
|
|
209
209
|
requiresAction: true,
|
|
210
210
|
urgency: "high",
|
|
@@ -271,14 +271,14 @@ export function emitAccessRequestCallbackHandoff(
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
const dedupeKey = `access-request-callback-handoff:${params.accessRequestId}`;
|
|
274
|
-
const
|
|
274
|
+
const sourceContextId =
|
|
275
275
|
canonicalRequest?.conversationId ??
|
|
276
276
|
`access-req-callback-${params.accessRequestId}`;
|
|
277
277
|
|
|
278
278
|
void emitNotificationSignal({
|
|
279
279
|
sourceEventName: "ingress.access_request.callback_handoff",
|
|
280
280
|
sourceChannel: "phone",
|
|
281
|
-
|
|
281
|
+
sourceContextId,
|
|
282
282
|
attentionHints: {
|
|
283
283
|
requiresAction: false,
|
|
284
284
|
urgency: "medium",
|