@vellumai/assistant 0.5.16 → 0.6.0
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 +1 -1
- package/Dockerfile +0 -3
- package/knip.json +2 -1
- package/openapi.yaml +660 -80
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +57 -3
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +25 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/cli-memory.test.ts +74 -69
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +9 -0
- package/src/__tests__/conversation-agent-loop.test.ts +9 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +5 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +11 -408
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +2 -0
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +154 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +292 -0
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -14
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/llm-context-route-provider.test.ts +2 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +2 -6
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +2 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/search-skills-unified.test.ts +421 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +2 -6
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +11 -11
- package/src/__tests__/skill-memory.test.ts +140 -98
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +173 -229
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +1 -15
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/cli-memory.ts +67 -64
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/memory.ts +41 -55
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +11 -6
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/skills.ts +88 -16
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +2 -10
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +10 -18
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/slack/SKILL.md +1 -7
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +15 -8
- package/src/config/feature-flag-registry.json +21 -124
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
- package/src/daemon/conversation-agent-loop.ts +96 -61
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-lifecycle.ts +33 -0
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-runtime-assembly.ts +5 -0
- package/src/daemon/conversation.ts +41 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/handlers/shared.ts +22 -12
- package/src/daemon/handlers/skills.ts +416 -202
- package/src/daemon/lifecycle.ts +40 -1
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +4 -1
- package/src/daemon/message-types/messages.ts +3 -1
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +11 -2
- package/src/daemon/tool-side-effects.ts +27 -5
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/memory/admin.ts +11 -45
- package/src/memory/conversation-bootstrap.ts +2 -0
- package/src/memory/conversation-crud.ts +242 -348
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +4 -2
- package/src/memory/db-init.ts +30 -3
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +512 -0
- package/src/memory/graph/capability-seed.ts +297 -0
- package/src/memory/graph/consolidation.ts +691 -0
- package/src/memory/graph/conversation-graph-memory.ts +630 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +69 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1254 -0
- package/src/memory/graph/graph-search.ts +266 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +439 -0
- package/src/memory/graph/inspect.ts +534 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1008 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1050 -0
- package/src/memory/graph/store.ts +699 -0
- package/src/memory/graph/tool-handlers.ts +426 -0
- package/src/memory/graph/tools.ts +141 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +271 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +0 -53
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +50 -70
- package/src/memory/jobs-worker.ts +147 -112
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +28 -50
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +24 -3
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/workspace-policy.ts +1 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +3 -29
- package/src/providers/anthropic/client.ts +47 -19
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +23 -3
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +8 -0
- package/src/runtime/routes/conversation-management-routes.ts +2 -0
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/memory-item-routes.test.ts +2 -14
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/schedule/scheduler.ts +8 -1
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +15 -14
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +27 -16
- package/src/skills/skill-memory.ts +152 -77
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/tasks/task-runner.ts +3 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +7 -1
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +3 -3
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { and, eq } from "drizzle-orm";
|
|
1
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
|
+
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
4
5
|
import { getConfig } from "../config/loader.js";
|
|
5
6
|
import { resolveSkillStates } from "../config/skill-state.js";
|
|
6
7
|
import { loadSkillCatalog, type SkillSummary } from "../config/skills.js";
|
|
7
8
|
import { getDb } from "../memory/db.js";
|
|
8
|
-
import { computeMemoryFingerprint } from "../memory/fingerprint.js";
|
|
9
9
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
10
|
-
import {
|
|
10
|
+
import { memoryGraphNodes } from "../memory/schema.js";
|
|
11
11
|
import { getLogger } from "../util/logger.js";
|
|
12
|
+
import { getCachedCatalogSync } from "./catalog-cache.js";
|
|
13
|
+
import type { CatalogSkill } from "./catalog-install.js";
|
|
12
14
|
|
|
13
15
|
const log = getLogger("skill-memory");
|
|
14
16
|
|
|
17
|
+
/** Escape SQL LIKE wildcards so they match literally.
|
|
18
|
+
* Uses backslash as the escape character — callers must pair with ESCAPE '\\'. */
|
|
19
|
+
function escapeLike(s: string): string {
|
|
20
|
+
return s.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
/**
|
|
16
24
|
* Generic input for building capability statements.
|
|
17
25
|
* Decoupled from CatalogSkill so other skill sources (e.g. bundled skills) can
|
|
@@ -39,6 +47,20 @@ export function fromSkillSummary(entry: SkillSummary): SkillCapabilityInput {
|
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Convert a CatalogSkill to a SkillCapabilityInput.
|
|
52
|
+
* CatalogSkill stores display-name and hints inside nested metadata.
|
|
53
|
+
*/
|
|
54
|
+
export function fromCatalogSkill(entry: CatalogSkill): SkillCapabilityInput {
|
|
55
|
+
return {
|
|
56
|
+
id: entry.id,
|
|
57
|
+
displayName: entry.metadata?.vellum?.["display-name"] ?? entry.name,
|
|
58
|
+
description: entry.description,
|
|
59
|
+
activationHints: entry.metadata?.vellum?.["activation-hints"],
|
|
60
|
+
avoidWhen: entry.metadata?.vellum?.["avoid-when"],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
42
64
|
/**
|
|
43
65
|
* Build a semantically rich capability statement from a skill capability input.
|
|
44
66
|
* Truncated to 500 chars max (matching the limit used by memory item extraction).
|
|
@@ -62,8 +84,17 @@ export function buildCapabilityStatement(input: SkillCapabilityInput): string {
|
|
|
62
84
|
return statement;
|
|
63
85
|
}
|
|
64
86
|
|
|
87
|
+
/** Default emotional charge for capability graph nodes. */
|
|
88
|
+
const DEFAULT_EMOTIONAL_CHARGE = JSON.stringify({
|
|
89
|
+
valence: 0,
|
|
90
|
+
intensity: 0.1,
|
|
91
|
+
decayCurve: "linear",
|
|
92
|
+
decayRate: 0.05,
|
|
93
|
+
originalIntensity: 0.1,
|
|
94
|
+
});
|
|
95
|
+
|
|
65
96
|
/**
|
|
66
|
-
* Upsert a capability memory
|
|
97
|
+
* Upsert a capability memory graph node for a skill.
|
|
67
98
|
* Best-effort: errors are logged but never thrown.
|
|
68
99
|
*/
|
|
69
100
|
export function upsertSkillCapabilityMemory(
|
|
@@ -72,124 +103,121 @@ export function upsertSkillCapabilityMemory(
|
|
|
72
103
|
): void {
|
|
73
104
|
try {
|
|
74
105
|
const db = getDb();
|
|
75
|
-
const subject = `skill:${skillId}`;
|
|
76
106
|
const statement = buildCapabilityStatement(input);
|
|
77
|
-
const
|
|
107
|
+
const content = `skill:${skillId}\n${statement}`;
|
|
78
108
|
const scopeId = "default";
|
|
79
|
-
const confidence = 1.0;
|
|
80
|
-
const importance = 0.7;
|
|
81
|
-
const fingerprint = computeMemoryFingerprint(
|
|
82
|
-
scopeId,
|
|
83
|
-
kind,
|
|
84
|
-
subject,
|
|
85
|
-
statement,
|
|
86
|
-
);
|
|
87
109
|
const now = Date.now();
|
|
88
110
|
|
|
89
111
|
const existing = db
|
|
90
112
|
.select()
|
|
91
|
-
.from(
|
|
113
|
+
.from(memoryGraphNodes)
|
|
92
114
|
.where(
|
|
93
115
|
and(
|
|
94
|
-
eq(
|
|
95
|
-
|
|
96
|
-
eq(
|
|
116
|
+
eq(memoryGraphNodes.type, "procedural"),
|
|
117
|
+
sql`${memoryGraphNodes.content} LIKE ${'skill:' + escapeLike(skillId) + '\n%'} ESCAPE '\\'`,
|
|
118
|
+
eq(memoryGraphNodes.scopeId, scopeId),
|
|
97
119
|
),
|
|
98
120
|
)
|
|
99
121
|
.get();
|
|
100
122
|
|
|
101
123
|
if (existing) {
|
|
102
124
|
if (
|
|
103
|
-
existing.
|
|
104
|
-
existing.
|
|
125
|
+
existing.content === content &&
|
|
126
|
+
existing.fidelity !== "gone"
|
|
105
127
|
) {
|
|
106
|
-
// Same content — just touch
|
|
107
|
-
db.update(
|
|
108
|
-
.set({
|
|
109
|
-
.where(eq(
|
|
128
|
+
// Same content — just touch lastAccessed
|
|
129
|
+
db.update(memoryGraphNodes)
|
|
130
|
+
.set({ lastAccessed: now })
|
|
131
|
+
.where(eq(memoryGraphNodes.id, existing.id))
|
|
110
132
|
.run();
|
|
111
133
|
return;
|
|
112
134
|
}
|
|
113
135
|
|
|
114
|
-
if (existing.
|
|
115
|
-
// Content changed — update
|
|
116
|
-
db.update(
|
|
136
|
+
if (existing.fidelity !== "gone") {
|
|
137
|
+
// Content changed — update content
|
|
138
|
+
db.update(memoryGraphNodes)
|
|
117
139
|
.set({
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
lastSeenAt: now,
|
|
140
|
+
content,
|
|
141
|
+
lastAccessed: now,
|
|
121
142
|
})
|
|
122
|
-
.where(eq(
|
|
143
|
+
.where(eq(memoryGraphNodes.id, existing.id))
|
|
123
144
|
.run();
|
|
124
|
-
enqueueMemoryJob("
|
|
145
|
+
enqueueMemoryJob("embed_graph_node", { nodeId: existing.id });
|
|
125
146
|
return;
|
|
126
147
|
}
|
|
127
148
|
|
|
128
|
-
//
|
|
129
|
-
db.update(
|
|
149
|
+
// fidelity === "gone" — reactivate
|
|
150
|
+
db.update(memoryGraphNodes)
|
|
130
151
|
.set({
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
firstSeenAt: now,
|
|
152
|
+
fidelity: "vivid",
|
|
153
|
+
content,
|
|
154
|
+
created: now,
|
|
155
|
+
lastAccessed: now,
|
|
136
156
|
})
|
|
137
|
-
.where(eq(
|
|
157
|
+
.where(eq(memoryGraphNodes.id, existing.id))
|
|
138
158
|
.run();
|
|
139
|
-
enqueueMemoryJob("
|
|
159
|
+
enqueueMemoryJob("embed_graph_node", { nodeId: existing.id });
|
|
160
|
+
log.info({ skillId, nodeId: existing.id }, "Reactivated skill capability memory");
|
|
140
161
|
return;
|
|
141
162
|
}
|
|
142
163
|
|
|
143
|
-
// No existing — insert new
|
|
164
|
+
// No existing — insert new graph node
|
|
144
165
|
const id = uuid();
|
|
145
|
-
db.insert(
|
|
166
|
+
db.insert(memoryGraphNodes)
|
|
146
167
|
.values({
|
|
147
168
|
id,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
169
|
+
content,
|
|
170
|
+
type: "procedural",
|
|
171
|
+
created: now,
|
|
172
|
+
lastAccessed: now,
|
|
173
|
+
lastConsolidated: now,
|
|
174
|
+
emotionalCharge: DEFAULT_EMOTIONAL_CHARGE,
|
|
175
|
+
fidelity: "vivid",
|
|
176
|
+
confidence: 1.0,
|
|
177
|
+
significance: 0.7,
|
|
178
|
+
stability: 14,
|
|
179
|
+
reinforcementCount: 0,
|
|
180
|
+
lastReinforced: now,
|
|
181
|
+
sourceConversations: JSON.stringify([]),
|
|
182
|
+
sourceType: "inferred",
|
|
183
|
+
narrativeRole: null,
|
|
184
|
+
partOfStory: null,
|
|
156
185
|
scopeId,
|
|
157
|
-
firstSeenAt: now,
|
|
158
|
-
lastSeenAt: now,
|
|
159
186
|
})
|
|
160
187
|
.run();
|
|
161
|
-
enqueueMemoryJob("
|
|
188
|
+
enqueueMemoryJob("embed_graph_node", { nodeId: id });
|
|
189
|
+
log.info({ skillId, nodeId: id }, "Created skill capability memory");
|
|
162
190
|
} catch (err) {
|
|
163
191
|
log.warn({ err, skillId }, "Failed to upsert skill capability memory");
|
|
164
192
|
}
|
|
165
193
|
}
|
|
166
194
|
|
|
167
195
|
/**
|
|
168
|
-
* Soft-delete the capability memory
|
|
196
|
+
* Soft-delete the capability memory graph node for a skill.
|
|
169
197
|
* Best-effort: errors are logged but never thrown.
|
|
170
198
|
*/
|
|
171
199
|
export function deleteSkillCapabilityMemory(skillId: string): void {
|
|
172
200
|
try {
|
|
173
201
|
const db = getDb();
|
|
174
|
-
const subject = `skill:${skillId}`;
|
|
175
202
|
const now = Date.now();
|
|
176
203
|
|
|
177
204
|
const existing = db
|
|
178
205
|
.select()
|
|
179
|
-
.from(
|
|
206
|
+
.from(memoryGraphNodes)
|
|
180
207
|
.where(
|
|
181
208
|
and(
|
|
182
|
-
eq(
|
|
183
|
-
|
|
184
|
-
eq(
|
|
209
|
+
eq(memoryGraphNodes.type, "procedural"),
|
|
210
|
+
sql`${memoryGraphNodes.content} LIKE ${'skill:' + escapeLike(skillId) + '\n%'} ESCAPE '\\'`,
|
|
211
|
+
eq(memoryGraphNodes.scopeId, "default"),
|
|
212
|
+
sql`${memoryGraphNodes.fidelity} != 'gone'`,
|
|
185
213
|
),
|
|
186
214
|
)
|
|
187
215
|
.get();
|
|
188
216
|
|
|
189
|
-
if (existing
|
|
190
|
-
db.update(
|
|
191
|
-
.set({
|
|
192
|
-
.where(eq(
|
|
217
|
+
if (existing) {
|
|
218
|
+
db.update(memoryGraphNodes)
|
|
219
|
+
.set({ fidelity: "gone", lastAccessed: now })
|
|
220
|
+
.where(eq(memoryGraphNodes.id, existing.id))
|
|
193
221
|
.run();
|
|
194
222
|
}
|
|
195
223
|
} catch (err) {
|
|
@@ -198,7 +226,7 @@ export function deleteSkillCapabilityMemory(skillId: string): void {
|
|
|
198
226
|
}
|
|
199
227
|
|
|
200
228
|
/**
|
|
201
|
-
* Seed capability memory
|
|
229
|
+
* Seed capability memory graph nodes for all enabled skills (bundled, managed, workspace, extra).
|
|
202
230
|
* Prunes stale entries whose skills are no longer in the enabled set.
|
|
203
231
|
* Best-effort: errors are logged but never thrown.
|
|
204
232
|
*/
|
|
@@ -231,31 +259,78 @@ export function seedCatalogSkillMemories(): void {
|
|
|
231
259
|
}
|
|
232
260
|
|
|
233
261
|
// Prune stale capability memories for skills no longer in the enabled set
|
|
262
|
+
// and not available in the remote/local catalog.
|
|
234
263
|
const db = getDb();
|
|
235
264
|
const allCapabilities = db
|
|
236
265
|
.select()
|
|
237
|
-
.from(
|
|
266
|
+
.from(memoryGraphNodes)
|
|
238
267
|
.where(
|
|
239
268
|
and(
|
|
240
|
-
eq(
|
|
241
|
-
eq(
|
|
242
|
-
|
|
269
|
+
eq(memoryGraphNodes.type, "procedural"),
|
|
270
|
+
eq(memoryGraphNodes.scopeId, "default"),
|
|
271
|
+
sql`${memoryGraphNodes.fidelity} != 'gone'`,
|
|
243
272
|
),
|
|
244
273
|
)
|
|
245
274
|
.all();
|
|
246
275
|
|
|
276
|
+
const allLocalSkillIds = new Set(catalog.map((s) => s.id));
|
|
277
|
+
const cachedCatalog = getCachedCatalogSync();
|
|
278
|
+
const cachedCatalogIds = new Set(cachedCatalog.map((s) => s.id));
|
|
279
|
+
|
|
247
280
|
const now = Date.now();
|
|
248
281
|
for (const item of allCapabilities) {
|
|
249
|
-
if (!item.
|
|
250
|
-
const itemSkillId = item.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
282
|
+
if (!item.content.startsWith("skill:")) continue;
|
|
283
|
+
const itemSkillId = item.content.split("\n")[0].replace("skill:", "");
|
|
284
|
+
|
|
285
|
+
// Keep enabled skills
|
|
286
|
+
if (catalogIds.has(itemSkillId)) continue;
|
|
287
|
+
|
|
288
|
+
// Keep uninstalled catalog skills that are still in the remote catalog
|
|
289
|
+
if (cachedCatalogIds.has(itemSkillId)) continue;
|
|
290
|
+
|
|
291
|
+
// If the catalog cache is empty (cold start, before async fetch),
|
|
292
|
+
// we can't tell whether an unknown skill is a stale entry or
|
|
293
|
+
// a valid uninstalled catalog skill. Only prune skills we can
|
|
294
|
+
// positively identify as local-but-disabled.
|
|
295
|
+
if (cachedCatalogIds.size === 0 && !allLocalSkillIds.has(itemSkillId)) continue;
|
|
296
|
+
|
|
297
|
+
log.info({ skillId: itemSkillId, nodeId: item.id, catalogSize: catalogIds.size, cacheSize: cachedCatalogIds.size }, "Pruning stale skill capability memory");
|
|
298
|
+
db.update(memoryGraphNodes)
|
|
299
|
+
.set({ fidelity: "gone", lastAccessed: now })
|
|
300
|
+
.where(eq(memoryGraphNodes.id, item.id))
|
|
301
|
+
.run();
|
|
257
302
|
}
|
|
258
303
|
} catch (err) {
|
|
259
304
|
log.warn({ err }, "Failed to seed catalog skill memories");
|
|
260
305
|
}
|
|
261
306
|
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Seed capability memories for catalog skills that are not yet installed.
|
|
310
|
+
* This makes uninstalled skills discoverable via memory injection so the LLM
|
|
311
|
+
* can auto-install them via skill_load when relevant.
|
|
312
|
+
* Best-effort: errors are logged but never thrown.
|
|
313
|
+
*/
|
|
314
|
+
export async function seedUninstalledCatalogSkillMemories(): Promise<void> {
|
|
315
|
+
try {
|
|
316
|
+
const { getCatalog } = await import("./catalog-cache.js");
|
|
317
|
+
const fullCatalog = await getCatalog();
|
|
318
|
+
if (fullCatalog.length === 0) return;
|
|
319
|
+
|
|
320
|
+
const installedCatalog = loadSkillCatalog();
|
|
321
|
+
const installedIds = new Set(installedCatalog.map((s) => s.id));
|
|
322
|
+
|
|
323
|
+
const config = getConfig();
|
|
324
|
+
for (const entry of fullCatalog) {
|
|
325
|
+
if (installedIds.has(entry.id)) continue;
|
|
326
|
+
|
|
327
|
+
const flagKey = entry.metadata?.vellum?.["feature-flag"];
|
|
328
|
+
if (flagKey && !isAssistantFeatureFlagEnabled(flagKey, config)) continue;
|
|
329
|
+
|
|
330
|
+
const input = fromCatalogSkill(entry);
|
|
331
|
+
upsertSkillCapabilityMemory(entry.id, input);
|
|
332
|
+
}
|
|
333
|
+
} catch (err) {
|
|
334
|
+
log.warn({ err }, "Failed to seed uninstalled catalog skill memories");
|
|
335
|
+
}
|
|
336
|
+
}
|
|
@@ -5,6 +5,7 @@ import { dirname, join, resolve, sep } from "node:path";
|
|
|
5
5
|
|
|
6
6
|
import { getWorkspaceSkillsDir } from "../util/platform.js";
|
|
7
7
|
import { upsertSkillsIndex } from "./catalog-install.js";
|
|
8
|
+
import { computeSkillHash, writeInstallMeta } from "./install-meta.js";
|
|
8
9
|
|
|
9
10
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
10
11
|
|
|
@@ -434,9 +435,12 @@ export function validateSkillSlug(slug: string): void {
|
|
|
434
435
|
* 1. Validates the skill slug for path safety
|
|
435
436
|
* 2. Fetches all files from `skills/<skillSlug>/` in the source repo
|
|
436
437
|
* 3. Writes them to `<workspace>/skills/<skillSlug>/` with path traversal protection
|
|
437
|
-
* 4. Writes `
|
|
438
|
-
* 5.
|
|
439
|
-
* 6.
|
|
438
|
+
* 4. Writes `install-meta.json` with origin metadata
|
|
439
|
+
* 5. Installs npm dependencies (if package.json exists)
|
|
440
|
+
* 6. Updates SKILLS.md index
|
|
441
|
+
*
|
|
442
|
+
* Auto-enable and memory seeding are handled by the caller (e.g.
|
|
443
|
+
* `postInstallSkill()` in the daemon, or left to the user for CLI installs).
|
|
440
444
|
*/
|
|
441
445
|
export async function installExternalSkill(
|
|
442
446
|
owner: string,
|
|
@@ -444,6 +448,7 @@ export async function installExternalSkill(
|
|
|
444
448
|
skillSlug: string,
|
|
445
449
|
overwrite: boolean,
|
|
446
450
|
ref?: string,
|
|
451
|
+
contactId?: string,
|
|
447
452
|
): Promise<void> {
|
|
448
453
|
// Validate slug before using in filesystem paths
|
|
449
454
|
validateSkillSlug(skillSlug);
|
|
@@ -480,20 +485,19 @@ export async function installExternalSkill(
|
|
|
480
485
|
writeFileSync(destPath, content, "utf-8");
|
|
481
486
|
}
|
|
482
487
|
|
|
483
|
-
// Write
|
|
484
|
-
|
|
485
|
-
origin: "
|
|
486
|
-
|
|
487
|
-
|
|
488
|
+
// Write install metadata
|
|
489
|
+
writeInstallMeta(skillDir, {
|
|
490
|
+
origin: "skillssh",
|
|
491
|
+
slug: skillSlug,
|
|
492
|
+
sourceRepo: `${owner}/${repo}`,
|
|
488
493
|
installedAt: new Date().toISOString(),
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
JSON.stringify(meta, null, 2) + "\n",
|
|
493
|
-
"utf-8",
|
|
494
|
-
);
|
|
494
|
+
...(contactId ? { installedBy: contactId } : {}),
|
|
495
|
+
contentHash: computeSkillHash(skillDir) ?? undefined,
|
|
496
|
+
});
|
|
495
497
|
|
|
496
|
-
//
|
|
498
|
+
// Post-install: install dependencies first, then index the skill.
|
|
499
|
+
// Running bun install before upsertSkillsIndex ensures we don't index a
|
|
500
|
+
// skill whose dependencies failed to install.
|
|
497
501
|
if (existsSync(join(skillDir, "package.json"))) {
|
|
498
502
|
const bunPath = `${homedir()}/.bun/bin`;
|
|
499
503
|
execSync("bun install", {
|
|
@@ -502,7 +506,5 @@ export async function installExternalSkill(
|
|
|
502
506
|
env: { ...process.env, PATH: `${bunPath}:${process.env.PATH}` },
|
|
503
507
|
});
|
|
504
508
|
}
|
|
505
|
-
|
|
506
|
-
// Register in SKILLS.md only after files are written and deps installed
|
|
507
509
|
upsertSkillsIndex(skillSlug);
|
|
508
510
|
}
|
package/src/tasks/task-runner.ts
CHANGED
|
@@ -64,8 +64,10 @@ export async function runTask(
|
|
|
64
64
|
// Scheduled section; non-schedule tasks use "background" to stay out of
|
|
65
65
|
// the main conversation list.
|
|
66
66
|
conversationType: opts.source === "schedule" ? undefined : "background",
|
|
67
|
-
source: opts.source,
|
|
67
|
+
source: opts.source === "schedule" ? "schedule" : "task",
|
|
68
68
|
scheduleJobId: opts.scheduleJobId,
|
|
69
|
+
groupId:
|
|
70
|
+
opts.source === "schedule" ? "system:scheduled" : "system:background",
|
|
69
71
|
origin: "task",
|
|
70
72
|
systemHint: `Task: ${task.title}`,
|
|
71
73
|
});
|
|
@@ -504,17 +504,15 @@ describe("UsageTelemetryReporter", () => {
|
|
|
504
504
|
// No HTTP call should have been made
|
|
505
505
|
expect(mockFetch).not.toHaveBeenCalled();
|
|
506
506
|
|
|
507
|
-
// All
|
|
508
|
-
|
|
507
|
+
// All 3 timestamp watermarks should have been advanced (IDs left untouched
|
|
508
|
+
// so the compound-cursor branch stays active)
|
|
509
|
+
expect(mockSetMemoryCheckpoint).toHaveBeenCalledTimes(3);
|
|
509
510
|
|
|
510
511
|
const calls = mockSetMemoryCheckpoint.mock.calls;
|
|
511
512
|
const keys = calls.map((c) => c[0]);
|
|
512
513
|
expect(keys).toContain("telemetry:usage:last_reported_at");
|
|
513
|
-
expect(keys).toContain("telemetry:usage:last_reported_id");
|
|
514
514
|
expect(keys).toContain("telemetry:turns:last_reported_at");
|
|
515
|
-
expect(keys).toContain("telemetry:turns:last_reported_id");
|
|
516
515
|
expect(keys).toContain("telemetry:lifecycle:last_reported_at");
|
|
517
|
-
expect(keys).toContain("telemetry:lifecycle:last_reported_id");
|
|
518
516
|
});
|
|
519
517
|
|
|
520
518
|
test("events sent normally after re-enabling collectUsageData", async () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
+
import { ensureBun } from "../../util/bun-runtime.js";
|
|
4
5
|
import { getExternalDir } from "../../util/platform.js";
|
|
5
6
|
|
|
6
7
|
export interface BrowserRuntimeStatus {
|
|
@@ -83,7 +84,8 @@ export async function importPlaywright(): Promise<typeof import("playwright")> {
|
|
|
83
84
|
if (!existsSync(join(externalDir, "package.json"))) {
|
|
84
85
|
writeFileSync(join(externalDir, "package.json"), '{"private":true}\n');
|
|
85
86
|
}
|
|
86
|
-
const
|
|
87
|
+
const bunPath = await ensureBun();
|
|
88
|
+
const proc = Bun.spawn([bunPath, "add", "playwright"], {
|
|
87
89
|
cwd: externalDir,
|
|
88
90
|
stdout: "pipe",
|
|
89
91
|
stderr: "pipe",
|
|
@@ -1,67 +1,56 @@
|
|
|
1
1
|
import { getConfig } from "../../config/loader.js";
|
|
2
|
+
import {
|
|
3
|
+
handleRecall,
|
|
4
|
+
handleRemember,
|
|
5
|
+
type RecallInput,
|
|
6
|
+
type RememberInput,
|
|
7
|
+
} from "../../memory/graph/tool-handlers.js";
|
|
8
|
+
import {
|
|
9
|
+
graphRecallDefinition,
|
|
10
|
+
graphRememberDefinition,
|
|
11
|
+
} from "../../memory/graph/tools.js";
|
|
2
12
|
import { RiskLevel } from "../../permissions/types.js";
|
|
3
13
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
4
14
|
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
5
|
-
import {
|
|
6
|
-
memoryManageDefinition,
|
|
7
|
-
memoryRecallDefinition,
|
|
8
|
-
} from "./definitions.js";
|
|
9
|
-
import {
|
|
10
|
-
handleMemoryDelete,
|
|
11
|
-
handleMemoryRecall,
|
|
12
|
-
handleMemorySave,
|
|
13
|
-
handleMemoryUpdate,
|
|
14
|
-
} from "./handlers.js";
|
|
15
15
|
|
|
16
|
-
// ──
|
|
16
|
+
// ── remember ────────────────────────────────────────────────────────
|
|
17
17
|
|
|
18
|
-
class
|
|
19
|
-
name = "
|
|
20
|
-
description =
|
|
18
|
+
class RememberTool implements Tool {
|
|
19
|
+
name = "remember";
|
|
20
|
+
description = graphRememberDefinition.description;
|
|
21
21
|
category = "memory";
|
|
22
22
|
defaultRiskLevel = RiskLevel.Low;
|
|
23
23
|
|
|
24
24
|
getDefinition(): ToolDefinition {
|
|
25
|
-
return
|
|
25
|
+
return graphRememberDefinition;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async execute(
|
|
29
29
|
input: Record<string, unknown>,
|
|
30
30
|
context: ToolContext,
|
|
31
31
|
): Promise<ToolExecutionResult> {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
case "update":
|
|
43
|
-
return handleMemoryUpdate(input, config, context.memoryScopeId);
|
|
44
|
-
case "delete":
|
|
45
|
-
return handleMemoryDelete(input, config, context.memoryScopeId);
|
|
46
|
-
default:
|
|
47
|
-
return {
|
|
48
|
-
content: `Error: unknown op "${input.op}". Must be one of: save, update, delete`,
|
|
49
|
-
isError: true,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
32
|
+
const result = handleRemember(
|
|
33
|
+
input as unknown as RememberInput,
|
|
34
|
+
context.conversationId,
|
|
35
|
+
context.memoryScopeId ?? "default",
|
|
36
|
+
);
|
|
37
|
+
return {
|
|
38
|
+
content: result.message,
|
|
39
|
+
isError: !result.success,
|
|
40
|
+
};
|
|
52
41
|
}
|
|
53
42
|
}
|
|
54
43
|
|
|
55
|
-
// ──
|
|
44
|
+
// ── recall ──────────────────────────────────────────────────────────
|
|
56
45
|
|
|
57
|
-
class
|
|
58
|
-
name = "
|
|
59
|
-
description =
|
|
46
|
+
class RecallTool implements Tool {
|
|
47
|
+
name = "recall";
|
|
48
|
+
description = graphRecallDefinition.description;
|
|
60
49
|
category = "memory";
|
|
61
50
|
defaultRiskLevel = RiskLevel.Low;
|
|
62
51
|
|
|
63
52
|
getDefinition(): ToolDefinition {
|
|
64
|
-
return
|
|
53
|
+
return graphRecallDefinition;
|
|
65
54
|
}
|
|
66
55
|
|
|
67
56
|
async execute(
|
|
@@ -69,16 +58,44 @@ class MemoryRecallTool implements Tool {
|
|
|
69
58
|
context: ToolContext,
|
|
70
59
|
): Promise<ToolExecutionResult> {
|
|
71
60
|
const config = getConfig();
|
|
72
|
-
|
|
73
|
-
input,
|
|
61
|
+
const result = await handleRecall(
|
|
62
|
+
input as unknown as RecallInput,
|
|
74
63
|
config,
|
|
75
|
-
context.memoryScopeId,
|
|
76
|
-
context.conversationId,
|
|
64
|
+
context.memoryScopeId ?? "default",
|
|
77
65
|
);
|
|
66
|
+
|
|
67
|
+
if (result.results.length === 0) {
|
|
68
|
+
return { content: "No results found.", isError: false };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const formatted = result.results
|
|
72
|
+
.map((r) => {
|
|
73
|
+
const ts = formatTimestamp(r.created);
|
|
74
|
+
const meta =
|
|
75
|
+
result.mode === "memory"
|
|
76
|
+
? `[${r.type}] ${ts} (confidence: ${r.confidence.toFixed(2)}, score: ${r.score.toFixed(3)})`
|
|
77
|
+
: `[archive] ${ts}`;
|
|
78
|
+
return `${meta}\n${r.content}`;
|
|
79
|
+
})
|
|
80
|
+
.join("\n\n---\n\n");
|
|
81
|
+
|
|
82
|
+
return { content: formatted, isError: false };
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
|
|
86
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
function formatTimestamp(epochMs: number): string {
|
|
89
|
+
const d = new Date(epochMs);
|
|
90
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
91
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
92
|
+
const yy = String(d.getFullYear()).slice(-2);
|
|
93
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
94
|
+
const min = String(d.getMinutes()).padStart(2, "0");
|
|
95
|
+
return `${mm}/${dd}/${yy} ${hh}:${min}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
81
98
|
// ── Exported tool instances ──────────────────────────────────────────
|
|
82
99
|
|
|
83
|
-
export const
|
|
84
|
-
export const
|
|
100
|
+
export const rememberTool = new RememberTool();
|
|
101
|
+
export const recallTool = new RecallTool();
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "../permissions/checker.js";
|
|
9
9
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
10
10
|
import { addRule } from "../permissions/trust-store.js";
|
|
11
|
+
import { RiskLevel } from "../permissions/types.js";
|
|
11
12
|
import {
|
|
12
13
|
getEffectiveMode,
|
|
13
14
|
setConversationMode,
|
|
@@ -145,6 +146,10 @@ export class PermissionChecker {
|
|
|
145
146
|
// Exception: inline-command skill loads (skill_load_dynamic:*) must
|
|
146
147
|
// never be silently auto-approved — they execute embedded commands
|
|
147
148
|
// and require explicit human review or a pinned trust rule.
|
|
149
|
+
// Exception: high-risk tools (e.g. destructive shell commands, writes
|
|
150
|
+
// to sensitive paths) are denied — unattended sessions must not
|
|
151
|
+
// auto-approve operations that could cause significant damage if
|
|
152
|
+
// triggered by prompt injection from untrusted content.
|
|
148
153
|
const isDynamicSkillLoad =
|
|
149
154
|
result.matchedRule?.pattern.startsWith("skill_load_dynamic:") ===
|
|
150
155
|
true;
|
|
@@ -152,7 +157,8 @@ export class PermissionChecker {
|
|
|
152
157
|
context.isInteractive === false &&
|
|
153
158
|
context.trustClass === "guardian" &&
|
|
154
159
|
!context.requireFreshApproval &&
|
|
155
|
-
!isDynamicSkillLoad
|
|
160
|
+
!isDynamicSkillLoad &&
|
|
161
|
+
riskLevel !== RiskLevel.High
|
|
156
162
|
) {
|
|
157
163
|
log.info(
|
|
158
164
|
{ toolName: name, riskLevel },
|