@decocms/bindings 1.3.0 → 1.3.2
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 +2 -1
- package/src/core/server-plugin.ts +8 -1
- package/src/index.ts +28 -0
- package/src/well-known/ai-gateway.ts +63 -0
- package/src/well-known/language-model.ts +13 -1
- package/src/well-known/reports.ts +333 -0
- package/src/well-known/workflow.ts +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/bindings",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"check": "tsc --noEmit",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"./workflow": "./src/well-known/workflow.ts",
|
|
31
31
|
"./plugins": "./src/core/plugins.ts",
|
|
32
32
|
"./plugin-router": "./src/core/plugin-router.tsx",
|
|
33
|
+
"./ai-gateway": "./src/well-known/ai-gateway.ts",
|
|
33
34
|
"./server-plugin": "./src/core/server-plugin.ts"
|
|
34
35
|
},
|
|
35
36
|
"engines": {
|
|
@@ -40,7 +40,14 @@ export interface ServerPluginToolContext {
|
|
|
40
40
|
structuredContent?: unknown;
|
|
41
41
|
}>;
|
|
42
42
|
listTools: () => Promise<{
|
|
43
|
-
tools: Array<{
|
|
43
|
+
tools: Array<{
|
|
44
|
+
name: string;
|
|
45
|
+
title?: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
inputSchema?: Record<string, unknown>;
|
|
48
|
+
outputSchema?: Record<string, unknown>;
|
|
49
|
+
annotations?: Record<string, unknown>;
|
|
50
|
+
}>;
|
|
44
51
|
}>;
|
|
45
52
|
close?: () => Promise<void>;
|
|
46
53
|
}>;
|
package/src/index.ts
CHANGED
|
@@ -104,3 +104,31 @@ export {
|
|
|
104
104
|
|
|
105
105
|
// Re-export workflow binding types
|
|
106
106
|
export { WORKFLOWS_COLLECTION_BINDING } from "./well-known/workflow";
|
|
107
|
+
|
|
108
|
+
// Re-export reports binding types
|
|
109
|
+
export {
|
|
110
|
+
REPORTS_BINDING,
|
|
111
|
+
type ReportsBinding,
|
|
112
|
+
type ReportStatus,
|
|
113
|
+
type ReportLifecycleStatus,
|
|
114
|
+
type CriterionItem,
|
|
115
|
+
type MetricItem,
|
|
116
|
+
type RankedListRow,
|
|
117
|
+
type ReportSection,
|
|
118
|
+
type ReportSummary,
|
|
119
|
+
type Report,
|
|
120
|
+
type ReportsListInput,
|
|
121
|
+
type ReportsListOutput,
|
|
122
|
+
type ReportsGetInput,
|
|
123
|
+
type ReportsGetOutput,
|
|
124
|
+
type ReportsUpdateStatusInput,
|
|
125
|
+
type ReportsUpdateStatusOutput,
|
|
126
|
+
ReportStatusSchema,
|
|
127
|
+
ReportLifecycleStatusSchema,
|
|
128
|
+
MetricItemSchema,
|
|
129
|
+
ReportSectionSchema,
|
|
130
|
+
ReportSummarySchema,
|
|
131
|
+
ReportSchema,
|
|
132
|
+
type SectionGroup,
|
|
133
|
+
groupSections,
|
|
134
|
+
} from "./well-known/reports";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Gateway Billing Well-Known Binding
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for AI gateways that support billing management.
|
|
5
|
+
* Any MCP that implements this binding is recognized as a billing-capable
|
|
6
|
+
* AI gateway, regardless of its URL.
|
|
7
|
+
*
|
|
8
|
+
* Required tools:
|
|
9
|
+
* - GATEWAY_USAGE: Returns spending, usage, limits, and alert configuration
|
|
10
|
+
*
|
|
11
|
+
* Optional tools:
|
|
12
|
+
* - GATEWAY_SET_LIMIT: Configure spending limit / add credit
|
|
13
|
+
* - GATEWAY_SET_ALERT: Configure usage/balance alerts
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import type { Binder } from "../core/binder";
|
|
18
|
+
|
|
19
|
+
export const GATEWAY_USAGE_INPUT = z.object({}).strict();
|
|
20
|
+
|
|
21
|
+
export const GATEWAY_USAGE_OUTPUT = z.object({
|
|
22
|
+
billing: z.object({
|
|
23
|
+
mode: z.enum(["prepaid", "postpaid"]),
|
|
24
|
+
limitPeriod: z.enum(["daily", "weekly", "monthly"]).nullable(),
|
|
25
|
+
}),
|
|
26
|
+
limit: z.object({
|
|
27
|
+
total: z.number().nullable(),
|
|
28
|
+
remaining: z.number().nullable(),
|
|
29
|
+
reset: z.string().nullable(),
|
|
30
|
+
}),
|
|
31
|
+
usage: z.object({
|
|
32
|
+
total: z.number(),
|
|
33
|
+
daily: z.number(),
|
|
34
|
+
weekly: z.number(),
|
|
35
|
+
monthly: z.number(),
|
|
36
|
+
}),
|
|
37
|
+
alert: z.object({
|
|
38
|
+
enabled: z.boolean(),
|
|
39
|
+
threshold_usd: z.number(),
|
|
40
|
+
email: z.string().nullable(),
|
|
41
|
+
}),
|
|
42
|
+
connectionId: z.string(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const AI_GATEWAY_BILLING_BINDING = [
|
|
46
|
+
{
|
|
47
|
+
name: "GATEWAY_USAGE" as const,
|
|
48
|
+
inputSchema: GATEWAY_USAGE_INPUT,
|
|
49
|
+
outputSchema: GATEWAY_USAGE_OUTPUT,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "GATEWAY_SET_LIMIT" as const,
|
|
53
|
+
inputSchema: z.object({}),
|
|
54
|
+
outputSchema: z.object({}),
|
|
55
|
+
opt: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "GATEWAY_SET_ALERT" as const,
|
|
59
|
+
inputSchema: z.object({}),
|
|
60
|
+
outputSchema: z.object({}),
|
|
61
|
+
opt: true,
|
|
62
|
+
},
|
|
63
|
+
] as const satisfies Binder;
|
|
@@ -166,7 +166,10 @@ const ToolCallOutputPartSchema = z.object({
|
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
168
|
* Tool Result Output Schema
|
|
169
|
-
* The output of a tool result
|
|
169
|
+
* The output of a tool result.
|
|
170
|
+
* Accepts typed objects (text, json, error-text, error-json, content),
|
|
171
|
+
* execution-denied (from AI SDK tool approval flow), and raw strings
|
|
172
|
+
* (JSON-serialized outputs from mapToolResultOutput).
|
|
170
173
|
*/
|
|
171
174
|
const ToolResultOutputSchema = z.union([
|
|
172
175
|
z.object({
|
|
@@ -201,6 +204,15 @@ const ToolResultOutputSchema = z.union([
|
|
|
201
204
|
]),
|
|
202
205
|
),
|
|
203
206
|
}),
|
|
207
|
+
z.object({
|
|
208
|
+
type: z.literal("execution-denied"),
|
|
209
|
+
reason: z.string().optional(),
|
|
210
|
+
}),
|
|
211
|
+
z
|
|
212
|
+
.string()
|
|
213
|
+
.describe(
|
|
214
|
+
"Raw or JSON-serialized output (e.g. from AI SDK mapToolResultOutput)",
|
|
215
|
+
),
|
|
204
216
|
]);
|
|
205
217
|
|
|
206
218
|
/**
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reports Well-Known Binding
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for viewing automated reports.
|
|
5
|
+
* Any MCP that implements this binding can provide reports to the Reports plugin
|
|
6
|
+
* (e.g. performance audits, security scans, accessibility checks).
|
|
7
|
+
*
|
|
8
|
+
* This binding includes:
|
|
9
|
+
* - REPORTS_LIST: List all available reports with metadata
|
|
10
|
+
* - REPORTS_GET: Get a specific report with full content
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import type { Binder, ToolBinder } from "../core/binder";
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Shared Schemas
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Report status indicates the overall health/outcome of the report.
|
|
22
|
+
*/
|
|
23
|
+
export const ReportStatusSchema = z.enum([
|
|
24
|
+
"passing",
|
|
25
|
+
"warning",
|
|
26
|
+
"failing",
|
|
27
|
+
"info",
|
|
28
|
+
]);
|
|
29
|
+
export type ReportStatus = z.infer<typeof ReportStatusSchema>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A single metric item within a metrics section.
|
|
33
|
+
*/
|
|
34
|
+
export const MetricItemSchema = z.object({
|
|
35
|
+
label: z.string().describe("Metric label (e.g. 'LCP', 'Performance')"),
|
|
36
|
+
value: z.union([z.number(), z.string()]).describe("Current metric value"),
|
|
37
|
+
unit: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Unit of measurement (e.g. 's', 'ms', 'score')"),
|
|
41
|
+
previousValue: z
|
|
42
|
+
.union([z.number(), z.string()])
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("Previous value for delta comparison"),
|
|
45
|
+
status: ReportStatusSchema.optional().describe(
|
|
46
|
+
"Status of this individual metric",
|
|
47
|
+
),
|
|
48
|
+
});
|
|
49
|
+
export type MetricItem = z.infer<typeof MetricItemSchema>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A single criterion item within a criteria section.
|
|
53
|
+
*/
|
|
54
|
+
export const CriterionItemSchema = z.object({
|
|
55
|
+
label: z.string().describe("Short name of the criterion"),
|
|
56
|
+
description: z.string().optional().describe("Longer explanation"),
|
|
57
|
+
status: ReportStatusSchema.optional().describe(
|
|
58
|
+
"Status of this individual criterion (passing/warning/failing/info)",
|
|
59
|
+
),
|
|
60
|
+
});
|
|
61
|
+
export type CriterionItem = z.infer<typeof CriterionItemSchema>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A single row within a ranked-list section.
|
|
65
|
+
*/
|
|
66
|
+
export const RankedListRowSchema = z.object({
|
|
67
|
+
position: z.number().describe("Current rank position"),
|
|
68
|
+
reference_position: z
|
|
69
|
+
.number()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe(
|
|
72
|
+
"Previous rank position before reordering. Used to compute delta automatically (delta = reference_position - position).",
|
|
73
|
+
),
|
|
74
|
+
delta: z
|
|
75
|
+
.number()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe(
|
|
78
|
+
"Explicit change in position. Ignored when reference_position is provided.",
|
|
79
|
+
),
|
|
80
|
+
label: z.string().describe("Item name"),
|
|
81
|
+
image: z.string().describe("URL of the item image"),
|
|
82
|
+
values: z
|
|
83
|
+
.array(z.union([z.string(), z.number()]))
|
|
84
|
+
.describe("Values matching columns"),
|
|
85
|
+
note: z
|
|
86
|
+
.union([
|
|
87
|
+
z.string(),
|
|
88
|
+
z.record(z.string(), z.union([z.string(), z.number()])),
|
|
89
|
+
])
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("Inline annotation or structured key-value metrics"),
|
|
92
|
+
});
|
|
93
|
+
export type RankedListRow = z.infer<typeof RankedListRowSchema>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Report sections -- polymorphic by type.
|
|
97
|
+
* Sections represent the main content blocks of a report.
|
|
98
|
+
*/
|
|
99
|
+
export const ReportSectionSchema = z.discriminatedUnion("type", [
|
|
100
|
+
z.object({
|
|
101
|
+
type: z.literal("markdown"),
|
|
102
|
+
content: z.string().describe("Markdown content"),
|
|
103
|
+
}),
|
|
104
|
+
z.object({
|
|
105
|
+
type: z.literal("metrics"),
|
|
106
|
+
title: z.string().optional().describe("Section title"),
|
|
107
|
+
items: z.array(MetricItemSchema).describe("Metric items"),
|
|
108
|
+
}),
|
|
109
|
+
z.object({
|
|
110
|
+
type: z.literal("table"),
|
|
111
|
+
title: z.string().optional().describe("Section title"),
|
|
112
|
+
columns: z.array(z.string()).describe("Column headers"),
|
|
113
|
+
rows: z
|
|
114
|
+
.array(z.array(z.union([z.string(), z.number(), z.null()])))
|
|
115
|
+
.describe("Table rows"),
|
|
116
|
+
}),
|
|
117
|
+
z.object({
|
|
118
|
+
type: z.literal("criteria"),
|
|
119
|
+
title: z.string().optional().describe("Section title"),
|
|
120
|
+
items: z.array(CriterionItemSchema).describe("List of criteria items"),
|
|
121
|
+
}),
|
|
122
|
+
z.object({
|
|
123
|
+
type: z.literal("note"),
|
|
124
|
+
content: z.string().describe("The note text"),
|
|
125
|
+
}),
|
|
126
|
+
z.object({
|
|
127
|
+
type: z.literal("ranked-list"),
|
|
128
|
+
title: z.string().optional().describe("Section title"),
|
|
129
|
+
rows: z.array(RankedListRowSchema).describe("Ranked items"),
|
|
130
|
+
}),
|
|
131
|
+
]);
|
|
132
|
+
export type ReportSection = z.infer<typeof ReportSectionSchema>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Lifecycle status of a report within the inbox workflow.
|
|
136
|
+
*/
|
|
137
|
+
export const ReportLifecycleStatusSchema = z.enum([
|
|
138
|
+
"unread",
|
|
139
|
+
"read",
|
|
140
|
+
"dismissed",
|
|
141
|
+
]);
|
|
142
|
+
export type ReportLifecycleStatus = z.infer<typeof ReportLifecycleStatusSchema>;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Summary of a report returned by REPORTS_LIST.
|
|
146
|
+
*/
|
|
147
|
+
export const ReportSummarySchema = z.object({
|
|
148
|
+
id: z.string().describe("Unique report identifier"),
|
|
149
|
+
collectionId: z
|
|
150
|
+
.string()
|
|
151
|
+
.describe("Collection identifier used to scope reports"),
|
|
152
|
+
title: z.string().describe("Report title"),
|
|
153
|
+
category: z
|
|
154
|
+
.string()
|
|
155
|
+
.describe(
|
|
156
|
+
"Report category (e.g. 'performance', 'security', 'accessibility')",
|
|
157
|
+
),
|
|
158
|
+
status: ReportStatusSchema.describe("Overall report status"),
|
|
159
|
+
summary: z.string().describe("One-line summary of findings"),
|
|
160
|
+
updatedAt: z.string().describe("ISO 8601 timestamp of last update"),
|
|
161
|
+
source: z
|
|
162
|
+
.string()
|
|
163
|
+
.optional()
|
|
164
|
+
.describe(
|
|
165
|
+
"Agent or service that generated the report (e.g. 'security-auditor', 'performance-monitor')",
|
|
166
|
+
),
|
|
167
|
+
tags: z
|
|
168
|
+
.array(z.string())
|
|
169
|
+
.optional()
|
|
170
|
+
.describe("Free-form tags for filtering (e.g. 'homepage', 'api', 'ci')"),
|
|
171
|
+
lifecycleStatus: ReportLifecycleStatusSchema.optional().describe(
|
|
172
|
+
"Inbox lifecycle status of the report (default: unread)",
|
|
173
|
+
),
|
|
174
|
+
});
|
|
175
|
+
export type ReportSummary = z.infer<typeof ReportSummarySchema>;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Full report returned by REPORTS_GET.
|
|
179
|
+
*/
|
|
180
|
+
export const ReportSchema = ReportSummarySchema.extend({
|
|
181
|
+
sections: z.array(ReportSectionSchema).describe("Ordered content sections"),
|
|
182
|
+
});
|
|
183
|
+
export type Report = z.infer<typeof ReportSchema>;
|
|
184
|
+
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// UI Helpers
|
|
187
|
+
// ============================================================================
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Groups adjacent criteria+metrics sections into side-by-side pairs for display.
|
|
191
|
+
* In a pair, criteria always goes left and metrics always goes right,
|
|
192
|
+
* regardless of their original order.
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
type SingleGroup = { type: "single"; section: ReportSection; idx: number };
|
|
196
|
+
type SideBySideGroup = {
|
|
197
|
+
type: "side-by-side";
|
|
198
|
+
left: Extract<ReportSection, { type: "criteria" }>;
|
|
199
|
+
right: Extract<ReportSection, { type: "metrics" }>;
|
|
200
|
+
leftIdx: number;
|
|
201
|
+
rightIdx: number;
|
|
202
|
+
};
|
|
203
|
+
export type SectionGroup = SingleGroup | SideBySideGroup;
|
|
204
|
+
|
|
205
|
+
export function groupSections(sections: ReportSection[]): SectionGroup[] {
|
|
206
|
+
const groups: SectionGroup[] = [];
|
|
207
|
+
let i = 0;
|
|
208
|
+
while (i < sections.length) {
|
|
209
|
+
const current = sections[i]!;
|
|
210
|
+
const next = sections[i + 1];
|
|
211
|
+
const isPair =
|
|
212
|
+
(current.type === "criteria" && next?.type === "metrics") ||
|
|
213
|
+
(current.type === "metrics" && next?.type === "criteria");
|
|
214
|
+
|
|
215
|
+
if (isPair) {
|
|
216
|
+
const isCriteriaFirst = current.type === "criteria";
|
|
217
|
+
const criteria = isCriteriaFirst ? current : next!;
|
|
218
|
+
const metrics = isCriteriaFirst ? next! : current;
|
|
219
|
+
const criteriaIdx = isCriteriaFirst ? i : i + 1;
|
|
220
|
+
const metricsIdx = isCriteriaFirst ? i + 1 : i;
|
|
221
|
+
groups.push({
|
|
222
|
+
type: "side-by-side",
|
|
223
|
+
left: criteria as Extract<ReportSection, { type: "criteria" }>,
|
|
224
|
+
right: metrics as Extract<ReportSection, { type: "metrics" }>,
|
|
225
|
+
leftIdx: criteriaIdx,
|
|
226
|
+
rightIdx: metricsIdx,
|
|
227
|
+
});
|
|
228
|
+
i += 2;
|
|
229
|
+
} else {
|
|
230
|
+
groups.push({ type: "single", section: current, idx: i });
|
|
231
|
+
i += 1;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return groups;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ============================================================================
|
|
238
|
+
// Tool Schemas
|
|
239
|
+
// ============================================================================
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* REPORTS_LIST - List all available reports with optional filters
|
|
243
|
+
*/
|
|
244
|
+
const ReportsListInputSchema = z.object({
|
|
245
|
+
category: z
|
|
246
|
+
.string()
|
|
247
|
+
.optional()
|
|
248
|
+
.describe("Filter by category (e.g. 'performance', 'security')"),
|
|
249
|
+
status: ReportStatusSchema.optional().describe("Filter by report status"),
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
const ReportsListOutputSchema = z.object({
|
|
253
|
+
reports: z.array(ReportSummarySchema).describe("List of report summaries"),
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
export type ReportsListInput = z.infer<typeof ReportsListInputSchema>;
|
|
257
|
+
export type ReportsListOutput = z.infer<typeof ReportsListOutputSchema>;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* REPORTS_GET - Get a specific report with full content
|
|
261
|
+
*/
|
|
262
|
+
const ReportsGetInputSchema = z.object({
|
|
263
|
+
id: z.string().describe("Report identifier"),
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const ReportsGetOutputSchema = ReportSchema;
|
|
267
|
+
|
|
268
|
+
export type ReportsGetInput = z.infer<typeof ReportsGetInputSchema>;
|
|
269
|
+
export type ReportsGetOutput = z.infer<typeof ReportsGetOutputSchema>;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* REPORTS_UPDATE_STATUS - Update the lifecycle status of a report (optional tool)
|
|
273
|
+
*/
|
|
274
|
+
const ReportsUpdateStatusInputSchema = z.object({
|
|
275
|
+
reportId: z.string().describe("Report identifier"),
|
|
276
|
+
lifecycleStatus: ReportLifecycleStatusSchema.describe(
|
|
277
|
+
"New lifecycle status for the report",
|
|
278
|
+
),
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const ReportsUpdateStatusOutputSchema = z.object({
|
|
282
|
+
success: z.boolean().describe("Whether the operation succeeded"),
|
|
283
|
+
message: z.string().optional().describe("Human-readable result message"),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
export type ReportsUpdateStatusInput = z.infer<
|
|
287
|
+
typeof ReportsUpdateStatusInputSchema
|
|
288
|
+
>;
|
|
289
|
+
export type ReportsUpdateStatusOutput = z.infer<
|
|
290
|
+
typeof ReportsUpdateStatusOutputSchema
|
|
291
|
+
>;
|
|
292
|
+
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// Binding Definition
|
|
295
|
+
// ============================================================================
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Reports Binding
|
|
299
|
+
*
|
|
300
|
+
* Defines the interface for viewing automated reports.
|
|
301
|
+
* Any MCP that implements this binding can be used with the Reports plugin.
|
|
302
|
+
*
|
|
303
|
+
* Required tools:
|
|
304
|
+
* - REPORTS_LIST: List available reports with optional filtering
|
|
305
|
+
* - REPORTS_GET: Get a single report with full content
|
|
306
|
+
*
|
|
307
|
+
* Optional tools:
|
|
308
|
+
* - REPORTS_UPDATE_STATUS: Update the lifecycle status of a report (unread → read → dismissed)
|
|
309
|
+
*/
|
|
310
|
+
export const REPORTS_BINDING = [
|
|
311
|
+
{
|
|
312
|
+
name: "REPORTS_LIST" as const,
|
|
313
|
+
inputSchema: ReportsListInputSchema,
|
|
314
|
+
outputSchema: ReportsListOutputSchema,
|
|
315
|
+
} satisfies ToolBinder<"REPORTS_LIST", ReportsListInput, ReportsListOutput>,
|
|
316
|
+
{
|
|
317
|
+
name: "REPORTS_GET" as const,
|
|
318
|
+
inputSchema: ReportsGetInputSchema,
|
|
319
|
+
outputSchema: ReportsGetOutputSchema,
|
|
320
|
+
} satisfies ToolBinder<"REPORTS_GET", ReportsGetInput, ReportsGetOutput>,
|
|
321
|
+
{
|
|
322
|
+
name: "REPORTS_UPDATE_STATUS" as const,
|
|
323
|
+
inputSchema: ReportsUpdateStatusInputSchema,
|
|
324
|
+
outputSchema: ReportsUpdateStatusOutputSchema,
|
|
325
|
+
opt: true,
|
|
326
|
+
} satisfies ToolBinder<
|
|
327
|
+
"REPORTS_UPDATE_STATUS",
|
|
328
|
+
ReportsUpdateStatusInput,
|
|
329
|
+
ReportsUpdateStatusOutput
|
|
330
|
+
>,
|
|
331
|
+
] as const satisfies Binder;
|
|
332
|
+
|
|
333
|
+
export type ReportsBinding = typeof REPORTS_BINDING;
|
|
@@ -99,6 +99,7 @@ export type StepConfig = z.infer<typeof StepConfigSchema>;
|
|
|
99
99
|
* Data flow uses @ref syntax:
|
|
100
100
|
* - @input.field → workflow input
|
|
101
101
|
* - @stepName.field → output from a previous step
|
|
102
|
+
* - @ctx.execution_id → current workflow execution ID
|
|
102
103
|
*/
|
|
103
104
|
|
|
104
105
|
type JsonSchema = {
|
|
@@ -124,10 +125,22 @@ const JsonSchemaSchema: z.ZodType<JsonSchema> = z.lazy(() =>
|
|
|
124
125
|
.passthrough(),
|
|
125
126
|
);
|
|
126
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Step names that are reserved by the @ref system and cannot be used as step names.
|
|
130
|
+
* These are intercepted before step lookup in the ref resolver.
|
|
131
|
+
*/
|
|
132
|
+
export const RESERVED_STEP_NAMES = ["input", "item", "index", "ctx"] as const;
|
|
133
|
+
|
|
127
134
|
export const StepSchema = z.object({
|
|
128
135
|
name: z
|
|
129
136
|
.string()
|
|
130
137
|
.min(1)
|
|
138
|
+
.refine(
|
|
139
|
+
(name) => !(RESERVED_STEP_NAMES as readonly string[]).includes(name),
|
|
140
|
+
{
|
|
141
|
+
message: `Step name is reserved. Reserved names: ${RESERVED_STEP_NAMES.join(", ")}`,
|
|
142
|
+
},
|
|
143
|
+
)
|
|
131
144
|
.describe(
|
|
132
145
|
"Unique identifier for this step. Other steps reference its output as @name.field",
|
|
133
146
|
),
|
|
@@ -137,7 +150,7 @@ export const StepSchema = z.object({
|
|
|
137
150
|
.record(z.string(), z.unknown())
|
|
138
151
|
.optional()
|
|
139
152
|
.describe(
|
|
140
|
-
"Data passed to the action. Use @ref for dynamic values: @input.field (workflow input), @stepName.field (previous step output), @item/@index (loop context). Example: { 'userId': '@input.user_id', 'data': '@fetch.result' }",
|
|
153
|
+
"Data passed to the action. Use @ref for dynamic values: @input.field (workflow input), @stepName.field (previous step output), @item/@index (loop context), @ctx.execution_id (current execution ID). Example: { 'userId': '@input.user_id', 'data': '@fetch.result', 'executionId': '@ctx.execution_id' }",
|
|
141
154
|
),
|
|
142
155
|
outputSchema: JsonSchemaSchema.optional().describe(
|
|
143
156
|
"Optional JSON Schema describing the expected output of the step.",
|