@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
|
@@ -354,6 +354,9 @@ function getDetailedHealth() {
|
|
|
354
354
|
ces: {
|
|
355
355
|
connected: cesClient?.isReady() ?? false,
|
|
356
356
|
},
|
|
357
|
+
capabilities: {
|
|
358
|
+
memoryOptOut: true,
|
|
359
|
+
},
|
|
357
360
|
...(profiler ? { profiler } : {}),
|
|
358
361
|
};
|
|
359
362
|
}
|
|
@@ -645,6 +648,10 @@ const cesHealthSchema = z.object({
|
|
|
645
648
|
connected: z.boolean(),
|
|
646
649
|
});
|
|
647
650
|
|
|
651
|
+
const healthCapabilitiesSchema = z.object({
|
|
652
|
+
memoryOptOut: z.boolean(),
|
|
653
|
+
});
|
|
654
|
+
|
|
648
655
|
const healthDiskSchema = z.object({
|
|
649
656
|
path: z.string(),
|
|
650
657
|
totalMb: z.number(),
|
|
@@ -677,6 +684,7 @@ const detailedHealthSchema = z.object({
|
|
|
677
684
|
cpu: healthCpuSchema,
|
|
678
685
|
migrations: healthMigrationsSchema,
|
|
679
686
|
ces: cesHealthSchema,
|
|
687
|
+
capabilities: healthCapabilitiesSchema,
|
|
680
688
|
profiler: profilerStatusSchema.optional(),
|
|
681
689
|
});
|
|
682
690
|
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
findByInviteCodeHash,
|
|
24
24
|
findByInviteCodeHashAnyChannel,
|
|
25
25
|
} from "../../../memory/invite-store.js";
|
|
26
|
-
import { MESSAGE_PREVIEW_MAX_LENGTH } from "../../../notifications/copy
|
|
26
|
+
import { MESSAGE_PREVIEW_MAX_LENGTH } from "../../../notifications/access-request-copy.js";
|
|
27
27
|
import { resolveGuardianName } from "../../../prompts/user-reference.js";
|
|
28
28
|
import { getLogger } from "../../../util/logger.js";
|
|
29
29
|
import { truncate } from "../../../util/truncate.js";
|
|
@@ -332,12 +332,12 @@ export async function enforceIngressAcl(
|
|
|
332
332
|
|
|
333
333
|
return {
|
|
334
334
|
resolvedMember: null,
|
|
335
|
-
earlyResponse:
|
|
335
|
+
earlyResponse: {
|
|
336
336
|
accepted: true,
|
|
337
337
|
denied: true,
|
|
338
338
|
reason: "verification_challenge_sent",
|
|
339
339
|
verificationSessionId: slackVerifyResult.sessionId,
|
|
340
|
-
}
|
|
340
|
+
},
|
|
341
341
|
};
|
|
342
342
|
}
|
|
343
343
|
}
|
|
@@ -375,12 +375,12 @@ export async function enforceIngressAcl(
|
|
|
375
375
|
|
|
376
376
|
return {
|
|
377
377
|
resolvedMember: null,
|
|
378
|
-
earlyResponse:
|
|
378
|
+
earlyResponse: {
|
|
379
379
|
accepted: true,
|
|
380
380
|
denied: true,
|
|
381
381
|
reason: "verification_challenge_sent",
|
|
382
382
|
verificationSessionId: emailVerifyResult.sessionId,
|
|
383
|
-
}
|
|
383
|
+
},
|
|
384
384
|
};
|
|
385
385
|
}
|
|
386
386
|
}
|
|
@@ -438,14 +438,14 @@ export async function enforceIngressAcl(
|
|
|
438
438
|
|
|
439
439
|
return {
|
|
440
440
|
resolvedMember: null,
|
|
441
|
-
earlyResponse:
|
|
441
|
+
earlyResponse: {
|
|
442
442
|
accepted: true,
|
|
443
443
|
denied: true,
|
|
444
444
|
reason: "not_a_member",
|
|
445
445
|
// Include reply text so the gateway can deliver directly when
|
|
446
446
|
// callback delivery failed (e.g. signing-key mismatch → 401).
|
|
447
447
|
...(!replyDelivered && { replyText }),
|
|
448
|
-
}
|
|
448
|
+
},
|
|
449
449
|
};
|
|
450
450
|
}
|
|
451
451
|
}
|
|
@@ -610,12 +610,12 @@ export async function enforceIngressAcl(
|
|
|
610
610
|
|
|
611
611
|
return {
|
|
612
612
|
resolvedMember,
|
|
613
|
-
earlyResponse:
|
|
613
|
+
earlyResponse: {
|
|
614
614
|
accepted: true,
|
|
615
615
|
denied: true,
|
|
616
616
|
reason: "verification_challenge_sent",
|
|
617
617
|
verificationSessionId: slackVerifyResult.sessionId,
|
|
618
|
-
}
|
|
618
|
+
},
|
|
619
619
|
};
|
|
620
620
|
}
|
|
621
621
|
}
|
|
@@ -682,12 +682,12 @@ export async function enforceIngressAcl(
|
|
|
682
682
|
}
|
|
683
683
|
return {
|
|
684
684
|
resolvedMember,
|
|
685
|
-
earlyResponse:
|
|
685
|
+
earlyResponse: {
|
|
686
686
|
accepted: true,
|
|
687
687
|
denied: true,
|
|
688
688
|
reason: `member_${channelStatusToMemberStatus(resolvedMember.channel.status)}`,
|
|
689
689
|
...(!inactiveReplyDelivered && { replyText: inactiveReplyText }),
|
|
690
|
-
}
|
|
690
|
+
},
|
|
691
691
|
};
|
|
692
692
|
}
|
|
693
693
|
}
|
|
@@ -722,15 +722,14 @@ export async function enforceIngressAcl(
|
|
|
722
722
|
}
|
|
723
723
|
return {
|
|
724
724
|
resolvedMember,
|
|
725
|
-
earlyResponse:
|
|
725
|
+
earlyResponse: {
|
|
726
726
|
accepted: true,
|
|
727
727
|
denied: true,
|
|
728
728
|
reason: "policy_deny",
|
|
729
729
|
...(!denyReplyDelivered && { replyText: denyReplyText }),
|
|
730
|
-
}
|
|
730
|
+
},
|
|
731
731
|
};
|
|
732
732
|
}
|
|
733
|
-
|
|
734
733
|
}
|
|
735
734
|
}
|
|
736
735
|
|
|
@@ -786,11 +785,11 @@ async function handleInviteTokenIntercept(params: {
|
|
|
786
785
|
);
|
|
787
786
|
|
|
788
787
|
if (dedupResult.duplicate) {
|
|
789
|
-
return
|
|
788
|
+
return {
|
|
790
789
|
accepted: true,
|
|
791
790
|
duplicate: true,
|
|
792
791
|
eventId: dedupResult.eventId,
|
|
793
|
-
}
|
|
792
|
+
};
|
|
794
793
|
}
|
|
795
794
|
|
|
796
795
|
const outcome = redeemInvite({
|
|
@@ -835,11 +834,11 @@ async function handleInviteTokenIntercept(params: {
|
|
|
835
834
|
}
|
|
836
835
|
}
|
|
837
836
|
markProcessed(dedupResult.eventId);
|
|
838
|
-
return
|
|
837
|
+
return {
|
|
839
838
|
accepted: true,
|
|
840
839
|
eventId: dedupResult.eventId,
|
|
841
840
|
inviteRedemption: "already_member",
|
|
842
|
-
}
|
|
841
|
+
};
|
|
843
842
|
}
|
|
844
843
|
|
|
845
844
|
const replyText = getInviteRedemptionReply(outcome);
|
|
@@ -861,22 +860,22 @@ async function handleInviteTokenIntercept(params: {
|
|
|
861
860
|
|
|
862
861
|
if (outcome.ok && outcome.type === "redeemed") {
|
|
863
862
|
markProcessed(dedupResult.eventId);
|
|
864
|
-
return
|
|
863
|
+
return {
|
|
865
864
|
accepted: true,
|
|
866
865
|
eventId: dedupResult.eventId,
|
|
867
866
|
inviteRedemption: "redeemed",
|
|
868
867
|
memberId: outcome.memberId,
|
|
869
|
-
}
|
|
868
|
+
};
|
|
870
869
|
}
|
|
871
870
|
|
|
872
871
|
// Failed redemption — inform the user and deny
|
|
873
872
|
markProcessed(dedupResult.eventId);
|
|
874
|
-
return
|
|
873
|
+
return {
|
|
875
874
|
accepted: true,
|
|
876
875
|
eventId: dedupResult.eventId,
|
|
877
876
|
denied: true,
|
|
878
877
|
inviteRedemption: outcome.reason,
|
|
879
|
-
}
|
|
878
|
+
};
|
|
880
879
|
}
|
|
881
880
|
|
|
882
881
|
// ---------------------------------------------------------------------------
|
|
@@ -942,11 +941,11 @@ async function handleInviteCodeIntercept(params: {
|
|
|
942
941
|
);
|
|
943
942
|
|
|
944
943
|
if (dedupResult.duplicate) {
|
|
945
|
-
return
|
|
944
|
+
return {
|
|
946
945
|
accepted: true,
|
|
947
946
|
duplicate: true,
|
|
948
947
|
eventId: dedupResult.eventId,
|
|
949
|
-
}
|
|
948
|
+
};
|
|
950
949
|
}
|
|
951
950
|
|
|
952
951
|
const mismatchReply = "This invite is not valid for this channel.";
|
|
@@ -965,12 +964,12 @@ async function handleInviteCodeIntercept(params: {
|
|
|
965
964
|
}
|
|
966
965
|
}
|
|
967
966
|
markProcessed(dedupResult.eventId);
|
|
968
|
-
return
|
|
967
|
+
return {
|
|
969
968
|
accepted: true,
|
|
970
969
|
eventId: dedupResult.eventId,
|
|
971
970
|
denied: true,
|
|
972
971
|
inviteRedemption: "channel_mismatch",
|
|
973
|
-
}
|
|
972
|
+
};
|
|
974
973
|
}
|
|
975
974
|
return null;
|
|
976
975
|
}
|
|
@@ -988,11 +987,11 @@ async function handleInviteCodeIntercept(params: {
|
|
|
988
987
|
);
|
|
989
988
|
|
|
990
989
|
if (dedupResult.duplicate) {
|
|
991
|
-
return
|
|
990
|
+
return {
|
|
992
991
|
accepted: true,
|
|
993
992
|
duplicate: true,
|
|
994
993
|
eventId: dedupResult.eventId,
|
|
995
|
-
}
|
|
994
|
+
};
|
|
996
995
|
}
|
|
997
996
|
|
|
998
997
|
let outcome: ReturnType<typeof redeemInviteByCode>;
|
|
@@ -1046,11 +1045,11 @@ async function handleInviteCodeIntercept(params: {
|
|
|
1046
1045
|
}
|
|
1047
1046
|
}
|
|
1048
1047
|
markProcessed(dedupResult.eventId);
|
|
1049
|
-
return
|
|
1048
|
+
return {
|
|
1050
1049
|
accepted: true,
|
|
1051
1050
|
eventId: dedupResult.eventId,
|
|
1052
1051
|
inviteRedemption: "already_member",
|
|
1053
|
-
}
|
|
1052
|
+
};
|
|
1054
1053
|
}
|
|
1055
1054
|
|
|
1056
1055
|
const replyText = getInviteRedemptionReply(outcome);
|
|
@@ -1072,22 +1071,22 @@ async function handleInviteCodeIntercept(params: {
|
|
|
1072
1071
|
|
|
1073
1072
|
if (outcome.ok && outcome.type === "redeemed") {
|
|
1074
1073
|
markProcessed(dedupResult.eventId);
|
|
1075
|
-
return
|
|
1074
|
+
return {
|
|
1076
1075
|
accepted: true,
|
|
1077
1076
|
eventId: dedupResult.eventId,
|
|
1078
1077
|
inviteRedemption: "redeemed",
|
|
1079
1078
|
memberId: outcome.memberId,
|
|
1080
|
-
}
|
|
1079
|
+
};
|
|
1081
1080
|
}
|
|
1082
1081
|
|
|
1083
1082
|
// Failed redemption (expired, revoked, etc.) — inform and deny
|
|
1084
1083
|
markProcessed(dedupResult.eventId);
|
|
1085
|
-
return
|
|
1084
|
+
return {
|
|
1086
1085
|
accepted: true,
|
|
1087
1086
|
eventId: dedupResult.eventId,
|
|
1088
1087
|
denied: true,
|
|
1089
1088
|
inviteRedemption: !outcome.ok ? outcome.reason : undefined,
|
|
1090
|
-
}
|
|
1089
|
+
};
|
|
1091
1090
|
}
|
|
1092
1091
|
|
|
1093
1092
|
// ---------------------------------------------------------------------------
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
|
-
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
14
13
|
import { getConfigReadOnly } from "../../config/loader.js";
|
|
15
14
|
import { getDb } from "../../memory/db-connection.js";
|
|
16
15
|
import {
|
|
@@ -44,22 +43,6 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
44
43
|
// ---------------------------------------------------------------------------
|
|
45
44
|
|
|
46
45
|
const providerConnectionResponseSchema = ProviderConnectionSchema;
|
|
47
|
-
const OPENAI_COMPATIBLE_ENDPOINTS_FLAG = "openai-compatible-endpoints";
|
|
48
|
-
|
|
49
|
-
function openAICompatibleEndpointsEnabled(): boolean {
|
|
50
|
-
return isAssistantFeatureFlagEnabled(
|
|
51
|
-
OPENAI_COMPATIBLE_ENDPOINTS_FLAG,
|
|
52
|
-
getConfigReadOnly(),
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function rejectDisabledOpenAICompatibleProvider(provider: string): void {
|
|
57
|
-
if (provider !== "openai-compatible") return;
|
|
58
|
-
if (openAICompatibleEndpointsEnabled()) return;
|
|
59
|
-
throw new BadRequestError(
|
|
60
|
-
"OpenAI-compatible endpoints are disabled. Enable the openai-compatible-endpoints feature flag to configure this provider.",
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
46
|
|
|
64
47
|
// ---------------------------------------------------------------------------
|
|
65
48
|
// Custom provider field parsing (openai-compatible base_url + models)
|
|
@@ -170,18 +153,10 @@ async function parseCustomProviderFields(
|
|
|
170
153
|
|
|
171
154
|
function handleListConnections({ queryParams = {} }: RouteHandlerArgs) {
|
|
172
155
|
const provider = queryParams.provider;
|
|
173
|
-
if (provider) rejectDisabledOpenAICompatibleProvider(provider);
|
|
174
156
|
const connections = listConnections(
|
|
175
157
|
getDb(),
|
|
176
158
|
provider ? { provider } : undefined,
|
|
177
159
|
);
|
|
178
|
-
if (!openAICompatibleEndpointsEnabled()) {
|
|
179
|
-
return {
|
|
180
|
-
connections: connections.filter(
|
|
181
|
-
(conn) => conn.provider !== "openai-compatible",
|
|
182
|
-
),
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
160
|
return { connections };
|
|
186
161
|
}
|
|
187
162
|
|
|
@@ -191,12 +166,6 @@ function handleGetConnection({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
191
166
|
|
|
192
167
|
const conn = getConnection(getDb(), name);
|
|
193
168
|
if (!conn) throw new NotFoundError(`Connection "${name}" not found.`);
|
|
194
|
-
if (
|
|
195
|
-
conn.provider === "openai-compatible" &&
|
|
196
|
-
!openAICompatibleEndpointsEnabled()
|
|
197
|
-
) {
|
|
198
|
-
throw new NotFoundError(`Connection "${name}" not found.`);
|
|
199
|
-
}
|
|
200
169
|
|
|
201
170
|
return conn;
|
|
202
171
|
}
|
|
@@ -216,8 +185,6 @@ async function handleCreateConnection({ body = {} }: RouteHandlerArgs) {
|
|
|
216
185
|
`Invalid provider "${String(provider)}". Valid: ${VALID_CONNECTION_PROVIDERS.join(", ")}`,
|
|
217
186
|
);
|
|
218
187
|
}
|
|
219
|
-
rejectDisabledOpenAICompatibleProvider(providerResult.data);
|
|
220
|
-
|
|
221
188
|
const authResult = AuthSchema.safeParse(auth);
|
|
222
189
|
if (!authResult.success) {
|
|
223
190
|
throw new BadRequestError(`Invalid auth: ${authResult.error.message}`);
|
|
@@ -280,12 +247,6 @@ async function handleUpdateConnection({
|
|
|
280
247
|
|
|
281
248
|
const existing = getConnection(getDb(), name);
|
|
282
249
|
if (!existing) throw new NotFoundError(`Connection "${name}" not found.`);
|
|
283
|
-
if (
|
|
284
|
-
existing.provider === "openai-compatible" &&
|
|
285
|
-
!openAICompatibleEndpointsEnabled()
|
|
286
|
-
) {
|
|
287
|
-
throw new NotFoundError(`Connection "${name}" not found.`);
|
|
288
|
-
}
|
|
289
250
|
|
|
290
251
|
const auth = body.auth;
|
|
291
252
|
const authResult = AuthSchema.safeParse(auth);
|
|
@@ -355,12 +316,6 @@ function handleDeleteConnection({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
355
316
|
if (!existing) {
|
|
356
317
|
throw new NotFoundError(`Connection "${name}" not found.`);
|
|
357
318
|
}
|
|
358
|
-
if (
|
|
359
|
-
existing.provider === "openai-compatible" &&
|
|
360
|
-
!openAICompatibleEndpointsEnabled()
|
|
361
|
-
) {
|
|
362
|
-
throw new NotFoundError(`Connection "${name}" not found.`);
|
|
363
|
-
}
|
|
364
319
|
|
|
365
320
|
// Managed connections are write-protected: `seedCanonicalConnections` would
|
|
366
321
|
// re-upsert them on the next daemon boot anyway, so a successful delete here
|
|
@@ -99,27 +99,20 @@ const pluginsListResponseSchema = z.object({
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
const pluginMatchSourceSchema = z
|
|
102
|
-
.
|
|
103
|
-
z.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
),
|
|
117
|
-
ref: z.string().describe("Pinned git ref the plugin is fetched from."),
|
|
118
|
-
}),
|
|
119
|
-
])
|
|
120
|
-
.describe(
|
|
121
|
-
"Origin of the match: a first-party in-repo plugin or a whitelisted external one.",
|
|
122
|
-
);
|
|
102
|
+
.object({
|
|
103
|
+
kind: z.literal("github"),
|
|
104
|
+
repo: z
|
|
105
|
+
.string()
|
|
106
|
+
.describe("`owner/repo` of the external plugin repository."),
|
|
107
|
+
path: z
|
|
108
|
+
.string()
|
|
109
|
+
.optional()
|
|
110
|
+
.describe(
|
|
111
|
+
"Directory within the repo, when the plugin is not at the root.",
|
|
112
|
+
),
|
|
113
|
+
ref: z.string().describe("Pinned git ref the plugin is fetched from."),
|
|
114
|
+
})
|
|
115
|
+
.describe("Origin of the match: a whitelisted external plugin repository.");
|
|
123
116
|
|
|
124
117
|
const pluginSearchMatchSchema = z.object({
|
|
125
118
|
name: z
|
|
@@ -128,7 +121,7 @@ const pluginSearchMatchSchema = z.object({
|
|
|
128
121
|
path: z
|
|
129
122
|
.string()
|
|
130
123
|
.describe(
|
|
131
|
-
"Human-readable origin: a
|
|
124
|
+
"Human-readable origin: a `github:owner/repo@ref` locator for the external plugin.",
|
|
132
125
|
),
|
|
133
126
|
description: z
|
|
134
127
|
.string()
|
|
@@ -186,7 +179,11 @@ const pluginDetailsResponseSchema = z.object({
|
|
|
186
179
|
.describe(
|
|
187
180
|
"Resolved version (installed copy first, then repo `package.json`).",
|
|
188
181
|
),
|
|
189
|
-
source: pluginMatchSourceSchema
|
|
182
|
+
source: pluginMatchSourceSchema
|
|
183
|
+
.nullable()
|
|
184
|
+
.describe(
|
|
185
|
+
"Pinned origin from the marketplace entry, or null when an installed copy has no catalog entry.",
|
|
186
|
+
),
|
|
190
187
|
readme: z
|
|
191
188
|
.string()
|
|
192
189
|
.nullable()
|
|
@@ -199,9 +196,7 @@ const pluginDetailsResponseSchema = z.object({
|
|
|
199
196
|
const pluginInstallRequestSchema = z.object({
|
|
200
197
|
name: z
|
|
201
198
|
.string()
|
|
202
|
-
.describe(
|
|
203
|
-
"Install name to resolve against the catalog (first-party directory or marketplace entry).",
|
|
204
|
-
),
|
|
199
|
+
.describe("Install name to resolve against the marketplace catalog."),
|
|
205
200
|
force: z
|
|
206
201
|
.boolean()
|
|
207
202
|
.optional()
|
|
@@ -255,9 +250,7 @@ interface PluginMatchView {
|
|
|
255
250
|
name: string;
|
|
256
251
|
path: string;
|
|
257
252
|
description?: string;
|
|
258
|
-
source:
|
|
259
|
-
| { kind: "first-party" }
|
|
260
|
-
| { kind: "github"; repo: string; path?: string; ref: string };
|
|
253
|
+
source: { kind: "github"; repo: string; path?: string; ref: string };
|
|
261
254
|
}
|
|
262
255
|
|
|
263
256
|
/**
|
|
@@ -269,15 +262,12 @@ function projectMatch(m: PluginSearchMatch): PluginMatchView {
|
|
|
269
262
|
const view: PluginMatchView = {
|
|
270
263
|
name: m.name,
|
|
271
264
|
path: m.path,
|
|
272
|
-
source:
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
...(m.source.path !== undefined ? { path: m.source.path } : {}),
|
|
279
|
-
}
|
|
280
|
-
: { kind: "first-party" },
|
|
265
|
+
source: {
|
|
266
|
+
kind: "github",
|
|
267
|
+
repo: m.source.repo,
|
|
268
|
+
ref: m.source.ref,
|
|
269
|
+
...(m.source.path !== undefined ? { path: m.source.path } : {}),
|
|
270
|
+
},
|
|
281
271
|
};
|
|
282
272
|
if (m.description !== undefined) {
|
|
283
273
|
view.description = m.description;
|
|
@@ -441,11 +431,10 @@ async function handleInstallPlugin({ body = {} }: RouteHandlerArgs) {
|
|
|
441
431
|
// The ref is pinned to the curated `DEFAULT_PLUGIN_REF` rather than taken
|
|
442
432
|
// from the request: a caller-supplied ref would let any `settings.write`
|
|
443
433
|
// principal install from an unreviewed revision (a PR branch, fork ref,
|
|
444
|
-
// ...) whose marketplace manifest
|
|
445
|
-
//
|
|
446
|
-
//
|
|
447
|
-
//
|
|
448
|
-
// `assistant plugins install --ref`.
|
|
434
|
+
// ...) whose marketplace manifest could carry attacker code that the loader
|
|
435
|
+
// then dynamically imports. Installs over HTTP therefore only ever resolve
|
|
436
|
+
// against the reviewed catalog on the default ref. Operators who need
|
|
437
|
+
// another ref use the local CLI's `assistant plugins install --ref`.
|
|
449
438
|
try {
|
|
450
439
|
const result = await installPlugin(
|
|
451
440
|
{ name, ref: DEFAULT_PLUGIN_REF, force },
|
|
@@ -517,7 +506,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
517
506
|
},
|
|
518
507
|
summary: "Search the plugin catalog",
|
|
519
508
|
description:
|
|
520
|
-
"List installable plugins from the
|
|
509
|
+
"List installable plugins from the curated `plugins/marketplace.json` catalog. The query is an ECMAScript regex matched case-insensitively against the plugin name (e.g. `memory`, `^simple`). Empty query returns every entry. Mirrors the CLI's `assistant plugins search`.",
|
|
521
510
|
tags: ["plugins"],
|
|
522
511
|
queryParams: [
|
|
523
512
|
{
|
|
@@ -546,7 +535,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
546
535
|
},
|
|
547
536
|
summary: "Install a plugin",
|
|
548
537
|
description:
|
|
549
|
-
"Install a plugin by name from the canonical source — a whitelisted `
|
|
538
|
+
"Install a plugin by name from the canonical source — a whitelisted `plugins/marketplace.json` entry. Always resolves against the curated default git ref (no caller-supplied ref): installing from an unreviewed revision would bypass the marketplace curation boundary and let attacker-controlled code be loaded. Materializes the plugin under `<workspaceDir>/plugins/<name>/`; the assistant must be restarted to load it. Mirrors the CLI's `assistant plugins install <name>`. An already-installed name without `force` returns 409; a name that resolves to nothing returns 404. Sibling to `POST /v1/skills/install`.",
|
|
550
539
|
tags: ["plugins"],
|
|
551
540
|
requestBody: pluginInstallRequestSchema,
|
|
552
541
|
responseBody: pluginInstallResponseSchema,
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
getSchedule,
|
|
29
29
|
getScheduleRuns,
|
|
30
30
|
listSchedules,
|
|
31
|
+
type ScheduleJob,
|
|
31
32
|
setScheduleRunConversationId,
|
|
32
33
|
updateSchedule,
|
|
33
34
|
} from "../../schedule/schedule-store.js";
|
|
@@ -64,7 +65,8 @@ const scheduleSchema = z.object({
|
|
|
64
65
|
createdFromConversationId: z.string().nullable(),
|
|
65
66
|
createdFromConversationExists: z.boolean(),
|
|
66
67
|
createdFromConversationArchivedAt: z.number().nullable(),
|
|
67
|
-
description: z.string()
|
|
68
|
+
description: z.string(),
|
|
69
|
+
cadenceDescription: z.string(),
|
|
68
70
|
mode: z.enum(["notify", "execute", "script", "wake"]),
|
|
69
71
|
status: z.enum(["active", "firing", "fired", "cancelled"]),
|
|
70
72
|
routingIntent: z.enum(["single_channel", "multi_channel", "all_channels"]),
|
|
@@ -125,6 +127,18 @@ function getCreatedFromConversationState(
|
|
|
125
127
|
return state;
|
|
126
128
|
}
|
|
127
129
|
|
|
130
|
+
function getCadenceDescription(
|
|
131
|
+
job: Pick<ScheduleJob, "syntax" | "cronExpression" | "expression">,
|
|
132
|
+
): string {
|
|
133
|
+
if (job.cronExpression === null) {
|
|
134
|
+
return describeCronExpression(job.cronExpression);
|
|
135
|
+
}
|
|
136
|
+
if (job.syntax === "cron") {
|
|
137
|
+
return describeCronExpression(job.cronExpression);
|
|
138
|
+
}
|
|
139
|
+
return job.expression ?? "";
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
function handleListSchedules(queryParams: Record<string, string>) {
|
|
129
143
|
const includeAll = queryParams.include_all === "true";
|
|
130
144
|
const jobs = listSchedules();
|
|
@@ -161,10 +175,8 @@ function handleListSchedules(queryParams: Record<string, string>) {
|
|
|
161
175
|
createdFromConversationId: j.createdFromConversationId,
|
|
162
176
|
createdFromConversationExists: sourceConversation.exists,
|
|
163
177
|
createdFromConversationArchivedAt: sourceConversation.archivedAt,
|
|
164
|
-
description:
|
|
165
|
-
|
|
166
|
-
? describeCronExpression(j.cronExpression)
|
|
167
|
-
: j.expression,
|
|
178
|
+
description: j.description,
|
|
179
|
+
cadenceDescription: getCadenceDescription(j),
|
|
168
180
|
mode: j.mode,
|
|
169
181
|
status: j.status,
|
|
170
182
|
routingIntent: j.routingIntent,
|
|
@@ -180,6 +192,12 @@ function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
180
192
|
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
181
193
|
const expression =
|
|
182
194
|
typeof body.expression === "string" ? body.expression.trim() : "";
|
|
195
|
+
const description =
|
|
196
|
+
body.description === undefined
|
|
197
|
+
? undefined
|
|
198
|
+
: typeof body.description === "string"
|
|
199
|
+
? body.description.trim()
|
|
200
|
+
: "";
|
|
183
201
|
const message = typeof body.message === "string" ? body.message : "";
|
|
184
202
|
const timezoneRaw =
|
|
185
203
|
typeof body.timezone === "string" ? body.timezone.trim() : "";
|
|
@@ -190,6 +208,9 @@ function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
190
208
|
if (!name) throw new BadRequestError("name is required");
|
|
191
209
|
if (!expression) throw new BadRequestError("expression is required");
|
|
192
210
|
if (!message) throw new BadRequestError("message is required");
|
|
211
|
+
if (description === "") {
|
|
212
|
+
throw new BadRequestError("description is required");
|
|
213
|
+
}
|
|
193
214
|
|
|
194
215
|
// The settings UI only exposes execute mode for now. Other modes
|
|
195
216
|
// remain reachable via the schedule_create LLM tool.
|
|
@@ -209,6 +230,7 @@ function handleCreateSchedule(body: Record<string, unknown>) {
|
|
|
209
230
|
try {
|
|
210
231
|
const job = createSchedule({
|
|
211
232
|
name,
|
|
233
|
+
description,
|
|
212
234
|
message,
|
|
213
235
|
mode: "execute",
|
|
214
236
|
enabled,
|
|
@@ -304,6 +326,15 @@ function handleUpdateSchedule(id: string, body: Record<string, unknown>) {
|
|
|
304
326
|
}
|
|
305
327
|
}
|
|
306
328
|
|
|
329
|
+
if ("description" in body) {
|
|
330
|
+
const description =
|
|
331
|
+
typeof body.description === "string" ? body.description.trim() : "";
|
|
332
|
+
if (!description) {
|
|
333
|
+
throw new BadRequestError("description is required");
|
|
334
|
+
}
|
|
335
|
+
updates.description = description;
|
|
336
|
+
}
|
|
337
|
+
|
|
307
338
|
if (updates.timeoutMs != null) {
|
|
308
339
|
if (typeof updates.timeoutMs !== "number") {
|
|
309
340
|
throw new BadRequestError("timeoutMs must be a number or null");
|
|
@@ -460,6 +491,12 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
460
491
|
tags: ["schedules"],
|
|
461
492
|
requestBody: z.object({
|
|
462
493
|
name: z.string().describe("Display name"),
|
|
494
|
+
description: z
|
|
495
|
+
.string()
|
|
496
|
+
.describe(
|
|
497
|
+
"Authored schedule description. Defaults to the schedule name when omitted for backward compatibility.",
|
|
498
|
+
)
|
|
499
|
+
.optional(),
|
|
463
500
|
expression: z.string().describe("Cron or RRULE expression"),
|
|
464
501
|
message: z.string().describe("Message body to execute on each fire"),
|
|
465
502
|
timezone: z
|
|
@@ -552,6 +589,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
552
589
|
tags: ["schedules"],
|
|
553
590
|
requestBody: z.object({
|
|
554
591
|
name: z.string().optional(),
|
|
592
|
+
description: z.string().optional(),
|
|
555
593
|
expression: z.string().optional(),
|
|
556
594
|
timezone: z.string().optional(),
|
|
557
595
|
message: z.string().optional(),
|