@vellumai/assistant 0.9.0 → 0.9.1-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 (222) hide show
  1. package/ARCHITECTURE.md +18 -34
  2. package/bun.lock +7 -8
  3. package/docs/activation-funnel-telemetry.md +4 -4
  4. package/docs/architecture/security.md +29 -28
  5. package/docs/stt-provider-onboarding.md +3 -5
  6. package/docs/workflows-testing.md +13 -44
  7. package/docs/workflows.md +3 -5
  8. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
  9. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
  10. package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
  11. package/node_modules/@vellumai/gateway-client/src/index.ts +17 -6
  12. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
  13. package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
  14. package/openapi.yaml +135 -59
  15. package/package.json +2 -1
  16. package/scripts/sync-llm-catalog.ts +6 -15
  17. package/scripts/sync-web-search-catalog.ts +3 -11
  18. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +14 -26
  19. package/src/__tests__/agent-loop-compaction-strip.test.ts +240 -0
  20. package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
  21. package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
  22. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  23. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  24. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  25. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  26. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  27. package/src/__tests__/btw-routes.test.ts +6 -8
  28. package/src/__tests__/checker.test.ts +0 -3
  29. package/src/__tests__/config-loader-backfill.test.ts +103 -6
  30. package/src/__tests__/config-watcher.test.ts +0 -18
  31. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  32. package/src/__tests__/credential-broker.test.ts +449 -1
  33. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  34. package/src/__tests__/credential-prompt-route.test.ts +3 -4
  35. package/src/__tests__/credential-routes.test.ts +360 -0
  36. package/src/__tests__/credential-security-invariants.test.ts +2 -13
  37. package/src/__tests__/dynamic-page-surface.test.ts +101 -1
  38. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  39. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  40. package/src/__tests__/identity-routes.test.ts +0 -189
  41. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  42. package/src/__tests__/invite-redemption-service.test.ts +4 -4
  43. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  44. package/src/__tests__/llm-catalog-parity.test.ts +0 -22
  45. package/src/__tests__/llm-resolver.test.ts +49 -24
  46. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  47. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  48. package/src/__tests__/persona-resolver.test.ts +11 -14
  49. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  50. package/src/__tests__/registry.test.ts +2 -7
  51. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  52. package/src/__tests__/schedule-routes.test.ts +0 -30
  53. package/src/__tests__/schedule-tools.test.ts +2 -18
  54. package/src/__tests__/skill-execute-input.test.ts +46 -1
  55. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  56. package/src/__tests__/subagent-tools.test.ts +116 -0
  57. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  58. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  59. package/src/__tests__/token-manager.test.ts +519 -0
  60. package/src/__tests__/tool-executor.test.ts +0 -79
  61. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  62. package/src/__tests__/trusted-contact-verification.test.ts +6 -6
  63. package/src/__tests__/voice-invite-redemption.test.ts +2 -2
  64. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  65. package/src/__tests__/workspace-greetings.test.ts +152 -0
  66. package/src/agent/loop.ts +25 -5
  67. package/src/api/README.md +6 -6
  68. package/src/api/responses/conversation-message.ts +2 -4
  69. package/src/api/responses/home.ts +0 -4
  70. package/src/approvals/guardian-request-resolvers.ts +2 -2
  71. package/src/calls/relay-access-wait.ts +1 -1
  72. package/src/calls/voice-session-bridge.ts +2 -2
  73. package/src/cli/commands/plugins.ts +143 -2
  74. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  75. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +313 -0
  76. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +253 -2
  77. package/src/cli/lib/diff-plugin.ts +346 -0
  78. package/src/cli/lib/install-from-github.ts +105 -17
  79. package/src/cli/lib/merge-plugin-tree.ts +228 -0
  80. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  81. package/src/cli/lib/upgrade-plugin.ts +270 -10
  82. package/src/cli/program.ts +0 -2
  83. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  84. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  85. package/src/config/bundled-skills/workflows/SKILL.md +0 -1
  86. package/src/config/bundled-tool-registry.ts +2 -7
  87. package/src/config/call-site-defaults.ts +12 -2
  88. package/src/config/feature-flag-registry.json +1 -17
  89. package/src/config/inference-profile-validation.ts +26 -0
  90. package/src/config/loader.ts +4 -0
  91. package/src/config/profile-order.ts +28 -0
  92. package/src/config/schemas/elevenlabs.ts +0 -1
  93. package/src/config/schemas/platform.ts +0 -8
  94. package/src/config/seed-inference-profiles.ts +25 -20
  95. package/src/contacts/contact-store.ts +87 -96
  96. package/src/contacts/contacts-write.ts +5 -21
  97. package/src/context/compactor.ts +2 -2
  98. package/src/credential-execution/process-manager.ts +55 -14
  99. package/src/credential-execution/prompted-credential.ts +2 -3
  100. package/src/daemon/config-watcher.ts +0 -4
  101. package/src/daemon/conversation-agent-loop.ts +15 -4
  102. package/src/daemon/conversation-slash.ts +2 -23
  103. package/src/daemon/conversation-tool-setup.ts +11 -3
  104. package/src/daemon/conversation.ts +2 -0
  105. package/src/daemon/handlers/config-channels.ts +20 -16
  106. package/src/daemon/handlers/config-slack-channel.ts +2 -3
  107. package/src/daemon/lifecycle.ts +0 -7
  108. package/src/daemon/message-types/conversations.ts +3 -3
  109. package/src/daemon/message-types/sync.ts +0 -1
  110. package/src/daemon/orphan-reaper.test.ts +0 -19
  111. package/src/daemon/orphan-reaper.ts +2 -24
  112. package/src/daemon/server.ts +0 -10
  113. package/src/home/relationship-state.ts +2 -4
  114. package/src/memory/__tests__/memory-retrospective-job.test.ts +195 -401
  115. package/src/memory/bookmark-crud.ts +1 -2
  116. package/src/memory/db-init.ts +7 -17
  117. package/src/memory/embedding-backend.ts +23 -0
  118. package/src/memory/embedding-billing-breaker.ts +96 -0
  119. package/src/memory/jobs-store.ts +25 -13
  120. package/src/memory/jobs-worker.ts +52 -0
  121. package/src/memory/memory-retrospective-constants.ts +4 -4
  122. package/src/memory/memory-retrospective-job.ts +19 -227
  123. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +62 -0
  124. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +311 -0
  125. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  126. package/src/memory/migrations/index.ts +1 -0
  127. package/src/memory/migrations/run-migrations.ts +41 -0
  128. package/src/memory/migrations/validate-migration-state.ts +1 -1
  129. package/src/memory/schema/contacts.ts +0 -4
  130. package/src/messaging/providers/slack/adapter.ts +1 -1
  131. package/src/notifications/adapters/shared.ts +29 -0
  132. package/src/notifications/adapters/slack.ts +5 -32
  133. package/src/notifications/adapters/telegram.ts +2 -20
  134. package/src/notifications/broadcaster.ts +10 -1
  135. package/src/notifications/home-feed-side-effect.ts +4 -3
  136. package/src/notifications/notification-utils.ts +17 -19
  137. package/src/notifications/types.ts +7 -0
  138. package/src/oauth/AGENTS.md +5 -24
  139. package/src/plugin-api/constants.ts +1 -1
  140. package/src/plugin-api/index.ts +6 -1
  141. package/src/plugin-api/model-profiles.ts +33 -0
  142. package/src/plugin-api/types.ts +50 -2
  143. package/src/plugins/defaults/index.ts +25 -0
  144. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +54 -2
  145. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +107 -7
  146. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  147. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  148. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  149. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  150. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +1 -1
  151. package/src/prompts/persona-resolver.ts +2 -2
  152. package/src/runtime/AGENTS.md +0 -1
  153. package/src/runtime/actor-trust-resolver.ts +12 -44
  154. package/src/runtime/btw-sidechain.ts +3 -6
  155. package/src/runtime/channel-approval-types.ts +18 -45
  156. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  157. package/src/runtime/channel-verification-service.ts +4 -3
  158. package/src/runtime/invite-redemption-service.ts +3 -3
  159. package/src/runtime/routes/__tests__/plugins-routes.test.ts +218 -1
  160. package/src/runtime/routes/app-routes.ts +1 -1
  161. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  162. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  163. package/src/runtime/routes/btw-routes.ts +1 -27
  164. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  165. package/src/runtime/routes/conversation-routes.ts +2 -2
  166. package/src/runtime/routes/credential-routes.ts +40 -16
  167. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  168. package/src/runtime/routes/identity-routes.ts +1 -296
  169. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +1 -1
  170. package/src/runtime/routes/plugins-routes.ts +171 -5
  171. package/src/runtime/routes/schedule-routes.ts +0 -22
  172. package/src/runtime/routes/workflow-routes.test.ts +4 -43
  173. package/src/runtime/routes/workflow-routes.ts +0 -28
  174. package/src/runtime/routes/workspace-greetings.ts +55 -0
  175. package/src/runtime/sync/resource-sync-events.ts +1 -11
  176. package/src/schedule/inference-profile.ts +2 -14
  177. package/src/subagent/manager.ts +6 -0
  178. package/src/subagent/types.ts +6 -0
  179. package/src/tools/AGENTS.md +3 -3
  180. package/src/tools/browser/browser-execution.ts +1 -1
  181. package/src/tools/network/web-search-error.ts +1 -1
  182. package/src/tools/permission-checker.ts +1 -1
  183. package/src/tools/schedule/create.ts +3 -9
  184. package/src/tools/schedule/update.ts +2 -10
  185. package/src/tools/side-effects.ts +2 -17
  186. package/src/tools/skills/execute.ts +34 -0
  187. package/src/tools/subagent/spawn.ts +34 -9
  188. package/src/tools/tool-approval-handler.ts +1 -3
  189. package/src/tools/tool-manifest.ts +0 -2
  190. package/src/tools/ui-surface/definitions.ts +39 -1
  191. package/src/tools/workflows/run-workflow.test.ts +8 -18
  192. package/src/util/platform.ts +2 -2
  193. package/src/workflows/capabilities.ts +2 -3
  194. package/src/workflows/run-manager.test.ts +0 -25
  195. package/src/workflows/run-manager.ts +2 -24
  196. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  197. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  198. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  199. package/src/__tests__/credential-vault.test.ts +0 -1706
  200. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  201. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  202. package/src/cli/commands/__tests__/task.test.ts +0 -914
  203. package/src/cli/commands/task.ts +0 -771
  204. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  205. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  206. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  207. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  208. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  209. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  210. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  211. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  212. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  213. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  214. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  215. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  216. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  217. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  218. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  219. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  220. package/src/memory/preloaded-apps.ts +0 -116
  221. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  222. package/src/tools/credentials/vault.ts +0 -712
