@vellumai/assistant 0.11.10 → 0.11.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.
Files changed (199) hide show
  1. package/AGENTS.md +1 -1
  2. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  3. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/plan-credit.test.ts +51 -0
  4. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  5. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/plan-credit.ts +66 -0
  6. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  7. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/plan-credit.test.ts +51 -0
  8. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  9. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/plan-credit.ts +66 -0
  10. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  11. package/node_modules/@vellumai/service-contracts/src/__tests__/plan-credit.test.ts +51 -0
  12. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  13. package/node_modules/@vellumai/service-contracts/src/plan-credit.ts +66 -0
  14. package/openapi.yaml +152 -55
  15. package/package.json +1 -1
  16. package/src/__tests__/anthropic-provider.test.ts +60 -0
  17. package/src/__tests__/config-get-vision-flag.test.ts +36 -0
  18. package/src/__tests__/conversation-error.test.ts +38 -0
  19. package/src/__tests__/copy-composer-tc-templates.test.ts +2 -2
  20. package/src/__tests__/guardian-action-service-scope.test.ts +53 -0
  21. package/src/__tests__/headless-browser-mode.test.ts +63 -13
  22. package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
  23. package/src/__tests__/heartbeat-service.test.ts +118 -27
  24. package/src/__tests__/host-app-control-proxy.test.ts +2 -2
  25. package/src/__tests__/host-app-control-routes.test.ts +41 -0
  26. package/src/__tests__/host-bash-routes.test.ts +30 -1
  27. package/src/__tests__/host-browser-routes.test.ts +34 -0
  28. package/src/__tests__/host-cu-routes-targeted.test.ts +29 -0
  29. package/src/__tests__/host-file-routes-targeted.test.ts +29 -0
  30. package/src/__tests__/host-proxy-base.test.ts +1 -0
  31. package/src/__tests__/host-transfer-routes-targeted.test.ts +86 -0
  32. package/src/__tests__/llm-schema.test.ts +32 -0
  33. package/src/__tests__/mcp-config-secret-boundary.test.ts +2 -0
  34. package/src/__tests__/memory-config-file-parity.test.ts +18 -0
  35. package/src/__tests__/memory-retrieval-hook.test.ts +15 -0
  36. package/src/__tests__/messaging-send-tool.test.ts +159 -13
  37. package/src/__tests__/messaging-shared.test.ts +19 -0
  38. package/src/__tests__/notification-events-source-context-probe.test.ts +211 -0
  39. package/src/__tests__/openai-responses-prompt-cache.test.ts +40 -6
  40. package/src/__tests__/outlook-messaging-provider.test.ts +9 -0
  41. package/src/__tests__/provider-catalog-visibility.test.ts +2 -2
  42. package/src/__tests__/schedule-routes.test.ts +30 -1
  43. package/src/__tests__/scheduler-result-notification.test.ts +209 -0
  44. package/src/__tests__/skills-install-extract.test.ts +26 -0
  45. package/src/__tests__/skills-install-staging.test.ts +11 -2
  46. package/src/api/constants/personality-sliders.test.ts +21 -0
  47. package/src/api/constants/personality-sliders.ts +64 -0
  48. package/src/api/index.ts +8 -0
  49. package/src/archive/ustar-size.test.ts +32 -0
  50. package/src/archive/ustar-size.ts +23 -0
  51. package/src/background-wake/next-wake.test.ts +13 -0
  52. package/src/background-wake/next-wake.ts +4 -2
  53. package/src/calls/voice-session-bridge.ts +26 -0
  54. package/src/cli/__tests__/catalog-search-help.test.ts +1 -0
  55. package/src/cli/commands/__tests__/plugins-search.test.ts +81 -0
  56. package/src/cli/commands/config.help.ts +3 -1
  57. package/src/cli/commands/memory/worker.ts +1 -1
  58. package/src/cli/commands/platform/__tests__/credits-format.test.ts +94 -5
  59. package/src/cli/commands/platform/__tests__/credits.test.ts +10 -0
  60. package/src/cli/commands/platform/credits-format.ts +57 -0
  61. package/src/cli/commands/platform/index.help.ts +19 -3
  62. package/src/cli/commands/plugins.help.ts +4 -1
  63. package/src/cli/commands/plugins.ts +2 -1
  64. package/src/cli/lib/bundled-marketplace.json +1 -1
  65. package/src/cli/lib/install-from-platform.ts +8 -10
  66. package/src/config/bundled-skills/messaging/SKILL.md +2 -0
  67. package/src/config/bundled-skills/messaging/TOOLS.json +4 -4
  68. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +85 -1
  69. package/src/config/bundled-skills/messaging/tools/shared.ts +6 -0
  70. package/src/config/bundled-skills/schedule/SKILL.md +9 -1
  71. package/src/config/bundled-skills/screen-annotation/SKILL.md +87 -20
  72. package/src/config/bundled-skills/screen-annotation/TOOLS.json +21 -5
  73. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +67 -0
  74. package/src/config/feature-flag-registry.json +17 -1
  75. package/src/config/input-modalities.test.ts +71 -0
  76. package/src/config/input-modalities.ts +95 -0
  77. package/src/config/schemas/heartbeat.ts +3 -3
  78. package/src/config/schemas/llm.ts +13 -3
  79. package/src/config/schemas/memory-storage.test.ts +39 -0
  80. package/src/config/schemas/memory-storage.ts +21 -0
  81. package/src/context/token-estimator.ts +2 -2
  82. package/src/daemon/__tests__/embedding-reconcile.test.ts +77 -0
  83. package/src/daemon/__tests__/lifecycle-embedding-reconcile.test.ts +3 -0
  84. package/src/daemon/conversation-error.ts +20 -7
  85. package/src/daemon/embedding-reconcile.ts +64 -1
  86. package/src/daemon/handlers/config-embeddings.ts +31 -0
  87. package/src/daemon/host-app-control-proxy.ts +2 -0
  88. package/src/daemon/host-bash-proxy.ts +1 -0
  89. package/src/daemon/host-cu-proxy.ts +6 -6
  90. package/src/daemon/host-file-proxy.ts +6 -6
  91. package/src/daemon/host-proxy-base.ts +10 -9
  92. package/src/daemon/host-transfer-proxy.ts +21 -24
  93. package/src/daemon/mcp-reload-service.ts +6 -0
  94. package/src/daemon/providers-setup.ts +5 -26
  95. package/src/heartbeat/heartbeat-service.ts +72 -13
  96. package/src/live-voice/__tests__/live-voice-photo.test.ts +72 -0
  97. package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +81 -0
  98. package/src/live-voice/live-voice-photo.ts +68 -4
  99. package/src/live-voice/live-voice-session.ts +36 -2
  100. package/src/live-voice/protocol.ts +98 -1
  101. package/src/mcp/__tests__/reload-signal-emission.test.ts +54 -0
  102. package/src/mcp/__tests__/reload-signal.test.ts +57 -0
  103. package/src/mcp/__tests__/startup.test.ts +150 -0
  104. package/src/mcp/reload-signal.ts +50 -0
  105. package/src/mcp/startup.ts +101 -0
  106. package/src/messaging/providers/outlook/adapter.ts +2 -13
  107. package/src/messaging/providers/outlook/client.ts +13 -1
  108. package/src/messaging/providers/outlook/types.ts +3 -0
  109. package/src/notifications/__tests__/decision-engine.test.ts +79 -6
  110. package/src/notifications/__tests__/home-feed-side-effect.test.ts +27 -0
  111. package/src/notifications/__tests__/schedule-result-producer.test.ts +397 -0
  112. package/src/notifications/copy-composer.ts +33 -11
  113. package/src/notifications/decision-engine.ts +48 -11
  114. package/src/notifications/events-store.ts +68 -2
  115. package/src/notifications/home-feed-side-effect.ts +15 -3
  116. package/src/notifications/schedule-result-producer.ts +275 -0
  117. package/src/notifications/signal.ts +5 -0
  118. package/src/oauth/seed-providers.ts +3 -2
  119. package/src/persistence/conversation-crud.ts +38 -0
  120. package/src/persistence/embeddings/embedding-backend.test.ts +162 -0
  121. package/src/persistence/embeddings/embedding-backend.ts +148 -11
  122. package/src/persistence/embeddings/embedding-openai.test.ts +113 -0
  123. package/src/persistence/embeddings/embedding-openai.ts +55 -4
  124. package/src/persistence/embeddings/embedding-types.test.ts +24 -0
  125. package/src/persistence/embeddings/embedding-types.ts +25 -1
  126. package/src/persistence/job-utils.ts +6 -2
  127. package/src/plugin-api/index.ts +2 -1
  128. package/src/plugin-api/vision-support.test.ts +81 -0
  129. package/src/plugin-api/vision-support.ts +57 -10
  130. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +8 -0
  131. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +1 -0
  132. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +11 -3
  133. package/src/plugins/defaults/memory/src/__tests__/memory-worker-routes.test.ts +20 -0
  134. package/src/plugins/defaults/memory/src/memory-worker-routes.ts +3 -1
  135. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +1 -0
  136. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +1 -0
  137. package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +82 -0
  138. package/src/plugins/defaults/memory/v3/section-dense-store.ts +9 -27
  139. package/src/providers/__tests__/provider-secret-catalog.test.ts +4 -0
  140. package/src/providers/__tests__/xml-tool-call-salvage.test.ts +172 -0
  141. package/src/providers/anthropic/client.ts +9 -4
  142. package/src/providers/inline-audio-support.test.ts +34 -0
  143. package/src/providers/inline-audio-support.ts +27 -0
  144. package/src/providers/model-catalog.ts +22 -2
  145. package/src/providers/openai/__tests__/api-error-normalization.test.ts +50 -0
  146. package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +51 -0
  147. package/src/providers/openai/__tests__/chat-completions-provider-xml-salvage.test.ts +291 -0
  148. package/src/providers/openai/api-error-normalization.ts +18 -3
  149. package/src/providers/openai/chat-completions-provider.ts +113 -13
  150. package/src/providers/openai/responses-provider.ts +10 -8
  151. package/src/providers/provider-secret-catalog.ts +11 -1
  152. package/src/providers/vellum/client.ts +14 -1
  153. package/src/providers/vellum/personality-directions.test.ts +163 -0
  154. package/src/providers/vellum/personality-directions.ts +120 -0
  155. package/src/providers/xml-tool-call-salvage.ts +212 -0
  156. package/src/runtime/__tests__/background-job-runner.test.ts +42 -4
  157. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -6
  158. package/src/runtime/auth/__tests__/route-policy.test.ts +65 -0
  159. package/src/runtime/auth/same-actor.ts +29 -5
  160. package/src/runtime/background-job-runner.ts +38 -29
  161. package/src/runtime/guardian-action-service.ts +20 -1
  162. package/src/runtime/migrations/vbundle-validator.ts +3 -3
  163. package/src/runtime/pending-interactions.ts +4 -5
  164. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +24 -0
  165. package/src/runtime/routes/__tests__/platform-credits-routes.test.ts +99 -5
  166. package/src/runtime/routes/conversation-query-routes.ts +53 -11
  167. package/src/runtime/routes/document-comments-routes.ts +8 -2
  168. package/src/runtime/routes/guardian-action-routes.ts +7 -0
  169. package/src/runtime/routes/heartbeat-routes.ts +41 -53
  170. package/src/runtime/routes/host-app-control-routes.ts +10 -36
  171. package/src/runtime/routes/host-bash-routes.ts +11 -45
  172. package/src/runtime/routes/host-browser-routes.ts +24 -0
  173. package/src/runtime/routes/host-cu-routes.ts +11 -45
  174. package/src/runtime/routes/host-file-routes.ts +11 -44
  175. package/src/runtime/routes/host-proxy-result-binding.ts +57 -0
  176. package/src/runtime/routes/host-transfer-routes.ts +33 -25
  177. package/src/runtime/routes/index.ts +0 -2
  178. package/src/runtime/routes/integrations/a2a.ts +12 -3
  179. package/src/runtime/routes/integrations/vercel.ts +13 -3
  180. package/src/runtime/routes/platform-routes.ts +121 -24
  181. package/src/runtime/routes/schedule-routes.ts +15 -1
  182. package/src/schedule/__tests__/schedule-timezone.test.ts +21 -3
  183. package/src/schedule/__tests__/worker-mcp-tools.test.ts +88 -0
  184. package/src/schedule/schedule-timezone.ts +25 -0
  185. package/src/schedule/scheduler.ts +19 -0
  186. package/src/schedule/worker.ts +119 -2
  187. package/src/skills/catalog-install.ts +40 -5
  188. package/src/tools/browser/__tests__/browser-status.test.ts +3 -0
  189. package/src/tools/browser/browser-execution.ts +117 -53
  190. package/src/tools/browser/browser-status-constants.ts +6 -6
  191. package/src/tools/capability-offer.test.ts +87 -0
  192. package/src/tools/capability-offer.ts +93 -0
  193. package/src/tools/terminal/__tests__/safe-env.test.ts +17 -0
  194. package/src/tools/terminal/safe-env.ts +3 -2
  195. package/src/util/provider-error-patterns.ts +34 -0
  196. package/src/watcher/__tests__/engine.test.ts +5 -2
  197. package/src/watcher/engine.ts +7 -4
  198. package/src/runtime/routes/__tests__/sight-frame-routes.test.ts +0 -487
  199. package/src/runtime/routes/sight-frame-routes.ts +0 -136
