@winstonsayno/mcp-gateway 6.0.0 → 6.2.0

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.
@@ -0,0 +1,172 @@
1
+ /**
2
+ * GraphQL / gRPC upstreams (6.1): expose GraphQL operations and gRPC methods as tools, without an MCP server.
3
+ *
4
+ * - **GraphQL:** each configured operation (a query or mutation document) becomes a tool; its input schema is derived
5
+ * from the operation's variable definitions (`$id: ID!` → required string, `Int` → integer, `[String]` → array …).
6
+ * Calls POST `{ query, variables, operationName }` to the endpoint; GraphQL `errors` turn the call into an error.
7
+ * - **gRPC:** unary methods over the [Connect protocol](https://connectrpc.com/docs/protocol) or gRPC-JSON
8
+ * transcoding (`POST <url>/<package.Service>/<Method>` with a JSON body) — what Connect, Envoy's transcoder and
9
+ * gRPC-Gateway serve. Methods carry a JSON Schema for their request message (optional). Non-2xx responses with a
10
+ * Connect error body (`{ code, message }`) become errors.
11
+ *
12
+ * ```yaml
13
+ * apiUpstreams:
14
+ * - id: shop
15
+ * kind: graphql
16
+ * url: https://shop.example/graphql
17
+ * headers: { authorization: "Bearer ${SHOP_TOKEN}" }
18
+ * operations:
19
+ * - name: product
20
+ * description: Look up a product
21
+ * document: "query product($id: ID!, $locale: String) { product(id: $id) { id title price } }"
22
+ * - id: billing
23
+ * kind: grpc
24
+ * url: https://billing.example
25
+ * methods:
26
+ * - { name: getInvoice, service: billing.v1.Invoices, method: Get, inputSchema: { type: object, properties: { id: { type: string } } } }
27
+ * ```
28
+ *
29
+ * - `GET /admin/api-upstreams` — upstreams and their tools (`<upstream>.<operation>`) with input schemas.
30
+ * - `POST /admin/api-upstreams/call` — `{ tool, arguments }` → `{ success, result | error, durationMs }`.
31
+ *
32
+ * @module features/api-upstreams
33
+ */
34
+ import { z } from 'zod';
35
+ import { registerFeature, objectBody, badRequest } from '../gateway/features.js';
36
+ const Name = z.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
37
+ const Common = { id: Name, url: z.string().url(), headers: z.record(z.string()).default({}), timeoutMs: z.number().int().min(100).max(120_000).default(15_000) };
38
+ const GraphqlUpstream = z
39
+ .object({ ...Common, kind: z.literal('graphql'), operations: z.array(z.object({ name: Name, description: z.string().optional(), document: z.string().min(1) }).strict()).min(1) })
40
+ .strict();
41
+ const GrpcUpstream = z
42
+ .object({
43
+ ...Common,
44
+ kind: z.literal('grpc'),
45
+ methods: z
46
+ .array(z.object({ name: Name, description: z.string().optional(), service: z.string().regex(/^[A-Za-z_][\w.]*$/), method: z.string().regex(/^[A-Za-z_]\w*$/), inputSchema: z.record(z.unknown()).optional() }).strict())
47
+ .min(1),
48
+ })
49
+ .strict();
50
+ export const ApiUpstreamsSchema = z
51
+ .array(z.discriminatedUnion('kind', [GraphqlUpstream, GrpcUpstream]))
52
+ .superRefine((ups, ctx) => {
53
+ const seen = new Set();
54
+ ups.forEach((u, i) => {
55
+ if (seen.has(u.id))
56
+ ctx.addIssue({ code: 'custom', path: [i, 'id'], message: `duplicate upstream id "${u.id}"` });
57
+ seen.add(u.id);
58
+ });
59
+ });
60
+ const SCALARS = { ID: { type: 'string' }, String: { type: 'string' }, Int: { type: 'integer' }, Float: { type: 'number' }, Boolean: { type: 'boolean' } };
61
+ function gqlType(t) {
62
+ t = t.trim();
63
+ const required = t.endsWith('!');
64
+ if (required)
65
+ t = t.slice(0, -1).trim();
66
+ if (t.startsWith('[') && t.endsWith(']'))
67
+ return { schema: { type: 'array', items: gqlType(t.slice(1, -1)).schema }, required };
68
+ return { schema: SCALARS[t] ?? { description: `GraphQL input type ${t}` }, required };
69
+ }
70
+ /** JSON Schema for a GraphQL operation's variables (`query q($a: Int!, $b: [String])`). */
71
+ export function graphqlVariables(document) {
72
+ const head = /^\s*(?:query|mutation|subscription)\s*[A-Za-z_]\w*\s*\(([^)]*)\)/.exec(document);
73
+ const properties = {};
74
+ const required = [];
75
+ if (head) {
76
+ for (const m of head[1].matchAll(/\$([A-Za-z_]\w*)\s*:\s*([\w[\]!\s]+?)(?:\s*=\s*[^,$]+)?(?=,|\s*\$|$)/g)) {
77
+ const t = gqlType(m[2]);
78
+ properties[m[1]] = t.schema;
79
+ if (t.required && !/=/.test(m[0]))
80
+ required.push(m[1]);
81
+ }
82
+ }
83
+ return { type: 'object', properties, ...(required.length ? { required } : {}), additionalProperties: false };
84
+ }
85
+ const upstreams = (cfg) => (cfg.apiUpstreams ? ApiUpstreamsSchema.parse(cfg.apiUpstreams) : []);
86
+ /** Every tool exposed by the configured upstreams. */
87
+ export function apiUpstreamTools(cfg) {
88
+ return upstreams(cfg).flatMap((u) => u.kind === 'graphql'
89
+ ? u.operations.map((o) => ({ name: `${u.id}.${o.name}`, upstream: u.id, kind: 'graphql', description: o.description, inputSchema: graphqlVariables(o.document) }))
90
+ : u.methods.map((m) => ({ name: `${u.id}.${m.name}`, upstream: u.id, kind: 'grpc', description: m.description ?? `${m.service}/${m.method}`, inputSchema: m.inputSchema ?? { type: 'object' } })));
91
+ }
92
+ /** Call `<upstream>.<operation>`; `fetchImpl` is injectable for tests. */
93
+ export async function callApiUpstream(cfg, tool, args, fetchImpl = fetch) {
94
+ const dot = tool.indexOf('.');
95
+ const u = upstreams(cfg).find((x) => x.id === tool.slice(0, dot));
96
+ if (!u || dot < 0)
97
+ return undefined;
98
+ const name = tool.slice(dot + 1);
99
+ const t0 = Date.now();
100
+ const fail = (code, message, details) => ({ success: false, error: { code, message, ...(details === undefined ? {} : { details }) }, durationMs: Date.now() - t0 });
101
+ let url;
102
+ let body;
103
+ if (u.kind === 'graphql') {
104
+ const op = u.operations.find((o) => o.name === name);
105
+ if (!op)
106
+ return undefined;
107
+ url = u.url;
108
+ body = { query: op.document, variables: args, operationName: /^\s*(?:query|mutation|subscription)\s*([A-Za-z_]\w*)/.exec(op.document)?.[1] };
109
+ }
110
+ else {
111
+ const m = u.methods.find((x) => x.name === name);
112
+ if (!m)
113
+ return undefined;
114
+ url = `${u.url.replace(/\/+$/, '')}/${m.service}/${m.method}`;
115
+ body = args;
116
+ }
117
+ let res;
118
+ try {
119
+ res = await fetchImpl(url, {
120
+ method: 'POST',
121
+ headers: { 'content-type': 'application/json', accept: 'application/json', ...(u.kind === 'grpc' ? { 'connect-protocol-version': '1' } : {}), ...u.headers },
122
+ body: JSON.stringify(body),
123
+ signal: AbortSignal.timeout(u.timeoutMs),
124
+ });
125
+ }
126
+ catch (e) {
127
+ return fail('unavailable', `upstream ${u.id} unreachable: ${e.message}`);
128
+ }
129
+ let json;
130
+ try {
131
+ json = await res.json();
132
+ }
133
+ catch {
134
+ return fail(res.ok ? 'invalid_response' : 'http_' + res.status, `upstream ${u.id} returned ${res.status} without a JSON body`);
135
+ }
136
+ const j = (json ?? {});
137
+ if (u.kind === 'graphql') {
138
+ if (Array.isArray(j.errors) && j.errors.length)
139
+ return fail('graphql', j.errors.map((e) => e.message ?? 'error').join('; '), { errors: j.errors, data: j.data ?? null });
140
+ if (!res.ok)
141
+ return fail('http_' + res.status, `upstream ${u.id} returned ${res.status}`);
142
+ return { success: true, result: j.data ?? null, durationMs: Date.now() - t0 };
143
+ }
144
+ if (!res.ok)
145
+ return fail(typeof j.code === 'string' ? j.code : 'http_' + res.status, typeof j.message === 'string' ? j.message : `upstream ${u.id} returned ${res.status}`, j.details);
146
+ return { success: true, result: json, durationMs: Date.now() - t0 };
147
+ }
148
+ registerFeature({
149
+ id: 'api-upstreams',
150
+ since: '6.1.0',
151
+ summary: 'GraphQL and gRPC (Connect / JSON transcoding) upstreams exposed as tools',
152
+ mount: (router, ctx) => {
153
+ router.get('/', (_req, res) => {
154
+ const cfg = ctx.config();
155
+ res.json({ upstreams: upstreams(cfg).map((u) => ({ id: u.id, kind: u.kind, url: u.url })), tools: apiUpstreamTools(cfg) });
156
+ });
157
+ router.post('/call', async (req, res) => {
158
+ const b = objectBody(req, res);
159
+ if (!b)
160
+ return;
161
+ if (typeof b.tool !== 'string')
162
+ return badRequest(res, '"tool" must be "<upstream>.<operation>"');
163
+ if (b.arguments !== undefined && (typeof b.arguments !== 'object' || b.arguments === null || Array.isArray(b.arguments)))
164
+ return badRequest(res, '"arguments" must be an object');
165
+ const out = await callApiUpstream(ctx.config(), b.tool, b.arguments ?? {});
166
+ if (!out)
167
+ return void res.status(404).json({ error: 'Not Found', message: `no API upstream tool "${b.tool}"` });
168
+ res.status(out.success ? 200 : 502).json({ tool: b.tool, ...out });
169
+ });
170
+ },
171
+ });
172
+ //# sourceMappingURL=api-upstreams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-upstreams.js","sourceRoot":"","sources":["../../src/features/api-upstreams.ts"],"names":[],"mappings":"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"}
@@ -42,23 +42,23 @@ export declare const EdgeFleetSchema: z.ZodObject<{
42
42
  labels?: Record<string, string> | undefined;
43
43
  }>, "many">>;