@@ -19,20 +19,26 @@ export * from "./gateway-ipc-contracts.js";
19
19
 
20
20
  export { ipcCall, IpcCallError, PersistentIpcClient } from "./ipc-client.js";
21
21
 
22
+ // Outbound delivery contract (daemon → gateway) — Zod schemas + derived types
23
+ export {
24
+ ApprovalActionOptionSchema,
25
+ ApprovalUIMetadataSchema,
26
+ AttachmentMetadataSchema,
27
+ ChannelDeliveryResultSchema,
28
+ ChannelReplyPayloadSchema,
29
+ PermissionRequestDetailsSchema,
30
+ } from "./outbound-contract.js";
31
+
22
32
  export type {
23
33
  ApprovalActionOption,
24
34
  ApprovalUIMetadata,
25
35
  AttachmentMetadata,
26
36
  ChannelDeliveryResult,
27
37
  ChannelReplyPayload,
28
- IpcRequest,
29
- IpcResponse,
30
- Logger,
31
38
  PermissionRequestDetails,
32
- } from "./types.js";
33
-
34
- export { noopLogger } from "./types.js";
39
+ } from "./outbound-contract.js";
35
40
 
41
+ // Inbound contract (gateway → daemon) — Zod schemas + derived types
36
42
  export {
37
43
  CommandIntentSchema,
38
44
  RuntimeInboundPayloadSchema,
@@ -44,3 +50,8 @@ export type {
44
50
  RuntimeInboundPayload,
45
51
  SourceMetadata,
46
52
  } from "./inbound-contract.js";
53
+
54
+ // IPC, logger, and utility types
55
+ export type { IpcRequest, IpcResponse, Logger } from "./types.js";
56
+
57
+ export { noopLogger } from "./types.js";
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Daemon → gateway outbound delivery contract.
3
+ *
4
+ * Zod schemas defining the wire format for channel replies delivered from
5
+ * the daemon to the gateway via `POST /deliver/{channel}`. Both services
6
+ * import from here so the contract is enforced at compile time.
7
+ *
8
+ * The daemon constructs these payloads in `deliverChannelReply()` and
9
+ * `deliverApprovalPrompt()`; the gateway validates and dispatches them
10
+ * to the target channel provider.
11
+ */
12
+
13
+ import { z } from "zod";
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Attachment metadata
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export const AttachmentMetadataSchema = z.object({
20
+ id: z.string(),
21
+ filename: z.string(),
22
+ mimeType: z.string(),
23
+ sizeBytes: z.number(),
24
+ kind: z.string(),
25
+ data: z.string().optional(),
26
+ thumbnailData: z.string().optional(),
27
+ fileBacked: z.boolean().optional(),
28
+ });
29
+
30
+ export type AttachmentMetadata = z.infer<typeof AttachmentMetadataSchema>;
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Approval UI types
34
+ // ---------------------------------------------------------------------------
35
+
36
+ export const ApprovalActionOptionSchema = z.object({
37
+ id: z.string(),
38
+ label: z.string(),
39
+ });
40
+
41
+ export type ApprovalActionOption = z.infer<typeof ApprovalActionOptionSchema>;
42
+
43
+ export const PermissionRequestDetailsSchema = z.object({
44
+ toolName: z.string(),
45
+ riskLevel: z.string(),
46
+ toolInput: z.record(z.string(), z.unknown()),
47
+ requesterIdentifier: z.string().optional(),
48
+ });
49
+
50
+ export type PermissionRequestDetails = z.infer<
51
+ typeof PermissionRequestDetailsSchema
52
+ >;
53
+
54
+ export const ApprovalUIMetadataSchema = z.object({
55
+ requestId: z.string(),
56
+ actions: z.array(ApprovalActionOptionSchema),
57
+ plainTextFallback: z.string(),
58
+ permissionDetails: PermissionRequestDetailsSchema.optional(),
59
+ });
60
+
61
+ export type ApprovalUIMetadata = z.infer<typeof ApprovalUIMetadataSchema>;
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // Channel reply payload — the full outbound wire format
65
+ // ---------------------------------------------------------------------------
66
+
67
+ export const ChannelReplyPayloadSchema = z.object({
68
+ chatId: z.string(),
69
+ text: z.string().optional(),
70
+ /** Pre-formatted Block Kit blocks for Slack delivery. */
71
+ blocks: z.array(z.unknown()).optional(),
72
+ assistantId: z.string().optional(),
73
+ attachments: z.array(AttachmentMetadataSchema).optional(),
74
+ approval: ApprovalUIMetadataSchema.optional(),
75
+ chatAction: z.literal("typing").optional(),
76
+ /**
77
+ * When true, deliver via `chat.postEphemeral` so only the target `user`
78
+ * sees the message.
79
+ */
80
+ ephemeral: z.boolean().optional(),
81
+ /** Slack user ID — required when `ephemeral` is true. */
82
+ user: z.string().optional(),
83
+ /** When provided, update an existing message instead of posting a new one. */
84
+ messageTs: z.string().optional(),
85
+ /** When true, auto-generate Block Kit blocks from text via textToBlocks(). */
86
+ useBlocks: z.boolean().optional(),
87
+ /** When provided, add or remove an emoji reaction on a message. */
88
+ reaction: z
89
+ .object({
90
+ action: z.enum(["add", "remove"]),
91
+ name: z.string(),
92
+ messageTs: z.string(),
93
+ })
94
+ .optional(),
95
+ /** When provided, set or clear the Slack Assistants API thread status. */
96
+ assistantThreadStatus: z
97
+ .object({
98
+ channel: z.string(),
99
+ threadTs: z.string(),
100
+ status: z.string(),
101
+ /** Serialized to Slack as `loading_messages`. */
102
+ loadingMessages: z.array(z.string()).optional(),
103
+ })
104
+ .optional(),
105
+ });
106
+
107
+ export type ChannelReplyPayload = z.infer<typeof ChannelReplyPayloadSchema>;
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Channel delivery result — gateway response
111
+ // ---------------------------------------------------------------------------
112
+
113
+ export const ChannelDeliveryResultSchema = z.object({
114
+ ok: z.boolean(),
115
+ /** The message timestamp returned by the delivery endpoint. */
116
+ ts: z.string().optional(),
117
+ });
118
+
119
+ export type ChannelDeliveryResult = z.infer<typeof ChannelDeliveryResultSchema>;
@@ -4,92 +4,23 @@
4
4
  * Type definitions for assistant-to-gateway communication. These are
5
5
  * intentionally decoupled from the assistant's internal types so the
6
6
  * package can be consumed without importing assistant internals.
7
+ *
8
+ * HTTP delivery types (ChannelReplyPayload, ApprovalUIMetadata, etc.)
9
+ * are defined as Zod schemas in `outbound-contract.ts` and re-exported
10
+ * from the barrel `index.ts`. This file retains only IPC and utility
11
+ * types that don't cross an HTTP wire boundary.
7
12
  */
8
13
 
9
- // ---------------------------------------------------------------------------
10
- // HTTP delivery types
11
- // ---------------------------------------------------------------------------
12
-
13
- /** Metadata for a file attachment delivered alongside a channel reply. */
14
- export interface AttachmentMetadata {
15
- id: string;
16
- filename: string;
17
- mimeType: string;
18
- sizeBytes: number;
19
- kind: string;
20
- data?: string;
21
- thumbnailData?: string;
22
- fileBacked?: boolean;
23
- }
24
-
25
- /** An action option presented to the user in an approval prompt. */
26
- export interface ApprovalActionOption {
27
- id: string;
28
- label: string;
29
- }
30
-
31
- /**
32
- * Tool-permission-specific details carried alongside the approval payload.
33
- * Channels that support rich UI (e.g. Slack Block Kit) use these fields
34
- * to render a detailed permission request card.
35
- */
36
- export interface PermissionRequestDetails {
37
- toolName: string;
38
- riskLevel: string;
39
- toolInput: Record<string, unknown>;
40
- requesterIdentifier?: string;
41
- }
42
-
43
- /**
44
- * Metadata attached to gateway callback payloads for rendering approval
45
- * UI and routing decisions back to the correct pending interaction.
46
- */
47
- export interface ApprovalUIMetadata {
48
- requestId: string;
49
- actions: ApprovalActionOption[];
50
- plainTextFallback: string;
51
- permissionDetails?: PermissionRequestDetails;
52
- }
53
-
54
- /** Payload for a channel reply delivered via the gateway. */
55
- export interface ChannelReplyPayload {
56
- chatId: string;
57
- text?: string;
58
- /** Pre-formatted Block Kit blocks for Slack delivery. */
59
- blocks?: unknown[];
60
- assistantId?: string;
61
- attachments?: AttachmentMetadata[];
62
- approval?: ApprovalUIMetadata;
63
- chatAction?: "typing";
64
- /**
65
- * When true, deliver via `chat.postEphemeral` so only the target `user`
66
- * sees the message.
67
- */
68
- ephemeral?: boolean;
69
- /** Slack user ID — required when `ephemeral` is true. */
70
- user?: string;
71
- /** When provided, update an existing message instead of posting a new one. */
72
- messageTs?: string;
73
- /** When true, auto-generate Block Kit blocks from text via textToBlocks(). */
74
- useBlocks?: boolean;
75
- /** When provided, add or remove an emoji reaction on a message. */
76
- reaction?: { action: "add" | "remove"; name: string; messageTs: string };
77
- /** When provided, set or clear the Slack Assistants API thread status. */
78
- assistantThreadStatus?: {
79
- channel: string;
80
- threadTs: string;
81
- status: string;
82
- /** Serialized to Slack as `loading_messages`. */
83
- loadingMessages?: string[];
84
- };
85
- }
86
-
87
- /** Result from a channel delivery attempt. */
88
- export interface ChannelDeliveryResult {
89
- ok: boolean;
90
- /** The message timestamp returned by the delivery endpoint. */
91
- ts?: string;
92
- }
14
+ // Re-export outbound delivery types for backward compatibility — consumers
15
+ // that import from "./types.js" continue to work.
16
+ export type {
17
+ ApprovalActionOption,
18
+ ApprovalUIMetadata,
19
+ AttachmentMetadata,
20
+ ChannelDeliveryResult,
21
+ ChannelReplyPayload,
22
+ PermissionRequestDetails,
23
+ } from "./outbound-contract.js";
93
24
 
94
25
  // ---------------------------------------------------------------------------
95
26
  // IPC types
package/openapi.yaml CHANGED
@@ -13030,60 +13030,6 @@ paths:
13030
13030
  - home
13031
13031
  - version
13032
13032
  additionalProperties: false
13033
- /v1/identity/intro:
13034
- get:
13035
- operationId: identity_intro_get
13036
- summary: Get identity greetings
13037
- description:
13038
- Returns greetings sourced from SOUL.md, the generated cache, or generic fallbacks while background
13039
- generation refreshes the cache.
13040
- tags:
13041
- - identity
13042
- parameters:
13043
- - name: localHour
13044
- in: query
13045
- required: false
13046
- schema:
13047
- type: integer
13048
- minimum: 0
13049
- maximum: 23
13050
- description: Optional client-local hour of day used only when refreshing generated greetings.
13051
- - name: localMinute
13052
- in: query
13053
- required: false
13054
- schema:
13055
- type: integer
13056
- minimum: 0
13057
- maximum: 59
13058
- description: Optional client-local minute used only when refreshing generated greetings.
13059
- responses:
13060
- "200":
13061
- description: Successful response
13062
- content:
13063
- application/json:
13064
- schema:
13065
- type: object
13066
- properties:
13067
- greetings:
13068
- type: array
13069
- items:
13070
- type: string
13071
- text:
13072
- type: string
13073
- source:
13074
- type: string
13075
- enum:
13076
- - workspace
13077
- - cache
13078
- - fallback
13079
- refreshing:
13080
- type: boolean
13081
- required:
13082
- - greetings
13083
- - text
13084
- - source
13085
- - refreshing
13086
- additionalProperties: false
13087
13033
  /v1/image-generation/generate:
13088
13034
  post:
13089
13035
  operationId: imagegeneration_generate_post
@@ -19245,6 +19191,109 @@ paths:
19245
19191
  description: The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters).
