@vellumai/assistant 0.12.4 → 0.12.5-dev.202609251017.e467a6c
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/docs/architecture/memory.md +9 -1
- package/docs/architecture/scheduling.md +13 -5
- package/docs/desktop-browser-cli.md +3 -2
- package/docs/guardian-request-flow.md +1 -1
- package/node_modules/@vellumai/avatar-manifest/src/__tests__/notification-avatar.test.ts +48 -4
- package/node_modules/@vellumai/avatar-manifest/src/notification-avatar.ts +12 -8
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/guardian-requests.test.ts +26 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +77 -3
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/guardian-requests.test.ts +26 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +77 -3
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +2 -4
- package/node_modules/@vellumai/service-contracts/src/__tests__/guardian-requests.test.ts +26 -0
- package/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +77 -3
- package/openapi.yaml +152 -3
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +76 -0
- package/src/__tests__/anthropic-error-formatting.test.ts +9 -0
- package/src/__tests__/background-shell-bash.test.ts +34 -0
- package/src/__tests__/background-shell-host-bash.test.ts +98 -1
- package/src/__tests__/background-tool-registry.test.ts +39 -0
- package/src/__tests__/channel-readiness-discord.test.ts +8 -0
- package/src/__tests__/channel-readiness-slack-remote.test.ts +8 -0
- package/src/__tests__/client-os-metadata-persistence.test.ts +4 -20
- package/src/__tests__/conversation-agent-loop.test.ts +529 -1
- package/src/__tests__/conversation-error.test.ts +18 -0
- package/src/__tests__/conversation-pairing.test.ts +69 -0
- package/src/__tests__/conversation-queue.test.ts +257 -4
- package/src/__tests__/conversation-runtime-assembly.test.ts +27 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +62 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +21 -0
- package/src/__tests__/gemini-provider.test.ts +9 -0
- package/src/__tests__/host-cu-proxy.test.ts +79 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +14 -5
- package/src/__tests__/introduction-card-resolver.test.ts +53 -8
- package/src/__tests__/job-handler-registration-guard.test.ts +1 -0
- package/src/__tests__/non-member-access-request.test.ts +48 -0
- package/src/__tests__/notification-events-source-context-probe.test.ts +48 -1
- package/src/__tests__/notification-platform-adapter.test.ts +97 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +103 -3
- package/src/__tests__/platform-callback-registration.test.ts +46 -1
- package/src/__tests__/plugin-import-boundary-guard.test.ts +3 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +116 -66
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -0
- package/src/__tests__/scheduler-result-notification.test.ts +521 -7
- package/src/__tests__/scheduler-wake.test.ts +1 -0
- package/src/__tests__/skill-load-inline-command.test.ts +35 -0
- package/src/__tests__/subagent-cron-run-attribution.test.ts +41 -2
- package/src/__tests__/subagent-manager-notify.test.ts +48 -0
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +6 -6
- package/src/__tests__/usage-attribution.test.ts +31 -0
- package/src/__tests__/wake-schedule-escalation.test.ts +1 -0
- package/src/agent/loop.ts +23 -0
- package/src/api/ask-question-tool.ts +50 -0
- package/src/api/events/generation-handoff.ts +4 -0
- package/src/api/events/message-complete.ts +4 -0
- package/src/api/events/tool-result.ts +11 -0
- package/src/api/index.ts +11 -0
- package/src/api/requests/guardian-actions.test.ts +45 -0
- package/src/api/requests/guardian-actions.ts +20 -0
- package/src/api/responses/conversation-message.ts +4 -0
- package/src/api/responses/home.ts +27 -0
- package/src/approvals/guardian-decision-primitive.ts +6 -4
- package/src/approvals/guardian-request-resolvers.ts +35 -30
- package/src/avatar/notification-avatar.test.ts +42 -34
- package/src/avatar/notification-avatar.ts +1 -0
- package/src/calls/__tests__/call-controller.test.ts +18 -0
- package/src/calls/__tests__/voice-control-protocol.test.ts +6 -1
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +70 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +116 -4
- package/src/calls/__tests__/voice-triage-escalate.test.ts +77 -11
- package/src/calls/call-controller.ts +3 -1
- package/src/calls/voice-control-protocol.ts +12 -4
- package/src/calls/voice-escalation-judge.ts +2 -2
- package/src/calls/voice-leg-coordinator.ts +23 -5
- package/src/calls/voice-screen-annotation.ts +44 -0
- package/src/calls/voice-session-bridge.ts +63 -20
- package/src/calls/voice-triage-escalate.ts +82 -27
- package/src/cli/commands/__tests__/conversations-clear.test.ts +156 -0
- package/src/cli/commands/conversations.help.ts +7 -2
- package/src/cli/commands/conversations.ts +36 -30
- package/src/cli/commands/oauth/index.help.ts +8 -2
- package/src/cli/commands/oauth/request.test.ts +32 -0
- package/src/cli/commands/platform/index.help.ts +2 -1
- package/src/cli/commands/platform/index.ts +8 -2
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +60 -0
- package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +66 -2
- package/src/cli/lib/bundled-marketplace.json +35 -0
- package/src/cli/lib/bundled-plugin-packages.json +21 -0
- package/src/cli/lib/plugin-catalog-cache.ts +17 -2
- package/src/cli/lib/plugin-catalog-platform.ts +48 -9
- package/src/config/__tests__/default-profile-catalog.test.ts +28 -0
- package/src/config/__tests__/platform-identity.test.ts +59 -0
- package/src/config/__tests__/profile-order.test.ts +19 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +71 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +20 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +11 -11
- package/src/config/bundled-skills/screen-annotation/SKILL.md +41 -29
- package/src/config/bundled-skills/screen-annotation/TOOLS.json +5 -5
- package/src/config/call-site-defaults.ts +6 -0
- package/src/config/default-profile-catalog.ts +30 -1
- package/src/config/default-profile-names.ts +36 -2
- package/src/config/feature-flag-registry.json +9 -1
- package/src/config/platform-identity.ts +22 -5
- package/src/config/profile-order.ts +7 -1
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/llm.ts +21 -5
- package/src/config/sync-gated-profiles.ts +96 -44
- package/src/daemon/__tests__/abort-null-controller.test.ts +135 -1
- package/src/daemon/__tests__/auto-profile-router.test.ts +380 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +16 -0
- package/src/daemon/activity-trail.test.ts +206 -0
- package/src/daemon/activity-trail.ts +190 -0
- package/src/daemon/auto-profile-router.ts +431 -0
- package/src/daemon/computer-use-observation.test.ts +81 -0
- package/src/daemon/computer-use-observation.ts +23 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +11 -0
- package/src/daemon/conversation-agent-loop.ts +157 -32
- package/src/daemon/conversation-error.ts +19 -0
- package/src/daemon/conversation-lifecycle.ts +70 -7
- package/src/daemon/conversation-media-retry.ts +1 -2
- package/src/daemon/conversation-messaging.ts +31 -2
- package/src/daemon/conversation-process.ts +107 -16
- package/src/daemon/conversation-queue-manager.ts +7 -0
- package/src/daemon/conversation-runtime-assembly.ts +1 -0
- package/src/daemon/conversation-turn-finalize.ts +14 -0
- package/src/daemon/conversation.ts +25 -6
- package/src/daemon/event-loop-watchdog.test.ts +201 -2
- package/src/daemon/event-loop-watchdog.ts +182 -6
- package/src/daemon/host-cu-proxy.ts +34 -3
- package/src/daemon/pkb-reminder-builder.test.ts +10 -3
- package/src/daemon/pkb-reminder-builder.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -2
- package/src/desktop/desktop-computer-use.test.ts +14 -4
- package/src/home/feed-types.ts +2 -0
- package/src/inbound/platform-callback-registration.ts +19 -6
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +27 -0
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +83 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +48 -1
- package/src/live-voice/__tests__/live-voice-vad.test.ts +34 -2
- package/src/live-voice/__tests__/protocol.test.ts +22 -0
- package/src/live-voice/continuation-judge.ts +1 -1
- package/src/live-voice/live-voice-session.ts +25 -19
- package/src/live-voice/protocol.ts +16 -5
- package/src/messaging/providers/discord/withdraw.ts +4 -5
- package/src/messaging/providers/gmail/client.ts +4 -0
- package/src/messaging/providers/slack/withdraw.ts +5 -5
- package/src/messaging/providers/telegram-bot/withdraw.ts +4 -5
- package/src/monitoring/__tests__/proc-fixtures.ts +28 -0
- package/src/monitoring/__tests__/proc-wait-state.test.ts +232 -0
- package/src/monitoring/__tests__/process-usage.test.ts +243 -0
- package/src/monitoring/proc-wait-state.ts +366 -0
- package/src/monitoring/process-memory.ts +4 -3
- package/src/monitoring/process-usage.ts +215 -0
- package/src/monitoring/resource-sample-types.ts +8 -0
- package/src/monitoring/resource-sampler.ts +17 -2
- package/src/monitoring/stall-capture.ts +12 -0
- package/src/notifications/README.md +88 -9
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +390 -119
- package/src/notifications/__tests__/background-result-producer.test.ts +1272 -0
- package/src/notifications/__tests__/broadcaster.test.ts +292 -1
- package/src/notifications/__tests__/completion-policy.test.ts +243 -0
- package/src/notifications/__tests__/decision-engine.test.ts +51 -4
- package/src/notifications/__tests__/has-pending-background-work.test.ts +281 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +161 -3
- package/src/notifications/__tests__/resolve-visible-in-source.test.ts +110 -1
- package/src/notifications/__tests__/schedule-result-producer.test.ts +11 -4
- package/src/notifications/adapters/macos.ts +24 -12
- package/src/notifications/adapters/platform.ts +16 -5
- package/src/notifications/assistant-reply-producer.ts +96 -71
- package/src/notifications/background-result-producer.ts +369 -0
- package/src/notifications/broadcaster.ts +28 -8
- package/src/notifications/completion-policy.ts +115 -0
- package/src/notifications/completion-work.ts +46 -0
- package/src/notifications/conversation-pairing.ts +32 -13
- package/src/notifications/decision-engine.ts +18 -24
- package/src/notifications/emit-signal.ts +16 -1
- package/src/notifications/events-store.ts +4 -0
- package/src/notifications/has-pending-background-work.ts +91 -0
- package/src/notifications/home-feed-mirror.ts +44 -0
- package/src/notifications/home-feed-side-effect.ts +54 -28
- package/src/notifications/resolve-visible-in-source.ts +56 -2
- package/src/notifications/result-output.ts +154 -0
- package/src/notifications/schedule-result-producer.ts +6 -187
- package/src/notifications/types.ts +2 -0
- package/src/oauth/AGENTS.md +9 -1
- package/src/oauth/byo-connection.test.ts +28 -0
- package/src/persistence/__tests__/recent-conversation-messages.test.ts +41 -0
- package/src/persistence/conversation-crud.ts +26 -0
- package/src/persistence/conversation-types.ts +15 -37
- package/src/persistence/embeddings/__tests__/embedding-local-lifecycle.test.ts +85 -14
- package/src/persistence/jobs-store.ts +229 -0
- package/src/persistence/migrations/383-normalize-opencode-host-connections.ts +44 -0
- package/src/persistence/migrations/__tests__/383-normalize-opencode-host-connections.test.ts +102 -0
- package/src/persistence/steps.ts +12 -0
- package/src/platform/sync-avatar.test.ts +29 -0
- package/src/plugins/defaults/memory/AGENTS.md +5 -3
- package/src/plugins/defaults/memory/__tests__/skill-update-receipt-boundary-guard.test.ts +45 -0
- package/src/plugins/defaults/memory/__tests__/skill-update-receipt-job.test.ts +580 -0
- package/src/plugins/defaults/memory/__tests__/turn-retrieval.test.ts +21 -0
- package/src/plugins/defaults/memory/graph/tools.ts +9 -5
- package/src/plugins/defaults/memory/hooks/conversation-deleted.ts +4 -0
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +7 -3
- package/src/plugins/defaults/memory/job-handlers.ts +8 -2
- package/src/plugins/defaults/memory/skill-update-receipt-job.ts +334 -0
- package/src/plugins/defaults/memory/tools.test.ts +17 -0
- package/src/plugins/defaults/memory/turn-retrieval.ts +8 -0
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +24 -0
- package/src/plugins/defaults/memory/v3/injector.ts +4 -4
- package/src/plugins/types.ts +2 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +8 -0
- package/src/providers/anthropic/client.ts +4 -0
- package/src/providers/gemini/client.ts +7 -1
- package/src/providers/inference/auth.ts +25 -0
- package/src/providers/inference/profile-probe.ts +1 -0
- package/src/{calls/__tests__/typesafe-noul.test.ts → providers/jev/ask.test.ts} +4 -4
- package/src/{calls/typesafe-noul.ts → providers/jev/ask.ts} +67 -34
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +12 -0
- package/src/providers/openai/api-error-normalization.ts +4 -0
- package/src/providers/retry.ts +2 -0
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +7 -0
- package/src/providers/usage-tracking.ts +5 -3
- package/src/runtime/__tests__/agent-wake.test.ts +308 -0
- package/src/runtime/access-request-helper.ts +16 -9
- package/src/runtime/agent-wake-queue.ts +52 -0
- package/src/runtime/agent-wake.ts +111 -18
- package/src/runtime/channel-approval-types.ts +6 -38
- package/src/runtime/channel-approvals.ts +4 -5
- package/src/runtime/http-server.ts +4 -1
- package/src/runtime/introduction-policy.test.ts +17 -1
- package/src/runtime/introduction-policy.ts +25 -7
- package/src/runtime/migrations/vbundle-builder.ts +9 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +21 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +60 -0
- package/src/runtime/routes/__tests__/oauth-proxy-routes.test.ts +61 -3
- package/src/runtime/routes/auto-profile-routes.ts +83 -0
- package/src/runtime/routes/conversation-management-routes.ts +1 -3
- package/src/runtime/routes/conversation-routes.ts +9 -0
- package/src/runtime/routes/guardian-action-routes.ts +8 -23
- package/src/runtime/routes/host-cu-routes.ts +3 -1
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-profiles-routes.ts +5 -2
- package/src/runtime/routes/inference-provider-connection-routes.ts +25 -8
- package/src/runtime/routes/migration-routes.ts +8 -2
- package/src/runtime/routes/oauth-proxy-passthrough.test.ts +32 -0
- package/src/runtime/routes/platform-routes.ts +6 -1
- package/src/runtime/routes/user-route-dispatcher.ts +1 -2
- package/src/runtime/web-presence.ts +3 -4
- package/src/schedule/schedule-store.ts +10 -0
- package/src/schedule/scheduler.ts +92 -24
- package/src/subagent/manager.ts +32 -12
- package/src/telegram/__tests__/webhook-health.test.ts +8 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +1 -0
- package/src/tools/background-tool-registry.ts +30 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +1 -2
- package/src/tools/host-terminal/host-shell.ts +7 -0
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +28 -1
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +34 -0
- package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +35 -1
- package/src/tools/network/__tests__/web-search.test.ts +96 -0
- package/src/tools/network/web-fetch.ts +30 -9
- package/src/tools/network/web-search.ts +235 -4
- package/src/tools/skills/load.ts +13 -17
- package/src/tools/skills/scaffold-managed.ts +86 -71
- package/src/tools/terminal/shell-launch.test.ts +27 -1
- package/src/tools/terminal/shell.ts +4 -0
- package/src/tools/workspace-tools/loader.ts +1 -2
- package/src/usage/attribution.ts +18 -1
- package/src/util/abort-reasons.ts +2 -0
- package/src/util/errors.ts +1 -0
- package/src/util/oauth-request-body.test.ts +5 -1
- package/src/util/provider-error-patterns.ts +11 -0
- package/src/util/single-flight.test.ts +6 -0
- package/src/util/single-flight.ts +2 -0
- package/src/util/worker-pipe.test.ts +56 -10
- package/src/util/worker-pipe.ts +9 -4
- package/src/workspace/git-service.ts +6 -1
- package/src/workspace/migrations/158-repoint-opencode-host-provider-fragments.ts +163 -0
- package/src/workspace/migrations/__tests__/158-repoint-opencode-host-provider-fragments.test.ts +188 -0
- package/src/workspace/migrations/registry.ts +2 -0
package/openapi.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
openapi: 3.1.0
|
|
4
4
|
info:
|
|
5
5
|
title: Vellum Assistant API
|
|
6
|
-
version: 0.12.
|
|
6
|
+
version: 0.12.5
|
|
7
7
|
description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
|
|
8
8
|
servers:
|
|
9
9
|
- url: http://127.0.0.1:7821
|
|
@@ -2597,6 +2597,58 @@ paths:
|
|
|
2597
2597
|
- userId
|
|
2598
2598
|
- authenticated
|
|
2599
2599
|
additionalProperties: false
|
|
2600
|
+
/v1/auto-profile/preview:
|
|
2601
|
+
post:
|
|
2602
|
+
operationId: autoprofile_preview_post
|
|
2603
|
+
summary: Preview the Auto profile's pick for a draft
|
|
2604
|
+
description:
|
|
2605
|
+
Ask the Auto profile which default profile a draft message would run on, using the conversation's recent
|
|
2606
|
+
history when one is given. The pick is kept briefly so the turn that sends the same text reuses it. Spends one
|
|
2607
|
+
Jev call per request.
|
|
2608
|
+
tags:
|
|
2609
|
+
- conversations
|
|
2610
|
+
requestBody:
|
|
2611
|
+
required: true
|
|
2612
|
+
content:
|
|
2613
|
+
application/json:
|
|
2614
|
+
schema:
|
|
2615
|
+
type: object
|
|
2616
|
+
properties:
|
|
2617
|
+
text:
|
|
2618
|
+
type: string
|
|
2619
|
+
minLength: 1
|
|
2620
|
+
maxLength: 20000
|
|
2621
|
+
conversationId:
|
|
2622
|
+
type: string
|
|
2623
|
+
description: Conversation the draft belongs to, for recent history. Omit for a new chat.
|
|
2624
|
+
required:
|
|
2625
|
+
- text
|
|
2626
|
+
responses:
|
|
2627
|
+
"200":
|
|
2628
|
+
description: Successful response
|
|
2629
|
+
content:
|
|
2630
|
+
application/json:
|
|
2631
|
+
schema:
|
|
2632
|
+
type: object
|
|
2633
|
+
properties:
|
|
2634
|
+
profile:
|
|
2635
|
+
anyOf:
|
|
2636
|
+
- type: string
|
|
2637
|
+
- type: "null"
|
|
2638
|
+
outcome:
|
|
2639
|
+
type: string
|
|
2640
|
+
enum:
|
|
2641
|
+
- routed
|
|
2642
|
+
- unavailable
|
|
2643
|
+
- timeout
|
|
2644
|
+
- error
|
|
2645
|
+
- fallback
|
|
2646
|
+
confidence:
|
|
2647
|
+
type: number
|
|
2648
|
+
required:
|
|
2649
|
+
- profile
|
|
2650
|
+
- outcome
|
|
2651
|
+
additionalProperties: false
|
|
2600
2652
|
/v1/avatar/accent:
|
|
2601
2653
|
post:
|
|
2602
2654
|
operationId: avatar_accent_post
|
|
@@ -14054,7 +14106,7 @@ paths:
|
|
|
14054
14106
|
post:
|
|
14055
14107
|
operationId: guardianactions_decision_post
|
|
14056
14108
|
summary: Submit guardian decision
|
|
14057
|
-
description: Submit a guardian
|
|
14109
|
+
description: Submit a guardian decision on a pending request.
|
|
14058
14110
|
tags:
|
|
14059
14111
|
- guardian
|
|
14060
14112
|
requestBody:
|
|
@@ -14066,9 +14118,17 @@ paths:
|
|
|
14066
14118
|
properties:
|
|
14067
14119
|
requestId:
|
|
14068
14120
|
type: string
|
|
14121
|
+
minLength: 1
|
|
14069
14122
|
description: Guardian request ID
|
|
14070
14123
|
action:
|
|
14071
14124
|
type: string
|
|
14125
|
+
enum:
|
|
14126
|
+
- approve_once
|
|
14127
|
+
- reject
|
|
14128
|
+
- trust
|
|
14129
|
+
- verify_code
|
|
14130
|
+
- leave_unverified
|
|
14131
|
+
- block
|
|
14072
14132
|
description: Decision action
|
|
14073
14133
|
conversationId:
|
|
14074
14134
|
type: string
|
|
@@ -15079,6 +15139,24 @@ paths:
|
|
|
15079
15139
|
- intent
|
|
15080
15140
|
- status
|
|
15081
15141
|
additionalProperties: false
|
|
15142
|
+
updates:
|
|
15143
|
+
type: array
|
|
15144
|
+
items:
|
|
15145
|
+
type: object
|
|
15146
|
+
properties:
|
|
15147
|
+
skillId:
|
|
15148
|
+
type: string
|
|
15149
|
+
name:
|
|
15150
|
+
type: string
|
|
15151
|
+
summary:
|
|
15152
|
+
type: string
|
|
15153
|
+
conversationId:
|
|
15154
|
+
type: string
|
|
15155
|
+
required:
|
|
15156
|
+
- skillId
|
|
15157
|
+
- name
|
|
15158
|
+
- summary
|
|
15159
|
+
additionalProperties: false
|
|
15082
15160
|
category:
|
|
15083
15161
|
type: string
|
|
15084
15162
|
enum:
|
|
@@ -15314,6 +15392,24 @@ paths:
|
|
|
15314
15392
|
- intent
|
|
15315
15393
|
- status
|
|
15316
15394
|
additionalProperties: false
|
|
15395
|
+
updates:
|
|
15396
|
+
type: array
|
|
15397
|
+
items:
|
|
15398
|
+
type: object
|
|
15399
|
+
properties:
|
|
15400
|
+
skillId:
|
|
15401
|
+
type: string
|
|
15402
|
+
name:
|
|
15403
|
+
type: string
|
|
15404
|
+
summary:
|
|
15405
|
+
type: string
|
|
15406
|
+
conversationId:
|
|
15407
|
+
type: string
|
|
15408
|
+
required:
|
|
15409
|
+
- skillId
|
|
15410
|
+
- name
|
|
15411
|
+
- summary
|
|
15412
|
+
additionalProperties: false
|
|
15317
15413
|
category:
|
|
15318
15414
|
type: string
|
|
15319
15415
|
enum:
|
|
@@ -15643,6 +15739,24 @@ paths:
|
|
|
15643
15739
|
- intent
|
|
15644
15740
|
- status
|
|
15645
15741
|
additionalProperties: false
|
|
15742
|
+
updates:
|
|
15743
|
+
type: array
|
|
15744
|
+
items:
|
|
15745
|
+
type: object
|
|
15746
|
+
properties:
|
|
15747
|
+
skillId:
|
|
15748
|
+
type: string
|
|
15749
|
+
name:
|
|
15750
|
+
type: string
|
|
15751
|
+
summary:
|
|
15752
|
+
type: string
|
|
15753
|
+
conversationId:
|
|
15754
|
+
type: string
|
|
15755
|
+
required:
|
|
15756
|
+
- skillId
|
|
15757
|
+
- name
|
|
15758
|
+
- summary
|
|
15759
|
+
additionalProperties: false
|
|
15646
15760
|
category:
|
|
15647
15761
|
type: string
|
|
15648
15762
|
enum:
|
|
@@ -21280,6 +21394,7 @@ paths:
|
|
|
21280
21394
|
- fastcrw
|
|
21281
21395
|
- searxng
|
|
21282
21396
|
- tinyfish
|
|
21397
|
+
- exa
|
|
21283
21398
|
resultCount:
|
|
21284
21399
|
type: number
|
|
21285
21400
|
durationMs:
|
|
@@ -21358,6 +21473,10 @@ paths:
|
|
|
21358
21473
|
type: string
|
|
21359
21474
|
mayRequireJavaScript:
|
|
21360
21475
|
type: boolean
|
|
21476
|
+
startIndexPastEnd:
|
|
21477
|
+
type: boolean
|
|
21478
|
+
providerWarning:
|
|
21479
|
+
type: string
|
|
21361
21480
|
required:
|
|
21362
21481
|
- url
|
|
21363
21482
|
- finalUrl
|
|
@@ -21894,6 +22013,7 @@ paths:
|
|
|
21894
22013
|
- fastcrw
|
|
21895
22014
|
- searxng
|
|
21896
22015
|
- tinyfish
|
|
22016
|
+
- exa
|
|
21897
22017
|
resultCount:
|
|
21898
22018
|
type: number
|
|
21899
22019
|
durationMs:
|
|
@@ -21972,6 +22092,10 @@ paths:
|
|
|
21972
22092
|
type: string
|
|
21973
22093
|
mayRequireJavaScript:
|
|
21974
22094
|
type: boolean
|
|
22095
|
+
startIndexPastEnd:
|
|
22096
|
+
type: boolean
|
|
22097
|
+
providerWarning:
|
|
22098
|
+
type: string
|
|
21975
22099
|
required:
|
|
21976
22100
|
- url
|
|
21977
22101
|
- finalUrl
|
|
@@ -22454,6 +22578,8 @@ paths:
|
|
|
22454
22578
|
type: boolean
|
|
22455
22579
|
noResponse:
|
|
22456
22580
|
type: boolean
|
|
22581
|
+
autoRoutedProfile:
|
|
22582
|
+
type: string
|
|
22457
22583
|
cameraFrame:
|
|
22458
22584
|
type: boolean
|
|
22459
22585
|
const: true
|
|
@@ -24794,6 +24920,24 @@ paths:
|
|
|
24794
24920
|
- intent
|
|
24795
24921
|
- status
|
|
24796
24922
|
additionalProperties: false
|
|
24923
|
+
updates:
|
|
24924
|
+
type: array
|
|
24925
|
+
items:
|
|
24926
|
+
type: object
|
|
24927
|
+
properties:
|
|
24928
|
+
skillId:
|
|
24929
|
+
type: string
|
|
24930
|
+
name:
|
|
24931
|
+
type: string
|
|
24932
|
+
summary:
|
|
24933
|
+
type: string
|
|
24934
|
+
conversationId:
|
|
24935
|
+
type: string
|
|
24936
|
+
required:
|
|
24937
|
+
- skillId
|
|
24938
|
+
- name
|
|
24939
|
+
- summary
|
|
24940
|
+
additionalProperties: false
|
|
24797
24941
|
category:
|
|
24798
24942
|
type: string
|
|
24799
24943
|
enum:
|
|
@@ -26891,7 +27035,12 @@ paths:
|
|
|
26891
27035
|
assistantId:
|
|
26892
27036
|
type: string
|
|
26893
27037
|
hasAssistantApiKey:
|
|
26894
|
-
|
|
27038
|
+
anyOf:
|
|
27039
|
+
- type: boolean
|
|
27040
|
+
- type: "null"
|
|
27041
|
+
description:
|
|
27042
|
+
Whether a managed assistant API key is stored. Null when the credential store could not be read, which is
|
|
27043
|
+
not evidence that no key is stored.
|
|
26895
27044
|
hasWebhookSecret:
|
|
26896
27045
|
type: boolean
|
|
26897
27046
|
clientInstallationId:
|
package/package.json
CHANGED
|
@@ -181,6 +181,82 @@ describe("AgentLoop", () => {
|
|
|
181
181
|
expect(calls[1].options?.config?.overrideProfile).toBe("quality-optimized");
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
test("the auto origin follows the routed override and drops once a switch replaces it", async () => {
|
|
185
|
+
const toolCallId = "tool-1";
|
|
186
|
+
const { provider, calls } = createMockProvider([
|
|
187
|
+
toolUseResponse(toolCallId, "read_file", { path: "/tmp/test.txt" }),
|
|
188
|
+
textResponse("done"),
|
|
189
|
+
]);
|
|
190
|
+
let overrideProfile = "quality-optimized";
|
|
191
|
+
const loop = new AgentLoop({
|
|
192
|
+
provider: provider,
|
|
193
|
+
systemPrompt: "system",
|
|
194
|
+
conversationId: "test-conversation",
|
|
195
|
+
tools: dummyTools,
|
|
196
|
+
toolExecutor: async () => {
|
|
197
|
+
// A confirmed profile session mid-turn: the user's pick, not Auto's.
|
|
198
|
+
overrideProfile = "cost-optimized";
|
|
199
|
+
return { content: "ok", isError: false };
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await loop.run({
|
|
204
|
+
messages: [userMessage],
|
|
205
|
+
onEvent: collectEvents([]),
|
|
206
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
207
|
+
requestId: "req-1",
|
|
208
|
+
callSite: "mainAgent",
|
|
209
|
+
overrideProfile: "quality-optimized",
|
|
210
|
+
overrideProfileOrigin: "auto",
|
|
211
|
+
resolveOverrideProfile: () => overrideProfile,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(calls).toHaveLength(2);
|
|
215
|
+
expect(calls[0].options?.config?.overrideProfile).toBe("quality-optimized");
|
|
216
|
+
expect(calls[0].options?.config?.overrideProfileOrigin).toBe("auto");
|
|
217
|
+
expect(calls[1].options?.config?.overrideProfile).toBe("cost-optimized");
|
|
218
|
+
expect(calls[1].options?.config?.overrideProfileOrigin).toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("a pre-model-call hook keeps the auto origin unless it changes the profile", async () => {
|
|
222
|
+
let hookProfile: string | null | undefined;
|
|
223
|
+
registerPlugin({
|
|
224
|
+
manifest: { name: "profile-hook", version: "0.0.1" },
|
|
225
|
+
hooks: {
|
|
226
|
+
"pre-model-call": async (ctx) =>
|
|
227
|
+
hookProfile === undefined
|
|
228
|
+
? ctx
|
|
229
|
+
: { ...ctx, modelProfile: hookProfile },
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
const run = async () => {
|
|
233
|
+
const { provider, calls } = createMockProvider([textResponse("ok")]);
|
|
234
|
+
const loop = new AgentLoop({
|
|
235
|
+
provider: provider,
|
|
236
|
+
systemPrompt: "system",
|
|
237
|
+
conversationId: "test-conversation",
|
|
238
|
+
tools: dummyTools,
|
|
239
|
+
});
|
|
240
|
+
await loop.run({
|
|
241
|
+
messages: [userMessage],
|
|
242
|
+
onEvent: collectEvents([]),
|
|
243
|
+
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
244
|
+
requestId: "req-1",
|
|
245
|
+
callSite: "mainAgent",
|
|
246
|
+
overrideProfile: "quality-optimized",
|
|
247
|
+
overrideProfileOrigin: "auto",
|
|
248
|
+
});
|
|
249
|
+
return calls[0].options?.config;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
hookProfile = undefined;
|
|
253
|
+
expect((await run())?.overrideProfileOrigin).toBe("auto");
|
|
254
|
+
hookProfile = "cost-optimized";
|
|
255
|
+
expect((await run())?.overrideProfileOrigin).toBeUndefined();
|
|
256
|
+
hookProfile = null;
|
|
257
|
+
expect((await run())?.overrideProfileOrigin).toBeUndefined();
|
|
258
|
+
});
|
|
259
|
+
|
|
184
260
|
test("re-resolves max input tokens before truncating tool results", async () => {
|
|
185
261
|
const toolCallId = "tool-1";
|
|
186
262
|
const toolOutput = "x".repeat(2_500);
|
|
@@ -207,6 +207,15 @@ describe("AnthropicProvider — semantic reason stamping", () => {
|
|
|
207
207
|
),
|
|
208
208
|
reason: "insufficient_credits",
|
|
209
209
|
},
|
|
210
|
+
{
|
|
211
|
+
name: "free-tier daily-limit body code → free_tier_daily_limit_reached (before insufficient_credits)",
|
|
212
|
+
error: new FakeAPIError(
|
|
213
|
+
402,
|
|
214
|
+
'{"code":"free_tier_daily_limit_reached","detail":"free usage"}',
|
|
215
|
+
anthropicBody("invalid_request_error"),
|
|
216
|
+
),
|
|
217
|
+
reason: "free_tier_daily_limit_reached",
|
|
218
|
+
},
|
|
210
219
|
{
|
|
211
220
|
name: "daily-limit body code → daily_limit_reached (before insufficient_credits)",
|
|
212
221
|
error: new FakeAPIError(
|
|
@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import type { WakeOptions } from "../runtime/agent-wake.js";
|
|
4
4
|
import type { BackgroundTool } from "../tools/background-tool-registry.js";
|
|
5
|
+
import type { ToolContext } from "../tools/types.js";
|
|
5
6
|
|
|
6
7
|
// ── Mock modules ────────────────────────────────────────────────────────────
|
|
7
8
|
|
|
@@ -239,4 +240,37 @@ describe("bash tool background mode", () => {
|
|
|
239
240
|
expect(mockRegisterBackgroundTool).not.toHaveBeenCalled();
|
|
240
241
|
expect(mockWakeAgentForOpportunity).not.toHaveBeenCalled();
|
|
241
242
|
});
|
|
243
|
+
|
|
244
|
+
for (const cronRunId of [undefined, null, "cron-run-123"]) {
|
|
245
|
+
for (const outcome of ["completed", "failed", "cancelled"] as const) {
|
|
246
|
+
test(`preserves originating schedule ${String(cronRunId)} on ${outcome}`, async () => {
|
|
247
|
+
const context: ToolContext = {
|
|
248
|
+
...baseContext,
|
|
249
|
+
cronRunId,
|
|
250
|
+
};
|
|
251
|
+
await shellTool.execute(
|
|
252
|
+
{
|
|
253
|
+
command:
|
|
254
|
+
outcome === "cancelled"
|
|
255
|
+
? "sleep 30"
|
|
256
|
+
: `sleep 0.1; exit ${outcome === "failed" ? "1" : "0"}`,
|
|
257
|
+
activity: "test",
|
|
258
|
+
background: true,
|
|
259
|
+
},
|
|
260
|
+
context,
|
|
261
|
+
);
|
|
262
|
+
context.cronRunId = "cron-run-later";
|
|
263
|
+
expect(registeredTools[0]!.cronRunId).toBe(cronRunId ?? undefined);
|
|
264
|
+
if (outcome === "cancelled") {
|
|
265
|
+
registeredTools[0]!.cancel();
|
|
266
|
+
}
|
|
267
|
+
await waitForWake(mockWakeAgentForOpportunity);
|
|
268
|
+
|
|
269
|
+
expect(mockWakeAgentForOpportunity).toHaveBeenCalledTimes(1);
|
|
270
|
+
const wake = mockWakeAgentForOpportunity.mock.calls[0]![0];
|
|
271
|
+
expect(wake.cronRunId).toBe(cronRunId ?? undefined);
|
|
272
|
+
expect(wake.backgroundToolCompletion?.status).toBe(outcome);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
242
276
|
});
|
|
@@ -84,7 +84,11 @@ mock.module("../daemon/host-bash-proxy.js", () => ({
|
|
|
84
84
|
// Import under test — MUST come after mock.module calls.
|
|
85
85
|
// ---------------------------------------------------------------------------
|
|
86
86
|
|
|
87
|
-
import type {
|
|
87
|
+
import type { WakeOptions } from "../runtime/agent-wake.js";
|
|
88
|
+
import type {
|
|
89
|
+
BackgroundTool,
|
|
90
|
+
CompletedBackgroundTool,
|
|
91
|
+
} from "../tools/background-tool-registry.js";
|
|
88
92
|
import { hostShellTool } from "../tools/host-terminal/host-shell.js";
|
|
89
93
|
import type { ToolContext, ToolExecutionResult } from "../tools/types.js";
|
|
90
94
|
|
|
@@ -148,6 +152,56 @@ afterEach(() => {
|
|
|
148
152
|
// ---------------------------------------------------------------------------
|
|
149
153
|
|
|
150
154
|
describe("host_bash background mode — proxy path", () => {
|
|
155
|
+
for (const cronRunId of [undefined, null, "cron-run-123"]) {
|
|
156
|
+
for (const outcome of [
|
|
157
|
+
"completed",
|
|
158
|
+
"failed",
|
|
159
|
+
"rejected",
|
|
160
|
+
"cancelled",
|
|
161
|
+
"cancelled-rejection",
|
|
162
|
+
] as const) {
|
|
163
|
+
test(`preserves originating schedule ${String(cronRunId)} on ${outcome}`, async () => {
|
|
164
|
+
mockProxyAvailable = true;
|
|
165
|
+
const result = Promise.withResolvers<ToolExecutionResult>();
|
|
166
|
+
mockProxyRequestImpl = () => result.promise;
|
|
167
|
+
const context = makeContext({ cronRunId });
|
|
168
|
+
|
|
169
|
+
await hostShellTool.execute(
|
|
170
|
+
{ command: "echo bg-proxy", background: true },
|
|
171
|
+
context,
|
|
172
|
+
);
|
|
173
|
+
context.cronRunId = "cron-run-later";
|
|
174
|
+
const ownedCommand = (
|
|
175
|
+
mockRegisterBackgroundTool.mock.calls as unknown[][]
|
|
176
|
+
)[0]![0] as BackgroundTool;
|
|
177
|
+
expect(ownedCommand.cronRunId).toBe(cronRunId ?? undefined);
|
|
178
|
+
const cancelled =
|
|
179
|
+
outcome === "cancelled" || outcome === "cancelled-rejection";
|
|
180
|
+
if (cancelled) {
|
|
181
|
+
const registered = (
|
|
182
|
+
mockRegisterBackgroundTool.mock.calls as unknown[][]
|
|
183
|
+
)[0]![0] as BackgroundTool;
|
|
184
|
+
registered.cancel();
|
|
185
|
+
}
|
|
186
|
+
if (outcome === "rejected" || outcome === "cancelled-rejection") {
|
|
187
|
+
result.reject(new Error("proxy transport error"));
|
|
188
|
+
} else {
|
|
189
|
+
result.resolve({ content: "done", isError: outcome === "failed" });
|
|
190
|
+
}
|
|
191
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
192
|
+
|
|
193
|
+
expect(mockWakeAgentForOpportunity).toHaveBeenCalledTimes(1);
|
|
194
|
+
const wake = (
|
|
195
|
+
mockWakeAgentForOpportunity.mock.calls as unknown[][]
|
|
196
|
+
)[0]![0] as WakeOptions;
|
|
197
|
+
expect(wake.cronRunId).toBe(cronRunId ?? undefined);
|
|
198
|
+
expect(wake.backgroundToolCompletion?.status).toBe(
|
|
199
|
+
cancelled ? "cancelled" : outcome === "rejected" ? "failed" : outcome,
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
151
205
|
test("returns immediately with backgrounded response", async () => {
|
|
152
206
|
const proxyResult: ToolExecutionResult = {
|
|
153
207
|
content: "proxy output",
|
|
@@ -311,6 +365,49 @@ describe("host_bash background mode — proxy path", () => {
|
|
|
311
365
|
// ---------------------------------------------------------------------------
|
|
312
366
|
|
|
313
367
|
describe("host_bash background mode — direct execution path", () => {
|
|
368
|
+
for (const cronRunId of [undefined, null, "cron-run-123"]) {
|
|
369
|
+
for (const outcome of [
|
|
370
|
+
"completed",
|
|
371
|
+
"failed",
|
|
372
|
+
"spawn-error",
|
|
373
|
+
"cancelled",
|
|
374
|
+
] as const) {
|
|
375
|
+
test(`preserves originating schedule ${String(cronRunId)} on ${outcome}`, async () => {
|
|
376
|
+
const context = makeContext({ cronRunId });
|
|
377
|
+
await hostShellTool.execute(
|
|
378
|
+
{ command: "echo bg-local", background: true },
|
|
379
|
+
context,
|
|
380
|
+
);
|
|
381
|
+
context.cronRunId = "cron-run-later";
|
|
382
|
+
const ownedCommand = (
|
|
383
|
+
mockRegisterBackgroundTool.mock.calls as unknown[][]
|
|
384
|
+
)[0]![0] as BackgroundTool;
|
|
385
|
+
expect(ownedCommand.cronRunId).toBe(cronRunId ?? undefined);
|
|
386
|
+
if (outcome === "cancelled") {
|
|
387
|
+
const registered = (
|
|
388
|
+
mockRegisterBackgroundTool.mock.calls as unknown[][]
|
|
389
|
+
)[0]![0] as BackgroundTool;
|
|
390
|
+
registered.cancel();
|
|
391
|
+
}
|
|
392
|
+
if (outcome === "spawn-error") {
|
|
393
|
+
latestChild!.emit("error", new Error("spawn ENOENT"));
|
|
394
|
+
latestChild!.emit("close", null);
|
|
395
|
+
} else {
|
|
396
|
+
latestChild!.emit("close", outcome === "failed" ? 1 : 0);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
expect(mockWakeAgentForOpportunity).toHaveBeenCalledTimes(1);
|
|
400
|
+
const wake = (
|
|
401
|
+
mockWakeAgentForOpportunity.mock.calls as unknown[][]
|
|
402
|
+
)[0]![0] as WakeOptions;
|
|
403
|
+
expect(wake.cronRunId).toBe(cronRunId ?? undefined);
|
|
404
|
+
expect(wake.backgroundToolCompletion?.status).toBe(
|
|
405
|
+
outcome === "spawn-error" ? "failed" : outcome,
|
|
406
|
+
);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
314
411
|
test("returns immediately with backgrounded response", async () => {
|
|
315
412
|
const ctx = makeContext();
|
|
316
413
|
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
cancelBackgroundTool,
|
|
7
7
|
type CompletedBackgroundTool,
|
|
8
8
|
generateBackgroundToolId,
|
|
9
|
+
hasBackgroundToolWork,
|
|
9
10
|
listBackgroundTools,
|
|
10
11
|
listCompletedBackgroundTools,
|
|
11
12
|
MAX_BACKGROUND_TOOLS,
|
|
@@ -21,6 +22,7 @@ function makeTool(overrides: Partial<BackgroundTool> = {}): BackgroundTool {
|
|
|
21
22
|
toolName: overrides.toolName ?? "bash",
|
|
22
23
|
conversationId: overrides.conversationId ?? "conv-xyz",
|
|
23
24
|
command: overrides.command ?? "echo hello",
|
|
25
|
+
cronRunId: overrides.cronRunId,
|
|
24
26
|
startedAt: overrides.startedAt ?? Date.now(),
|
|
25
27
|
cancel: overrides.cancel ?? mock(() => {}),
|
|
26
28
|
};
|
|
@@ -58,6 +60,27 @@ describe("background-tool-registry", () => {
|
|
|
58
60
|
});
|
|
59
61
|
|
|
60
62
|
describe("cancelBackgroundTool", () => {
|
|
63
|
+
test("filters both running and cancelling commands by schedule owner", () => {
|
|
64
|
+
const owned = makeTool({ id: "bg-owned", cronRunId: "run-owned" });
|
|
65
|
+
registerBackgroundTool(owned);
|
|
66
|
+
registerBackgroundTool(makeTool({ id: "bg-user" }));
|
|
67
|
+
registerBackgroundTool(
|
|
68
|
+
makeTool({ id: "bg-other", cronRunId: "run-other" }),
|
|
69
|
+
);
|
|
70
|
+
expect(
|
|
71
|
+
hasBackgroundToolWork(owned.conversationId, { cronRunId: "run-owned" }),
|
|
72
|
+
).toBe(true);
|
|
73
|
+
cancelBackgroundTool(owned.id);
|
|
74
|
+
expect(
|
|
75
|
+
hasBackgroundToolWork(owned.conversationId, { cronRunId: "run-owned" }),
|
|
76
|
+
).toBe(true);
|
|
77
|
+
removeBackgroundTool(owned.id);
|
|
78
|
+
expect(
|
|
79
|
+
hasBackgroundToolWork(owned.conversationId, { cronRunId: "run-owned" }),
|
|
80
|
+
).toBe(false);
|
|
81
|
+
expect(hasBackgroundToolWork(owned.conversationId)).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
61
84
|
test("calls cancel(), removes the entry, and returns true", () => {
|
|
62
85
|
const cancelFn = mock(() => {});
|
|
63
86
|
const tool = makeTool({ id: "bg-cancel-1", cancel: cancelFn });
|
|
@@ -68,6 +91,20 @@ describe("background-tool-registry", () => {
|
|
|
68
91
|
expect(result).toBe(true);
|
|
69
92
|
expect(cancelFn).toHaveBeenCalledTimes(1);
|
|
70
93
|
expect(listBackgroundTools()).toHaveLength(0);
|
|
94
|
+
expect(hasBackgroundToolWork(tool.conversationId)).toBe(true);
|
|
95
|
+
removeBackgroundTool(tool.id);
|
|
96
|
+
expect(hasBackgroundToolWork(tool.conversationId)).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("a synchronous terminal callback settles cancellation work", () => {
|
|
100
|
+
registerBackgroundTool(
|
|
101
|
+
makeTool({
|
|
102
|
+
id: "bg-sync-cancel",
|
|
103
|
+
cancel: () => removeBackgroundTool("bg-sync-cancel"),
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
cancelBackgroundTool("bg-sync-cancel");
|
|
107
|
+
expect(hasBackgroundToolWork("conv-xyz")).toBe(false);
|
|
71
108
|
});
|
|
72
109
|
|
|
73
110
|
test("returns false for unknown IDs", () => {
|
|
@@ -105,6 +142,8 @@ describe("background-tool-registry", () => {
|
|
|
105
142
|
|
|
106
143
|
expect(listBackgroundTools("conv-2")).toHaveLength(1);
|
|
107
144
|
expect(listBackgroundTools("conv-nonexistent")).toHaveLength(0);
|
|
145
|
+
expect(hasBackgroundToolWork("conv-1")).toBe(true);
|
|
146
|
+
expect(hasBackgroundToolWork("conv-nonexistent")).toBe(false);
|
|
108
147
|
});
|
|
109
148
|
});
|
|
110
149
|
|
|
@@ -4,8 +4,16 @@ import { credentialKey } from "../security/credential-key.js";
|
|
|
4
4
|
|
|
5
5
|
let mockSecureKeys: Record<string, string>;
|
|
6
6
|
|
|
7
|
+
// Spread the real module: mocks are shared across files in a combined run,
|
|
8
|
+
// and a wholesale replacement drops the exports peer modules import.
|
|
9
|
+
const actualSecureKeys = await import("../security/secure-keys.js");
|
|
7
10
|
mock.module("../security/secure-keys.js", () => ({
|
|
11
|
+
...actualSecureKeys,
|
|
8
12
|
getSecureKeyAsync: async (key: string) => mockSecureKeys[key] ?? null,
|
|
13
|
+
getSecureKeyResultAsync: async (key: string) => ({
|
|
14
|
+
value: mockSecureKeys[key] ?? undefined,
|
|
15
|
+
unreachable: false,
|
|
16
|
+
}),
|
|
9
17
|
setSecureKeyAsync: async (key: string, value: string) => {
|
|
10
18
|
mockSecureKeys[key] = value;
|
|
11
19
|
return true;
|
|
@@ -5,8 +5,16 @@ import { setConfig } from "./helpers/set-config.js";
|
|
|
5
5
|
|
|
6
6
|
let mockSecureKeys: Record<string, string>;
|
|
7
7
|
|
|
8
|
+
// Spread the real module: mocks are shared across files in a combined run,
|
|
9
|
+
// and a wholesale replacement drops the exports peer modules import.
|
|
10
|
+
const actualSecureKeys = await import("../security/secure-keys.js");
|
|
8
11
|
mock.module("../security/secure-keys.js", () => ({
|
|
12
|
+
...actualSecureKeys,
|
|
9
13
|
getSecureKeyAsync: async (key: string) => mockSecureKeys[key] ?? null,
|
|
14
|
+
getSecureKeyResultAsync: async (key: string) => ({
|
|
15
|
+
value: mockSecureKeys[key] ?? undefined,
|
|
16
|
+
unreachable: false,
|
|
17
|
+
}),
|
|
10
18
|
setSecureKeyAsync: async (key: string, value: string) => {
|
|
11
19
|
mockSecureKeys[key] = value;
|
|
12
20
|
return true;
|