package/openapi.yaml CHANGED
@@ -5102,7 +5102,7 @@ paths:
5102
5102
  put:
5103
5103
  operationId: config_embeddings_put
5104
5104
  summary: Set embedding config
5105
- description: Change the embedding provider and optionally model.
5105
+ description: Change the embedding provider, model, and optional custom endpoint.
5106
5106
  tags:
5107
5107
  - config
5108
5108
  requestBody:
@@ -5116,6 +5116,14 @@ paths:
5116
5116
  type: string
5117
5117
  model:
5118
5118
  type: string
5119
+ baseUrl:
5120
+ type: string
5121
+ dimensions:
5122
+ anyOf:
5123
+ - type: integer
5124
+ exclusiveMinimum: 0
5125
+ maximum: 9007199254740991
5126
+ - type: "null"
5119
5127
  required:
5120
5128
  - provider
5121
5129
  responses:
@@ -5421,6 +5429,10 @@ paths:
5421
5429
  minLength: 1
5422
5430
  allowUnlisted:
5423
5431
  type: boolean
5432
+ inputModalities:
5433
+ anyOf:
5434
+ - $ref: "#/components/schemas/InputModalities"
5435
+ - type: "null"
5424
5436
  status:
5425
5437
  anyOf:
5426
5438
  - $ref: "#/components/schemas/ProfileStatus"