19246
19192
  "404":
19247
19193
  description: No installed copy and no catalog entry claims the given name.
19194
+ /v1/plugins/{name}/diff:
19195
+ post:
19196
+ operationId: plugins_by_name_diff_post
19197
+ summary: Diff a plugin against its install commit
19198
+ description:
19199
+ "Show a unified diff of local edits to an installed plugin against the exact commit it was installed at
19200
+ (recorded in its `install-meta.json`). Computing the diff re-materializes the baseline through the install
19201
+ pipeline — a network clone plus a temp-dir write — so this is a POST: it is not a safe, cacheable GET even
19202
+ though it leaves persistent state untouched (requires only `settings.read`). Drift is classified against the
19203
+ install-time fingerprint so an adapter overlay that moved since install never reads as a local change. Returns
19204
+ the baseline `commit`, a `clean` flag, and a `files` array of `{ path, status, diff, binary, reconstructed }`
19205
+ for each modified/added/removed file. The baseline is the install commit, not the marketplace pin — comparing
19206
+ against the current pin is `POST /v1/plugins/:name/upgrade` with `dryRun`. A name with no installed copy returns
19207
+ 404; an install that recorded no commit or fingerprint returns 409; an unreachable source returns 503. Mirrors
19208
+ the CLI's `assistant plugins diff <name>`."
19209
+ tags:
19210
+ - plugins
19211
+ parameters:
19212
+ - name: name
19213
+ in: path
19214
+ required: true
19215
+ schema:
19216
+ type: string
19217
+ responses:
19218
+ "200":
19219
+ description: Successful response
19220
+ content:
19221
+ application/json:
19222
+ schema:
19223
+ type: object
19224
+ properties:
19225
+ name:
19226
+ type: string
19227
+ description: Install name. Matches `assistant plugins install <name>`.
19228
+ target:
19229
+ type: string
19230
+ description: Absolute path to the installed plugin directory on the host.
19231
+ commit:
19232
+ type: string
19233
+ description: Commit the baseline was re-materialized from (the recorded install SHA).
19234
+ committedAt:
19235
+ anyOf:
19236
+ - type: string
19237
+ - type: "null"
19238
+ description: ISO-8601 committer timestamp (UTC) of `commit`; null when not recorded.
19239
+ clean:
19240
+ type: boolean
19241
+ description: True when the on-disk tree exactly matches the re-materialized baseline.
19242
+ files:
19243
+ type: array
19244
+ items:
19245
+ type: object
19246
+ properties:
19247
+ path:
19248
+ type: string
19249
+ description: POSIX-relative path within the plugin root.
19250
+ status:
19251
+ type: string
19252
+ enum:
19253
+ - modified
19254
+ - added
19255
+ - removed
19256
+ description: Whether the file was edited, newly added, or deleted since install.
19257
+ diff:
19258
+ type: string
19259
+ description:
19260
+ Unified diff (`--- a/… / +++ b/…`) of the file. A short `Binary files differ` marker for binary files, or a
19261
+ `Baseline unavailable` marker when `reconstructed` is false.
19262
+ binary:
19263
+ type: boolean
19264
+ description: True when either side was detected as binary (NUL byte present).
19265
+ reconstructed:
19266
+ type: boolean
19267
+ description:
19268
+ True when the install-time baseline for this file was faithfully recovered (re-materialized bytes
19269
+ hash-match the install fingerprint). False when it could not be reconstructed (e.g. the
19270
+ curated adapter overlay changed since install), in which case `diff` is a marker, not a
19271
+ patch. Always true for added files.
19272
+ required:
19273
+ - path
19274
+ - status
19275
+ - diff
19276
+ - binary
19277
+ - reconstructed
19278
+ additionalProperties: false
19279
+ description: Unified diff of a single drifted file.
19280
+ description: One entry per drifted file, sorted by path. Empty when `clean`.
19281
+ required:
19282
+ - name
19283
+ - target
19284
+ - commit
19285
+ - committedAt
19286
+ - clean
19287
+ - files
19288
+ additionalProperties: false
19289
+ "400":
19290
+ description: The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters).
19291
+ "404":
19292
+ description: No copy of the plugin is installed, or its recorded commit resolves to nothing.
19293
+ "409":
19294
+ description: The install recorded no commit or no fingerprint to re-materialize and verify a baseline from.
19295
+ "503":
19296
+ description: The plugin source (GitHub) was temporarily unavailable; the diff is retryable.
19248
19297
  /v1/plugins/{name}/inspect:
