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.
@@ -1,44 +1,41 @@
1
- import { TaskAction, TaskContextInput, DiscriminatedApprovalResult } from '@robotrock/core';
2
- export { ApprovalResult, DiscriminatedApprovalResult, TaskContextInput, TaskResult } from '@robotrock/core';
3
- import { a as RobotRock, R as RobotRockConfig } from '../client-BQ-j7q68.js';
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
- * JSON body posted by Convex when an action handler runs.
7
- * POSTing this to Trigger's `token.url` completes `wait.forToken`.
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
- interface RobotRockHandlerWebhookPayload {
16
+ declare const sendToHumanTask: _trigger_dev_sdk.Task<"robotrock/send-to-human", SendToHumanPayload<readonly SendToHumanActionInput[]>, {
10
17
  taskId: string;
11
- action: {
12
- id: string;
13
- title: string;
14
- data: unknown;
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
- * Ask a human inside a Trigger.dev task run (waitpoint token + RobotRock handlers).
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 function askHuman<const A extends readonly TaskAction[]>(params: AskHumanTriggerParams<A>): Promise<DiscriminatedApprovalResult<A>>;
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 AskHumanTriggerOptions, type AskHumanTriggerParams, RobotRockConfig, type RobotRockHandlerWebhookPayload, askHuman, createTriggerClient };
41
+ export { type ApproveByHumanPayload, type SendToHumanPayload, approveByHumanTask, sendToHumanTask };
@@ -1,56 +1,39 @@
1
+ import {
2
+ isRobotRockHandlerWebhookPayload,
3
+ resolveWaitTiming
4
+ } from "../chunk-D2FBSEZK.js";
1
5
  import {
2
6
  createClient,
3
- resolveRobotRockClient,
7
+ resolveRobotRockConfig,
4
8
  toDiscriminatedApprovalResult
5
- } from "../chunk-TUQXDKV6.js";
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/v3";
9
- function createTriggerClient(config) {
10
- return createClient(config);
11
- }
12
- async function askHuman(params) {
13
- const {
14
- task,
15
- app,
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 resolvedApp = app ?? task.app;
26
- const taskWithHandlers = {
27
- ...task,
28
- ...resolvedApp !== void 0 ? { app: resolvedApp } : {},
29
- actions: task.actions.map((action) => {
30
- const waitHandler = {
31
- type: "trigger",
32
- url: token.url,
33
- headers: {},
34
- tokenId: token.id
35
- };
36
- const callbackHandlers = callbackUrl ? [
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 timeout after ${timeout}`);
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
- task.actions,
45
+ payload.actions,
63
46
  {
64
47
  id: output.taskId,
65
48
  createdAt: /* @__PURE__ */ new Date(),
66
49
  status: "handled",
67
- context: taskWithHandlers,
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
- function assertTriggerTimeoutFormat(timeout) {
82
- const match = timeout.match(/^(\d+)(s|m|h|d)$/);
83
- if (!match) {
84
- throw new Error(`Invalid timeout format: ${timeout}. Use format like "1h", "30m", "7d"`);
85
- }
86
- }
87
- function isRobotRockHandlerWebhookPayload(value) {
88
- if (typeof value !== "object" || value === null) {
89
- return false;
90
- }
91
- const v = value;
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
- askHuman,
104
- createTriggerClient
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 {\n DiscriminatedApprovalResult,\n TaskAction,\n TaskContextInput,\n} from \"@robotrock/core\";\nimport { wait } from \"@trigger.dev/sdk/v3\";\nimport { createClient, type RobotRock, type RobotRockConfig } from \"../client.js\";\nimport { resolveRobotRockClient } from \"../env.js\";\nimport { toDiscriminatedApprovalResult } from \"../approval-result.js\";\n\n/**\n * JSON body posted by Convex when an action handler runs.\n * POSTing this to Trigger's `token.url` completes `wait.forToken`.\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 interface AskHumanTriggerOptions {\n app?: string;\n /** Trigger waitpoint timeout (e.g. \"1h\", \"30m\", \"7d\"). @default \"24h\" */\n timeout?: string;\n /** Optional side-channel webhook URL (same payload as the wait token). */\n callbackUrl?: string;\n}\n\nexport type AskHumanTriggerParams<A extends readonly TaskAction[]> = AskHumanTriggerOptions & {\n task: Omit<TaskContextInput, \"actions\"> & { readonly actions: A };\n client?: RobotRock;\n apiKey?: string;\n baseUrl?: string;\n};\n\nexport function createTriggerClient(config: RobotRockConfig): RobotRock {\n return createClient(config);\n}\n\n/**\n * Ask a human inside a Trigger.dev task run (waitpoint token + RobotRock handlers).\n *\n * Return type is inferred from `task.actions` (`actionId` narrows `data`).\n * Must run inside `task({ run })` with `@trigger.dev/sdk` installed.\n */\nexport async function askHuman<const A extends readonly TaskAction[]>(\n params: AskHumanTriggerParams<A>\n): Promise<DiscriminatedApprovalResult<A>> {\n const {\n task,\n app,\n timeout = \"24h\",\n callbackUrl,\n client: explicitClient,\n apiKey,\n baseUrl,\n } = params;\n\n assertTriggerTimeoutFormat(timeout);\n\n const client = resolveRobotRockClient(explicitClient, { apiKey, baseUrl });\n\n const token = await wait.createToken({ timeout });\n\n const resolvedApp = app ?? task.app;\n const taskWithHandlers: TaskContextInput = {\n ...task,\n ...(resolvedApp !== undefined ? { app: resolvedApp } : {}),\n actions: task.actions.map((action: TaskAction) => {\n const waitHandler = {\n type: \"trigger\" as const,\n url: token.url,\n headers: {} as Record<string, string>,\n tokenId: token.id,\n };\n const callbackHandlers = callbackUrl\n ? [\n {\n type: \"trigger\" as const,\n url: callbackUrl,\n headers: {} as Record<string, string>,\n tokenId: crypto.randomUUID(),\n },\n ]\n : [];\n\n return {\n ...action,\n handlers: [waitHandler, ...(action.handlers ?? []), ...callbackHandlers],\n };\n }),\n };\n\n await client.createTask(taskWithHandlers);\n\n const outcome = await wait.forToken<RobotRockHandlerWebhookPayload>(token.id);\n\n if (!outcome.ok) {\n throw new Error(`Human response timeout after ${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 task.actions,\n {\n id: output.taskId,\n createdAt: new Date(),\n status: \"handled\",\n context: taskWithHandlers,\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 output.taskId\n );\n}\n\nfunction assertTriggerTimeoutFormat(timeout: string): void {\n const match = timeout.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) {\n throw new Error(`Invalid timeout format: ${timeout}. Use format like \"1h\", \"30m\", \"7d\"`);\n }\n}\n\nfunction 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\nexport type {\n ApprovalResult,\n DiscriminatedApprovalResult,\n TaskContextInput,\n TaskResult,\n} from \"@robotrock/core\";\nexport type { RobotRockConfig } from \"../client.js\";\n"],"mappings":";;;;;;;AAKA,SAAS,YAAY;AAoCd,SAAS,oBAAoB,QAAoC;AACtE,SAAO,aAAa,MAAM;AAC5B;AAQA,eAAsB,SACpB,QACyC;AACzC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,6BAA2B,OAAO;AAElC,QAAM,SAAS,uBAAuB,gBAAgB,EAAE,QAAQ,QAAQ,CAAC;AAEzE,QAAM,QAAQ,MAAM,KAAK,YAAY,EAAE,QAAQ,CAAC;AAEhD,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,mBAAqC;AAAA,IACzC,GAAG;AAAA,IACH,GAAI,gBAAgB,SAAY,EAAE,KAAK,YAAY,IAAI,CAAC;AAAA,IACxD,SAAS,KAAK,QAAQ,IAAI,CAAC,WAAuB;AAChD,YAAM,cAAc;AAAA,QAClB,MAAM;AAAA,QACN,KAAK,MAAM;AAAA,QACX,SAAS,CAAC;AAAA,QACV,SAAS,MAAM;AAAA,MACjB;AACA,YAAM,mBAAmB,cACrB;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,KAAK;AAAA,UACL,SAAS,CAAC;AAAA,UACV,SAAS,OAAO,WAAW;AAAA,QAC7B;AAAA,MACF,IACA,CAAC;AAEL,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,CAAC,aAAa,GAAI,OAAO,YAAY,CAAC,GAAI,GAAG,gBAAgB;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,WAAW,gBAAgB;AAExC,QAAM,UAAU,MAAM,KAAK,SAAyC,MAAM,EAAE;AAE5E,MAAI,CAAC,QAAQ,IAAI;AACf,UAAM,IAAI,MAAM,gCAAgC,OAAO,EAAE;AAAA,EAC3D;AAEA,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,iCAAiC,MAAM,GAAG;AAC7C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL;AAAA,MACE,IAAI,OAAO;AAAA,MACX,WAAW,oBAAI,KAAK;AAAA,MACpB,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,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,IACA,OAAO;AAAA,EACT;AACF;AAEA,SAAS,2BAA2B,SAAuB;AACzD,QAAM,QAAQ,QAAQ,MAAM,kBAAkB;AAC9C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,2BAA2B,OAAO,qCAAqC;AAAA,EACzF;AACF;AAEA,SAAS,iCACP,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;","names":[]}
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":[]}