@@ -8373,54 +8385,6 @@ paths:
8373
8385
  description: The assistant is currently responding
8374
8386
  "422":
8375
8387
  description: No user message exists to retry from
8376
- /v1/conversations/{id}/sight-frame:
8377
- post:
8378
- operationId: conversations_by_id_sightframe_post
8379
- summary: Persist an ambient camera frame
8380
- description:
8381
- Add an already-uploaded camera frame to a conversation as its own message, tagged so retention can age the
8382
- image out of the model's context while the transcript keeps it. No reply is generated. Returns persisted=false
8383
- when the frame was dropped, in which case the assistant owns the upload and there is nothing to clean up.
8384
- tags:
8385
- - conversations
8386
- parameters:
8387
- - name: id
8388
- in: path
8389
- required: true
8390
- schema:
8391
- type: string
8392
- requestBody:
8393
- required: true
8394
- content:
8395
- application/json:
8396
- schema:
8397
- type: object
8398
- properties:
8399
- attachmentId:
8400
- type: string
8401
- description: Id of the uploaded attachment holding the frame.
8402
- required:
8403
- - attachmentId
8404
- responses:
8405
- "200":
8406
- description: Successful response
8407
- content:
8408
- application/json:
8409
- schema:
8410
- type: object
8411
- properties:
8412
- persisted:
8413
- type: boolean
8414
- messageId:
8415
- description: The message the frame landed on, when one was written.
8416
- type: string
8417
- required:
8418
- - persisted
8419
- additionalProperties: false
8420
- "400":
8421
- description: Missing or empty attachmentId
8422
- "404":
8423
- description: Conversation not found
8424
8388
  /v1/conversations/{id}/slash:
8425
8389
  post:
8426
8390
  operationId: conversations_by_id_slash_post
@@ -13242,6 +13206,13 @@ paths:
13242
13206
  reason:
13243
13207
  description: Decline reason (present only when applied is false)
13244
13208
  type: string
13209
+ committed:
13210
+ description:
13211
+ "Whether the decision was recorded before the decline. Present only for a resolver failure: true under
13212
+ resolver_failed (the decision committed and its follow-through failed), false under
13213
+ decision_not_persisted (nothing was written; retry is safe). Absent on daemons that report both
13214
+ under resolver_failed."
13215
+ type: boolean
13245
13216
  replyText:
13246
13217
  description: Resolver reply text for the guardian (e.g. verification code)
13247
13218
  type: string
@@ -13782,6 +13753,13 @@ paths:
13782
13753
  anyOf:
13783
13754
  - type: string
13784
13755
  - type: "null"
13756
+ effectiveTimezone:
13757
+ anyOf:
13758
+ - type: string
13759
+ - type: "null"
13760
+ description:
13761
+ Timezone used for cron and active-hours evaluation after resolving heartbeat.timezone, then the user's
13762
+ configured or detected zone
13785
13763
  nextRunAt:
13786
13764
  anyOf:
13787
13765
  - type: number
@@ -13799,6 +13777,7 @@ paths:
13799
13777
  - activeHoursEnd
13800
13778
  - cronExpression
13801
13779
  - timezone
13780
+ - effectiveTimezone
13802
13781
  - nextRunAt
13803
13782
  - lastRunAt
13804
13783
  - success
@@ -13838,7 +13817,7 @@ paths:
13838
13817
  - type: string
13839
13818
  - type: "null"
13840
13819
  timezone:
13841
- description: Timezone for cron evaluation
13820
+ description: Timezone for cron and active-hours evaluation
13842
13821
  anyOf:
13843
13822
  - type: string
13844
13823
  - type: "null"
@@ -13870,6 +13849,13 @@ paths:
13870
13849
  anyOf:
13871
13850
  - type: string
13872
13851
  - type: "null"
