@decocms/bindings 1.0.1-alpha.11 → 1.0.1-alpha.13
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/package.json +3 -2
- package/src/index.ts +7 -0
- package/src/well-known/language-model.ts +217 -5
- package/src/well-known/mcp.ts +1 -1
- package/src/well-known/registry.ts +128 -0
- package/src/well-known/workflow.ts +297 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/bindings",
|
|
3
|
-
"version": "1.0.1-alpha.
|
|
3
|
+
"version": "1.0.1-alpha.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "vitest run",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"./connection": "./src/core/connection.ts",
|
|
20
20
|
"./client": "./src/core/client/index.ts",
|
|
21
21
|
"./mcp": "./src/well-known/mcp.ts",
|
|
22
|
-
"./agent": "./src/well-known/agent.ts"
|
|
22
|
+
"./agent": "./src/well-known/agent.ts",
|
|
23
|
+
"./workflow": "./src/well-known/workflow.ts"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"vitest": "3.2.4"
|
package/src/index.ts
CHANGED
|
@@ -13,3 +13,10 @@ export {
|
|
|
13
13
|
type ToolBinder,
|
|
14
14
|
type ToolWithSchemas,
|
|
15
15
|
} from "./core/binder";
|
|
16
|
+
|
|
17
|
+
// Re-export registry binding types
|
|
18
|
+
export {
|
|
19
|
+
MCPRegistryServerSchema,
|
|
20
|
+
type RegistryAppCollectionEntity,
|
|
21
|
+
REGISTRY_APP_BINDING,
|
|
22
|
+
} from "./well-known/registry";
|
|
@@ -17,17 +17,229 @@ import {
|
|
|
17
17
|
createCollectionBindings,
|
|
18
18
|
} from "./collections";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* JSON Value Schema
|
|
22
|
+
* Represents any valid JSON value: null, string, number, boolean, object, or array
|
|
23
|
+
*/
|
|
24
|
+
const JSONValueSchema: z.ZodType<unknown> = z.lazy(() =>
|
|
25
|
+
z.union([
|
|
26
|
+
z.null(),
|
|
27
|
+
z.string(),
|
|
28
|
+
z.number(),
|
|
29
|
+
z.boolean(),
|
|
30
|
+
z.record(z.string(), JSONValueSchema),
|
|
31
|
+
z.array(JSONValueSchema),
|
|
32
|
+
]),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Provider Options Schema
|
|
37
|
+
* Additional provider-specific options passed through to the provider
|
|
38
|
+
*/
|
|
39
|
+
const ProviderOptionsSchema = z
|
|
40
|
+
.record(z.string(), z.record(z.string(), JSONValueSchema))
|
|
41
|
+
.optional()
|
|
42
|
+
.describe(
|
|
43
|
+
"Additional provider-specific options. Outer record keyed by provider name, inner by option key",
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Text Part Schema
|
|
48
|
+
* Text content part of a prompt
|
|
49
|
+
*/
|
|
50
|
+
const TextPartSchema = z.object({
|
|
51
|
+
type: z.literal("text"),
|
|
52
|
+
text: z.string().describe("The text content"),
|
|
53
|
+
providerOptions: ProviderOptionsSchema,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Data Content Schema
|
|
58
|
+
* File data can be Uint8Array (as base64 string), base64 encoded string, or URL string
|
|
59
|
+
*/
|
|
60
|
+
const DataContentSchema = z
|
|
61
|
+
.union([z.string(), z.instanceof(Uint8Array)])
|
|
62
|
+
.describe("File data as base64 encoded string, URL string, or Uint8Array");
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* File Part Schema
|
|
66
|
+
* File content part of a prompt
|
|
67
|
+
*/
|
|
68
|
+
const FilePartSchema = z.object({
|
|
69
|
+
type: z.literal("file"),
|
|
70
|
+
filename: z.string().optional().describe("Optional filename of the file"),
|
|
71
|
+
data: DataContentSchema,
|
|
72
|
+
mediaType: z
|
|
73
|
+
.string()
|
|
74
|
+
.describe("IANA media type of the file (e.g., image/png, audio/mp3)"),
|
|
75
|
+
providerOptions: ProviderOptionsSchema,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Reasoning Part Schema
|
|
80
|
+
* Reasoning content part of a prompt
|
|
81
|
+
*/
|
|
82
|
+
const ReasoningPartSchema = z.object({
|
|
83
|
+
type: z.literal("reasoning"),
|
|
84
|
+
text: z.string().describe("The reasoning text"),
|
|
85
|
+
providerOptions: ProviderOptionsSchema,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Tool Call Part Schema
|
|
90
|
+
* Tool call content part of a prompt (usually generated by the AI model)
|
|
91
|
+
*/
|
|
92
|
+
const ToolCallPartSchema = z.object({
|
|
93
|
+
type: z.literal("tool-call"),
|
|
94
|
+
toolCallId: z
|
|
95
|
+
.string()
|
|
96
|
+
.describe("ID of the tool call, used to match with tool result"),
|
|
97
|
+
toolName: z.string().describe("Name of the tool being called"),
|
|
98
|
+
input: z
|
|
99
|
+
.unknown()
|
|
100
|
+
.describe(
|
|
101
|
+
"Arguments of the tool call (JSON-serializable object matching tool input schema)",
|
|
102
|
+
),
|
|
103
|
+
providerExecuted: z
|
|
104
|
+
.boolean()
|
|
105
|
+
.optional()
|
|
106
|
+
.describe("Whether the tool call will be executed by the provider"),
|
|
107
|
+
providerOptions: ProviderOptionsSchema,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Tool Result Output Schema
|
|
112
|
+
* The output of a tool result
|
|
113
|
+
*/
|
|
114
|
+
const ToolResultOutputSchema = z.union([
|
|
115
|
+
z.object({
|
|
116
|
+
type: z.literal("text"),
|
|
117
|
+
value: z.string(),
|
|
118
|
+
}),
|
|
119
|
+
z.object({
|
|
120
|
+
type: z.literal("json"),
|
|
121
|
+
value: JSONValueSchema,
|
|
122
|
+
}),
|
|
123
|
+
z.object({
|
|
124
|
+
type: z.literal("error-text"),
|
|
125
|
+
value: z.string(),
|
|
126
|
+
}),
|
|
127
|
+
z.object({
|
|
128
|
+
type: z.literal("error-json"),
|
|
129
|
+
value: JSONValueSchema,
|
|
130
|
+
}),
|
|
131
|
+
z.object({
|
|
132
|
+
type: z.literal("content"),
|
|
133
|
+
value: z.array(
|
|
134
|
+
z.union([
|
|
135
|
+
z.object({
|
|
136
|
+
type: z.literal("text"),
|
|
137
|
+
text: z.string().describe("Text content"),
|
|
138
|
+
}),
|
|
139
|
+
z.object({
|
|
140
|
+
type: z.literal("media"),
|
|
141
|
+
data: z.string().describe("Base-64 encoded media data"),
|
|
142
|
+
mediaType: z.string().describe("IANA media type"),
|
|
143
|
+
}),
|
|
144
|
+
]),
|
|
145
|
+
),
|
|
146
|
+
}),
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Tool Result Part Schema
|
|
151
|
+
* Tool result content part of a prompt
|
|
152
|
+
*/
|
|
153
|
+
const ToolResultPartSchema = z.object({
|
|
154
|
+
type: z.literal("tool-result"),
|
|
155
|
+
toolCallId: z
|
|
156
|
+
.string()
|
|
157
|
+
.describe("ID of the tool call that this result is associated with"),
|
|
158
|
+
toolName: z.string().describe("Name of the tool that generated this result"),
|
|
159
|
+
output: ToolResultOutputSchema.describe("Result of the tool call"),
|
|
160
|
+
providerOptions: ProviderOptionsSchema,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* System Message Schema
|
|
165
|
+
*/
|
|
166
|
+
const SystemMessageSchema = z.object({
|
|
167
|
+
role: z.literal("system"),
|
|
168
|
+
content: z.string().describe("System message content"),
|
|
169
|
+
providerOptions: ProviderOptionsSchema,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* User Message Schema
|
|
174
|
+
*/
|
|
175
|
+
const UserMessageSchema = z.object({
|
|
176
|
+
role: z.literal("user"),
|
|
177
|
+
content: z
|
|
178
|
+
.array(z.union([TextPartSchema, FilePartSchema]))
|
|
179
|
+
.describe("User message content parts (text or file)"),
|
|
180
|
+
providerOptions: ProviderOptionsSchema,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Assistant Message Schema
|
|
185
|
+
*/
|
|
186
|
+
const AssistantMessageSchema = z.object({
|
|
187
|
+
role: z.literal("assistant"),
|
|
188
|
+
content: z
|
|
189
|
+
.array(
|
|
190
|
+
z.union([
|
|
191
|
+
TextPartSchema,
|
|
192
|
+
FilePartSchema,
|
|
193
|
+
ReasoningPartSchema,
|
|
194
|
+
ToolCallPartSchema,
|
|
195
|
+
ToolResultPartSchema,
|
|
196
|
+
]),
|
|
197
|
+
)
|
|
198
|
+
.describe(
|
|
199
|
+
"Assistant message content parts (text, file, reasoning, tool-call, or tool-result)",
|
|
200
|
+
),
|
|
201
|
+
providerOptions: ProviderOptionsSchema,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Tool Message Schema
|
|
206
|
+
*/
|
|
207
|
+
const ToolMessageSchema = z.object({
|
|
208
|
+
role: z.literal("tool"),
|
|
209
|
+
content: z
|
|
210
|
+
.array(ToolResultPartSchema)
|
|
211
|
+
.describe("Tool message content (tool results)"),
|
|
212
|
+
providerOptions: ProviderOptionsSchema,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Language Model Message Schema
|
|
217
|
+
* A message in a language model prompt
|
|
218
|
+
*/
|
|
219
|
+
export const LanguageModelMessageSchema = z.union([
|
|
220
|
+
SystemMessageSchema,
|
|
221
|
+
UserMessageSchema,
|
|
222
|
+
AssistantMessageSchema,
|
|
223
|
+
ToolMessageSchema,
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Language Model Prompt Schema
|
|
228
|
+
* A prompt is a list of messages based on LanguageModelV2Prompt from @ai-sdk/provider
|
|
229
|
+
*/
|
|
230
|
+
export const LanguageModelPromptSchema = z
|
|
231
|
+
.array(LanguageModelMessageSchema)
|
|
232
|
+
.describe("A list of messages forming the prompt");
|
|
233
|
+
|
|
20
234
|
/**
|
|
21
235
|
* Language Model Call Options Schema
|
|
22
236
|
* Based on LanguageModelV2CallOptions from @ai-sdk/provider
|
|
23
237
|
*/
|
|
24
238
|
export const LanguageModelCallOptionsSchema = z.object({
|
|
25
239
|
// Core parameters
|
|
26
|
-
prompt:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"A language mode prompt is a standardized prompt type (messages, system, etc.)",
|
|
30
|
-
),
|
|
240
|
+
prompt: LanguageModelPromptSchema.describe(
|
|
241
|
+
"A language model prompt is a standardized prompt type (array of messages with roles: system, user, assistant, tool)",
|
|
242
|
+
),
|
|
31
243
|
|
|
32
244
|
// Generation parameters
|
|
33
245
|
maxOutputTokens: z
|
package/src/well-known/mcp.ts
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry App Well-Known Binding
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for accessing public registry apps.
|
|
5
|
+
* Any MCP that implements this binding can provide a list of available apps
|
|
6
|
+
* with their configurations and tools.
|
|
7
|
+
*
|
|
8
|
+
* This binding includes:
|
|
9
|
+
* - Collection bindings for LIST and GET operations (read-only)
|
|
10
|
+
* - Only exposes public apps (unlisted: false)
|
|
11
|
+
* - Removes sensitive fields (connection details, workspace info)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import {
|
|
16
|
+
BaseCollectionEntitySchema,
|
|
17
|
+
createCollectionBindings,
|
|
18
|
+
} from "./collections";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Tool definition schema from registry
|
|
22
|
+
*/
|
|
23
|
+
const RegistryToolSchema = z.object({
|
|
24
|
+
id: z.string(),
|
|
25
|
+
name: z.string(),
|
|
26
|
+
description: z.string().optional(),
|
|
27
|
+
inputSchema: z.record(z.unknown()),
|
|
28
|
+
outputSchema: z.record(z.unknown()).optional(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* MCP Registry Server schema extending Collection Entity base
|
|
33
|
+
* Combines BaseCollectionEntitySchema with MCP Registry Spec format
|
|
34
|
+
* https://spec.modelcontextprotocol.io/specification/2025-03-26/registry/
|
|
35
|
+
*/
|
|
36
|
+
export const MCPRegistryServerSchema = BaseCollectionEntitySchema.extend({
|
|
37
|
+
// MCP Registry Spec structure
|
|
38
|
+
_meta: z
|
|
39
|
+
.object({
|
|
40
|
+
"io.decocms": z
|
|
41
|
+
.object({
|
|
42
|
+
id: z.string(),
|
|
43
|
+
verified: z.boolean(),
|
|
44
|
+
scopeName: z.string(),
|
|
45
|
+
appName: z.string(),
|
|
46
|
+
friendlyName: z.string().nullable().optional(),
|
|
47
|
+
metadata: z.record(z.unknown()).nullable().optional(),
|
|
48
|
+
publishedAt: z.string().datetime().optional(),
|
|
49
|
+
updatedAt: z.string().datetime().optional(),
|
|
50
|
+
tools: z
|
|
51
|
+
.array(RegistryToolSchema)
|
|
52
|
+
.nullable()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Available tools exposed by this app"),
|
|
55
|
+
})
|
|
56
|
+
.optional(),
|
|
57
|
+
})
|
|
58
|
+
.optional(),
|
|
59
|
+
server: z.object({
|
|
60
|
+
$schema: z.string().optional(),
|
|
61
|
+
_meta: z.record(z.unknown()).optional(),
|
|
62
|
+
name: z.string().describe("The server name (scope/app)"),
|
|
63
|
+
title: z.string().optional().describe("User-friendly title"),
|
|
64
|
+
description: z.string().optional().describe("Server description"),
|
|
65
|
+
icons: z
|
|
66
|
+
.array(
|
|
67
|
+
z.object({
|
|
68
|
+
src: z.string(),
|
|
69
|
+
mimeType: z.string().optional(),
|
|
70
|
+
sizes: z.array(z.string()).optional(),
|
|
71
|
+
theme: z.enum(["light", "dark"]).optional(),
|
|
72
|
+
}),
|
|
73
|
+
)
|
|
74
|
+
.optional(),
|
|
75
|
+
remotes: z
|
|
76
|
+
.array(
|
|
77
|
+
z.object({
|
|
78
|
+
type: z.enum(["http", "stdio", "sse"]),
|
|
79
|
+
url: z.string().optional(),
|
|
80
|
+
headers: z.array(z.unknown()).optional(),
|
|
81
|
+
}),
|
|
82
|
+
)
|
|
83
|
+
.optional(),
|
|
84
|
+
packages: z.array(z.unknown()).optional(),
|
|
85
|
+
repository: z
|
|
86
|
+
.object({
|
|
87
|
+
url: z.string(),
|
|
88
|
+
source: z.string().optional(),
|
|
89
|
+
subfolder: z.string().optional(),
|
|
90
|
+
})
|
|
91
|
+
.optional(),
|
|
92
|
+
version: z.string().optional(),
|
|
93
|
+
websiteUrl: z.string().optional(),
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export type RegistryAppCollectionEntity = z.infer<
|
|
98
|
+
typeof MCPRegistryServerSchema
|
|
99
|
+
>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Registry App Collection Binding (read-only)
|
|
103
|
+
*
|
|
104
|
+
* Collection bindings for registry apps (read-only).
|
|
105
|
+
* Provides LIST and GET operations for public apps.
|
|
106
|
+
* Only includes public apps (unlisted: false).
|
|
107
|
+
*
|
|
108
|
+
* Returns servers in MCP Registry Spec format with:
|
|
109
|
+
* - _meta: DecoCMS-specific metadata (id, verified, tools, etc.)
|
|
110
|
+
* - server: MCP Registry Spec compliant server definition
|
|
111
|
+
*/
|
|
112
|
+
const REGISTRY_APP_COLLECTION_BINDING = createCollectionBindings(
|
|
113
|
+
"registry_app",
|
|
114
|
+
MCPRegistryServerSchema,
|
|
115
|
+
{ readOnly: true },
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Registry App Binding
|
|
120
|
+
*
|
|
121
|
+
* Defines the interface for accessing public registry apps.
|
|
122
|
+
* Any MCP that implements this binding can provide a searchable list of apps.
|
|
123
|
+
*
|
|
124
|
+
* Required tools:
|
|
125
|
+
* - COLLECTION_REGISTRY_APP_LIST: List available apps with filtering and pagination
|
|
126
|
+
* - COLLECTION_REGISTRY_APP_GET: Get a single app by ID
|
|
127
|
+
*/
|
|
128
|
+
export const REGISTRY_APP_BINDING = REGISTRY_APP_COLLECTION_BINDING;
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflows Well-Known Binding
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for workflow providers.
|
|
5
|
+
* Any MCP that implements this binding can expose configurable workflows,
|
|
6
|
+
* executions, step results, and events via collection bindings.
|
|
7
|
+
*
|
|
8
|
+
* This binding uses collection bindings for LIST and GET operations (read-only).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import type { Binder } from "../core/binder";
|
|
13
|
+
import {
|
|
14
|
+
BaseCollectionEntitySchema,
|
|
15
|
+
createCollectionBindings,
|
|
16
|
+
} from "./collections";
|
|
17
|
+
|
|
18
|
+
export const ToolCallActionSchema = z.object({
|
|
19
|
+
connectionId: z.string().describe("Integration connection ID"),
|
|
20
|
+
toolName: z.string().describe("Name of the tool to call"),
|
|
21
|
+
});
|
|
22
|
+
export type ToolCallAction = z.infer<typeof ToolCallActionSchema>;
|
|
23
|
+
|
|
24
|
+
export const CodeActionSchema = z.object({
|
|
25
|
+
code: z.string().describe("TypeScript code for pure data transformation"),
|
|
26
|
+
});
|
|
27
|
+
export type CodeAction = z.infer<typeof CodeActionSchema>;
|
|
28
|
+
export const SleepActionSchema = z.union([
|
|
29
|
+
z.object({
|
|
30
|
+
sleepMs: z.number().describe("Milliseconds to sleep"),
|
|
31
|
+
}),
|
|
32
|
+
z.object({
|
|
33
|
+
sleepUntil: z.string().describe("ISO date string or @ref to sleep until"),
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export const WaitForSignalActionSchema = z.object({
|
|
38
|
+
signalName: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe("Name of the signal to wait for (must be unique per execution)"),
|
|
41
|
+
timeoutMs: z
|
|
42
|
+
.number()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("Maximum time to wait in milliseconds (default: no timeout)"),
|
|
45
|
+
description: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("Human-readable description of what this signal is waiting for"),
|
|
49
|
+
});
|
|
50
|
+
export type WaitForSignalAction = z.infer<typeof WaitForSignalActionSchema>;
|
|
51
|
+
|
|
52
|
+
export const StepActionSchema = z.union([
|
|
53
|
+
ToolCallActionSchema.describe(
|
|
54
|
+
"Call an external tool (non-deterministic, checkpointed)",
|
|
55
|
+
),
|
|
56
|
+
CodeActionSchema.describe(
|
|
57
|
+
"Pure TypeScript data transformation (deterministic, replayable)",
|
|
58
|
+
),
|
|
59
|
+
SleepActionSchema.describe("Wait for time"),
|
|
60
|
+
WaitForSignalActionSchema.describe("Wait for external signal"),
|
|
61
|
+
]);
|
|
62
|
+
export type StepAction = z.infer<typeof StepActionSchema>;
|
|
63
|
+
/**
|
|
64
|
+
* Step Schema - Unified schema for all step types
|
|
65
|
+
*
|
|
66
|
+
* Step types:
|
|
67
|
+
* - tool: Call external service via MCP (non-deterministic, checkpointed)
|
|
68
|
+
* - transform: Pure TypeScript data transformation (deterministic, replayable)
|
|
69
|
+
* - sleep: Wait for time
|
|
70
|
+
* - waitForSignal: Block until external signal (human-in-the-loop)
|
|
71
|
+
*/
|
|
72
|
+
export const StepSchema = z.object({
|
|
73
|
+
name: z.string().min(1).describe("Unique step name within workflow"),
|
|
74
|
+
action: StepActionSchema,
|
|
75
|
+
input: z
|
|
76
|
+
.record(z.unknown())
|
|
77
|
+
.optional()
|
|
78
|
+
.describe(
|
|
79
|
+
"Input object with @ref resolution or default values. Example: { 'user_id': '@input.user_id', 'product_id': '@input.product_id' }",
|
|
80
|
+
),
|
|
81
|
+
config: z
|
|
82
|
+
.object({
|
|
83
|
+
maxAttempts: z.number().default(3).describe("Maximum retry attempts"),
|
|
84
|
+
backoffMs: z
|
|
85
|
+
.number()
|
|
86
|
+
.default(1000)
|
|
87
|
+
.describe("Initial backoff in milliseconds"),
|
|
88
|
+
timeoutMs: z.number().default(10000).describe("Timeout in milliseconds"),
|
|
89
|
+
})
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("Step configuration (max attempts, backoff, timeout)"),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export type Step = z.infer<typeof StepSchema>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Trigger Schema - Fire another workflow when execution completes
|
|
98
|
+
*/
|
|
99
|
+
export const TriggerSchema = z.object({
|
|
100
|
+
/**
|
|
101
|
+
* Target workflow ID to execute
|
|
102
|
+
*/
|
|
103
|
+
workflowId: z.string().describe("Target workflow ID to trigger"),
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Input for the new execution (uses @refs like step inputs)
|
|
107
|
+
* Maps output data to workflow input fields.
|
|
108
|
+
*
|
|
109
|
+
* If any @ref doesn't resolve (property missing), this trigger is SKIPPED.
|
|
110
|
+
*/
|
|
111
|
+
input: z
|
|
112
|
+
.record(z.unknown())
|
|
113
|
+
.describe(
|
|
114
|
+
"Input mapping with @refs from current workflow output. Example: { 'user_id': '@stepName.output.user_id' }",
|
|
115
|
+
),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export type Trigger = z.infer<typeof TriggerSchema>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Workflow Execution Status
|
|
122
|
+
*
|
|
123
|
+
* States:
|
|
124
|
+
* - pending: Created but not started
|
|
125
|
+
* - running: Currently executing
|
|
126
|
+
* - completed: Successfully finished
|
|
127
|
+
* - cancelled: Manually cancelled
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
const WorkflowExecutionStatusEnum = z
|
|
131
|
+
.enum(["pending", "running", "completed", "cancelled"])
|
|
132
|
+
.default("pending");
|
|
133
|
+
export type WorkflowExecutionStatus = z.infer<
|
|
134
|
+
typeof WorkflowExecutionStatusEnum
|
|
135
|
+
>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Workflow Execution Schema
|
|
139
|
+
*
|
|
140
|
+
* Includes lock columns and retry tracking.
|
|
141
|
+
*/
|
|
142
|
+
export const WorkflowExecutionSchema = BaseCollectionEntitySchema.extend({
|
|
143
|
+
workflow_id: z.string(),
|
|
144
|
+
status: WorkflowExecutionStatusEnum,
|
|
145
|
+
input: z.record(z.unknown()).optional(),
|
|
146
|
+
output: z.unknown().optional(),
|
|
147
|
+
parent_execution_id: z.string().nullish(),
|
|
148
|
+
completed_at_epoch_ms: z.number().nullish(),
|
|
149
|
+
locked_until_epoch_ms: z.number().nullish(),
|
|
150
|
+
lock_id: z.string().nullish(),
|
|
151
|
+
retry_count: z.number().default(0),
|
|
152
|
+
max_retries: z.number().default(10),
|
|
153
|
+
error: z.string().nullish(),
|
|
154
|
+
});
|
|
155
|
+
export type WorkflowExecution = z.infer<typeof WorkflowExecutionSchema>;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Execution Step Result Schema
|
|
159
|
+
*
|
|
160
|
+
* Includes attempt tracking and error history.
|
|
161
|
+
*/
|
|
162
|
+
export const WorkflowExecutionStepResultSchema =
|
|
163
|
+
BaseCollectionEntitySchema.extend({
|
|
164
|
+
execution_id: z.string(),
|
|
165
|
+
step_id: z.string(),
|
|
166
|
+
|
|
167
|
+
input: z.record(z.unknown()).nullish(),
|
|
168
|
+
output: z.unknown().nullish(), // Can be object or array (forEach steps produce arrays)
|
|
169
|
+
error: z.string().nullish(),
|
|
170
|
+
completed_at_epoch_ms: z.number().nullish(),
|
|
171
|
+
});
|
|
172
|
+
export type WorkflowExecutionStepResult = z.infer<
|
|
173
|
+
typeof WorkflowExecutionStepResultSchema
|
|
174
|
+
>;
|
|
175
|
+
/**
|
|
176
|
+
* Event Type Enum
|
|
177
|
+
*
|
|
178
|
+
* Event types for the unified events table:
|
|
179
|
+
* - signal: External signal (human-in-the-loop)
|
|
180
|
+
* - timer: Durable sleep wake-up
|
|
181
|
+
* - message: Inter-workflow communication (send/recv)
|
|
182
|
+
* - output: Published value (setEvent/getEvent)
|
|
183
|
+
* - step_started: Observability - step began
|
|
184
|
+
* - step_completed: Observability - step finished
|
|
185
|
+
* - workflow_started: Workflow began execution
|
|
186
|
+
* - workflow_completed: Workflow finished
|
|
187
|
+
*/
|
|
188
|
+
export const EventTypeEnum = z.enum([
|
|
189
|
+
"signal",
|
|
190
|
+
"timer",
|
|
191
|
+
"message",
|
|
192
|
+
"output",
|
|
193
|
+
"step_started",
|
|
194
|
+
"step_completed",
|
|
195
|
+
"workflow_started",
|
|
196
|
+
"workflow_completed",
|
|
197
|
+
]);
|
|
198
|
+
|
|
199
|
+
export type EventType = z.infer<typeof EventTypeEnum>;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Workflow Event Schema
|
|
203
|
+
*
|
|
204
|
+
* Unified events table for signals, timers, messages, and observability.
|
|
205
|
+
*/
|
|
206
|
+
export const WorkflowEventSchema = BaseCollectionEntitySchema.extend({
|
|
207
|
+
execution_id: z.string(),
|
|
208
|
+
type: EventTypeEnum,
|
|
209
|
+
name: z.string().nullish(),
|
|
210
|
+
payload: z.unknown().optional(),
|
|
211
|
+
visible_at: z.number().nullish(),
|
|
212
|
+
consumed_at: z.number().nullish(),
|
|
213
|
+
source_execution_id: z.string().nullish(),
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
export type WorkflowEvent = z.infer<typeof WorkflowEventSchema>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Workflow entity schema for workflows
|
|
220
|
+
* Extends BaseCollectionEntitySchema with workflow-specific fields
|
|
221
|
+
* Base schema already includes: id, title, created_at, updated_at, created_by, updated_by
|
|
222
|
+
*/
|
|
223
|
+
export const WorkflowSchema = BaseCollectionEntitySchema.extend({
|
|
224
|
+
description: z.string().optional().describe("Workflow description"),
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Steps organized into phases.
|
|
228
|
+
* - Phases execute sequentially
|
|
229
|
+
* - Steps within a phase execute in parallel
|
|
230
|
+
*/
|
|
231
|
+
steps: z
|
|
232
|
+
.array(z.array(StepSchema))
|
|
233
|
+
.describe("2D array: phases (sequential) containing steps (parallel)"),
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Triggers to fire when execution completes successfully
|
|
237
|
+
*/
|
|
238
|
+
triggers: z
|
|
239
|
+
.array(TriggerSchema)
|
|
240
|
+
.optional()
|
|
241
|
+
.describe("Workflows to trigger on completion"),
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
export type Workflow = z.infer<typeof WorkflowSchema>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* WORKFLOW Collection Binding
|
|
248
|
+
*
|
|
249
|
+
* Collection bindings for workflows (read-only).
|
|
250
|
+
* Provides LIST and GET operations for workflows.
|
|
251
|
+
*/
|
|
252
|
+
export const WORKFLOWS_COLLECTION_BINDING = createCollectionBindings(
|
|
253
|
+
"workflow",
|
|
254
|
+
WorkflowSchema,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
export const WORKFLOW_EXECUTIONS_COLLECTION_BINDING = createCollectionBindings(
|
|
258
|
+
"workflow_execution",
|
|
259
|
+
WorkflowExecutionSchema,
|
|
260
|
+
{
|
|
261
|
+
readOnly: true,
|
|
262
|
+
},
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
export const WORKFLOW_STEP_RESULTS_COLLECTION_BINDING =
|
|
266
|
+
createCollectionBindings(
|
|
267
|
+
"workflow_execution_step_results",
|
|
268
|
+
WorkflowExecutionStepResultSchema,
|
|
269
|
+
{
|
|
270
|
+
readOnly: true,
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
export const WORKFLOW_EVENTS_COLLECTION_BINDING = createCollectionBindings(
|
|
275
|
+
"workflow_events",
|
|
276
|
+
WorkflowEventSchema,
|
|
277
|
+
{
|
|
278
|
+
readOnly: true,
|
|
279
|
+
},
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* WORKFLOWS Binding
|
|
284
|
+
*
|
|
285
|
+
* Defines the interface for workflow providers.
|
|
286
|
+
* Any MCP that implements this binding can provide configurable workflows.
|
|
287
|
+
*
|
|
288
|
+
* Required tools:
|
|
289
|
+
* - COLLECTION_WORKFLOW_LIST: List available workflows with their configurations
|
|
290
|
+
* - COLLECTION_WORKFLOW_GET: Get a single workflow by ID (includes steps and triggers)
|
|
291
|
+
*/
|
|
292
|
+
export const WORKFLOWS_BINDING = [
|
|
293
|
+
...WORKFLOWS_COLLECTION_BINDING,
|
|
294
|
+
...WORKFLOW_EXECUTIONS_COLLECTION_BINDING,
|
|
295
|
+
...WORKFLOW_STEP_RESULTS_COLLECTION_BINDING,
|
|
296
|
+
...WORKFLOW_EVENTS_COLLECTION_BINDING,
|
|
297
|
+
] as const satisfies Binder;
|