19249
19298
  get:
19250
19299
  operationId: plugins_by_name_inspect_get
@@ -19481,9 +19530,12 @@ paths:
19481
19530
  mirroring `plugins install`''s curation boundary. A no-op (`outcome: "already-up-to-date"`) when the installed
19482
19531
  commit already equals the pin; pass `dryRun` to preview the move (`outcome: "would-upgrade"`) without touching
19483
19532
  the install. Installs lacking provenance are re-pinned to the current SHA. The assistant must be restarted to
19484
- load the upgraded code. This does not gate on local edits callers should consult `GET
19485
- /v1/plugins/:name/inspect` (`local.localChanges`) first and confirm before overwriting. Mirrors the CLI''s
19486
- `assistant plugins upgrade <name>`.'
19533
+ load the upgraded code. `strategy` controls how local edits are reconciled: `overwrite` (default) discards them
19534
+ and re-installs the pin wholesale; `ours`/`theirs` perform a three-way merge against the re-materialized install
19535
+ commit, carrying non-conflicting edits from both sides forward and resolving conflicting hunks toward the local
19536
+ edit or the pin respectively; `assistant` is not yet supported (400). A merge strategy whose install-time
19537
+ baseline cannot be reconstructed returns 409. Mirrors the CLI''s `assistant plugins upgrade <name> [--strategy
19538
+ <s>]`.'
19487
19539
  tags:
19488
19540
  - plugins
19489
19541
  parameters:
@@ -19502,6 +19554,17 @@ paths:
19502
19554
  dryRun:
19503
19555
  description: Report what would change without modifying the install. Defaults to false.
19504
19556
  type: boolean
19557
+ strategy:
19558
+ description:
19559
+ How to reconcile local edits with the pin. `overwrite` (default) discards local edits and re-installs the
19560
+ pin; `ours`/`theirs` three-way merge, resolving conflicting hunks toward the local edit or the pin
19561
+ respectively; `assistant` is not yet supported.
19562
+ type: string
19563
+ enum:
19564
+ - ours
19565
+ - theirs
19566
+ - overwrite
19567
+ - assistant
19505
19568
  responses:
19506
19569
  "200":
19507
19570
  description: Successful response
@@ -19553,6 +19616,14 @@ paths:
19553
19616
  dryRun:
19554
19617
  type: boolean
19555
19618
  description: Whether this was a dry run (no changes made).
19619
+ strategy:
19620
+ type: string
19621
+ enum:
19622
+ - ours
19623
+ - theirs
19624
+ - overwrite
19625
+ - assistant
19626
+ description: Conflict-resolution strategy the upgrade applied.
19556
19627
  provenanceWasUnknown:
19557
19628
  type: boolean