44
44
  }, "strict", z.ZodTypeAny, {
45
- pushTimeoutMs: number;
46
- offlineAfterMs: number;
47
45
  nodes: {
48
46
  id: string;
49
47
  url: string;
50
48
  labels: Record<string, string>;
51
49
  apiKey?: string | undefined;
52
50
  }[];
51
+ pushTimeoutMs: number;
52
+ offlineAfterMs: number;
53
53
  }, {
54
- pushTimeoutMs?: number | undefined;
55
- offlineAfterMs?: number | undefined;
56
54
  nodes?: {
57
55
  id: string;
58
56
  url: string;
59
57
  apiKey?: string | undefined;
60
58
  labels?: Record<string, string> | undefined;
61
59
  }[] | undefined;
60
+ pushTimeoutMs?: number | undefined;
61
+ offlineAfterMs?: number | undefined;
62
62
  }>;
63
63
  export type EdgeFleetConfig = z.input<typeof EdgeFleetSchema>;
64
64
  type Resolved = z.output<typeof EdgeFleetSchema>;
@@ -11,5 +11,7 @@ import './marketplace.js';
11
11
  import './sessions.js';
12
12
  import './dlp.js';
13
13
  import './adaptive.js';
14
+ import './api-upstreams.js';
15
+ import './workflows.js';
14
16
  export { listFeatures, registerFeature, createFeatureRouter } from '../gateway/features.js';
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AACzB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,eAAe,CAAC;AACvB,OAAO,UAAU,CAAC;AAClB,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AACzB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,eAAe,CAAC;AACvB,OAAO,UAAU,CAAC;AAClB,OAAO,eAAe,CAAC;AACvB,OAAO,oBAAoB,CAAC;AAC5B,OAAO,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -11,5 +11,7 @@ import './marketplace.js';
11
11
  import './sessions.js';