13852
+ effectiveTimezone:
13853
+ anyOf:
13854
+ - type: string
13855
+ - type: "null"
13856
+ description:
13857
+ Timezone used for cron and active-hours evaluation after resolving heartbeat.timezone, then the user's
13858
+ configured or detected zone
13873
13859
  nextRunAt:
13874
13860
  anyOf:
13875
13861
  - type: number
@@ -13887,6 +13873,7 @@ paths:
13887
13873
  - activeHoursEnd
13888
13874
  - cronExpression
13889
13875
  - timezone
13876
+ - effectiveTimezone
13890
13877
  - nextRunAt
13891
13878
  - lastRunAt
13892
13879
  - success
@@ -20081,6 +20068,7 @@ paths:
20081
20068
  - openai
20082
20069
  - gemini
20083
20070
  - ollama
20071
+ - custom
20084
20072
  - type: "null"
20085
20073
  model:
20086
20074
  anyOf:
@@ -24705,12 +24693,13 @@ paths:
24705
24693
  /v1/platform/credits:
24706
24694
  get:
24707
24695
  operationId: platform_credits_get
24708
- summary: Get the organization's remaining credit balance and daily-limit state
24696
+ summary: Get the organization's credit balance, plan-credit usage, and daily-limit state
24709
24697
  description:
24710
24698
  "Fetches the org's settled, pending, and effective (remaining) credit balance in USD from the platform
24711
- billing summary, plus the daily-limit state: today's spend counted against the daily credit limit (which
24712
- excludes spend covered by plan-included credits, so it is not total spend), the limit itself, and the
24713
- low-balance warning state."
24699
+ billing summary, plus plan-included credit usage (remaining, total, and the used fraction shown by the in-app
24700
+ usage meter), extra credit bought or earned on top, credit expiring within 30 days, and the daily-limit state:
24701
+ today's spend counted against the daily credit limit (which excludes spend covered by plan-included credits, so
24702
+ it is not total spend), the limit itself, and the low-balance warning state."
24714
24703
  tags:
24715
24704
  - platform
24716
24705
  responses:
@@ -24761,6 +24750,56 @@ paths:
24761
24750
  low_balance_warning:
24762
24751
  type: boolean
24763
24752
  description: True when the balance is above zero but below the low-balance threshold and auto top-up is not enabled.
24753
+ plan_credit_remaining:
24754
+ anyOf:
24755
+ - type: number
24756
+ - type: "null"
24757
+ description:
24758
+ Unused credit (USD) remaining on the unexpired plan-included grants (initial credit, Pro credit bundle).
24759
+ Null when the platform did not report grant figures.
24760
+ plan_credit_total:
24761
+ anyOf:
24762
+ - type: number
24763
+ - type: "null"
24764
+ description:
24765
+ Total credit (USD) those plan-included grants were worth, net of refunds. Null when the platform did not
24766
+ report grant figures.
24767
+ plan_credit_used_fraction:
24768
+ anyOf:
24769
+ - type: number
24770
+ - type: "null"
24771
+ description:
24772
+ "Share of the plan-included credit already used, from 0 to 1: the same reading as the in-app usage meter. A
24773
+ Pro subscription whose unexpired grants total nothing reads as 1 (everything granted is used or
24774
+ expired). Null when there is no usable reading: grant figures missing, or a zero total on a base
24775
+ or unknown plan."
24776
+ plan_credits_spent:
24777
+ anyOf:
24778
+ - type: boolean
24779
+ - type: "null"
24780
+ description:
24781
+ True when the plan-included credit is used up or expired. Whether further managed usage is funded is
24782
+ extra_credit_remaining (zero means the organization is out of credit). Null when there is no
24783
+ plan-credit reading.
24784
+ extra_credit_remaining:
24785
+ anyOf:
24786
+ - type: number
24787
+ - type: "null"
24788
+ description:
24789
+ "Credit (USD) bought or earned on top of the plan-included grants: remaining minus plan_credit_remaining,
24790
+ floored at zero. Null when grant figures are missing."
24791
+ credits_expiring_soon:
24792
+ anyOf:
24793
+ - type: number
24794
+ - type: "null"
24795
+ description:
24796
+ Unexpired credit (USD) on grants that expire within the next 30 days. Null when the platform did not report
24797
+ it.
24798
+ next_credit_expiry_at:
24799
+ anyOf:
24800
+ - type: string
24801
+ - type: "null"
24802
+ description: Earliest upcoming expiry (ISO 8601) across grants that still hold credit, or null when none is scheduled.
24764
24803
  required:
24765
24804
  - remaining
24766
24805
  - settled
@@ -24774,6 +24813,13 @@ paths:
24774
24813
  - daily_limit_snoozed
24775
24814
  - low_balance_threshold
