robotrock 0.1.0 → 0.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.
- package/README.md +190 -33
- package/dist/ai/index.d.ts +24 -0
- package/dist/ai/index.js +46 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/trigger.d.ts +5 -0
- package/dist/ai/trigger.js +24 -0
- package/dist/ai/trigger.js.map +1 -0
- package/dist/ai/workflow.d.ts +5 -0
- package/dist/ai/workflow.js +24 -0
- package/dist/ai/workflow.js.map +1 -0
- package/dist/chunk-7FVE6OYZ.js +124 -0
- package/dist/chunk-7FVE6OYZ.js.map +1 -0
- package/dist/chunk-D2FBSEZK.js +67 -0
- package/dist/chunk-D2FBSEZK.js.map +1 -0
- package/dist/chunk-OJ57M3RW.js +518 -0
- package/dist/chunk-OJ57M3RW.js.map +1 -0
- package/dist/chunk-THVGHUTX.js +330 -0
- package/dist/chunk-THVGHUTX.js.map +1 -0
- package/dist/client-agOgTJob.d.ts +99 -0
- package/dist/handler-webhook-BqEi6Bk-.d.ts +16 -0
- package/dist/index.d.ts +79 -33
- package/dist/index.js +94 -40
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.d.ts +631 -0
- package/dist/schemas/index.js +11 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/trigger/index.d.ts +34 -37
- package/dist/trigger/index.js +44 -72
- package/dist/trigger/index.js.map +1 -1
- package/dist/workflow/index.d.ts +35 -0
- package/dist/workflow/index.js +99 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow-CHWiRPU9.d.ts +309 -0
- package/package.json +36 -7
- package/dist/chunk-TUQXDKV6.js +0 -209
- package/dist/chunk-TUQXDKV6.js.map +0 -1
- package/dist/client-BQ-j7q68.d.ts +0 -37
package/README.md
CHANGED
|
@@ -10,77 +10,234 @@ npm install robotrock
|
|
|
10
10
|
bun add robotrock
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
## Agent skill (Cursor, Claude Code, etc.)
|
|
14
|
+
|
|
15
|
+
Install the RobotRock agent skill from [skills.sh](https://skills.sh/quintenb/robotrock-skills/robotrock) to teach coding agents how to integrate the SDK:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx skills add quintenb/robotrock-skills --skill robotrock
|
|
19
|
+
```
|
|
20
|
+
|
|
13
21
|
For Trigger.dev, also install `@trigger.dev/sdk`.
|
|
14
22
|
|
|
15
23
|
## Quick Start
|
|
16
24
|
|
|
25
|
+
Create a shared client in its own module (for example `lib/robotrock.ts`), then import it wherever you create tasks.
|
|
26
|
+
|
|
17
27
|
```typescript
|
|
18
|
-
|
|
28
|
+
// lib/robotrock.ts
|
|
29
|
+
import { createClient } from "robotrock";
|
|
30
|
+
|
|
31
|
+
export const robotrock = createClient({
|
|
32
|
+
app: "budgeting-service",
|
|
33
|
+
webhook: {
|
|
34
|
+
url: "https://your-app.com/api/robotrock/webhook",
|
|
35
|
+
headers: {
|
|
36
|
+
// place your headers here
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
```
|
|
19
41
|
|
|
20
|
-
|
|
21
|
-
|
|
42
|
+
```typescript
|
|
43
|
+
import { robotrock } from "./lib/robotrock";
|
|
22
44
|
|
|
23
|
-
const response = await
|
|
45
|
+
const response = await robotrock.sendToHuman({
|
|
24
46
|
type: "budget-approval",
|
|
25
47
|
name: "Q1 Budget Approval",
|
|
48
|
+
description: "Please review and approve the Q1 budget",
|
|
26
49
|
actions: [
|
|
27
50
|
{ id: "approve", title: "Approve" },
|
|
28
51
|
{ id: "reject", title: "Reject" },
|
|
29
52
|
],
|
|
53
|
+
idempotencyKey: "budget-q1-approval-v1",
|
|
30
54
|
});
|
|
55
|
+
|
|
56
|
+
console.log("Task created:", response.task.taskId);
|
|
31
57
|
```
|
|
32
58
|
|
|
33
|
-
|
|
59
|
+
Set `ROBOTROCK_API_KEY` in your environment (create a named key in the RobotRock dashboard under Settings → API Keys). The client reads it when you omit `apiKey` on `createClient`.
|
|
60
|
+
|
|
61
|
+
## Inbox routing
|
|
62
|
+
|
|
63
|
+
Set `app` on `createClient` to control dashboard inbox grouping for every task from that client.
|
|
64
|
+
|
|
65
|
+
When `app` is omitted on the client, the API uses your API key **name** as the inbox bucket.
|
|
66
|
+
|
|
67
|
+
## Client webhook
|
|
68
|
+
|
|
69
|
+
Configure a single webhook on the client. It is applied to every action when you call `sendToHuman`:
|
|
34
70
|
|
|
35
71
|
```typescript
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
actions: [
|
|
43
|
-
{ id: "approve", title: "Approve" },
|
|
44
|
-
{ id: "reject", title: "Reject" },
|
|
45
|
-
] as const,
|
|
72
|
+
export const robotrock = createClient({
|
|
73
|
+
webhook: {
|
|
74
|
+
url: "https://your-app.com/api/robotrock/webhook",
|
|
75
|
+
headers: {
|
|
76
|
+
// place your headers here
|
|
77
|
+
}, // optional, defaults to {}
|
|
46
78
|
},
|
|
47
79
|
});
|
|
48
80
|
```
|
|
49
81
|
|
|
50
|
-
|
|
82
|
+
## Automatic fallback polling
|
|
83
|
+
|
|
84
|
+
When the client has no `webhook`, `sendToHuman` polls until a human handles the task or throws `TaskExpiredError` / `TaskTimeoutError`. Configure `polling` on `createClient` (not on `sendToHuman`). Polling stops at the earlier of `polling.timeoutMs` and the task's `validUntil`. You cannot set both `webhook` and `polling` on the same client.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { createClient, TaskExpiredError, TaskTimeoutError } from "robotrock";
|
|
88
|
+
|
|
89
|
+
const robotrock = createClient({
|
|
90
|
+
app: "my-service",
|
|
91
|
+
polling: {
|
|
92
|
+
intervalMs: 2_000,
|
|
93
|
+
timeoutMs: 5 * 60 * 1_000,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const actions = [
|
|
98
|
+
{
|
|
99
|
+
id: "approve",
|
|
100
|
+
title: "Approve",
|
|
101
|
+
schema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
required: ["ticket"],
|
|
104
|
+
properties: {
|
|
105
|
+
ticket: { type: "string" },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "reject",
|
|
111
|
+
title: "Reject",
|
|
112
|
+
schema: {
|
|
113
|
+
type: "object",
|
|
114
|
+
required: ["reason"],
|
|
115
|
+
properties: {
|
|
116
|
+
reason: { type: "string" },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
] as const;
|
|
121
|
+
|
|
122
|
+
const result = await robotrock.sendToHuman({
|
|
123
|
+
type: "approval",
|
|
124
|
+
name: "Review change",
|
|
125
|
+
actions,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (result.mode === "created") {
|
|
129
|
+
console.log("Task created:", result.task.taskId);
|
|
130
|
+
} else if (result.actionId === "approve") {
|
|
131
|
+
console.log("Approved with ticket", result.data.ticket);
|
|
132
|
+
} else {
|
|
133
|
+
console.log("Rejected because", result.data.reason);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Other client methods
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
await robotrock.getTask("task_...");
|
|
141
|
+
await robotrock.cancelTask("task_...");
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Webhook verification helper
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import {
|
|
148
|
+
verifyRobotRockWebhook,
|
|
149
|
+
RobotRockWebhookError,
|
|
150
|
+
type RobotRockWebhookPayload,
|
|
151
|
+
} from "robotrock";
|
|
152
|
+
|
|
153
|
+
export async function POST(request: Request) {
|
|
154
|
+
try {
|
|
155
|
+
const payload: RobotRockWebhookPayload = await verifyRobotRockWebhook(request);
|
|
156
|
+
console.log(payload.action.id, payload.headers["x-request-id"]);
|
|
157
|
+
return Response.json({ ok: true });
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error instanceof RobotRockWebhookError) {
|
|
160
|
+
return Response.json({ error: error.code }, { status: 401 });
|
|
161
|
+
}
|
|
162
|
+
return Response.json({ error: "Unknown error" }, { status: 500 });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
51
166
|
|
|
52
167
|
## Trigger.dev
|
|
53
168
|
|
|
169
|
+
Install `@trigger.dev/sdk`, re-export SDK tasks from your `trigger/` directory, and call them with `triggerAndWait()`:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// trigger/robotrock.ts
|
|
173
|
+
export { sendToHumanTask, approveByHumanTask } from "robotrock/trigger";
|
|
174
|
+
```
|
|
175
|
+
|
|
54
176
|
```typescript
|
|
55
|
-
import { task } from "@trigger.dev/sdk
|
|
56
|
-
import {
|
|
177
|
+
import { task } from "@trigger.dev/sdk";
|
|
178
|
+
import { approveByHumanTask } from "./robotrock";
|
|
57
179
|
|
|
58
|
-
export const
|
|
59
|
-
id: "
|
|
180
|
+
export const gate = task({
|
|
181
|
+
id: "gate",
|
|
60
182
|
run: async () => {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
name: "Deploy to production",
|
|
65
|
-
actions: [
|
|
66
|
-
{ id: "approve", title: "Deploy" },
|
|
67
|
-
{ id: "reject", title: "Cancel" },
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
timeout: "1h",
|
|
183
|
+
const waitResult = await approveByHumanTask.triggerAndWait({
|
|
184
|
+
type: "release-gate",
|
|
185
|
+
name: "Ship this release?",
|
|
71
186
|
});
|
|
72
187
|
|
|
73
|
-
|
|
188
|
+
if (!waitResult.ok) {
|
|
189
|
+
throw waitResult.error;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return waitResult.output.actionId === "approve";
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Set `ROBOTROCK_API_KEY` (and optionally `ROBOTROCK_APP`) in your Trigger worker environment.
|
|
198
|
+
|
|
199
|
+
## Vercel AI SDK
|
|
200
|
+
|
|
201
|
+
Install `ai` and use the optional `robotrock/ai` entry:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm install ai
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { generateText, stepCountIs } from "ai";
|
|
209
|
+
import { createClient } from "robotrock";
|
|
210
|
+
import { approveByHumanTool, createSendToHumanTool } from "robotrock/ai";
|
|
211
|
+
|
|
212
|
+
const robotrock = createClient({
|
|
213
|
+
app: "my-agent",
|
|
214
|
+
polling: { timeoutMs: 30 * 60_000 },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const result = await generateText({
|
|
218
|
+
model: "anthropic/claude-sonnet-4",
|
|
219
|
+
tools: {
|
|
220
|
+
approveByHuman: approveByHumanTool(robotrock),
|
|
74
221
|
},
|
|
222
|
+
stopWhen: stepCountIs(10),
|
|
223
|
+
prompt: "Plan a release; get human approval before finalizing.",
|
|
75
224
|
});
|
|
76
225
|
```
|
|
77
226
|
|
|
227
|
+
For AI SDK tool execution approval (approve `deleteFile` before it runs), use `createRobotRockToolApproval`, `resolveToolApprovalsViaRobotRock`, and `runWithRobotRockApprovals` from `robotrock/ai`. See the [Vercel AI integration docs](https://github.com/robotrock/robotrock/blob/main/apps/docs/content/docs/integrations/vercel-ai.mdx) in this repo.
|
|
228
|
+
|
|
229
|
+
Run long polls inside Trigger.dev or a worker — not short serverless HTTP handlers.
|
|
230
|
+
|
|
78
231
|
## Exports
|
|
79
232
|
|
|
80
233
|
| Import | Description |
|
|
81
234
|
|--------|-------------|
|
|
82
|
-
| `robotrock` |
|
|
83
|
-
| `robotrock/trigger` | `
|
|
235
|
+
| `robotrock` | `createClient`, `RobotRock`, env helpers, types, schemas |
|
|
236
|
+
| `robotrock/trigger` | `sendToHumanTask`, `approveByHumanTask` for Trigger.dev |
|
|
237
|
+
| `robotrock/workflow` | `sendToHumanInWorkflow`, `approveByHumanInWorkflow` for Vercel Workflow |
|
|
238
|
+
| `robotrock/ai` | Vercel AI SDK tools and `toolApproval` bridge (peer: `ai`) |
|
|
239
|
+
| `robotrock/ai/trigger` | Same API, documented for `mode: "trigger"` in Trigger.dev workers |
|
|
240
|
+
| `robotrock/ai/workflow` | Same API, documented for `mode: "workflow"` in Vercel Workflow |
|
|
84
241
|
|
|
85
242
|
## License
|
|
86
243
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { R as RobotRockToolCallInfo, F as FormatToolApprovalTaskOptions, H as HumanToolResult } from '../workflow-CHWiRPU9.js';
|
|
2
|
+
export { A as APPROVE_BY_HUMAN_ACTIONS, d as ApproveByHumanToolDurableOptions, c as ApproveByHumanToolOptions, r as CreateRobotRockAiToolsOptions, f as CreateSendToHumanToolDurableOptions, C as CreateSendToHumanToolOptions, B as ResolveToolApprovalsOptions, i as RobotRockAiContext, j as RobotRockAiMode, k as RobotRockAiPollingContext, l as RobotRockAiTriggerContext, m as RobotRockAiWorkflowContext, D as RobotRockToolApprovalConfig, z as RobotRockToolApprovalDecision, E as RunWithRobotRockApprovalsOptions, T as ToolApprovalRequestPart, t as applyRobotRockToolApprovalToTools, g as approveByHumanForAi, b as approveByHumanInputSchema, a as approveByHumanTool, u as collectApprovalRequests, o as createRobotRockAiTools, p as createRobotRockAiTriggerContext, q as createRobotRockAiWorkflowContext, v as createRobotRockNeedsApproval, w as createRobotRockToolApproval, e as createSendToHumanTool, n as normalizeRobotRockAiContext, x as resolveToolApprovalsViaRobotRock, y as runWithRobotRockApprovals, h as sendToHumanForAi, s as sendToHumanToolInputSchema } from '../workflow-CHWiRPU9.js';
|
|
3
|
+
import { a as SendToHumanInput } from '../client-agOgTJob.js';
|
|
4
|
+
import { DiscriminatedApprovalResult } from '../schemas/index.js';
|
|
5
|
+
import 'ai';
|
|
6
|
+
import 'zod';
|
|
7
|
+
|
|
8
|
+
declare const DEFAULT_APPROVE_ACTIONS: readonly [{
|
|
9
|
+
readonly id: "approve";
|
|
10
|
+
readonly title: "Approve execution";
|
|
11
|
+
}, {
|
|
12
|
+
readonly id: "deny";
|
|
13
|
+
readonly title: "Deny";
|
|
14
|
+
}];
|
|
15
|
+
/**
|
|
16
|
+
* Build a RobotRock task payload for an AI SDK tool approval request.
|
|
17
|
+
*/
|
|
18
|
+
declare function defaultFormatToolApprovalTask(toolCall: RobotRockToolCallInfo, options?: FormatToolApprovalTaskOptions): SendToHumanInput;
|
|
19
|
+
|
|
20
|
+
declare function toHumanToolResult(result: DiscriminatedApprovalResult<readonly {
|
|
21
|
+
id: string;
|
|
22
|
+
}[]>): HumanToolResult;
|
|
23
|
+
|
|
24
|
+
export { DEFAULT_APPROVE_ACTIONS, FormatToolApprovalTaskOptions, HumanToolResult, RobotRockToolCallInfo, defaultFormatToolApprovalTask, toHumanToolResult };
|
package/dist/ai/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APPROVE_BY_HUMAN_ACTIONS,
|
|
3
|
+
DEFAULT_APPROVE_ACTIONS,
|
|
4
|
+
applyRobotRockToolApprovalToTools,
|
|
5
|
+
approveByHumanForAi,
|
|
6
|
+
approveByHumanInputSchema,
|
|
7
|
+
approveByHumanTool,
|
|
8
|
+
collectApprovalRequests,
|
|
9
|
+
createRobotRockAiTools,
|
|
10
|
+
createRobotRockAiTriggerContext,
|
|
11
|
+
createRobotRockAiWorkflowContext,
|
|
12
|
+
createRobotRockNeedsApproval,
|
|
13
|
+
createRobotRockToolApproval,
|
|
14
|
+
createSendToHumanTool,
|
|
15
|
+
defaultFormatToolApprovalTask,
|
|
16
|
+
normalizeRobotRockAiContext,
|
|
17
|
+
resolveToolApprovalsViaRobotRock,
|
|
18
|
+
runWithRobotRockApprovals,
|
|
19
|
+
sendToHumanForAi,
|
|
20
|
+
sendToHumanToolInputSchema,
|
|
21
|
+
toHumanToolResult
|
|
22
|
+
} from "../chunk-OJ57M3RW.js";
|
|
23
|
+
import "../chunk-7FVE6OYZ.js";
|
|
24
|
+
export {
|
|
25
|
+
APPROVE_BY_HUMAN_ACTIONS,
|
|
26
|
+
DEFAULT_APPROVE_ACTIONS,
|
|
27
|
+
applyRobotRockToolApprovalToTools,
|
|
28
|
+
approveByHumanForAi,
|
|
29
|
+
approveByHumanInputSchema,
|
|
30
|
+
approveByHumanTool,
|
|
31
|
+
collectApprovalRequests,
|
|
32
|
+
createRobotRockAiTools,
|
|
33
|
+
createRobotRockAiTriggerContext,
|
|
34
|
+
createRobotRockAiWorkflowContext,
|
|
35
|
+
createRobotRockNeedsApproval,
|
|
36
|
+
createRobotRockToolApproval,
|
|
37
|
+
createSendToHumanTool,
|
|
38
|
+
defaultFormatToolApprovalTask,
|
|
39
|
+
normalizeRobotRockAiContext,
|
|
40
|
+
resolveToolApprovalsViaRobotRock,
|
|
41
|
+
runWithRobotRockApprovals,
|
|
42
|
+
sendToHumanForAi,
|
|
43
|
+
sendToHumanToolInputSchema,
|
|
44
|
+
toHumanToolResult
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { i as RobotRockAiContext, j as RobotRockAiMode, k as RobotRockAiPollingContext, l as RobotRockAiTriggerContext, t as applyRobotRockToolApprovalToTools, a as approveByHumanTool, o as createRobotRockAiTools, p as createRobotRockAiTriggerContext, v as createRobotRockNeedsApproval, w as createRobotRockToolApproval, e as createSendToHumanTool, x as resolveToolApprovalsViaRobotRock, y as runWithRobotRockApprovals } from '../workflow-CHWiRPU9.js';
|
|
2
|
+
import 'ai';
|
|
3
|
+
import 'zod';
|
|
4
|
+
import '../client-agOgTJob.js';
|
|
5
|
+
import '../schemas/index.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyRobotRockToolApprovalToTools,
|
|
3
|
+
approveByHumanTool,
|
|
4
|
+
createRobotRockAiTools,
|
|
5
|
+
createRobotRockAiTriggerContext,
|
|
6
|
+
createRobotRockNeedsApproval,
|
|
7
|
+
createRobotRockToolApproval,
|
|
8
|
+
createSendToHumanTool,
|
|
9
|
+
resolveToolApprovalsViaRobotRock,
|
|
10
|
+
runWithRobotRockApprovals
|
|
11
|
+
} from "../chunk-OJ57M3RW.js";
|
|
12
|
+
import "../chunk-7FVE6OYZ.js";
|
|
13
|
+
export {
|
|
14
|
+
applyRobotRockToolApprovalToTools,
|
|
15
|
+
approveByHumanTool,
|
|
16
|
+
createRobotRockAiTools,
|
|
17
|
+
createRobotRockAiTriggerContext,
|
|
18
|
+
createRobotRockNeedsApproval,
|
|
19
|
+
createRobotRockToolApproval,
|
|
20
|
+
createSendToHumanTool,
|
|
21
|
+
resolveToolApprovalsViaRobotRock,
|
|
22
|
+
runWithRobotRockApprovals
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=trigger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { i as RobotRockAiContext, j as RobotRockAiMode, k as RobotRockAiPollingContext, l as RobotRockAiTriggerContext, m as RobotRockAiWorkflowContext, t as applyRobotRockToolApprovalToTools, a as approveByHumanTool, o as createRobotRockAiTools, q as createRobotRockAiWorkflowContext, v as createRobotRockNeedsApproval, w as createRobotRockToolApproval, e as createSendToHumanTool, x as resolveToolApprovalsViaRobotRock, y as runWithRobotRockApprovals } from '../workflow-CHWiRPU9.js';
|
|
2
|
+
import 'ai';
|
|
3
|
+
import 'zod';
|
|
4
|
+
import '../client-agOgTJob.js';
|
|
5
|
+
import '../schemas/index.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyRobotRockToolApprovalToTools,
|
|
3
|
+
approveByHumanTool,
|
|
4
|
+
createRobotRockAiTools,
|
|
5
|
+
createRobotRockAiWorkflowContext,
|
|
6
|
+
createRobotRockNeedsApproval,
|
|
7
|
+
createRobotRockToolApproval,
|
|
8
|
+
createSendToHumanTool,
|
|
9
|
+
resolveToolApprovalsViaRobotRock,
|
|
10
|
+
runWithRobotRockApprovals
|
|
11
|
+
} from "../chunk-OJ57M3RW.js";
|
|
12
|
+
import "../chunk-7FVE6OYZ.js";
|
|
13
|
+
export {
|
|
14
|
+
applyRobotRockToolApprovalToTools,
|
|
15
|
+
approveByHumanTool,
|
|
16
|
+
createRobotRockAiTools,
|
|
17
|
+
createRobotRockAiWorkflowContext,
|
|
18
|
+
createRobotRockNeedsApproval,
|
|
19
|
+
createRobotRockToolApproval,
|
|
20
|
+
createSendToHumanTool,
|
|
21
|
+
resolveToolApprovalsViaRobotRock,
|
|
22
|
+
runWithRobotRockApprovals
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
5
|
+
var __using = (stack, value, async) => {
|
|
6
|
+
if (value != null) {
|
|
7
|
+
if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
|
|
8
|
+
var dispose, inner;
|
|
9
|
+
if (async) dispose = value[__knownSymbol("asyncDispose")];
|
|
10
|
+
if (dispose === void 0) {
|
|
11
|
+
dispose = value[__knownSymbol("dispose")];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") __typeError("Object not disposable");
|
|
15
|
+
if (inner) dispose = function() {
|
|
16
|
+
try {
|
|
17
|
+
inner.call(this);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
return Promise.reject(e);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
stack.push([async, dispose, value]);
|
|
23
|
+
} else if (async) {
|
|
24
|
+
stack.push([async]);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
var __callDispose = (stack, error, hasError) => {
|
|
29
|
+
var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
|
|
30
|
+
return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
|
|
31
|
+
};
|
|
32
|
+
var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
|
|
33
|
+
var next = (it) => {
|
|
34
|
+
while (it = stack.pop()) {
|
|
35
|
+
try {
|
|
36
|
+
var result = it[1] && it[1].call(it[2]);
|
|
37
|
+
if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
|
|
38
|
+
} catch (e) {
|
|
39
|
+
fail(e);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (hasError) throw error;
|
|
43
|
+
};
|
|
44
|
+
return next();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/schemas/index.ts
|
|
48
|
+
import { z } from "zod";
|
|
49
|
+
var safeUrlSchema = z.string().refine((url) => url.startsWith("http://") || url.startsWith("https://"), {
|
|
50
|
+
message: "URL must start with http:// or https://"
|
|
51
|
+
});
|
|
52
|
+
var jsonSchema7Schema = z.custom(
|
|
53
|
+
(val) => typeof val === "object" && val !== null,
|
|
54
|
+
{ message: "Must be a valid JSON Schema object" }
|
|
55
|
+
);
|
|
56
|
+
var uiSchemaSchema = z.custom((val) => typeof val === "object" && val !== null, {
|
|
57
|
+
message: "Must be a valid UiSchema object"
|
|
58
|
+
});
|
|
59
|
+
var webhookHandlerSchema = z.object({
|
|
60
|
+
type: z.literal("webhook"),
|
|
61
|
+
url: safeUrlSchema,
|
|
62
|
+
headers: z.record(z.string())
|
|
63
|
+
});
|
|
64
|
+
var triggerHandlerSchema = webhookHandlerSchema.extend({
|
|
65
|
+
type: z.literal("trigger"),
|
|
66
|
+
tokenId: z.string().min(1)
|
|
67
|
+
});
|
|
68
|
+
var handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
|
|
69
|
+
var taskActionSchema = z.object({
|
|
70
|
+
id: z.string().min(1),
|
|
71
|
+
title: z.string().min(1),
|
|
72
|
+
description: z.string().optional(),
|
|
73
|
+
schema: jsonSchema7Schema.optional(),
|
|
74
|
+
ui: uiSchemaSchema.optional(),
|
|
75
|
+
data: z.record(z.unknown()).optional(),
|
|
76
|
+
handlers: z.array(handlerSchema).min(1).optional()
|
|
77
|
+
});
|
|
78
|
+
var uiFieldSchemaSchema = z.object({
|
|
79
|
+
"ui:widget": z.string().optional(),
|
|
80
|
+
"ui:title": z.string().optional(),
|
|
81
|
+
"ui:description": z.string().optional(),
|
|
82
|
+
"ui:options": z.record(z.unknown()).optional(),
|
|
83
|
+
items: z.lazy(() => z.record(uiFieldSchemaSchema)).optional()
|
|
84
|
+
}).passthrough();
|
|
85
|
+
var contextUiSchema = z.record(uiFieldSchemaSchema).optional();
|
|
86
|
+
var contextDataSchema = z.object({
|
|
87
|
+
data: z.record(z.unknown()),
|
|
88
|
+
ui: contextUiSchema
|
|
89
|
+
}).optional();
|
|
90
|
+
var taskContextSchema = z.object({
|
|
91
|
+
app: z.string().min(1).optional(),
|
|
92
|
+
type: z.string().min(1),
|
|
93
|
+
name: z.string().min(1),
|
|
94
|
+
description: z.string().optional(),
|
|
95
|
+
validUntil: z.string().optional(),
|
|
96
|
+
context: contextDataSchema,
|
|
97
|
+
version: z.literal(2).optional(),
|
|
98
|
+
actions: z.array(taskActionSchema).min(1, "At least one action is required")
|
|
99
|
+
});
|
|
100
|
+
var assignToSchema = z.object({
|
|
101
|
+
users: z.array(z.string().email()).optional(),
|
|
102
|
+
groups: z.array(z.string().min(1)).optional()
|
|
103
|
+
}).refine(
|
|
104
|
+
(data) => {
|
|
105
|
+
const groups = data.groups ?? [];
|
|
106
|
+
if (groups.includes("all") && groups.length > 1) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
},
|
|
111
|
+
{ message: 'Cannot combine "all" with other group slugs' }
|
|
112
|
+
);
|
|
113
|
+
var createTaskBodySchema = taskContextSchema.extend({
|
|
114
|
+
assignTo: assignToSchema.optional()
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export {
|
|
118
|
+
__using,
|
|
119
|
+
__callDispose,
|
|
120
|
+
taskContextSchema,
|
|
121
|
+
assignToSchema,
|
|
122
|
+
createTaskBodySchema
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=chunk-7FVE6OYZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport interface JSONSchema7 {\n $id?: string;\n $ref?: string;\n $schema?: string;\n $comment?: string;\n type?: JSONSchema7TypeName | JSONSchema7TypeName[];\n enum?: unknown[];\n const?: unknown;\n multipleOf?: number;\n maximum?: number;\n exclusiveMaximum?: number;\n minimum?: number;\n exclusiveMinimum?: number;\n maxLength?: number;\n minLength?: number;\n pattern?: string;\n format?: string;\n items?: JSONSchema7 | JSONSchema7[];\n additionalItems?: JSONSchema7 | boolean;\n maxItems?: number;\n minItems?: number;\n uniqueItems?: boolean;\n contains?: JSONSchema7;\n maxProperties?: number;\n minProperties?: number;\n required?: string[];\n properties?: Record<string, JSONSchema7>;\n patternProperties?: Record<string, JSONSchema7>;\n additionalProperties?: JSONSchema7 | boolean;\n dependencies?: Record<string, JSONSchema7 | string[]>;\n propertyNames?: JSONSchema7;\n if?: JSONSchema7;\n then?: JSONSchema7;\n else?: JSONSchema7;\n allOf?: JSONSchema7[];\n anyOf?: JSONSchema7[];\n oneOf?: JSONSchema7[];\n not?: JSONSchema7;\n title?: string;\n description?: string;\n default?: unknown;\n readOnly?: boolean;\n writeOnly?: boolean;\n examples?: unknown[];\n}\n\nexport type JSONSchema7TypeName =\n | \"string\"\n | \"number\"\n | \"integer\"\n | \"boolean\"\n | \"object\"\n | \"array\"\n | \"null\";\n\nexport type ExtendedJSONSchema7 = JSONSchema7 & {\n enumNames?: string[];\n [key: string]: unknown;\n};\n\nexport type UiSchema = {\n \"ui:widget\"?: string;\n \"ui:title\"?: string;\n \"ui:description\"?: string;\n \"ui:placeholder\"?: string;\n \"ui:options\"?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nconst safeUrlSchema = z\n .string()\n .refine((url) => url.startsWith(\"http://\") || url.startsWith(\"https://\"), {\n message: \"URL must start with http:// or https://\",\n });\n\nconst jsonSchema7Schema = z.custom<ExtendedJSONSchema7>(\n (val) => typeof val === \"object\" && val !== null,\n { message: \"Must be a valid JSON Schema object\" }\n);\n\nconst uiSchemaSchema = z.custom<UiSchema>((val) => typeof val === \"object\" && val !== null, {\n message: \"Must be a valid UiSchema object\",\n});\n\nconst webhookHandlerSchema = z.object({\n type: z.literal(\"webhook\"),\n url: safeUrlSchema,\n headers: z.record(z.string()),\n});\n\nconst triggerHandlerSchema = webhookHandlerSchema.extend({\n type: z.literal(\"trigger\"),\n tokenId: z.string().min(1),\n});\n\nconst handlerSchema = z.discriminatedUnion(\"type\", [webhookHandlerSchema, triggerHandlerSchema]);\n\nconst taskActionSchema = z.object({\n id: z.string().min(1),\n title: z.string().min(1),\n description: z.string().optional(),\n schema: jsonSchema7Schema.optional(),\n ui: uiSchemaSchema.optional(),\n data: z.record(z.unknown()).optional(),\n handlers: z.array(handlerSchema).min(1).optional(),\n});\n\nconst uiFieldSchemaSchema: z.ZodType<Record<string, unknown>> = z\n .object({\n \"ui:widget\": z.string().optional(),\n \"ui:title\": z.string().optional(),\n \"ui:description\": z.string().optional(),\n \"ui:options\": z.record(z.unknown()).optional(),\n items: z.lazy(() => z.record(uiFieldSchemaSchema)).optional(),\n })\n .passthrough();\n\nconst contextUiSchema = z.record(uiFieldSchemaSchema).optional();\n\nconst contextDataSchema = z\n .object({\n data: z.record(z.unknown()),\n ui: contextUiSchema,\n })\n .optional();\n\nexport const taskContextSchema = z.object({\n app: z.string().min(1).optional(),\n type: z.string().min(1),\n name: z.string().min(1),\n description: z.string().optional(),\n validUntil: z.string().optional(),\n context: contextDataSchema,\n version: z.literal(2).optional(),\n actions: z.array(taskActionSchema).min(1, \"At least one action is required\"),\n});\n\n/** Assignment targets at task create (not stored in task context JSON). */\nexport const assignToSchema = z\n .object({\n users: z.array(z.string().email()).optional(),\n groups: z.array(z.string().min(1)).optional(),\n })\n .refine(\n (data) => {\n const groups = data.groups ?? [];\n if (groups.includes(\"all\") && groups.length > 1) {\n return false;\n }\n return true;\n },\n { message: 'Cannot combine \"all\" with other group slugs' }\n );\n\nexport const createTaskBodySchema = taskContextSchema.extend({\n assignTo: assignToSchema.optional(),\n});\n\nexport type AssignToInput = z.infer<typeof assignToSchema>;\nexport type CreateTaskBodyInput = z.input<typeof createTaskBodySchema>;\nexport type CreateTaskBody = z.output<typeof createTaskBodySchema>;\nexport type TaskContextInput = z.input<typeof taskContextSchema>;\nexport type TaskContextOutput = z.output<typeof taskContextSchema>;\nexport type TaskContext = TaskContextOutput;\nexport type TaskAction = z.infer<typeof taskActionSchema>;\nexport type WebhookHandler = z.infer<typeof webhookHandlerSchema>;\nexport type TriggerHandler = z.infer<typeof triggerHandlerSchema>;\nexport type Handler = z.infer<typeof handlerSchema>;\n\ntype InferObjectProperties<\n Props,\n Req extends PropertyKey,\n> = Props extends Record<string, unknown>\n ? ({\n [K in keyof Props as K extends Req ? K : never]-?: InferJsonSchema7<Props[K]>;\n } & {\n [K in keyof Props as K extends Req ? never : K]?: InferJsonSchema7<Props[K]>;\n } extends infer O\n ? { [K in keyof O]: O[K] }\n : never)\n : Record<string, unknown>;\n\ntype RequiredKeys<S> =\n S extends { readonly required: readonly string[] } ? S[\"required\"][number] : never;\n\nexport type InferJsonSchema7<S> = [S] extends [undefined]\n ? Record<string, never>\n : S extends { readonly const: infer C }\n ? C\n : S extends {\n readonly enum: readonly (infer E)[];\n }\n ? E\n : S extends {\n readonly type: \"object\";\n readonly properties?: infer Props;\n }\n ? InferObjectProperties<Props, RequiredKeys<S>>\n : S extends {\n readonly type: \"object\";\n readonly properties?: undefined;\n }\n ? Record<string, unknown>\n : S extends {\n readonly type: \"array\";\n readonly items?: infer Items;\n }\n ? Items extends readonly unknown[]\n ? InferJsonSchema7<Items[number]>[]\n : Items extends object\n ? InferJsonSchema7<Items>[]\n : unknown[]\n : S extends { readonly type: \"string\" }\n ? string\n : S extends { readonly type: \"number\" } | { readonly type: \"integer\" }\n ? number\n : S extends { readonly type: \"boolean\" }\n ? boolean\n : unknown;\n\nexport type TaskStatus = \"pending\" | \"open\" | \"handled\" | \"expired\";\n\nexport interface TaskResponse {\n success: boolean;\n task: {\n taskId: string;\n status: \"pending\" | \"open\";\n context: TaskContext;\n validUntil: string;\n submittedAt: string;\n };\n message: string;\n}\n\nexport interface Task {\n id: string;\n createdAt: Date;\n status: TaskStatus;\n context: TaskContext;\n validUntil: number;\n handledAt?: number;\n handled?: {\n action: {\n id: string;\n data: unknown;\n };\n handledBy?: string;\n userId?: string;\n token?: string;\n };\n}\n\nexport type InferActionData<T extends { schema?: unknown }> = [\n Exclude<T[\"schema\"], undefined>,\n] extends [\n never,\n]\n ? Record<string, never>\n : Exclude<T[\"schema\"], undefined> extends infer S\n ? InferJsonSchema7<S>\n : Record<string, never>;\n\nexport type TupleElementIndices<T extends readonly unknown[]> = T extends readonly [\n unknown,\n ...unknown[],\n]\n ? Exclude<keyof T, keyof unknown[]>\n : number;\n\nexport interface TaskResult<T = Record<string, unknown>> {\n actionId: string;\n data: T;\n handledBy?: string;\n handledAt: Date;\n}\n\nexport interface ApprovalResult<T = Record<string, unknown>> extends TaskResult<T> {\n taskId: string;\n}\n\nexport type DiscriminatedApprovalResult<\n TActions extends readonly { id: string; schema?: unknown }[],\n> = {\n [I in TupleElementIndices<TActions>]: TActions[I] extends { id: string; schema?: unknown }\n ? Omit<ApprovalResult<InferActionData<TActions[I]>>, \"actionId\" | \"data\"> & {\n actionId: TActions[I][\"id\"];\n data: InferActionData<TActions[I]>;\n }\n : never\n}[TupleElementIndices<TActions>];\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/handler-webhook.ts
|
|
2
|
+
function isRobotRockHandlerWebhookPayload(value) {
|
|
3
|
+
if (typeof value !== "object" || value === null) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
const v = value;
|
|
7
|
+
if (typeof v.taskId !== "string" || typeof v.handledAt !== "string") {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const action = v.action;
|
|
11
|
+
if (typeof action !== "object" || action === null) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
const a = action;
|
|
15
|
+
return typeof a.id === "string" && "data" in a;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/wait-timing.ts
|
|
19
|
+
var DEFAULT_WAIT_DURATION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
20
|
+
function resolveWaitTiming(validUntilInput) {
|
|
21
|
+
const validUntilMs = validUntilInput !== void 0 ? parseValidUntilMs(validUntilInput) : Date.now() + DEFAULT_WAIT_DURATION_MS;
|
|
22
|
+
const durationMs = validUntilMs - Date.now();
|
|
23
|
+
if (durationMs <= 0) {
|
|
24
|
+
throw new Error("validUntil must be in the future");
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
validUntil: validUntilInput ?? new Date(validUntilMs),
|
|
28
|
+
timeout: durationMsToTimeout(durationMs)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function parseValidUntilMs(value) {
|
|
32
|
+
if (value instanceof Date) {
|
|
33
|
+
const ms = value.getTime();
|
|
34
|
+
if (Number.isNaN(ms)) {
|
|
35
|
+
throw new Error("Invalid validUntil: Date is invalid");
|
|
36
|
+
}
|
|
37
|
+
return ms;
|
|
38
|
+
}
|
|
39
|
+
const parsed = Date.parse(value);
|
|
40
|
+
if (Number.isNaN(parsed)) {
|
|
41
|
+
throw new Error("Invalid validUntil: expected a parseable date string");
|
|
42
|
+
}
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
function durationMsToTimeout(durationMs) {
|
|
46
|
+
const seconds = Math.ceil(durationMs / 1e3);
|
|
47
|
+
if (seconds <= 0) {
|
|
48
|
+
throw new Error("validUntil must be in the future");
|
|
49
|
+
}
|
|
50
|
+
if (seconds >= 86400) {
|
|
51
|
+
return `${Math.ceil(seconds / 86400)}d`;
|
|
52
|
+
}
|
|
53
|
+
if (seconds >= 3600) {
|
|
54
|
+
return `${Math.ceil(seconds / 3600)}h`;
|
|
55
|
+
}
|
|
56
|
+
if (seconds >= 60) {
|
|
57
|
+
return `${Math.ceil(seconds / 60)}m`;
|
|
58
|
+
}
|
|
59
|
+
return `${seconds}s`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export {
|
|
63
|
+
isRobotRockHandlerWebhookPayload,
|
|
64
|
+
resolveWaitTiming,
|
|
65
|
+
parseValidUntilMs
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=chunk-D2FBSEZK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/handler-webhook.ts","../src/wait-timing.ts"],"sourcesContent":["/**\n * JSON body posted when a RobotRock action handler runs (webhook or Trigger wait token).\n */\nexport interface RobotRockHandlerWebhookPayload {\n taskId: string;\n action: {\n id: string;\n title: string;\n data: unknown;\n };\n handledBy?: string;\n handledAt: string;\n handlerType: string;\n}\n\nexport function isRobotRockHandlerWebhookPayload(\n value: unknown\n): value is RobotRockHandlerWebhookPayload {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const v = value as Record<string, unknown>;\n if (typeof v.taskId !== \"string\" || typeof v.handledAt !== \"string\") {\n return false;\n }\n const action = v.action;\n if (typeof action !== \"object\" || action === null) {\n return false;\n }\n const a = action as Record<string, unknown>;\n return typeof a.id === \"string\" && \"data\" in a;\n}\n","/** Default wait when `validUntil` is omitted. */\nexport const DEFAULT_WAIT_DURATION_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport function resolveWaitTiming(validUntilInput?: Date | string): {\n validUntil: Date | string;\n timeout: string;\n} {\n const validUntilMs =\n validUntilInput !== undefined\n ? parseValidUntilMs(validUntilInput)\n : Date.now() + DEFAULT_WAIT_DURATION_MS;\n\n const durationMs = validUntilMs - Date.now();\n if (durationMs <= 0) {\n throw new Error(\"validUntil must be in the future\");\n }\n\n return {\n validUntil: validUntilInput ?? new Date(validUntilMs),\n timeout: durationMsToTimeout(durationMs),\n };\n}\n\nexport function parseValidUntilMs(value: Date | string): number {\n if (value instanceof Date) {\n const ms = value.getTime();\n if (Number.isNaN(ms)) {\n throw new Error(\"Invalid validUntil: Date is invalid\");\n }\n return ms;\n }\n\n const parsed = Date.parse(value);\n if (Number.isNaN(parsed)) {\n throw new Error(\"Invalid validUntil: expected a parseable date string\");\n }\n\n return parsed;\n}\n\n/** Duration string for Trigger.dev `wait.createToken` and Workflow `sleep`. */\nexport function durationMsToTimeout(durationMs: number): string {\n const seconds = Math.ceil(durationMs / 1000);\n if (seconds <= 0) {\n throw new Error(\"validUntil must be in the future\");\n }\n\n if (seconds >= 86_400) {\n return `${Math.ceil(seconds / 86_400)}d`;\n }\n if (seconds >= 3_600) {\n return `${Math.ceil(seconds / 3_600)}h`;\n }\n if (seconds >= 60) {\n return `${Math.ceil(seconds / 60)}m`;\n }\n\n return `${seconds}s`;\n}\n"],"mappings":";AAeO,SAAS,iCACd,OACyC;AACzC,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,WAAW,YAAY,OAAO,EAAE,cAAc,UAAU;AACnE,WAAO;AAAA,EACT;AACA,QAAM,SAAS,EAAE;AACjB,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,SAAO,OAAO,EAAE,OAAO,YAAY,UAAU;AAC/C;;;AC9BO,IAAM,2BAA2B,IAAI,KAAK,KAAK,KAAK;AAEpD,SAAS,kBAAkB,iBAGhC;AACA,QAAM,eACJ,oBAAoB,SAChB,kBAAkB,eAAe,IACjC,KAAK,IAAI,IAAI;AAEnB,QAAM,aAAa,eAAe,KAAK,IAAI;AAC3C,MAAI,cAAc,GAAG;AACnB,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,SAAO;AAAA,IACL,YAAY,mBAAmB,IAAI,KAAK,YAAY;AAAA,IACpD,SAAS,oBAAoB,UAAU;AAAA,EACzC;AACF;AAEO,SAAS,kBAAkB,OAA8B;AAC9D,MAAI,iBAAiB,MAAM;AACzB,UAAM,KAAK,MAAM,QAAQ;AACzB,QAAI,OAAO,MAAM,EAAE,GAAG;AACpB,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,OAAO,MAAM,MAAM,GAAG;AACxB,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,SAAO;AACT;AAGO,SAAS,oBAAoB,YAA4B;AAC9D,QAAM,UAAU,KAAK,KAAK,aAAa,GAAI;AAC3C,MAAI,WAAW,GAAG;AAChB,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,MAAI,WAAW,OAAQ;AACrB,WAAO,GAAG,KAAK,KAAK,UAAU,KAAM,CAAC;AAAA,EACvC;AACA,MAAI,WAAW,MAAO;AACpB,WAAO,GAAG,KAAK,KAAK,UAAU,IAAK,CAAC;AAAA,EACtC;AACA,MAAI,WAAW,IAAI;AACjB,WAAO,GAAG,KAAK,KAAK,UAAU,EAAE,CAAC;AAAA,EACnC;AAEA,SAAO,GAAG,OAAO;AACnB;","names":[]}
|