19558
19629
  description:
@@ -19568,14 +19639,19 @@ paths:
19568
19639
  - target
19569
19640
  - fileCount
19570
19641
  - dryRun
19642
+ - strategy
19571
19643
  - provenanceWasUnknown
19572
19644
  additionalProperties: false
19573
19645
  "400":
19574
- description: The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters).
19646
+ description:
19647
+ The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters), or the
19648
+ `assistant` strategy was requested (not yet supported).
19575
19649
  "404":
19576
19650
  description: No copy of the plugin is installed, or its source resolves to nothing.
19577
19651
  "409":
19578
- description: The install exists but has no marketplace entry to advance to.
19652
+ description:
19653
+ The install exists but has no marketplace entry to advance to, or a merge strategy was requested whose
19654
+ install-time baseline cannot be reconstructed.
19579
19655
  "503":
19580
19656
  description: The plugin source (GitHub) was temporarily unavailable; the upgrade is retryable.
19581
19657
  /v1/plugins/install:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-staging.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -53,6 +53,7 @@
53
53
  "@vellumai/twilio-client": "file:../packages/twilio-client",
54
54
  "commander": "13.1.0",
55
55
  "croner": "10.0.1",
56
+ "diff": "8.0.4",
56
57
  "dotenv": "17.3.1",