24776
24815
  - low_balance_warning
24816
+ - plan_credit_remaining
24817
+ - plan_credit_total
24818
+ - plan_credit_used_fraction
24819
+ - plan_credits_spent
24820
+ - extra_credit_remaining
24821
+ - credits_expiring_soon
24822
+ - next_credit_expiry_at
24777
24823
  additionalProperties: false
24778
24824
  /v1/platform/disconnect:
24779
24825
  post:
@@ -29002,7 +29048,8 @@ paths:
29002
29048
  summary: Run schedule now
29003
29049
  description:
29004
29050
  Trigger an immediate execution of a schedule. A plugin-sourced schedule is rejected with a 400 when its
29005
- plugin is disabled or no longer declares it.
29051
+ plugin is disabled or no longer declares it. Returns 409 while a drain quiesce lease is active so run-now cannot
29052
+ start work the shutdown snapshot would miss.
29006
29053
  tags:
29007
29054
  - schedules
29008
29055
  parameters:
@@ -29198,6 +29245,8 @@ paths:
29198
29245
  required:
29199
29246
  - schedules
29200
29247
  additionalProperties: false
29248
+ "409":
29249
+ description: A drain quiesce lease is active, so run-now is not starting new work.
29201
29250
  /v1/schedules/{id}/runs:
29202
29251
  get:
29203
29252
  operationId: schedules_by_id_runs_get
@@ -36412,6 +36461,12 @@ components:
36412
36461
  anyOf:
36413
36462
  - type: boolean
36414
36463
  - type: "null"
36464
+ inputModalities:
36465
+ anyOf:
36466
+ - anyOf:
36467
+ - $ref: "#/components/schemas/InputModalities"
36468
+ - type: "null"
36469
+ - type: "null"
36415
36470
  status:
36416
36471
  anyOf:
36417
36472
  - anyOf:
@@ -36442,6 +36497,24 @@ components:
36442
36497
  minLength: 1
36443
36498
  - type: "null"
36444
36499
  additionalProperties: {}
36500
+ InputModalities:
36501
+ type: object
36502
+ properties:
36503
+ text:
36504
+ $ref: "#/components/schemas/ModalityOverride"
36505
+ image:
36506
+ $ref: "#/components/schemas/ModalityOverride"
36507
+ audio:
36508
+ $ref: "#/components/schemas/ModalityOverride"
36509
+ video:
36510
+ $ref: "#/components/schemas/ModalityOverride"
36511
+ ModalityOverride:
36512
+ type: object
36513
+ properties:
36514
+ enabled:
36515
+ type: boolean
36516
+ supported:
36517
+ type: boolean
36445
36518
  ProfileStatus:
36446
36519
  type: string
36447
36520
  enum:
@@ -37193,6 +37266,10 @@ components:
37193
37266
  minLength: 1
37194
37267
  allowUnlisted:
37195
37268
  type: boolean
37269
+ inputModalities:
37270
+ anyOf:
37271
+ - $ref: "#/components/schemas/InputModalitiesOutput"
37272
+ - type: "null"
37196
37273
  status:
37197
37274
  anyOf:
37198
37275
  - $ref: "#/components/schemas/ProfileStatus"
@@ -37735,6 +37812,26 @@ components:
37735
37812
  - status
37736
37813
  - origin
37737
37814
  additionalProperties: false
37815
+ InputModalitiesOutput:
37816
+ type: object
37817
+ properties:
37818
+ text:
37819
+ $ref: "#/components/schemas/ModalityOverrideOutput"
37820
+ image:
37821
+ $ref: "#/components/schemas/ModalityOverrideOutput"
37822
+ audio:
37823
+ $ref: "#/components/schemas/ModalityOverrideOutput"
37824
+ video:
37825
+ $ref: "#/components/schemas/ModalityOverrideOutput"
37826
+ additionalProperties: false
37827
+ ModalityOverrideOutput:
37828
+ type: object
37829
+ properties:
37830
+ enabled:
37831
+ type: boolean
37832
+ supported:
37833
+ type: boolean
37834
+ additionalProperties: false
37738
37835
  AuthOutput:
37739
37836
  oneOf:
37740
37837
  - type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.11.10",
3
+ "version": "0.11.11-staging.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -3194,6 +3194,66 @@ describe("AnthropicProvider — Haiku Model Gating", () => {
3194
3194
  // to the request at all.
3195
3195
  expect(lastStreamParams!.output_config).toBeUndefined();
3196
3196
  });
