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/dist/trigger/index.d.ts
CHANGED
|
@@ -1,44 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as _trigger_dev_sdk from '@trigger.dev/sdk';
|
|
2
|
+
import { S as SendToHumanActionInput, a as SendToHumanInput } from '../client-agOgTJob.js';
|
|
3
|
+
export { R as RobotRockHandlerWebhookPayload } from '../handler-webhook-BqEi6Bk-.js';
|
|
4
|
+
export { ApprovalResult, DiscriminatedApprovalResult, TaskContextInput, TaskResult } from '../schemas/index.js';
|
|
5
|
+
import 'zod';
|
|
4
6
|
|
|
7
|
+
type SendToHumanPayload<A extends readonly SendToHumanActionInput[] = readonly SendToHumanActionInput[]> = SendToHumanInput<A> & {
|
|
8
|
+
/** Inbox app bucket. Overrides `ROBOTROCK_APP` when set. */
|
|
9
|
+
app?: string;
|
|
10
|
+
};
|
|
11
|
+
type ApproveByHumanPayload = Omit<SendToHumanPayload, "actions">;
|
|
5
12
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
13
|
+
* Durable human-in-the-loop task for Trigger.dev.
|
|
14
|
+
* Re-export from your `trigger/` directory so Trigger.dev discovers it on deploy.
|
|
8
15
|
*/
|
|
9
|
-
|
|
16
|
+
declare const sendToHumanTask: _trigger_dev_sdk.Task<"robotrock/send-to-human", SendToHumanPayload<readonly SendToHumanActionInput[]>, {
|
|
10
17
|
taskId: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
handledBy?: string;
|
|
17
|
-
handledAt: string;
|
|
18
|
-
handlerType: string;
|
|
19
|
-
}
|
|
20
|
-
interface AskHumanTriggerOptions {
|
|
21
|
-
app?: string;
|
|
22
|
-
/** Trigger waitpoint timeout (e.g. "1h", "30m", "7d"). @default "24h" */
|
|
23
|
-
timeout?: string;
|
|
24
|
-
/** Optional side-channel webhook URL (same payload as the wait token). */
|
|
25
|
-
callbackUrl?: string;
|
|
26
|
-
}
|
|
27
|
-
type AskHumanTriggerParams<A extends readonly TaskAction[]> = AskHumanTriggerOptions & {
|
|
28
|
-
task: Omit<TaskContextInput, "actions"> & {
|
|
29
|
-
readonly actions: A;
|
|
30
|
-
};
|
|
31
|
-
client?: RobotRock;
|
|
32
|
-
apiKey?: string;
|
|
33
|
-
baseUrl?: string;
|
|
34
|
-
};
|
|
35
|
-
declare function createTriggerClient(config: RobotRockConfig): RobotRock;
|
|
18
|
+
handledBy?: string | undefined;
|
|
19
|
+
handledAt: Date;
|
|
20
|
+
actionId: string;
|
|
21
|
+
data: unknown;
|
|
22
|
+
}>;
|
|
36
23
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* Return type is inferred from `task.actions` (`actionId` narrows `data`).
|
|
40
|
-
* Must run inside `task({ run })` with `@trigger.dev/sdk` installed.
|
|
24
|
+
* Simple approve/decline human gate for Trigger.dev.
|
|
25
|
+
* Re-export from your `trigger/` directory so Trigger.dev discovers it on deploy.
|
|
41
26
|
*/
|
|
42
|
-
declare
|
|
27
|
+
declare const approveByHumanTask: _trigger_dev_sdk.Task<"robotrock/approve-by-human", ApproveByHumanPayload, {
|
|
28
|
+
taskId: string;
|
|
29
|
+
handledBy?: string | undefined;
|
|
30
|
+
handledAt: Date;
|
|
31
|
+
actionId: "approve";
|
|
32
|
+
data: unknown;
|
|
33
|
+
} | {
|
|
34
|
+
taskId: string;
|
|
35
|
+
handledBy?: string | undefined;
|
|
36
|
+
handledAt: Date;
|
|
37
|
+
actionId: "decline";
|
|
38
|
+
data: unknown;
|
|
39
|
+
}>;
|
|
43
40
|
|
|
44
|
-
export { type
|
|
41
|
+
export { type ApproveByHumanPayload, type SendToHumanPayload, approveByHumanTask, sendToHumanTask };
|
package/dist/trigger/index.js
CHANGED
|
@@ -1,56 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRobotRockHandlerWebhookPayload,
|
|
3
|
+
resolveWaitTiming
|
|
4
|
+
} from "../chunk-D2FBSEZK.js";
|
|
1
5
|
import {
|
|
2
6
|
createClient,
|
|
3
|
-
|
|
7
|
+
resolveRobotRockConfig,
|
|
4
8
|
toDiscriminatedApprovalResult
|
|
5
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-THVGHUTX.js";
|
|
10
|
+
import "../chunk-7FVE6OYZ.js";
|
|
6
11
|
|
|
7
12
|
// src/trigger/index.ts
|
|
8
|
-
import { wait } from "@trigger.dev/sdk
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
timeout = "24h",
|
|
17
|
-
callbackUrl,
|
|
18
|
-
client: explicitClient,
|
|
19
|
-
apiKey,
|
|
20
|
-
baseUrl
|
|
21
|
-
} = params;
|
|
22
|
-
assertTriggerTimeoutFormat(timeout);
|
|
23
|
-
const client = resolveRobotRockClient(explicitClient, { apiKey, baseUrl });
|
|
13
|
+
import { task, wait } from "@trigger.dev/sdk";
|
|
14
|
+
var APPROVE_BY_HUMAN_ACTIONS = [
|
|
15
|
+
{ id: "approve", title: "Approve" },
|
|
16
|
+
{ id: "decline", title: "Decline" }
|
|
17
|
+
];
|
|
18
|
+
async function runSendToHuman(payload) {
|
|
19
|
+
const { validUntil: validUntilInput, ...taskInput } = payload;
|
|
20
|
+
const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
|
|
24
21
|
const token = await wait.createToken({ timeout });
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
type: "trigger",
|
|
39
|
-
url: callbackUrl,
|
|
40
|
-
headers: {},
|
|
41
|
-
tokenId: crypto.randomUUID()
|
|
42
|
-
}
|
|
43
|
-
] : [];
|
|
44
|
-
return {
|
|
45
|
-
...action,
|
|
46
|
-
handlers: [waitHandler, ...action.handlers ?? [], ...callbackHandlers]
|
|
47
|
-
};
|
|
48
|
-
})
|
|
49
|
-
};
|
|
50
|
-
await client.createTask(taskWithHandlers);
|
|
22
|
+
const baseConfig = resolveRobotRockConfig();
|
|
23
|
+
const client = createClient({
|
|
24
|
+
apiKey: baseConfig.apiKey,
|
|
25
|
+
baseUrl: baseConfig.baseUrl,
|
|
26
|
+
...baseConfig.app ? { app: baseConfig.app } : {},
|
|
27
|
+
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
28
|
+
webhook: { url: token.url }
|
|
29
|
+
});
|
|
30
|
+
const sendResult = await client.sendToHuman({
|
|
31
|
+
...taskInput,
|
|
32
|
+
validUntil
|
|
33
|
+
});
|
|
51
34
|
const outcome = await wait.forToken(token.id);
|
|
52
35
|
if (!outcome.ok) {
|
|
53
|
-
throw new Error(`Human response
|
|
36
|
+
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
54
37
|
}
|
|
55
38
|
const output = outcome.output;
|
|
56
39
|
if (!isRobotRockHandlerWebhookPayload(output)) {
|
|
@@ -59,12 +42,12 @@ async function askHuman(params) {
|
|
|
59
42
|
);
|
|
60
43
|
}
|
|
61
44
|
return toDiscriminatedApprovalResult(
|
|
62
|
-
|
|
45
|
+
payload.actions,
|
|
63
46
|
{
|
|
64
47
|
id: output.taskId,
|
|
65
48
|
createdAt: /* @__PURE__ */ new Date(),
|
|
66
49
|
status: "handled",
|
|
67
|
-
context:
|
|
50
|
+
context: sendResult.task.context,
|
|
68
51
|
validUntil: Date.now(),
|
|
69
52
|
handledAt: new Date(output.handledAt).getTime(),
|
|
70
53
|
handled: {
|
|
@@ -74,33 +57,22 @@ async function askHuman(params) {
|
|
|
74
57
|
},
|
|
75
58
|
handledBy: output.handledBy
|
|
76
59
|
}
|
|
77
|
-
}
|
|
78
|
-
output.taskId
|
|
60
|
+
}
|
|
79
61
|
);
|
|
80
62
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (typeof v.taskId !== "string" || typeof v.handledAt !== "string") {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
const action = v.action;
|
|
96
|
-
if (typeof action !== "object" || action === null) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
const a = action;
|
|
100
|
-
return typeof a.id === "string" && "data" in a;
|
|
101
|
-
}
|
|
63
|
+
var sendToHumanTask = task({
|
|
64
|
+
id: "robotrock/send-to-human",
|
|
65
|
+
run: async (payload) => runSendToHuman(payload)
|
|
66
|
+
});
|
|
67
|
+
var approveByHumanTask = task({
|
|
68
|
+
id: "robotrock/approve-by-human",
|
|
69
|
+
run: async (payload) => runSendToHuman({
|
|
70
|
+
...payload,
|
|
71
|
+
actions: APPROVE_BY_HUMAN_ACTIONS
|
|
72
|
+
})
|
|
73
|
+
});
|
|
102
74
|
export {
|
|
103
|
-
|
|
104
|
-
|
|
75
|
+
approveByHumanTask,
|
|
76
|
+
sendToHumanTask
|
|
105
77
|
};
|
|
106
78
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/trigger/index.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../src/trigger/index.ts"],"sourcesContent":["import type { DiscriminatedApprovalResult } from \"../schemas/index.js\";\nimport { task, wait } from \"@trigger.dev/sdk\";\nimport {\n createClient,\n type SendToHumanActionInput,\n type SendToHumanInput,\n} from \"../client.js\";\nimport { resolveRobotRockConfig } from \"../env.js\";\nimport { toDiscriminatedApprovalResult } from \"../approval-result.js\";\nimport {\n isRobotRockHandlerWebhookPayload,\n type RobotRockHandlerWebhookPayload,\n} from \"../handler-webhook.js\";\nimport { resolveWaitTiming } from \"../wait-timing.js\";\n\nexport type { RobotRockHandlerWebhookPayload } from \"../handler-webhook.js\";\n\nexport type SendToHumanPayload<\n A extends readonly SendToHumanActionInput[] = readonly SendToHumanActionInput[],\n> = SendToHumanInput<A> & {\n /** Inbox app bucket. Overrides `ROBOTROCK_APP` when set. */\n app?: string;\n};\n\nexport type ApproveByHumanPayload = Omit<SendToHumanPayload, \"actions\">;\n\ntype Expand<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;\n\nconst APPROVE_BY_HUMAN_ACTIONS = [\n { id: \"approve\", title: \"Approve\" },\n { id: \"decline\", title: \"Decline\" },\n] as const;\n\nasync function runSendToHuman<const A extends readonly SendToHumanActionInput[]>(\n payload: SendToHumanPayload<A>\n): Promise<Expand<DiscriminatedApprovalResult<A>>> {\n const { validUntil: validUntilInput, ...taskInput } = payload;\n const { validUntil, timeout } = resolveWaitTiming(validUntilInput);\n\n const token = await wait.createToken({ timeout });\n\n const baseConfig = resolveRobotRockConfig();\n const client = createClient({\n apiKey: baseConfig.apiKey,\n baseUrl: baseConfig.baseUrl,\n ...(baseConfig.app ? { app: baseConfig.app } : {}),\n ...(baseConfig.version ? { version: baseConfig.version } : {}),\n webhook: { url: token.url },\n });\n\n const sendResult = await client.sendToHuman({\n ...taskInput,\n validUntil,\n });\n\n const outcome = await wait.forToken<RobotRockHandlerWebhookPayload>(token.id);\n\n if (!outcome.ok) {\n throw new Error(`Human response timed out before validUntil (${timeout})`);\n }\n\n const output = outcome.output;\n if (!isRobotRockHandlerWebhookPayload(output)) {\n throw new Error(\n \"Wait token completed with unexpected payload; expected RobotRock handler body (taskId, action.id, action.data).\"\n );\n }\n\n return toDiscriminatedApprovalResult(\n payload.actions,\n {\n id: output.taskId,\n createdAt: new Date(),\n status: \"handled\",\n context: sendResult.task.context,\n validUntil: Date.now(),\n handledAt: new Date(output.handledAt).getTime(),\n handled: {\n action: {\n id: output.action.id,\n data: output.action.data,\n },\n handledBy: output.handledBy,\n },\n }\n ) as unknown as Expand<DiscriminatedApprovalResult<A>>;\n}\n\n/**\n * Durable human-in-the-loop task for Trigger.dev.\n * Re-export from your `trigger/` directory so Trigger.dev discovers it on deploy.\n */\nexport const sendToHumanTask = task({\n id: \"robotrock/send-to-human\",\n run: async (payload: SendToHumanPayload) => runSendToHuman(payload),\n});\n\n/**\n * Simple approve/decline human gate for Trigger.dev.\n * Re-export from your `trigger/` directory so Trigger.dev discovers it on deploy.\n */\nexport const approveByHumanTask = task({\n id: \"robotrock/approve-by-human\",\n run: async (payload: ApproveByHumanPayload) =>\n runSendToHuman({\n ...payload,\n actions: APPROVE_BY_HUMAN_ACTIONS,\n }),\n});\n\nexport type {\n ApprovalResult,\n DiscriminatedApprovalResult,\n TaskContextInput,\n TaskResult,\n} from \"../schemas/index.js\";\n"],"mappings":";;;;;;;;;;;;AACA,SAAS,MAAM,YAAY;AA2B3B,IAAM,2BAA2B;AAAA,EAC/B,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,EAClC,EAAE,IAAI,WAAW,OAAO,UAAU;AACpC;AAEA,eAAe,eACb,SACiD;AACjD,QAAM,EAAE,YAAY,iBAAiB,GAAG,UAAU,IAAI;AACtD,QAAM,EAAE,YAAY,QAAQ,IAAI,kBAAkB,eAAe;AAEjE,QAAM,QAAQ,MAAM,KAAK,YAAY,EAAE,QAAQ,CAAC;AAEhD,QAAM,aAAa,uBAAuB;AAC1C,QAAM,SAAS,aAAa;AAAA,IAC1B,QAAQ,WAAW;AAAA,IACnB,SAAS,WAAW;AAAA,IACpB,GAAI,WAAW,MAAM,EAAE,KAAK,WAAW,IAAI,IAAI,CAAC;AAAA,IAChD,GAAI,WAAW,UAAU,EAAE,SAAS,WAAW,QAAQ,IAAI,CAAC;AAAA,IAC5D,SAAS,EAAE,KAAK,MAAM,IAAI;AAAA,EAC5B,CAAC;AAED,QAAM,aAAa,MAAM,OAAO,YAAY;AAAA,IAC1C,GAAG;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,UAAU,MAAM,KAAK,SAAyC,MAAM,EAAE;AAE5E,MAAI,CAAC,QAAQ,IAAI;AACf,UAAM,IAAI,MAAM,+CAA+C,OAAO,GAAG;AAAA,EAC3E;AAEA,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,iCAAiC,MAAM,GAAG;AAC7C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,MACE,IAAI,OAAO;AAAA,MACX,WAAW,oBAAI,KAAK;AAAA,MACpB,QAAQ;AAAA,MACR,SAAS,WAAW,KAAK;AAAA,MACzB,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,IAAI,KAAK,OAAO,SAAS,EAAE,QAAQ;AAAA,MAC9C,SAAS;AAAA,QACP,QAAQ;AAAA,UACN,IAAI,OAAO,OAAO;AAAA,UAClB,MAAM,OAAO,OAAO;AAAA,QACtB;AAAA,QACA,WAAW,OAAO;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,kBAAkB,KAAK;AAAA,EAClC,IAAI;AAAA,EACJ,KAAK,OAAO,YAAgC,eAAe,OAAO;AACpE,CAAC;AAMM,IAAM,qBAAqB,KAAK;AAAA,EACrC,IAAI;AAAA,EACJ,KAAK,OAAO,YACV,eAAe;AAAA,IACb,GAAG;AAAA,IACH,SAAS;AAAA,EACX,CAAC;AACL,CAAC;","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DiscriminatedApprovalResult } from '../schemas/index.js';
|
|
2
|
+
export { ApprovalResult, TaskContextInput, TaskResult } from '../schemas/index.js';
|
|
3
|
+
import { S as SendToHumanActionInput, a as SendToHumanInput } from '../client-agOgTJob.js';
|
|
4
|
+
export { R as RobotRockHandlerWebhookPayload } from '../handler-webhook-BqEi6Bk-.js';
|
|
5
|
+
import 'zod';
|
|
6
|
+
|
|
7
|
+
type SendToHumanWorkflowPayload<A extends readonly SendToHumanActionInput[] = readonly SendToHumanActionInput[]> = SendToHumanInput<A> & {
|
|
8
|
+
/** Inbox app bucket. Overrides `ROBOTROCK_APP` when set. */
|
|
9
|
+
app?: string;
|
|
10
|
+
};
|
|
11
|
+
type ApproveByHumanWorkflowPayload = Omit<SendToHumanWorkflowPayload, "actions">;
|
|
12
|
+
type Expand<T> = T extends unknown ? {
|
|
13
|
+
[K in keyof T]: T[K];
|
|
14
|
+
} : never;
|
|
15
|
+
declare const APPROVE_BY_HUMAN_ACTIONS: readonly [{
|
|
16
|
+
readonly id: "approve";
|
|
17
|
+
readonly title: "Approve";
|
|
18
|
+
}, {
|
|
19
|
+
readonly id: "decline";
|
|
20
|
+
readonly title: "Decline";
|
|
21
|
+
}];
|
|
22
|
+
/**
|
|
23
|
+
* Durable human-in-the-loop wait for Vercel Workflow.
|
|
24
|
+
*
|
|
25
|
+
* Call from a function with `"use workflow"` as its first statement. Creates a
|
|
26
|
+
* {@link createWebhook} URL, registers it as the RobotRock task webhook, and
|
|
27
|
+
* suspends until a human handles an action or `validUntil` passes.
|
|
28
|
+
*/
|
|
29
|
+
declare function sendToHumanInWorkflow<const A extends readonly SendToHumanActionInput[]>(payload: SendToHumanWorkflowPayload<A>): Promise<Expand<DiscriminatedApprovalResult<A>>>;
|
|
30
|
+
/**
|
|
31
|
+
* Approve / decline gate for Vercel Workflow (`sendToHumanInWorkflow` with fixed actions).
|
|
32
|
+
*/
|
|
33
|
+
declare function approveByHumanInWorkflow(payload: ApproveByHumanWorkflowPayload): Promise<Expand<DiscriminatedApprovalResult<typeof APPROVE_BY_HUMAN_ACTIONS>>>;
|
|
34
|
+
|
|
35
|
+
export { type ApproveByHumanWorkflowPayload, DiscriminatedApprovalResult, type SendToHumanWorkflowPayload, approveByHumanInWorkflow, sendToHumanInWorkflow };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRobotRockHandlerWebhookPayload,
|
|
3
|
+
parseValidUntilMs,
|
|
4
|
+
resolveWaitTiming
|
|
5
|
+
} from "../chunk-D2FBSEZK.js";
|
|
6
|
+
import {
|
|
7
|
+
createClient,
|
|
8
|
+
resolveRobotRockConfig,
|
|
9
|
+
toDiscriminatedApprovalResult
|
|
10
|
+
} from "../chunk-THVGHUTX.js";
|
|
11
|
+
import {
|
|
12
|
+
__callDispose,
|
|
13
|
+
__using
|
|
14
|
+
} from "../chunk-7FVE6OYZ.js";
|
|
15
|
+
|
|
16
|
+
// src/workflow/index.ts
|
|
17
|
+
import { createWebhook, sleep } from "workflow";
|
|
18
|
+
var APPROVE_BY_HUMAN_ACTIONS = [
|
|
19
|
+
{ id: "approve", title: "Approve" },
|
|
20
|
+
{ id: "decline", title: "Decline" }
|
|
21
|
+
];
|
|
22
|
+
async function createRobotRockTaskForWebhook(input) {
|
|
23
|
+
"use step";
|
|
24
|
+
const baseConfig = resolveRobotRockConfig();
|
|
25
|
+
const client = createClient({
|
|
26
|
+
apiKey: baseConfig.apiKey,
|
|
27
|
+
baseUrl: baseConfig.baseUrl,
|
|
28
|
+
...input.app ?? baseConfig.app ? { app: input.app ?? baseConfig.app } : {},
|
|
29
|
+
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
30
|
+
webhook: { url: input.webhookUrl }
|
|
31
|
+
});
|
|
32
|
+
return client.sendToHuman({
|
|
33
|
+
...input.taskInput,
|
|
34
|
+
validUntil: input.validUntil
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function parseRobotRockWebhookRequest(request) {
|
|
38
|
+
"use step";
|
|
39
|
+
const body = await request.json();
|
|
40
|
+
if (!isRobotRockHandlerWebhookPayload(body)) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"Workflow webhook completed with unexpected payload; expected RobotRock handler body (taskId, action.id, action.data)."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return body;
|
|
46
|
+
}
|
|
47
|
+
async function sendToHumanInWorkflow(payload) {
|
|
48
|
+
var _stack = [];
|
|
49
|
+
try {
|
|
50
|
+
const { validUntil: validUntilInput, app, ...taskInput } = payload;
|
|
51
|
+
const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
|
|
52
|
+
const timeoutMs = parseValidUntilMs(validUntil) - Date.now();
|
|
53
|
+
const webhook = __using(_stack, createWebhook());
|
|
54
|
+
const sendResult = await createRobotRockTaskForWebhook({
|
|
55
|
+
webhookUrl: webhook.url,
|
|
56
|
+
app,
|
|
57
|
+
validUntil,
|
|
58
|
+
taskInput
|
|
59
|
+
});
|
|
60
|
+
const outcome = await Promise.race([
|
|
61
|
+
webhook.then((request) => parseRobotRockWebhookRequest(request)),
|
|
62
|
+
sleep(timeoutMs).then(() => ({ timedOut: true }))
|
|
63
|
+
]);
|
|
64
|
+
if ("timedOut" in outcome) {
|
|
65
|
+
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
66
|
+
}
|
|
67
|
+
const output = outcome;
|
|
68
|
+
return toDiscriminatedApprovalResult(payload.actions, {
|
|
69
|
+
id: output.taskId,
|
|
70
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
71
|
+
status: "handled",
|
|
72
|
+
context: sendResult.task.context,
|
|
73
|
+
validUntil: Date.now(),
|
|
74
|
+
handledAt: new Date(output.handledAt).getTime(),
|
|
75
|
+
handled: {
|
|
76
|
+
action: {
|
|
77
|
+
id: output.action.id,
|
|
78
|
+
data: output.action.data
|
|
79
|
+
},
|
|
80
|
+
handledBy: output.handledBy
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
} catch (_) {
|
|
84
|
+
var _error = _, _hasError = true;
|
|
85
|
+
} finally {
|
|
86
|
+
__callDispose(_stack, _error, _hasError);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function approveByHumanInWorkflow(payload) {
|
|
90
|
+
return sendToHumanInWorkflow({
|
|
91
|
+
...payload,
|
|
92
|
+
actions: APPROVE_BY_HUMAN_ACTIONS
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
approveByHumanInWorkflow,
|
|
97
|
+
sendToHumanInWorkflow
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workflow/index.ts"],"sourcesContent":["import { createWebhook, sleep } from \"workflow\";\nimport type { DiscriminatedApprovalResult } from \"../schemas/index.js\";\nimport {\n createClient,\n type SendToHumanActionInput,\n type SendToHumanInput,\n} from \"../client.js\";\nimport { resolveRobotRockConfig } from \"../env.js\";\nimport { toDiscriminatedApprovalResult } from \"../approval-result.js\";\nimport {\n isRobotRockHandlerWebhookPayload,\n type RobotRockHandlerWebhookPayload,\n} from \"../handler-webhook.js\";\nimport { parseValidUntilMs, resolveWaitTiming } from \"../wait-timing.js\";\n\nexport type SendToHumanWorkflowPayload<\n A extends readonly SendToHumanActionInput[] = readonly SendToHumanActionInput[],\n> = SendToHumanInput<A> & {\n /** Inbox app bucket. Overrides `ROBOTROCK_APP` when set. */\n app?: string;\n};\n\nexport type ApproveByHumanWorkflowPayload = Omit<SendToHumanWorkflowPayload, \"actions\">;\n\ntype Expand<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;\n\nconst APPROVE_BY_HUMAN_ACTIONS = [\n { id: \"approve\", title: \"Approve\" },\n { id: \"decline\", title: \"Decline\" },\n] as const;\n\ntype CreateTaskStepInput = {\n webhookUrl: string;\n app?: string;\n validUntil: Date | string;\n taskInput: Omit<SendToHumanWorkflowPayload, \"validUntil\" | \"app\">;\n};\n\n/**\n * Creates the RobotRock inbox task with the workflow webhook URL as the handler.\n * Marked as a step so API calls run in full Node.js with retries.\n */\nasync function createRobotRockTaskForWebhook(input: CreateTaskStepInput) {\n \"use step\";\n\n const baseConfig = resolveRobotRockConfig();\n const client = createClient({\n apiKey: baseConfig.apiKey,\n baseUrl: baseConfig.baseUrl,\n ...((input.app ?? baseConfig.app) ? { app: input.app ?? baseConfig.app } : {}),\n ...(baseConfig.version ? { version: baseConfig.version } : {}),\n webhook: { url: input.webhookUrl },\n });\n\n return client.sendToHuman({\n ...input.taskInput,\n validUntil: input.validUntil,\n });\n}\n\nasync function parseRobotRockWebhookRequest(request: Request) {\n \"use step\";\n\n const body: unknown = await request.json();\n if (!isRobotRockHandlerWebhookPayload(body)) {\n throw new Error(\n \"Workflow webhook completed with unexpected payload; expected RobotRock handler body (taskId, action.id, action.data).\"\n );\n }\n\n return body;\n}\n\n/**\n * Durable human-in-the-loop wait for Vercel Workflow.\n *\n * Call from a function with `\"use workflow\"` as its first statement. Creates a\n * {@link createWebhook} URL, registers it as the RobotRock task webhook, and\n * suspends until a human handles an action or `validUntil` passes.\n */\nexport async function sendToHumanInWorkflow<\n const A extends readonly SendToHumanActionInput[],\n>(\n payload: SendToHumanWorkflowPayload<A>\n): Promise<Expand<DiscriminatedApprovalResult<A>>> {\n const { validUntil: validUntilInput, app, ...taskInput } = payload;\n const { validUntil, timeout } = resolveWaitTiming(validUntilInput);\n const timeoutMs = parseValidUntilMs(validUntil) - Date.now();\n\n using webhook = createWebhook();\n\n const sendResult = await createRobotRockTaskForWebhook({\n webhookUrl: webhook.url,\n app,\n validUntil,\n taskInput,\n });\n\n const outcome = await Promise.race([\n webhook.then((request) => parseRobotRockWebhookRequest(request)),\n sleep(timeoutMs).then(() => ({ timedOut: true }) as const),\n ]);\n\n if (\"timedOut\" in outcome) {\n throw new Error(`Human response timed out before validUntil (${timeout})`);\n }\n\n const output: RobotRockHandlerWebhookPayload = outcome;\n\n return toDiscriminatedApprovalResult(payload.actions, {\n id: output.taskId,\n createdAt: new Date(),\n status: \"handled\",\n context: sendResult.task.context,\n validUntil: Date.now(),\n handledAt: new Date(output.handledAt).getTime(),\n handled: {\n action: {\n id: output.action.id,\n data: output.action.data,\n },\n handledBy: output.handledBy,\n },\n }) as unknown as Expand<DiscriminatedApprovalResult<A>>;\n}\n\n/**\n * Approve / decline gate for Vercel Workflow (`sendToHumanInWorkflow` with fixed actions).\n */\nexport async function approveByHumanInWorkflow(\n payload: ApproveByHumanWorkflowPayload\n): Promise<Expand<DiscriminatedApprovalResult<typeof APPROVE_BY_HUMAN_ACTIONS>>> {\n return sendToHumanInWorkflow({\n ...payload,\n actions: APPROVE_BY_HUMAN_ACTIONS,\n });\n}\n\nexport type { RobotRockHandlerWebhookPayload } from \"../handler-webhook.js\";\nexport type {\n ApprovalResult,\n DiscriminatedApprovalResult,\n TaskContextInput,\n TaskResult,\n} from \"../schemas/index.js\";\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,eAAe,aAAa;AA0BrC,IAAM,2BAA2B;AAAA,EAC/B,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,EAClC,EAAE,IAAI,WAAW,OAAO,UAAU;AACpC;AAaA,eAAe,8BAA8B,OAA4B;AACvE;AAEA,QAAM,aAAa,uBAAuB;AAC1C,QAAM,SAAS,aAAa;AAAA,IAC1B,QAAQ,WAAW;AAAA,IACnB,SAAS,WAAW;AAAA,IACpB,GAAK,MAAM,OAAO,WAAW,MAAO,EAAE,KAAK,MAAM,OAAO,WAAW,IAAI,IAAI,CAAC;AAAA,IAC5E,GAAI,WAAW,UAAU,EAAE,SAAS,WAAW,QAAQ,IAAI,CAAC;AAAA,IAC5D,SAAS,EAAE,KAAK,MAAM,WAAW;AAAA,EACnC,CAAC;AAED,SAAO,OAAO,YAAY;AAAA,IACxB,GAAG,MAAM;AAAA,IACT,YAAY,MAAM;AAAA,EACpB,CAAC;AACH;AAEA,eAAe,6BAA6B,SAAkB;AAC5D;AAEA,QAAM,OAAgB,MAAM,QAAQ,KAAK;AACzC,MAAI,CAAC,iCAAiC,IAAI,GAAG;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AASA,eAAsB,sBAGpB,SACiD;AAKjD;AAAA;AAJA,UAAM,EAAE,YAAY,iBAAiB,KAAK,GAAG,UAAU,IAAI;AAC3D,UAAM,EAAE,YAAY,QAAQ,IAAI,kBAAkB,eAAe;AACjE,UAAM,YAAY,kBAAkB,UAAU,IAAI,KAAK,IAAI;AAE3D,UAAM,UAAU,8BAAc;AAE9B,UAAM,aAAa,MAAM,8BAA8B;AAAA,MACrD,YAAY,QAAQ;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,UAAU,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,KAAK,CAAC,YAAY,6BAA6B,OAAO,CAAC;AAAA,MAC/D,MAAM,SAAS,EAAE,KAAK,OAAO,EAAE,UAAU,KAAK,EAAW;AAAA,IAC3D,CAAC;AAED,QAAI,cAAc,SAAS;AACzB,YAAM,IAAI,MAAM,+CAA+C,OAAO,GAAG;AAAA,IAC3E;AAEA,UAAM,SAAyC;AAE/C,WAAO,8BAA8B,QAAQ,SAAS;AAAA,MACpD,IAAI,OAAO;AAAA,MACX,WAAW,oBAAI,KAAK;AAAA,MACpB,QAAQ;AAAA,MACR,SAAS,WAAW,KAAK;AAAA,MACzB,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,IAAI,KAAK,OAAO,SAAS,EAAE,QAAQ;AAAA,MAC9C,SAAS;AAAA,QACP,QAAQ;AAAA,UACN,IAAI,OAAO,OAAO;AAAA,UAClB,MAAM,OAAO,OAAO;AAAA,QACtB;AAAA,QACA,WAAW,OAAO;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,WAlCD;AAAA;AAAA;AAAA;AAAA;AAmCF;AAKA,eAAsB,yBACpB,SAC+E;AAC/E,SAAO,sBAAsB;AAAA,IAC3B,GAAG;AAAA,IACH,SAAS;AAAA,EACX,CAAC;AACH;","names":[]}
|