12
12
  import './dlp.js';
13
13
  import './adaptive.js';
14
+ import './api-upstreams.js';
15
+ import './workflows.js';
14
16
  export { listFeatures, registerFeature, createFeatureRouter } from '../gateway/features.js';
15
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AACzB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,eAAe,CAAC;AACvB,OAAO,UAAU,CAAC;AAClB,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AACzB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,eAAe,CAAC;AACvB,OAAO,UAAU,CAAC;AAClB,OAAO,eAAe,CAAC;AACvB,OAAO,oBAAoB,CAAC;AAC5B,OAAO,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Workflow engine (6.2): multi-tool DAGs that run inside the gateway.
3
+ *
4
+ * Unlike chains (4.2, an ordered pipeline), a workflow is a graph: each node names the nodes it `needs`, and every
5
+ * node whose dependencies are done runs at once (bounded by `concurrency`). Nodes can be conditional (`if`), retry
6
+ * with exponential backoff, and either fail the run or let it `continue`. Runs are asynchronous and kept in memory.
7
+ *
8
+ * ```yaml
9
+ * workflows:
10
+ * - id: enrich-lead
11
+ * concurrency: 4
12
+ * nodes:
13
+ * - { id: company, tool: crm/lookup, args: { domain: "{{input.domain}}" } }
14
+ * - { id: news, tool: search/web, args: { q: "{{input.domain}} funding" }, retry: { attempts: 3, backoffMs: 200 } }
15
+ * - { id: score, tool: llm/score, needs: [company, news], args: { company: "{{nodes.company.text}}", news: "{{nodes.news.text}}" } }
16
+ * - { id: notify, tool: slack/post, needs: [score], if: "nodes.score.structuredContent.hot", onError: continue }
17
+ * output: "{{nodes.score.structuredContent}}"
18
+ * ```
19
+ *
20
+ * Templates use the chain syntax (`{{input.x}}`, `{{nodes.<id>.text | structuredContent | …}}`). Calls go through
21
+ * the full invoker pipeline (policy, quotas, audit) as client `workflow:<id>`.
22
+ *
23
+ * - `GET /admin/workflows` — workflows with their execution layers.
24
+ * - `POST /admin/workflows/run` — `{ workflow, input?, wait? }` → `202 { runId }` (or the finished run with `wait: true`).
25
+ * - `GET /admin/workflows/runs` / `GET /admin/workflows/runs/:id` — run history and one run with per-node status.
26
+ *
27
+ * @module features/workflows
28
+ */
29
+ import { z } from 'zod';
30
+ import type { ProxyResponse } from '../utils/types.js';
31
+ declare const Workflow: z.ZodEffects<z.ZodObject<{
32
+ id: z.ZodString;
33
+ description: z.ZodOptional<z.ZodString>;
34
+ concurrency: z.ZodDefault<z.ZodNumber>;
35
+ nodes: z.ZodArray<z.ZodObject<{
36
+ id: z.ZodString;
37
+ tool: z.ZodEffects<z.ZodString, string, string>;
38
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
39
+ needs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
40
+ if: z.ZodOptional<z.ZodString>;
41
+ retry: z.ZodDefault<z.ZodObject<{
42
+ attempts: z.ZodDefault<z.ZodNumber>;
43
+ backoffMs: z.ZodDefault<z.ZodNumber>;
44
+ }, "strict", z.ZodTypeAny, {
45
+ attempts: number;
46
+ backoffMs: number;
47
+ }, {
48
+ attempts?: number | undefined;
49
+ backoffMs?: number | undefined;
50
+ }>>;
51
+ onError: z.ZodDefault<z.ZodEnum<["fail", "continue"]>>;
52
+ }, "strict", z.ZodTypeAny, {
53
+ id: string;
54
+ tool: string;
55
+ args: Record<string, unknown>;
56
+ needs: string[];
57
+ retry: {
58
+ attempts: number;
59
+ backoffMs: number;
60
+ };
61
+ onError: "fail" | "continue";
62
+ if?: string | undefined;
63
+ }, {
64
+ id: string;
65
+ tool: string;
66
+ args?: Record<string, unknown> | undefined;
67
+ needs?: string[] | undefined;
68
+ if?: string | undefined;
69
+ retry?: {
70
+ attempts?: number | undefined;
71
+ backoffMs?: number | undefined;
72
+ } | undefined;
73
+ onError?: "fail" | "continue" | undefined;
74
+ }>, "many">;
75
+ output: z.ZodOptional<z.ZodUnknown>;
76
+ }, "strict", z.ZodTypeAny, {
77
+ id: string;
78
+ concurrency: number;
79
+ nodes: {
80
+ id: string;
81
+ tool: string;
82
+ args: Record<string, unknown>;
83
+ needs: string[];
84
+ retry: {
85
+ attempts: number;
86
+ backoffMs: number;
87
+ };
88
+ onError: "fail" | "continue";
89
+ if?: string | undefined;
90
+ }[];
91
+ description?: string | undefined;
92
+ output?: unknown;
93
+ }, {
94
+ id: string;
95
+ nodes: {
96
+ id: string;
97
+ tool: string;
98
+ args?: Record<string, unknown> | undefined;
99
+ needs?: string[] | undefined;
100
+ if?: string | undefined;
101
+ retry?: {
102
+ attempts?: number | undefined;
103
+ backoffMs?: number | undefined;
104
+ } | undefined;
105
+ onError?: "fail" | "continue" | undefined;
106
+ }[];
107
+ description?: string | undefined;
108
+ concurrency?: number | undefined;
109
+ output?: unknown;
110
+ }>, {
111
+ id: string;
112
+ concurrency: number;
113
+ nodes: {
114
+ id: string;
115
+ tool: string;
116
+ args: Record<string, unknown>;
117
+ needs: string[];
118
+ retry: {
119
+ attempts: number;
120
+ backoffMs: number;
121
+ };
122
+ onError: "fail" | "continue";
123
+ if?: string | undefined;
124
+ }[];
125
+ description?: string | undefined;
126
+ output?: unknown;
127
+ }, {
128
+ id: string;
129
+ nodes: {
130
+ id: string;
131
+ tool: string;
132
+ args?: Record<string, unknown> | undefined;
133
+ needs?: string[] | undefined;
134
+ if?: string | undefined;
135
+ retry?: {
136
+ attempts?: number | undefined;
137
+ backoffMs?: number | undefined;
138
+ } | undefined;
139
+ onError?: "fail" | "continue" | undefined;
140
+ }[];
141
+ description?: string | undefined;
142
+ concurrency?: number | undefined;
143
+ output?: unknown;
144
+ }>;
145
+ export declare const WorkflowsSchema: z.ZodArray<z.ZodEffects<z.ZodObject<{
146
+ id: z.ZodString;
147
+ description: z.ZodOptional<z.ZodString>;
148
+ concurrency: z.ZodDefault<z.ZodNumber>;
149
+ nodes: z.ZodArray<z.ZodObject<{
150
+ id: z.ZodString;
151
+ tool: z.ZodEffects<z.ZodString, string, string>;
152
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
153
+ needs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
154
+ if: z.ZodOptional<z.ZodString>;
155
+ retry: z.ZodDefault<z.ZodObject<{
156
+ attempts: z.ZodDefault<z.ZodNumber>;
157
+ backoffMs: z.ZodDefault<z.ZodNumber>;
158
+ }, "strict", z.ZodTypeAny, {
159
+ attempts: number;
160
+ backoffMs: number;
161
+ }, {
162
+ attempts?: number | undefined;
163
+ backoffMs?: number | undefined;
164
+ }>>;
165
+ onError: z.ZodDefault<z.ZodEnum<["fail", "continue"]>>;
166
+ }, "strict", z.ZodTypeAny, {
167
+ id: string;
168
+ tool: string;
169
+ args: Record<string, unknown>;
170
+ needs: string[];
171
+ retry: {
172
+ attempts: number;
173
+ backoffMs: number;
174
+ };
175
+ onError: "fail" | "continue";
176
+ if?: string | undefined;
177
+ }, {
178
+ id: string;
179
+ tool: string;
180
+ args?: Record<string, unknown> | undefined;
181
+ needs?: string[] | undefined;
182
+ if?: string | undefined;
183
+ retry?: {
184
+ attempts?: number | undefined;
185
+ backoffMs?: number | undefined;
186
+ } | undefined;
187
+ onError?: "fail" | "continue" | undefined;
188
+ }>, "many">;
189
+ output: z.ZodOptional<z.ZodUnknown>;
190
+ }, "strict", z.ZodTypeAny, {
191
+ id: string;
192
+ concurrency: number;
193
+ nodes: {
194
+ id: string;
195
+ tool: string;
196
+ args: Record<string, unknown>;
197
+ needs: string[];
198
+ retry: {
199
+ attempts: number;
200
+ backoffMs: number;
201
+ };
202
+ onError: "fail" | "continue";
203
+ if?: string | undefined;
204
+ }[];
205
+ description?: string | undefined;
206
+ output?: unknown;
207
+ }, {
208
+ id: string;
209
+ nodes: {
210
+ id: string;
211
+ tool: string;
212
+ args?: Record<string, unknown> | undefined;
213
+ needs?: string[] | undefined;
214
+ if?: string | undefined;
215
+ retry?: {
216
+ attempts?: number | undefined;
217
+ backoffMs?: number | undefined;
218
+ } | undefined;
219
+ onError?: "fail" | "continue" | undefined;
220
+ }[];
221
+ description?: string | undefined;
222
+ concurrency?: number | undefined;
223
+ output?: unknown;
224
+ }>, {
225
+ id: string;
226
+ concurrency: number;
227
+ nodes: {
228
+ id: string;
229
+ tool: string;
230
+ args: Record<string, unknown>;
231
+ needs: string[];
232
+ retry: {
233
+ attempts: number;
234
+ backoffMs: number;
235
+ };
236
+ onError: "fail" | "continue";
237
+ if?: string | undefined;
238
+ }[];
239
+ description?: string | undefined;
240
+ output?: unknown;
241
+ }, {
242
+ id: string;
243
+ nodes: {
244
+ id: string;
245
+ tool: string;
246
+ args?: Record<string, unknown> | undefined;
247
+ needs?: string[] | undefined;
248
+ if?: string | undefined;
249
+ retry?: {
250
+ attempts?: number | undefined;
251
+ backoffMs?: number | undefined;
252
+ } | undefined;
253
+ onError?: "fail" | "continue" | undefined;
254
+ }[];
255
+ description?: string | undefined;
256
+ concurrency?: number | undefined;
257
+ output?: unknown;
258
+ }>, "many">;
259
+ export type WorkflowsConfig = z.input<typeof WorkflowsSchema>;
260
+ type WorkflowCfg = z.output<typeof Workflow>;
261
+ /** Kahn layering: nodes in each layer depend only on earlier layers; `undefined` on a cycle. */
262
+ export declare function topoLayers(nodes: ReadonlyArray<{
263
+ id: string;
264
+ needs: readonly string[];
265
+ }>): string[][] | undefined;
266
+ export type NodeStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped';
267
+ export interface NodeRun {
268
+ id: string;
269
+ status: NodeStatus;
270
+ attempts: number;
271
+ startedAt?: string;
272
+ durationMs?: number;
273
+ error?: string;
274
+ }
275
+ export interface WorkflowRun {
276
+ runId: string;
277
+ workflow: string;
278
+ status: 'running' | 'succeeded' | 'failed';
279
+ startedAt: string;
280
+ finishedAt?: string;
281
+ nodes: NodeRun[];
282
+ output?: unknown;
283
+ error?: string;
284
+ }
285
+ export type WorkflowInvoke = (serverId: string, tool: string, args: Record<string, unknown>) => Promise<ProxyResponse>;
286
+ /** Run a workflow to completion. `onUpdate` sees the run object as it changes (same reference). */
287
+ export declare function runWorkflow(wf: WorkflowCfg, input: Record<string, unknown>, invoke: WorkflowInvoke, opts?: {
288
+ runId?: string;
289
+ run?: WorkflowRun;
290
+ sleepFn?: (ms: number) => Promise<unknown>;
291
+ }): Promise<WorkflowRun>;
292
+ /** Bounded in-memory run history (newest last). */
293
+ export declare class WorkflowRuns {
294
+ private readonly max;
295
+ private readonly runs;
296
+ constructor(max?: number);
297
+ add(r: WorkflowRun): void;
298
+ get(id: string): WorkflowRun | undefined;
299
+ list(workflow?: string): WorkflowRun[];
300
+ }
301
+ export {};
302
+ //# sourceMappingURL=workflows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/features/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AActE,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBV,CAAC;AACL,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAoB,CAAC;AACjD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC9D,KAAK,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAG7C,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,EAAE,GAAG,SAAS,CAWjH;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AACpF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAIvH,mGAAmG;AACnG,wBAAsB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAgE7N;AAED,mDAAmD;AACnD,qBAAa,YAAY;IAEX,OAAO,CAAC,QAAQ,CAAC,GAAG;IADhC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;gBAC1B,GAAG,SAAM;IACtC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAIzB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAGxC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;CAGvC"}