3197
+
3198
+ test("effort is omitted for Sonnet 4.5, which rejects the parameter", async () => {
3199
+ const sonnet45Provider = new AnthropicProvider(
3200
+ "sk-ant-test",
3201
+ "claude-sonnet-4-5-20250929",
3202
+ );
3203
+ await sonnet45Provider.sendMessage([userMsg("Hi")], {
3204
+ systemPrompt: "You are helpful.",
3205
+ config: { effort: "high" },
3206
+ });
3207
+
3208
+ // Sonnet 4.5 400s on `output_config.effort` ("This model does not
3209
+ // support the effort parameter"), so a profile effort must be dropped
3210
+ // on the wire rather than forwarded.
3211
+ expect(lastStreamParams!.output_config).toBeUndefined();
3212
+ });
3213
+
3214
+ test("effort is omitted for OpenRouter's dotted Sonnet 4.5 id", async () => {
3215
+ // OpenRouter delegates `anthropic/*` models to this provider under
3216
+ // dotted ids, so the exclusion must survive that spelling.
3217
+ const openRouterProvider = new AnthropicProvider(
3218
+ "sk-or-test",
3219
+ "anthropic/claude-sonnet-4.5",
3220
+ );
3221
+ await openRouterProvider.sendMessage([userMsg("Hi")], {
3222
+ systemPrompt: "You are helpful.",
3223
+ config: { effort: "high" },
3224
+ });
3225
+
3226
+ expect(lastStreamParams!.output_config).toBeUndefined();
3227
+ });
3228
+
3229
+ test("effort is forwarded for Opus 4.5, which accepts the parameter", async () => {
3230
+ // Opus 4.5 shares Sonnet 4.5's generation (and its
3231
+ // adaptiveThinkingUnsupported flag) but accepts effort on the wire, so
3232
+ // the exclusion must stay narrow rather than family-wide.
3233
+ const opus45Provider = new AnthropicProvider(
3234
+ "sk-ant-test",
3235
+ "claude-opus-4-5-20251101",
3236
+ );
3237
+ await opus45Provider.sendMessage([userMsg("Hi")], {
3238
+ systemPrompt: "You are helpful.",
3239
+ config: { effort: "high" },
3240
+ });
3241
+
3242
+ expect(lastStreamParams!.output_config).toEqual({ effort: "high" });
3243
+ });
3244
+
3245
+ test("effort is forwarded for Sonnet 4.6", async () => {
3246
+ const sonnet46Provider = new AnthropicProvider(
3247
+ "sk-ant-test",
3248
+ "claude-sonnet-4-6",
3249
+ );
3250
+ await sonnet46Provider.sendMessage([userMsg("Hi")], {
3251
+ systemPrompt: "You are helpful.",
3252
+ config: { effort: "medium" },
3253
+ });
3254
+
3255
+ expect(lastStreamParams!.output_config).toEqual({ effort: "medium" });
3256
+ });
3197
3257
  });
3198
3258
 
3199
3259
  // ---------------------------------------------------------------------------
@@ -89,6 +89,42 @@ describe("GET /v1/config profile vision enrichment", () => {
89
89
  expect(result?.llm?.profiles?.["test-unknown"]?.supportsVision).toBe(true);
90
90
  });
91
91
 