57
58
  "drizzle-orm": "0.45.2",
58
59
  "jszip": "3.10.1",
@@ -3,19 +3,13 @@
3
3
  * Generate `llm-provider-catalog.json` from the canonical
4
4
  * `PROVIDER_CATALOG` in `assistant/src/providers/model-catalog.ts`.
5
5
  *
6
- * The JSON file is the client-facing catalog bundled into native clients
7
- * (macOS, web). Keeping it generated rather than hand-mirrored — eliminates
8
- * the recurring "I edited model-catalog.ts and forgot the JSON" failure mode
9
- * that the parity test only catches after push.
6
+ * The JSON file is the client-facing catalog. Keeping it generated — rather
7
+ * than hand-mirrored eliminates the recurring "I edited model-catalog.ts and
8
+ * forgot the JSON" failure mode that the parity test only catches after push.
10
9
  *
11
- * Two byte-identical copies are written:
10
+ * Output:
12
11
  * - `meta/llm-provider-catalog.json` — primary checked-in artifact, read
13
- * by web codegen (§D) and any non-Swift consumer.
14
- * - `clients/shared/Resources/llm-provider-catalog.json` — SwiftPM resource
15
- * bundled into `VellumAssistantShared`. SwiftPM cannot reach files
16
- * outside a target's source directory, so this mirror is necessary;
17
- * both files are produced by the same generator and asserted equal by
18
- * the parity test, making drift impossible.
12
+ * by web codegen (§D) and any downstream consumer.
19
13
  *
