@vellumai/assistant 0.8.10 → 0.8.11-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +62 -1
- package/docs/workspace-tools.md +196 -0
- package/examples/plugins/echo/README.md +3 -3
- package/knip.json +1 -0
- package/openapi.yaml +460 -128
- package/package.json +2 -1
- package/scripts/build-plugin-api.ts +299 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
- package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
- package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
- package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
- package/src/__tests__/agent-loop-thinking.test.ts +4 -0
- package/src/__tests__/agent-loop.test.ts +578 -5
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -1
- package/src/__tests__/build-persisted-content.test.ts +75 -1
- package/src/__tests__/catalog-install-normalize.test.ts +141 -0
- package/src/__tests__/ces-startup-timeout.test.ts +60 -0
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
- package/src/__tests__/context-overflow-reducer.test.ts +264 -124
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
- package/src/__tests__/conversation-agent-loop.test.ts +131 -551
- package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-fork-crud.test.ts +259 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +257 -1
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
- package/src/__tests__/conversation-queue.test.ts +1 -39
- package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
- package/src/__tests__/conversation-skill-tools.test.ts +491 -5
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-store.test.ts +74 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
- package/src/__tests__/corrected-target.test.ts +93 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
- package/src/__tests__/credential-execution-tools.test.ts +23 -11
- package/src/__tests__/credential-security-invariants.test.ts +6 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
- package/src/__tests__/device-id.test.ts +70 -1
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
- package/src/__tests__/empty-response-hook.test.ts +242 -66
- package/src/__tests__/external-plugin-loader.test.ts +0 -31
- package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
- package/src/__tests__/history-repair-hook.test.ts +228 -3
- package/src/__tests__/host-app-control-proxy.test.ts +45 -0
- package/src/__tests__/host-browser-proxy.test.ts +254 -9
- package/src/__tests__/identity-routes.test.ts +1 -0
- package/src/__tests__/image-recovery-hook.test.ts +387 -0
- package/src/__tests__/injector-chain.test.ts +5 -4
- package/src/__tests__/injector-v3-suppression.test.ts +373 -47
- package/src/__tests__/intent-routing.test.ts +7 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
- package/src/__tests__/notification-decision-strategy.test.ts +3 -3
- package/src/__tests__/oauth-store.test.ts +0 -85
- package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
- package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
- package/src/__tests__/persist-unsendable-image.test.ts +4 -4
- package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
- package/src/__tests__/plugin-bootstrap.test.ts +82 -73
- package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
- package/src/__tests__/plugin-types.test.ts +0 -8
- package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
- package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
- package/src/__tests__/registry.test.ts +240 -1
- package/src/__tests__/require-fresh-approval.test.ts +3 -0
- package/src/__tests__/schedule-routes.test.ts +116 -1
- package/src/__tests__/schedule-store.test.ts +28 -0
- package/src/__tests__/schedule-tools.test.ts +94 -1
- package/src/__tests__/server-history-render.test.ts +39 -0
- package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
- package/src/__tests__/skills.test.ts +202 -0
- package/src/__tests__/slim-skill-category.test.ts +195 -0
- package/src/__tests__/strip-memory-injections.test.ts +33 -39
- package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
- package/src/__tests__/title-generate-hook.test.ts +9 -7
- package/src/__tests__/tool-audit-listener.test.ts +264 -1
- package/src/__tests__/tool-error-hook.test.ts +4 -3
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +218 -0
- package/src/__tests__/tools-get-route.test.ts +202 -0
- package/src/__tests__/workspace-tool-loader.test.ts +319 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +569 -319
- package/src/api/events/tool-result.ts +9 -0
- package/src/api/events/tool-use-start.ts +7 -0
- package/src/api/index.ts +10 -0
- package/src/api/responses/conversation-message.ts +135 -27
- package/src/api/responses/memory-v3-selection-log.ts +4 -4
- package/src/approvals/guardian-request-resolvers.ts +26 -0
- package/src/browser-session/backends/host-bridge.ts +29 -0
- package/src/browser-session/index.ts +1 -0
- package/src/browser-session/types.ts +5 -1
- package/src/cli/commands/__tests__/schedules.test.ts +62 -4
- package/src/cli/commands/__tests__/skills.test.ts +53 -0
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/inference-providers.ts +0 -8
- package/src/cli/commands/plugins.ts +2 -2
- package/src/cli/commands/schedules.ts +27 -4
- package/src/cli/commands/skills.ts +187 -146
- package/src/cli/commands/tools.ts +106 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
- package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
- package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
- package/src/cli/lib/install-from-github.ts +187 -117
- package/src/cli/lib/plugin-catalog-cache.ts +9 -9
- package/src/cli/lib/plugin-details.ts +38 -68
- package/src/cli/lib/plugin-marketplace.ts +42 -14
- package/src/cli/lib/search-plugins.ts +29 -129
- package/src/cli/program.ts +2 -0
- package/src/config/bundled-skills/acp/SKILL.md +1 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
- package/src/config/bundled-skills/app-control/SKILL.md +1 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
- package/src/config/bundled-skills/followups/SKILL.md +1 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
- package/src/config/bundled-skills/messaging/SKILL.md +1 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/SKILL.md +1 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
- package/src/config/bundled-skills/sequences/SKILL.md +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +1 -0
- package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
- package/src/config/bundled-skills/subagent/SKILL.md +1 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
- package/src/config/env-registry.ts +23 -0
- package/src/config/feature-flag-registry.json +17 -81
- package/src/config/loader.ts +5 -22
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
- package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
- package/src/config/schemas/compaction-logs.ts +79 -0
- package/src/config/schemas/memory-v2.ts +0 -8
- package/src/config/schemas/memory-v3.ts +104 -33
- package/src/config/seed-inference-profiles.ts +1 -1
- package/src/config/skills.ts +117 -47
- package/src/context/compactor.ts +11 -0
- package/src/context/strip-injections.ts +38 -4
- package/src/credential-execution/feature-gates.ts +0 -21
- package/src/credential-execution/startup-timeout.ts +32 -4
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
- package/src/daemon/conversation-agent-loop.ts +123 -658
- package/src/daemon/conversation-error.ts +6 -33
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-runtime-assembly.ts +183 -22
- package/src/daemon/conversation-skill-tools.ts +137 -8
- package/src/daemon/conversation-slash.ts +0 -14
- package/src/daemon/conversation-store.ts +2 -19
- package/src/daemon/conversation-tool-setup.ts +87 -1
- package/src/daemon/conversation.ts +119 -50
- package/src/daemon/external-plugins-bootstrap.ts +36 -95
- package/src/daemon/handlers/config-channels.ts +11 -2
- package/src/daemon/handlers/shared.ts +9 -1
- package/src/daemon/handlers/skills.ts +10 -4
- package/src/daemon/host-app-control-proxy.ts +72 -57
- package/src/daemon/host-browser-proxy.ts +117 -22
- package/src/daemon/lifecycle.ts +34 -5
- package/src/daemon/message-protocol.ts +0 -7
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/skills.ts +17 -0
- package/src/daemon/providers-setup.ts +3 -0
- package/src/daemon/server.ts +3 -3
- package/src/daemon/tool-setup-types.ts +9 -3
- package/src/daemon/trust-context.ts +23 -0
- package/src/daemon/workspace-tools-watcher.ts +324 -0
- package/src/events/tool-audit-listener.ts +78 -16
- package/src/events/tool-metrics-listener.ts +2 -5
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
- package/src/memory/__tests__/conversation-queries.test.ts +176 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
- package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
- package/src/memory/conversation-crud.ts +134 -3
- package/src/memory/conversation-queries.ts +64 -7
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.test.ts +130 -1
- package/src/memory/embedding-backend.ts +79 -106
- package/src/memory/embedding-gemini.ts +5 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
- package/src/memory/graph/conversation-graph-memory.ts +36 -25
- package/src/memory/graph/tool-handlers.ts +3 -0
- package/src/memory/job-handlers/cleanup.ts +3 -1
- package/src/memory/jobs-store.ts +0 -28
- package/src/memory/jobs-worker.ts +10 -22
- package/src/memory/memory-marker.ts +29 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
- package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
- package/src/memory/migrations/270-schedule-description.ts +36 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
- package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
- package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
- package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
- package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
- package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
- package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
- package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
- package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +16 -0
- package/src/memory/schema/infrastructure.ts +26 -0
- package/src/memory/skill-loaded-events-store.test.ts +160 -0
- package/src/memory/skill-loaded-events-store.ts +95 -0
- package/src/memory/tool-executed-events-store.test.ts +219 -0
- package/src/memory/tool-executed-events-store.ts +102 -0
- package/src/memory/tool-usage-store.ts +15 -3
- package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
- package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
- package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
- package/src/memory/v2/__tests__/page-store.test.ts +33 -0
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
- package/src/memory/v2/activation-store.ts +50 -1
- package/src/memory/v2/consolidation-job.ts +113 -29
- package/src/memory/v2/injected-block-slugs.ts +79 -0
- package/src/memory/v2/injection.ts +6 -1
- package/src/memory/v2/prompts/consolidation.ts +414 -13
- package/src/memory/v2/router.ts +2 -28
- package/src/memory/v2/static-context.ts +1 -1
- package/src/memory/v2/types.ts +16 -0
- package/src/notifications/__tests__/copy-composer.test.ts +244 -0
- package/src/notifications/access-request-copy.ts +298 -0
- package/src/notifications/adapters/slack.ts +3 -3
- package/src/notifications/adapters/telegram.ts +2 -1
- package/src/notifications/copy-composer.ts +49 -267
- package/src/notifications/decision-engine.ts +16 -35
- package/src/notifications/home-feed-side-effect.ts +1 -6
- package/src/oauth/oauth-store.ts +0 -9
- package/src/permissions/checker.test.ts +83 -1
- package/src/permissions/checker.ts +25 -2
- package/src/permissions/gateway-threshold-reader.test.ts +182 -0
- package/src/permissions/gateway-threshold-reader.ts +80 -0
- package/src/platform/client.ts +1 -3
- package/src/platform/feature-gate.ts +3 -12
- package/src/plugin-api/constants.ts +4 -2
- package/src/plugin-api/index.ts +63 -11
- package/src/plugin-api/types.ts +236 -71
- package/src/plugins/defaults/compaction/compact.ts +66 -2
- package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
- package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
- package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
- package/src/plugins/defaults/compaction/window-manager.ts +303 -1
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
- package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
- package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
- package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
- package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
- package/src/plugins/defaults/history-repair/terminal.ts +39 -2
- package/src/plugins/defaults/image-recovery/detect.ts +25 -0
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
- package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
- package/src/plugins/defaults/image-recovery/package.json +14 -0
- package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
- package/src/plugins/defaults/index.ts +71 -5
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
- package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
- package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
- package/src/plugins/defaults/memory-retrieval/package.json +14 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
- package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
- package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
- package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
- package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
- package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
- package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
- package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
- package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
- package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
- package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
- package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
- package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
- package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
- package/src/plugins/pipeline.ts +8 -5
- package/src/plugins/types.ts +5 -51
- package/src/providers/cache-control.ts +26 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
- package/src/providers/model-catalog.ts +13 -1
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
- package/src/providers/openai/chat-completions-provider.ts +46 -0
- package/src/providers/openai/responses-provider.ts +45 -0
- package/src/providers/registry.ts +0 -8
- package/src/runtime/__tests__/agent-wake.test.ts +0 -1
- package/src/runtime/agent-wake.ts +13 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
- package/src/runtime/routes/acp-routes.test.ts +106 -0
- package/src/runtime/routes/acp-routes.ts +248 -2
- package/src/runtime/routes/browser-tabs-routes.ts +1 -1
- package/src/runtime/routes/channel-verification-routes.ts +14 -5
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
- package/src/runtime/routes/consolidation-routes.ts +6 -82
- package/src/runtime/routes/conversation-list-routes.ts +6 -0
- package/src/runtime/routes/conversation-management-routes.ts +71 -0
- package/src/runtime/routes/identity-routes.ts +8 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
- package/src/runtime/routes/plugins-routes.ts +34 -45
- package/src/runtime/routes/schedule-routes.ts +43 -5
- package/src/runtime/routes/settings-routes.ts +140 -15
- package/src/runtime/routes/skills-routes.ts +18 -6
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
- package/src/runtime/services/conversation-serializer.ts +38 -1
- package/src/runtime/verification-outbound-actions.ts +147 -2
- package/src/runtime/verification-templates.ts +29 -3
- package/src/schedule/schedule-store.ts +19 -0
- package/src/skills/catalog-install.ts +77 -13
- package/src/tasks/task-scheduler.ts +1 -0
- package/src/telemetry/types.ts +66 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
- package/src/telemetry/usage-telemetry-reporter.ts +213 -20
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
- package/src/tools/browser/browser-execution.ts +27 -9
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
- package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
- package/src/tools/browser/cdp-client/factory.ts +217 -17
- package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
- package/src/tools/browser/cdp-client/types.ts +22 -2
- package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
- package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
- package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
- package/src/tools/executor.ts +39 -7
- package/src/tools/registry.ts +387 -5
- package/src/tools/schedule/create.ts +16 -0
- package/src/tools/schedule/list.ts +12 -4
- package/src/tools/schedule/update.ts +12 -0
- package/src/tools/skills/load.ts +11 -6
- package/src/tools/terminal/safe-env.ts +2 -0
- package/src/tools/types.ts +65 -9
- package/src/tools/workspace-tools/loader.ts +673 -0
- package/src/usage/attribution.ts +28 -0
- package/src/util/device-id.ts +17 -3
- package/src/util/platform.ts +16 -0
- package/tsconfig.plugin-api.json +13 -0
- package/src/__tests__/plugin-external-api.test.ts +0 -68
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
- package/src/daemon/message-types/browser.ts +0 -10
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
- package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
- package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
- package/src/plugins/external-api.ts +0 -114
- package/src/plugins/plugin-skill-contributions.ts +0 -292
|
@@ -441,6 +441,57 @@ describe("GET /schedules — default defer exclusion", () => {
|
|
|
441
441
|
expect(noSource.createdFromConversationArchivedAt).toBeNull();
|
|
442
442
|
});
|
|
443
443
|
|
|
444
|
+
test("returns authored descriptions separately from cadence descriptions", () => {
|
|
445
|
+
createSchedule({
|
|
446
|
+
name: "Described schedule",
|
|
447
|
+
description: "Review the morning queue",
|
|
448
|
+
cronExpression: "0 9 * * *",
|
|
449
|
+
message: "review queue",
|
|
450
|
+
syntax: "cron",
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
const route = findRoute("schedules", "GET");
|
|
454
|
+
const result = route.handler({}) as {
|
|
455
|
+
schedules: Array<{
|
|
456
|
+
name: string;
|
|
457
|
+
description: string;
|
|
458
|
+
cadenceDescription: string;
|
|
459
|
+
}>;
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
expect(result.schedules).toHaveLength(1);
|
|
463
|
+
expect(result.schedules[0]).toMatchObject({
|
|
464
|
+
name: "Described schedule",
|
|
465
|
+
description: "Review the morning queue",
|
|
466
|
+
cadenceDescription: "Every day at 9:00 AM",
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
test("returns One-time as the cadence description for one-shot schedules", () => {
|
|
471
|
+
createSchedule({
|
|
472
|
+
name: "One-shot schedule",
|
|
473
|
+
description: "Send a one-time reminder",
|
|
474
|
+
cronExpression: null,
|
|
475
|
+
nextRunAt: Date.now() + 60_000,
|
|
476
|
+
message: "remember this",
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
const route = findRoute("schedules", "GET");
|
|
480
|
+
const result = route.handler({}) as {
|
|
481
|
+
schedules: Array<{
|
|
482
|
+
name: string;
|
|
483
|
+
description: string;
|
|
484
|
+
cadenceDescription: string;
|
|
485
|
+
}>;
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
expect(result.schedules[0]).toMatchObject({
|
|
489
|
+
name: "One-shot schedule",
|
|
490
|
+
description: "Send a one-time reminder",
|
|
491
|
+
cadenceDescription: "One-time",
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
|
|
444
495
|
test("mutation responses also exclude deferred wakes", () => {
|
|
445
496
|
createSchedule({
|
|
446
497
|
name: "Agent schedule",
|
|
@@ -997,6 +1048,7 @@ describe("POST /schedules — create", () => {
|
|
|
997
1048
|
test("creates a recurring execute schedule with defaults", () => {
|
|
998
1049
|
const result = postCreate({
|
|
999
1050
|
name: "Morning ping",
|
|
1051
|
+
description: "Start the morning workflow",
|
|
1000
1052
|
expression: "0 9 * * *",
|
|
1001
1053
|
message: "good morning",
|
|
1002
1054
|
});
|
|
@@ -1006,6 +1058,7 @@ describe("POST /schedules — create", () => {
|
|
|
1006
1058
|
expect(job.mode).toBe("execute");
|
|
1007
1059
|
expect(job.expression).toBe("0 9 * * *");
|
|
1008
1060
|
expect(job.syntax).toBe("cron");
|
|
1061
|
+
expect(job.description).toBe("Start the morning workflow");
|
|
1009
1062
|
expect(job.enabled).toBe(true);
|
|
1010
1063
|
expect(job.timezone).toBeNull();
|
|
1011
1064
|
});
|
|
@@ -1013,12 +1066,14 @@ describe("POST /schedules — create", () => {
|
|
|
1013
1066
|
test("trims whitespace and accepts an explicit timezone", () => {
|
|
1014
1067
|
postCreate({
|
|
1015
1068
|
name: " Trimmed ",
|
|
1069
|
+
description: " Trimmed description ",
|
|
1016
1070
|
expression: " 0 9 * * * ",
|
|
1017
1071
|
message: "hi",
|
|
1018
1072
|
timezone: " America/New_York ",
|
|
1019
1073
|
});
|
|
1020
1074
|
const job = listSchedules()[0];
|
|
1021
1075
|
expect(job.name).toBe("Trimmed");
|
|
1076
|
+
expect(job.description).toBe("Trimmed description");
|
|
1022
1077
|
expect(job.expression).toBe("0 9 * * *");
|
|
1023
1078
|
expect(job.timezone).toBe("America/New_York");
|
|
1024
1079
|
});
|
|
@@ -1027,6 +1082,7 @@ describe("POST /schedules — create", () => {
|
|
|
1027
1082
|
const expression = "DTSTART:20260101T000000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO";
|
|
1028
1083
|
postCreate({
|
|
1029
1084
|
name: "Weekly",
|
|
1085
|
+
description: "Weekly wake",
|
|
1030
1086
|
expression,
|
|
1031
1087
|
message: "monday wake",
|
|
1032
1088
|
});
|
|
@@ -1045,12 +1101,32 @@ describe("POST /schedules — create", () => {
|
|
|
1045
1101
|
expect(() => postCreate({ name: "x", expression: "* * * * *" })).toThrow(
|
|
1046
1102
|
"message is required",
|
|
1047
1103
|
);
|
|
1104
|
+
expect(() =>
|
|
1105
|
+
postCreate({
|
|
1106
|
+
name: "x",
|
|
1107
|
+
description: " ",
|
|
1108
|
+
expression: "* * * * *",
|
|
1109
|
+
message: "hi",
|
|
1110
|
+
}),
|
|
1111
|
+
).toThrow("description is required");
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
test("defaults omitted create descriptions for backward compatibility", () => {
|
|
1115
|
+
postCreate({
|
|
1116
|
+
name: "Description fallback",
|
|
1117
|
+
expression: "0 9 * * *",
|
|
1118
|
+
message: "hi",
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
const job = listSchedules()[0];
|
|
1122
|
+
expect(job.description).toBe("Description fallback");
|
|
1048
1123
|
});
|
|
1049
1124
|
|
|
1050
1125
|
test("rejects non-execute modes", () => {
|
|
1051
1126
|
expect(() =>
|
|
1052
1127
|
postCreate({
|
|
1053
1128
|
name: "x",
|
|
1129
|
+
description: "Run the thing",
|
|
1054
1130
|
expression: "* * * * *",
|
|
1055
1131
|
message: "hi",
|
|
1056
1132
|
mode: "notify",
|
|
@@ -1060,7 +1136,12 @@ describe("POST /schedules — create", () => {
|
|
|
1060
1136
|
|
|
1061
1137
|
test("rejects an unparseable expression", () => {
|
|
1062
1138
|
expect(() =>
|
|
1063
|
-
postCreate({
|
|
1139
|
+
postCreate({
|
|
1140
|
+
name: "x",
|
|
1141
|
+
description: "Run the thing",
|
|
1142
|
+
expression: "not-a-cron",
|
|
1143
|
+
message: "hi",
|
|
1144
|
+
}),
|
|
1064
1145
|
).toThrow("could not be parsed");
|
|
1065
1146
|
});
|
|
1066
1147
|
|
|
@@ -1068,6 +1149,7 @@ describe("POST /schedules — create", () => {
|
|
|
1068
1149
|
expect(() =>
|
|
1069
1150
|
postCreate({
|
|
1070
1151
|
name: "x",
|
|
1152
|
+
description: "Run the thing",
|
|
1071
1153
|
expression: "99 99 99 99 99",
|
|
1072
1154
|
message: "hi",
|
|
1073
1155
|
}),
|
|
@@ -1077,6 +1159,7 @@ describe("POST /schedules — create", () => {
|
|
|
1077
1159
|
test("respects enabled=false", () => {
|
|
1078
1160
|
postCreate({
|
|
1079
1161
|
name: "Off",
|
|
1162
|
+
description: "Disabled schedule",
|
|
1080
1163
|
expression: "0 9 * * *",
|
|
1081
1164
|
message: "hi",
|
|
1082
1165
|
enabled: false,
|
|
@@ -1086,6 +1169,38 @@ describe("POST /schedules — create", () => {
|
|
|
1086
1169
|
});
|
|
1087
1170
|
});
|
|
1088
1171
|
|
|
1172
|
+
// ── PATCH /schedules/:id — description ───────────────────────────────────
|
|
1173
|
+
|
|
1174
|
+
describe("PATCH /schedules/:id — description", () => {
|
|
1175
|
+
beforeEach(() => {
|
|
1176
|
+
clearTables();
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1179
|
+
test("updates authored descriptions", () => {
|
|
1180
|
+
const schedule = createSchedule({
|
|
1181
|
+
name: "Description update",
|
|
1182
|
+
description: "Original description",
|
|
1183
|
+
cronExpression: "0 9 * * *",
|
|
1184
|
+
message: "hi",
|
|
1185
|
+
syntax: "cron",
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
const route = findRoute("schedules/:id", "PATCH");
|
|
1189
|
+
const result = route.handler({
|
|
1190
|
+
pathParams: { id: schedule.id },
|
|
1191
|
+
body: { description: "Updated description" },
|
|
1192
|
+
}) as {
|
|
1193
|
+
schedules: Array<{ id: string; description: string }>;
|
|
1194
|
+
};
|
|
1195
|
+
|
|
1196
|
+
expect(result.schedules[0]).toMatchObject({
|
|
1197
|
+
id: schedule.id,
|
|
1198
|
+
description: "Updated description",
|
|
1199
|
+
});
|
|
1200
|
+
expect(listSchedules()[0].description).toBe("Updated description");
|
|
1201
|
+
});
|
|
1202
|
+
});
|
|
1203
|
+
|
|
1089
1204
|
// ── Wake mode support ─────────────────────────────────────────────────────
|
|
1090
1205
|
|
|
1091
1206
|
describe("wake mode in schedule routes", () => {
|
|
@@ -160,6 +160,7 @@ describe("createSchedule (cron)", () => {
|
|
|
160
160
|
expect(job.syntax).toBe("cron");
|
|
161
161
|
expect(job.expression).toBe("0 9 * * *");
|
|
162
162
|
expect(job.cronExpression).toBe("0 9 * * *");
|
|
163
|
+
expect(job.description).toBe("Morning ping");
|
|
163
164
|
expect(job.nextRunAt).toBeGreaterThan(Date.now() - 1000);
|
|
164
165
|
expect(job.enabled).toBe(true);
|
|
165
166
|
});
|
|
@@ -167,6 +168,7 @@ describe("createSchedule (cron)", () => {
|
|
|
167
168
|
test("persisted cron schedule is retrievable with new fields", () => {
|
|
168
169
|
const job = createSchedule({
|
|
169
170
|
name: "Hourly",
|
|
171
|
+
description: "Check the hourly status report",
|
|
170
172
|
cronExpression: "0 * * * *",
|
|
171
173
|
message: "hourly check",
|
|
172
174
|
syntax: "cron",
|
|
@@ -177,6 +179,32 @@ describe("createSchedule (cron)", () => {
|
|
|
177
179
|
expect(retrieved!.syntax).toBe("cron");
|
|
178
180
|
expect(retrieved!.expression).toBe("0 * * * *");
|
|
179
181
|
expect(retrieved!.cronExpression).toBe("0 * * * *");
|
|
182
|
+
expect(retrieved!.description).toBe("Check the hourly status report");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("normalizes schedule descriptions on create and update", () => {
|
|
186
|
+
const job = createSchedule({
|
|
187
|
+
name: "Description normalization",
|
|
188
|
+
description: " Daily executive summary ",
|
|
189
|
+
cronExpression: "0 8 * * *",
|
|
190
|
+
message: "summarize the day",
|
|
191
|
+
syntax: "cron",
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(job.description).toBe("Daily executive summary");
|
|
195
|
+
|
|
196
|
+
const raw = getRawDb()
|
|
197
|
+
.query("SELECT description FROM cron_jobs WHERE id = ?")
|
|
198
|
+
.get(job.id) as { description: string };
|
|
199
|
+
expect(raw.description).toBe("Daily executive summary");
|
|
200
|
+
|
|
201
|
+
const updated = updateSchedule(job.id, {
|
|
202
|
+
description: " Updated summary prompt ",
|
|
203
|
+
});
|
|
204
|
+
expect(updated).not.toBeNull();
|
|
205
|
+
expect(updated!.description).toBe("Updated summary prompt");
|
|
206
|
+
expect(getSchedule(job.id)!.description).toBe("Updated summary prompt");
|
|
207
|
+
expect(listSchedules()[0].description).toBe("Updated summary prompt");
|
|
180
208
|
});
|
|
181
209
|
|
|
182
210
|
test("defaults source conversation metadata to null", () => {
|
|
@@ -18,7 +18,7 @@ import type { Database } from "bun:sqlite";
|
|
|
18
18
|
|
|
19
19
|
import { getDb } from "../memory/db-connection.js";
|
|
20
20
|
import { initializeDb } from "../memory/db-init.js";
|
|
21
|
-
import { executeScheduleCreate } from "../tools/schedule/create.js";
|
|
21
|
+
import { executeScheduleCreate as rawExecuteScheduleCreate } from "../tools/schedule/create.js";
|
|
22
22
|
import { executeScheduleDelete } from "../tools/schedule/delete.js";
|
|
23
23
|
import { executeScheduleList } from "../tools/schedule/list.js";
|
|
24
24
|
import { executeScheduleUpdate } from "../tools/schedule/update.js";
|
|
@@ -41,6 +41,16 @@ const trustedCtx: ToolContext = {
|
|
|
41
41
|
trustClass: "trusted_contact",
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
function executeScheduleCreate(
|
|
45
|
+
input: Record<string, unknown>,
|
|
46
|
+
context: ToolContext,
|
|
47
|
+
) {
|
|
48
|
+
return rawExecuteScheduleCreate(
|
|
49
|
+
{ description: "Test schedule description", ...input },
|
|
50
|
+
context,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
// ── schedule_create ─────────────────────────────────────────────────
|
|
45
55
|
|
|
46
56
|
describe("schedule_create tool", () => {
|
|
@@ -53,6 +63,7 @@ describe("schedule_create tool", () => {
|
|
|
53
63
|
const result = await executeScheduleCreate(
|
|
54
64
|
{
|
|
55
65
|
name: "Daily standup",
|
|
66
|
+
description: "Remind the team to join the daily standup.",
|
|
56
67
|
expression: "0 9 * * 1-5",
|
|
57
68
|
message: "Time for standup!",
|
|
58
69
|
},
|
|
@@ -62,8 +73,16 @@ describe("schedule_create tool", () => {
|
|
|
62
73
|
expect(result.isError).toBe(false);
|
|
63
74
|
expect(result.content).toContain("schedule created successfully");
|
|
64
75
|
expect(result.content).toContain("Daily standup");
|
|
76
|
+
expect(result.content).toContain(
|
|
77
|
+
"Description: Remind the team to join the daily standup.",
|
|
78
|
+
);
|
|
65
79
|
expect(result.content).toContain("Every weekday at 9:00 AM");
|
|
66
80
|
expect(result.content).toContain("Enabled: true");
|
|
81
|
+
|
|
82
|
+
const row = getRawDb()
|
|
83
|
+
.query("SELECT description FROM cron_jobs LIMIT 1")
|
|
84
|
+
.get() as { description: string };
|
|
85
|
+
expect(row.description).toBe("Remind the team to join the daily standup.");
|
|
67
86
|
});
|
|
68
87
|
|
|
69
88
|
test("persists the creating conversation for recurring schedules", async () => {
|
|
@@ -126,6 +145,35 @@ describe("schedule_create tool", () => {
|
|
|
126
145
|
expect(result.content).toContain("name is required");
|
|
127
146
|
});
|
|
128
147
|
|
|
148
|
+
test("rejects missing description", async () => {
|
|
149
|
+
const result = await rawExecuteScheduleCreate(
|
|
150
|
+
{
|
|
151
|
+
name: "No description",
|
|
152
|
+
expression: "0 9 * * *",
|
|
153
|
+
message: "test",
|
|
154
|
+
},
|
|
155
|
+
ctx,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
expect(result.isError).toBe(true);
|
|
159
|
+
expect(result.content).toContain("description is required");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("rejects blank description", async () => {
|
|
163
|
+
const result = await rawExecuteScheduleCreate(
|
|
164
|
+
{
|
|
165
|
+
name: "Blank description",
|
|
166
|
+
description: " ",
|
|
167
|
+
expression: "0 9 * * *",
|
|
168
|
+
message: "test",
|
|
169
|
+
},
|
|
170
|
+
ctx,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
expect(result.isError).toBe(true);
|
|
174
|
+
expect(result.content).toContain("description is required");
|
|
175
|
+
});
|
|
176
|
+
|
|
129
177
|
test("rejects missing expression when no fire_at", async () => {
|
|
130
178
|
const result = await executeScheduleCreate(
|
|
131
179
|
{
|
|
@@ -195,6 +243,7 @@ describe("schedule_create with fire_at (one-shot)", () => {
|
|
|
195
243
|
const result = await executeScheduleCreate(
|
|
196
244
|
{
|
|
197
245
|
name: "One-time reminder",
|
|
246
|
+
description: "Remind the user about a one-time event.",
|
|
198
247
|
fire_at: futureDate,
|
|
199
248
|
message: "Don't forget!",
|
|
200
249
|
},
|
|
@@ -206,7 +255,15 @@ describe("schedule_create with fire_at (one-shot)", () => {
|
|
|
206
255
|
expect(result.content).toContain("Type: one-shot");
|
|
207
256
|
expect(result.content).toContain("Mode: execute");
|
|
208
257
|
expect(result.content).toContain("One-time reminder");
|
|
258
|
+
expect(result.content).toContain(
|
|
259
|
+
"Description: Remind the user about a one-time event.",
|
|
260
|
+
);
|
|
209
261
|
expect(result.content).toContain("Status: active");
|
|
262
|
+
|
|
263
|
+
const row = getRawDb()
|
|
264
|
+
.query("SELECT description FROM cron_jobs LIMIT 1")
|
|
265
|
+
.get() as { description: string };
|
|
266
|
+
expect(row.description).toBe("Remind the user about a one-time event.");
|
|
210
267
|
});
|
|
211
268
|
|
|
212
269
|
test("persists the creating conversation for one-shot schedules", async () => {
|
|
@@ -547,6 +604,7 @@ describe("schedule_list tool", () => {
|
|
|
547
604
|
await executeScheduleCreate(
|
|
548
605
|
{
|
|
549
606
|
name: "Detail Job",
|
|
607
|
+
description: "Describe the detail job purpose.",
|
|
550
608
|
expression: "30 14 * * *",
|
|
551
609
|
message: "Afternoon check",
|
|
552
610
|
},
|
|
@@ -561,6 +619,9 @@ describe("schedule_list tool", () => {
|
|
|
561
619
|
|
|
562
620
|
expect(result.isError).toBe(false);
|
|
563
621
|
expect(result.content).toContain("Schedule: Detail Job");
|
|
622
|
+
expect(result.content).toContain(
|
|
623
|
+
"Description: Describe the detail job purpose.",
|
|
624
|
+
);
|
|
564
625
|
expect(result.content).toContain("Every day at 2:30 PM");
|
|
565
626
|
expect(result.content).toContain("Message: Afternoon check");
|
|
566
627
|
expect(result.content).toContain("Enabled: true");
|
|
@@ -598,6 +659,7 @@ describe("schedule_list with one-shot schedules", () => {
|
|
|
598
659
|
|
|
599
660
|
expect(result.isError).toBe(false);
|
|
600
661
|
expect(result.content).toContain("One-shot Event");
|
|
662
|
+
expect(result.content).toContain("Test schedule description");
|
|
601
663
|
expect(result.content).toContain("one-shot");
|
|
602
664
|
expect(result.content).toContain("fire at:");
|
|
603
665
|
expect(result.content).toContain("active");
|
|
@@ -719,6 +781,37 @@ describe("schedule_update tool", () => {
|
|
|
719
781
|
expect(result.content).toContain("New Name");
|
|
720
782
|
});
|
|
721
783
|
|
|
784
|
+
test("updates the description of a schedule", async () => {
|
|
785
|
+
await executeScheduleCreate(
|
|
786
|
+
{
|
|
787
|
+
name: "Description update",
|
|
788
|
+
description: "Original purpose.",
|
|
789
|
+
expression: "0 9 * * *",
|
|
790
|
+
message: "test",
|
|
791
|
+
},
|
|
792
|
+
ctx,
|
|
793
|
+
);
|
|
794
|
+
|
|
795
|
+
const row = getRawDb().query("SELECT id FROM cron_jobs LIMIT 1").get() as {
|
|
796
|
+
id: string;
|
|
797
|
+
};
|
|
798
|
+
const result = await executeScheduleUpdate(
|
|
799
|
+
{
|
|
800
|
+
job_id: row.id,
|
|
801
|
+
description: "Updated purpose.",
|
|
802
|
+
},
|
|
803
|
+
ctx,
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
expect(result.isError).toBe(false);
|
|
807
|
+
expect(result.content).toContain("Description: Updated purpose.");
|
|
808
|
+
|
|
809
|
+
const dbRow = getRawDb()
|
|
810
|
+
.query("SELECT description FROM cron_jobs WHERE id = ?")
|
|
811
|
+
.get(row.id) as { description: string };
|
|
812
|
+
expect(dbRow.description).toBe("Updated purpose.");
|
|
813
|
+
});
|
|
814
|
+
|
|
722
815
|
test("updates the cron expression", async () => {
|
|
723
816
|
await executeScheduleCreate(
|
|
724
817
|
{
|
|
@@ -808,6 +808,45 @@ describe("renderHistoryContent contentBlocks", () => {
|
|
|
808
808
|
);
|
|
809
809
|
});
|
|
810
810
|
|
|
811
|
+
test("surfaces persisted thinking timing onto the thinking block", () => {
|
|
812
|
+
// GIVEN a thinking block the daemon stamped with internal `_startedAt` /
|
|
813
|
+
// `_completedAt` timing at message_complete
|
|
814
|
+
const output = renderHistoryContent([
|
|
815
|
+
{
|
|
816
|
+
type: "thinking",
|
|
817
|
+
thinking: "reasoning",
|
|
818
|
+
signature: "sig",
|
|
819
|
+
_startedAt: 1000,
|
|
820
|
+
_completedAt: 1500,
|
|
821
|
+
},
|
|
822
|
+
]);
|
|
823
|
+
|
|
824
|
+
// THEN the rendered block exposes them as the wire schema's
|
|
825
|
+
// startedAt/completedAt so the client can show the duration + hover state
|
|
826
|
+
expect(output.contentBlocks).toEqual([
|
|
827
|
+
{
|
|
828
|
+
type: "thinking",
|
|
829
|
+
thinking: "reasoning",
|
|
830
|
+
startedAt: 1000,
|
|
831
|
+
completedAt: 1500,
|
|
832
|
+
},
|
|
833
|
+
]);
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
test("omits thinking timing when the block carries none", () => {
|
|
837
|
+
// GIVEN a thinking block with no persisted timing (older daemon / thinking
|
|
838
|
+
// streaming disabled)
|
|
839
|
+
const output = renderHistoryContent([
|
|
840
|
+
{ type: "thinking", thinking: "reasoning", signature: "sig" },
|
|
841
|
+
]);
|
|
842
|
+
|
|
843
|
+
// THEN the rendered block has no startedAt/completedAt and the client hides
|
|
844
|
+
// the duration, exactly as a tool call with no timing
|
|
845
|
+
expect(output.contentBlocks).toEqual([
|
|
846
|
+
{ type: "thinking", thinking: "reasoning" },
|
|
847
|
+
]);
|
|
848
|
+
});
|
|
849
|
+
|
|
811
850
|
const pdfBlock = {
|
|
812
851
|
type: "file",
|
|
813
852
|
source: {
|
|
@@ -222,6 +222,19 @@ mock.module("../util/logger.js", () => ({
|
|
|
222
222
|
}),
|
|
223
223
|
}));
|
|
224
224
|
|
|
225
|
+
// Mock the skill_loaded telemetry dependencies of conversation-skill-tools so
|
|
226
|
+
// their heavy transitive imports (catalog-install → CLI program, sqlite) stay
|
|
227
|
+
// out of this import-light test.
|
|
228
|
+
mock.module("../skills/catalog-cache.js", () => ({
|
|
229
|
+
getCachedCatalogSync: () => [],
|
|
230
|
+
}));
|
|
231
|
+
mock.module("../skills/install-meta.js", () => ({
|
|
232
|
+
readInstallMeta: () => null,
|
|
233
|
+
}));
|
|
234
|
+
mock.module("../memory/skill-loaded-events-store.js", () => ({
|
|
235
|
+
recordSkillLoadedEvent: () => {},
|
|
236
|
+
}));
|
|
237
|
+
|
|
225
238
|
// ---------------------------------------------------------------------------
|
|
226
239
|
// Import module under test (after mocks)
|
|
227
240
|
// ---------------------------------------------------------------------------
|
|
@@ -96,6 +96,19 @@ mock.module("../skills/version-hash.js", () => ({
|
|
|
96
96
|
computeSkillVersionHash: () => "v1:deadbeef",
|
|
97
97
|
}));
|
|
98
98
|
|
|
99
|
+
// Mock the skill_loaded telemetry dependencies of conversation-skill-tools so
|
|
100
|
+
// their heavy transitive imports (catalog-install → CLI program, sqlite) stay
|
|
101
|
+
// out of this import-light test.
|
|
102
|
+
mock.module("../skills/catalog-cache.js", () => ({
|
|
103
|
+
getCachedCatalogSync: () => [],
|
|
104
|
+
}));
|
|
105
|
+
mock.module("../skills/install-meta.js", () => ({
|
|
106
|
+
readInstallMeta: () => null,
|
|
107
|
+
}));
|
|
108
|
+
mock.module("../memory/skill-loaded-events-store.js", () => ({
|
|
109
|
+
recordSkillLoadedEvent: () => {},
|
|
110
|
+
}));
|
|
111
|
+
|
|
99
112
|
// Mock createSkillToolsFromManifest to return lightweight Tool-like objects
|
|
100
113
|
mock.module("../tools/skills/skill-tool-factory.js", () => ({
|
|
101
114
|
createSkillToolsFromManifest: (
|
|
@@ -153,22 +166,27 @@ mock.module("node:fs", () => ({
|
|
|
153
166
|
Stats: class {},
|
|
154
167
|
}));
|
|
155
168
|
|
|
156
|
-
|
|
169
|
+
// Mirrors the current registry contract: ownership is recorded from the
|
|
170
|
+
// `registerSkillTools(skillId, tools)` call and reported via `getToolOwner`.
|
|
171
|
+
const benchmarkRegistry = new Map<string, { tool: unknown; skillId: string }>();
|
|
157
172
|
mock.module("../tools/registry.js", () => ({
|
|
158
173
|
registerSkillTools: (
|
|
174
|
+
skillId: string,
|
|
159
175
|
tools: Array<{ name: string; [k: string]: unknown }>,
|
|
160
176
|
) => {
|
|
161
|
-
for (const t of tools) benchmarkRegistry.set(t.name, t);
|
|
177
|
+
for (const t of tools) benchmarkRegistry.set(t.name, { tool: t, skillId });
|
|
162
178
|
return tools;
|
|
163
179
|
},
|
|
164
180
|
unregisterSkillTools: (skillId: string) => {
|
|
165
|
-
for (const [name,
|
|
166
|
-
|
|
167
|
-
if (owner?.kind === "skill" && owner.id === skillId)
|
|
168
|
-
benchmarkRegistry.delete(name);
|
|
181
|
+
for (const [name, entry] of benchmarkRegistry) {
|
|
182
|
+
if (entry.skillId === skillId) benchmarkRegistry.delete(name);
|
|
169
183
|
}
|
|
170
184
|
},
|
|
171
|
-
getTool: (name: string) => benchmarkRegistry.get(name),
|
|
185
|
+
getTool: (name: string) => benchmarkRegistry.get(name)?.tool,
|
|
186
|
+
getToolOwner: (name: string) => {
|
|
187
|
+
const entry = benchmarkRegistry.get(name);
|
|
188
|
+
return entry ? { kind: "skill" as const, id: entry.skillId } : undefined;
|
|
189
|
+
},
|
|
172
190
|
}));
|
|
173
191
|
|
|
174
192
|
// ---------------------------------------------------------------------------
|