92
+ test("an image modality override of supported:true stamps supportsVision true", () => {
93
+ seedProfiles({
94
+ gateway: {
95
+ provider: "openai-compatible",
96
+ model: "qwen2.5-vl",
97
+ inputModalities: { image: { enabled: true, supported: true } },
98
+ },
99
+ });
100
+
101
+ const result = configGetRoute.handler({}) as {
102
+ llm?: {
103
+ profiles?: Record<string, { supportsVision?: boolean }>;
104
+ };
105
+ };
106
+
107
+ expect(result?.llm?.profiles?.gateway?.supportsVision).toBe(true);
108
+ });
109
+
110
+ test("an image modality override of supported:false stamps supportsVision false", () => {
111
+ seedProfiles({
112
+ gateway: {
113
+ provider: "openai-compatible",
114
+ model: "qwen2.5-vl",
115
+ inputModalities: { image: { enabled: true, supported: false } },
116
+ },
117
+ });
118
+
119
+ const result = configGetRoute.handler({}) as {
120
+ llm?: {
121
+ profiles?: Record<string, { supportsVision?: boolean }>;
122
+ };
123
+ };
124
+
125
+ expect(result?.llm?.profiles?.gateway?.supportsVision).toBe(false);
126
+ });
127
+
92
128
  test("profile without provider/model is left without supportsVision", () => {
93
129
  seedProfiles({
94
130
  "test-empty": {},
@@ -816,6 +816,44 @@ describe("classifyConversationError", () => {
816
816
  );
817
817
  });
818
818
 
819
+ it("classifies an OpenCode 401 ModelError as model-not-found, not an invalid key", () => {
820
+ providerRoutingSources.opencode = "user-key";
821
+ const err = new ProviderError(
822
+ "OpenCode API error (401): Model muse-spark-1.3-contributor is not supported [type=ModelError]",
823
+ "opencode",
824
+ 401,
825
+ { reason: "model_not_found" },
826
+ );
827
+
828
+ const result = classifyConversationError(err, {
829
+ ...baseCtx,
830
+ profileName: "custom-profile",
831
+ connectionName: "opencode-personal",
832
+ });
833
+
834
+ expect(result.code).toBe("PROVIDER_API");
835
+ expect(result.errorCategory).toBe("provider_model_not_found");
836
+ expect(result.retryable).toBe(false);
837
+ expect(result.userMessage).toContain("wasn't found by the provider");
838
+ expect(result.userMessage).not.toContain("API key");
839
+ });
840
+
841
+ it("classifies a reason-less OpenCode 401 ModelError via the message, not credentials", () => {
842
+ providerRoutingSources.opencode = "user-key";
843
+ const err = new ProviderError(
844
+ "OpenCode API error (401): Model muse-spark-1.3-contributor is not supported [type=ModelError]",
845
+ "opencode",
846
+ 401,
847
+ );
848
+
849
+ const result = classifyConversationError(err, baseCtx);
850
+
851
+ expect(result.code).toBe("PROVIDER_API");
852
+ expect(result.errorCategory).toBe("provider_model_not_found");
853
+ expect(result.retryable).toBe(false);
854
+ expect(result.userMessage).not.toContain("API key");
855
+ });
856
+
819
857
  it("classifies managed-proxy auth failures as managed credential refresh failures", () => {
820
858
  providerRoutingSources.anthropic = "managed-proxy";
821
859
  const err = new ProviderError(
@@ -53,7 +53,7 @@ describe("guardian_decision fallback copy", () => {
53
53
  const result = composeFallbackCopy(signal, ["vellum"]);
54
54
  const copy = result.vellum!;
55
55
 
56
- expect(copy.title).toBe("Trusted Contact Decision");
56
+ expect(copy.title).toBe("Access request denied");
57
57
  expect(copy.body).toBe("Alice's access request has been denied by Bob.");
58
58
  });
59
59
 
@@ -216,7 +216,7 @@ describe("guardian_decision fallback copy", () => {
216
216
  const result = composeFallbackCopy(signal, ["vellum"]);
217
217
  const copy = result.vellum!;
218
218
 
219
- expect(copy.title).toBe("Trusted Contact Decision");
219
+ expect(copy.title).toBe("Access request denied");
220
220
  expect(copy.body).toBe(
221
221
  "Someone's access request has been denied by a guardian.",
222
222
  );
@@ -116,3 +116,56 @@ describe("processGuardianDecision conversation scoping", () => {
116
116
  );
117
117
  });
118
118
  });
119
+
120
+ describe("processGuardianDecision resolver failures", () => {
121
+ beforeEach(() => {
122
+ bridgeState.reset();
123
+ applyGuardianDecision.mockClear();
124
+ });
125
+
126
+ // The primitive reports both under `resolverFailed`; the route tells them
127
+ // apart for the client, which retires a committed decision and keeps a
128
+ // failed persist retryable.
129
+ test("a committed decision whose follow-through failed is resolver_failed", async () => {
130
+ const req = seedRequestWithProjections();
131
+ applyGuardianDecision.mockResolvedValueOnce({
132
+ applied: true as const,
133
+ requestId: req.id,
134
+ grantMinted: false,
135
+ decidedAction: "approve_once",
136
+ resolverFailed: true,
137
+ resolverFailureReason: "resolver_threw",
138
+ } as never);
139
+
140
+ const result = await decideFrom(req.id, "conv-thread");
141
+
142
+ expect(result).toMatchObject({
143
+ ok: true,
144
+ applied: false,
145
+ reason: "resolver_failed",
146
+ committed: true,
147
+ resolverFailureReason: "resolver_threw",
148
+ });
149
+ });
150
+
151
+ test("a decision whose persist never landed is decision_not_persisted", async () => {
152
+ const req = seedRequestWithProjections();
153
+ applyGuardianDecision.mockResolvedValueOnce({
154
+ applied: true as const,
155
+ requestId: req.id,
156
+ grantMinted: false,
157
+ resolverFailed: true,
158
+ resolverFailureReason: "gateway_unreachable",
159
+ } as never);
160
+
161
+ const result = await decideFrom(req.id, "conv-thread");
162
+
163
+ expect(result).toMatchObject({
164
+ ok: true,
165
+ applied: false,
166
+ reason: "decision_not_persisted",
167
+ committed: false,
168
+ resolverFailureReason: "gateway_unreachable",
169
+ });
170
+ });
171
+ });