20
14
  * The projection drops daemon-only fields (today: `apiKeyUrl`, which clients
21
15
  * read from `credentialsGuide.url` instead) and pins field order so the
@@ -37,10 +31,7 @@ import {
37
31
  } from "../src/providers/model-catalog.js";
38
32
 
39
33
  const ROOT = resolve(import.meta.dir, "../..");
40
- const OUTPUT_PATHS = [
41
- join(ROOT, "meta/llm-provider-catalog.json"),
42
- join(ROOT, "clients/shared/Resources/llm-provider-catalog.json"),
43
- ] as const;
34
+ const OUTPUT_PATHS = [join(ROOT, "meta/llm-provider-catalog.json")] as const;
44
35
 
45
36
  /**
46
37
  * Bumped when the *shape* of the client catalog JSON changes in a way native
@@ -4,7 +4,7 @@
4
4
  * canonical `SEARCH_PROVIDER_CATALOG` in
5
5
  * `assistant/src/providers/search-provider-catalog.ts`.
6
6
  *
7
- * Two byte-identical copies are written:
7
+ * Output:
8
8
  * - `meta/web-search-provider-catalog.json` — primary checked-in artifact,
9
9
  * consumed by:
10
10
  * - `cli/src/__tests__/search-provider-env-var-parity.test.ts`
@@ -12,13 +12,8 @@
12
12
  * - Downstream `vellum-assistant-platform/web/src/lib/generated/
13
13
  * web-search-provider-catalog.json` (manually sync'd today; the
14
14
  * scheduled sync workflow is a planned follow-up).
15
- * - `clients/shared/Resources/web-search-provider-catalog.json` — SwiftPM
16
- * resource bundled into `VellumAssistantShared`. SwiftPM cannot reach
17
- * files outside a target's source directory, so this mirror is
18
- * necessary; both files are produced by the same generator and
19
- * asserted equal by the parity test, making drift impossible.
20
15
  *
21
- * Companion to `sync-llm-catalog.ts`; same dual-write pattern.
16
+ * Companion to `sync-llm-catalog.ts`.
22
17
  *
23
18
  * Usage:
24
19
  * cd assistant && bun run scripts/sync-web-search-catalog.ts
@@ -37,7 +32,6 @@ import {
37
32
  const ROOT = resolve(import.meta.dir, "../..");
38
33
  const OUTPUT_PATHS = [
39
34
  join(ROOT, "meta/web-search-provider-catalog.json"),
40
- join(ROOT, "clients/shared/Resources/web-search-provider-catalog.json"),
41
35
  ] as const;
42
36
 
43
37
  /**
@@ -108,9 +102,7 @@ async function main(): Promise<void> {
108
102
  continue;
109
103
  }
110
104
  if (existing !== next) {
111
- console.error(
112
- `${rel} is stale. Run: bun run sync:web-search-catalog`,
113
- );
105
+ console.error(`${rel} is stale. Run: bun run sync:web-search-catalog`);
114
106
  anyStale = true;
115
107
  continue;
116
108
  }