@repogo/plugins 0.1.42 → 0.1.44

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/dist/testing.js CHANGED
@@ -91,6 +91,7 @@ function carryable(value) {
91
91
 
92
92
  // src/runtime.ts
93
93
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
94
+ import { existsSync } from "fs";
94
95
  import { mkdir as mkdir3, readdir as readdir3 } from "fs/promises";
95
96
  import { join as join3 } from "path";
96
97
  import { z as z5 } from "zod";
@@ -155,7 +156,7 @@ function recordRead(tag) {
155
156
  }
156
157
  function assertWritable(tag) {
157
158
  if (current.getStore()?.readOnly) {
158
- throw new MethodError("FORBIDDEN", `A query can't change data (it tried to write ${tag}).`);
159
+ throw new MethodError("FORBIDDEN", `A read can't change data (it tried to write ${tag}).`);
159
160
  }
160
161
  }
161
162
  function recordWrite(tag) {
@@ -953,32 +954,32 @@ function kvMethods(name, kv, schema) {
953
954
  const entry = z.object({ key: z.string(), value: schema, expiresAt: z.string().nullable(), createdAt: z.string(), updatedAt: z.string() });
954
955
  return {
955
956
  get: {
956
- kind: "query",
957
+ effect: "read",
957
958
  description: `Get one ${name} entry by key, or null`,
958
959
  input: z.object({ key }),
959
960
  output: entry.nullable(),
960
961
  run: ({ key: key2 }) => kv.entry(key2)
961
962
  },
962
963
  list: {
963
- kind: "query",
964
+ effect: "read",
964
965
  description: `List ${name} entries in key order, optionally by prefix`,
965
966
  input: z.object({ prefix: z.string().optional(), limit }),
966
967
  output: z.array(entry),
967
968
  run: (input) => kv.list(input)
968
969
  },
969
970
  set: {
970
- kind: "mutation",
971
+ effect: "write",
971
972
  description: `Set a ${name} key; ttl ("5m", "1h", "7d" or ms) makes it expire`,
972
973
  input: z.object({ key, value: schema, ttl }),
973
974
  output: entry,
974
975
  run: ({ key: key2, value, ttl: ttl2 }) => kv.set(key2, value, { ttl: ttl2 })
975
976
  },
976
977
  delete: {
977
- kind: "mutation",
978
+ effect: "destructive",
978
979
  description: `Delete a ${name} key`,
979
980
  input: z.object({ key }),
980
981
  output: z.null(),
981
- confirm: "Delete this key?",
982
+ approve: "Delete this key?",
982
983
  run: async ({ key: key2 }) => (await kv.delete(key2), null)
983
984
  }
984
985
  };
@@ -988,45 +989,46 @@ function streamMethods(name, stream, schema) {
988
989
  const line = z.object({ id: z.string(), key: z.string(), offset: z.number(), at: z.string(), data: schema });
989
990
  return {
990
991
  tail: {
991
- kind: "stream",
992
+ effect: "read",
993
+ stream: true,
992
994
  description: `Follow a ${name} key live: its last lines (100 unless last says), then each new one, until it ends`,
993
995
  input: z.object({ key, from: z.number().int().min(0).optional(), last: z.number().int().positive().max(500).optional() }),
994
996
  run: ({ key: key2, from, last }, signal) => stream.follow(key2, { from, last, signal })
995
997
  },
996
998
  read: {
997
- kind: "query",
999
+ effect: "read",
998
1000
  description: `Read a ${name} key's lines from an offset`,
999
1001
  input: z.object({ key, from: z.number().int().min(0).optional(), limit }),
1000
1002
  output: z.array(line),
1001
1003
  run: ({ key: key2, ...options }) => stream.read(key2, options)
1002
1004
  },
1003
1005
  keys: {
1004
- kind: "query",
1006
+ effect: "read",
1005
1007
  description: `List ${name} keys, most recently written first`,
1006
1008
  input: z.object({ limit }),
1007
1009
  output: z.array(z.object({ key: z.string(), lines: z.number(), bytes: z.number(), endedAt: z.string().nullable(), updatedAt: z.string() })),
1008
1010
  run: (input) => stream.keys(input)
1009
1011
  },
1010
1012
  append: {
1011
- kind: "mutation",
1013
+ effect: "write",
1012
1014
  description: `Append a line to a ${name} key`,
1013
1015
  input: z.object({ key, data: schema }),
1014
1016
  output: line,
1015
1017
  run: ({ key: key2, data }) => stream.append(key2, data)
1016
1018
  },
1017
1019
  end: {
1018
- kind: "mutation",
1020
+ effect: "write",
1019
1021
  description: `End a ${name} key: followers stop and appends fail`,
1020
1022
  input: z.object({ key }),
1021
1023
  output: z.null(),
1022
1024
  run: async ({ key: key2 }) => (await stream.end(key2), null)
1023
1025
  },
1024
1026
  delete: {
1025
- kind: "mutation",
1027
+ effect: "destructive",
1026
1028
  description: `Delete a ${name} key and its lines`,
1027
1029
  input: z.object({ key }),
1028
1030
  output: z.null(),
1029
- confirm: "Delete this stream and its lines?",
1031
+ approve: "Delete this stream and its lines?",
1030
1032
  run: async ({ key: key2 }) => (await stream.delete(key2), null)
1031
1033
  }
1032
1034
  };
@@ -1051,28 +1053,28 @@ function bucketMethods(name, bucket, schema) {
1051
1053
  const revision = z.number().int().optional();
1052
1054
  return {
1053
1055
  list: {
1054
- kind: "query",
1056
+ effect: "read",
1055
1057
  description: `List ${name} files, newest first, optionally in one folder or with one status`,
1056
1058
  input: z.object({ folder: z.string().optional(), status: status.optional(), limit }),
1057
1059
  output: z.array(file),
1058
1060
  run: (input) => bucket.list(input)
1059
1061
  },
1060
1062
  search: {
1061
- kind: "query",
1063
+ effect: "read",
1062
1064
  description: `Search ${name} files by name, folder and meta`,
1063
1065
  input: z.object({ query: z.string(), limit }),
1064
1066
  output: z.array(file),
1065
1067
  run: ({ query, limit: limit2 }) => bucket.search(query, { limit: limit2 })
1066
1068
  },
1067
1069
  get: {
1068
- kind: "query",
1070
+ effect: "read",
1069
1071
  description: `Get one ${name} file by id, or null`,
1070
1072
  input: z.object({ id }),
1071
1073
  output: file.nullable(),
1072
1074
  run: ({ id: id2 }) => bucket.get(id2)
1073
1075
  },
1074
1076
  put: {
1075
- kind: "mutation",
1077
+ effect: "write",
1076
1078
  description: `Add a file to ${name}: its name, and text or an absolute path to copy`,
1077
1079
  input: z.object({
1078
1080
  name: z.string(),
@@ -1089,25 +1091,25 @@ function bucketMethods(name, bucket, schema) {
1089
1091
  }
1090
1092
  },
1091
1093
  update: {
1092
- kind: "mutation",
1094
+ effect: "write",
1093
1095
  description: `Change fields of a ${name} file's meta; null removes one`,
1094
1096
  input: z.object({ id, meta: z.record(z.string(), z.unknown()), revision }),
1095
1097
  output: file,
1096
1098
  run: ({ id: id2, meta, revision: revision2 }) => bucket.update(id2, meta, { revision: revision2 })
1097
1099
  },
1098
1100
  move: {
1099
- kind: "mutation",
1101
+ effect: "write",
1100
1102
  description: `Rename a ${name} file or move it to another folder`,
1101
1103
  input: z.object({ id, name: z.string().optional(), folder: z.string().optional(), revision }),
1102
1104
  output: file,
1103
1105
  run: ({ id: id2, name: name2, folder, revision: revision2 }) => bucket.move(id2, { name: name2, folder }, { revision: revision2 })
1104
1106
  },
1105
1107
  delete: {
1106
- kind: "mutation",
1108
+ effect: "destructive",
1107
1109
  description: `Delete a ${name} file and its meta`,
1108
1110
  input: z.object({ id }),
1109
1111
  output: z.null(),
1110
- confirm: "Delete this file?",
1112
+ approve: "Delete this file?",
1111
1113
  run: async ({ id: id2 }) => (await bucket.delete(id2), null)
1112
1114
  }
1113
1115
  };
@@ -1501,7 +1503,7 @@ var RunMetadataSchema = z3.object({
1501
1503
  root: z3.string().refine(isAbsolute2),
1502
1504
  namespace: z3.string().regex(/^[a-z0-9][a-z0-9.-]*$/),
1503
1505
  plugin: z3.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1504
- caller: z3.enum(["card", "agent", "cron", "code", "http"]),
1506
+ caller: z3.enum(["card", "agent", "cron", "code", "http", "device"]),
1505
1507
  workflow: z3.string().regex(/^[a-z][a-zA-Z0-9_-]*$/),
1506
1508
  input: z3.json(),
1507
1509
  key: z3.string().nullable(),
@@ -1524,29 +1526,29 @@ function workflowMethods(plugin, namespace, name, definition, ctx, bridge, direc
1524
1526
  return bridge({ operation, dir, plugin, namespace, workflow: name, root: ctx.root, caller: ctx.caller, input, settings: workflowSettings(definition) });
1525
1527
  };
1526
1528
  const id = z4.object({ id: z4.string().uuid() }).strict();
1527
- const spec = (method, kind, input, description, confirm, output) => ({
1529
+ const spec = (method, effect, input, description, approve, output) => ({
1528
1530
  name: `${plugin}.${name}.${method}`,
1529
1531
  plugin,
1530
- kind,
1532
+ effect,
1531
1533
  input,
1532
1534
  description,
1533
- confirm,
1535
+ approve,
1534
1536
  output,
1535
1537
  run: async (input2, raw) => {
1536
- if (kind === "query")
1538
+ if (effect === "read")
1537
1539
  recordRead(workflowTag(namespace));
1538
1540
  const request = method === "start" ? { ...input2, input: raw.input } : input2;
1539
1541
  return invoke(method, request);
1540
1542
  }
1541
1543
  });
1542
1544
  return [
1543
- spec("list", "query", z4.object({ limit: z4.number().int().min(1).max(100).default(20), status: z4.string().optional(), cursor: z4.string().optional() }).strict(), "List workflow runs", undefined, z4.object({ items: z4.array(RunSummarySchema), cursor: z4.string().nullable() })),
1544
- spec("get", "query", id, "Get one workflow run"),
1545
- spec("start", "mutation", z4.object({ input: definition.input, key: z4.string().min(1).max(200).optional() }).strict(), definition.description ?? "Start a durable workflow", definition.confirm, RunSummarySchema),
1546
- spec("retry", "mutation", id, "Retry a safely failed query step", undefined, RunSummarySchema),
1547
- spec("restart", "mutation", id, "Start a run that needs attention over from the beginning, on the current code", undefined, RunSummarySchema),
1548
- spec("cancel", "mutation", id, "Request cancellation of a workflow", undefined, RunSummarySchema),
1549
- spec("cancelAll", "mutation", z4.object({ status: z4.string().optional() }).strict(), "Cancel every unfinished run, or only those in one status", undefined, z4.object({ cancelled: z4.number().int() }))
1545
+ spec("list", "read", z4.object({ limit: z4.number().int().min(1).max(100).default(20), status: z4.string().optional(), cursor: z4.string().optional() }).strict(), "List workflow runs", undefined, z4.object({ items: z4.array(RunSummarySchema), cursor: z4.string().nullable() })),
1546
+ spec("get", "read", id, "Get one workflow run"),
1547
+ spec("start", "write", z4.object({ input: definition.input, key: z4.string().min(1).max(200).optional() }).strict(), definition.description ?? "Start a durable workflow", definition.approve, RunSummarySchema),
1548
+ spec("retry", "write", id, "Retry a safely failed query step", undefined, RunSummarySchema),
1549
+ spec("restart", "write", id, "Start a run that needs attention over from the beginning, on the current code", undefined, RunSummarySchema),
1550
+ spec("cancel", "write", id, "Request cancellation of a workflow", undefined, RunSummarySchema),
1551
+ spec("cancelAll", "write", z4.object({ status: z4.string().optional() }).strict(), "Cancel every unfinished run, or only those in one status", undefined, z4.object({ cancelled: z4.number().int() }))
1550
1552
  ];
1551
1553
  }
1552
1554
  function workflowSettings(definition) {
@@ -1606,6 +1608,8 @@ class Runtime {
1606
1608
  continue;
1607
1609
  if (only && !only.includes(entry.name))
1608
1610
  continue;
1611
+ if (!existsSync(join3(pluginsDir, entry.name, "app.ts")))
1612
+ continue;
1609
1613
  const module = await logContext.run({ plugin: entry.name }, () => import(join3(pluginsDir, entry.name, "app.ts")));
1610
1614
  await this.add(entry.name, module.default);
1611
1615
  }
@@ -1731,9 +1735,11 @@ class Runtime {
1731
1735
  this.register({
1732
1736
  name: fullName,
1733
1737
  plugin: name,
1734
- kind: method.kind,
1738
+ effect: method.effect,
1739
+ stream: method.stream,
1735
1740
  description: method.description,
1736
- confirm: method.confirm,
1741
+ approve: method.approve,
1742
+ approveUpTo: method.approveUpTo,
1737
1743
  http: method.http,
1738
1744
  input: method.input,
1739
1745
  output: method.output,
@@ -1764,6 +1770,10 @@ class Runtime {
1764
1770
  })))));
1765
1771
  }
1766
1772
  async call(name, input = {}, options = {}) {
1773
+ if (options.signal) {
1774
+ const { signal, ...rest } = options;
1775
+ return this.callSignal.run(signal, () => this.call(name, input, rest));
1776
+ }
1767
1777
  if (options.files) {
1768
1778
  const { files, ...rest } = options;
1769
1779
  const fields = input ?? {};
@@ -1787,17 +1797,17 @@ class Runtime {
1787
1797
  return runWith(where, () => this.call(name, input, options));
1788
1798
  if (where !== logContext.getStore())
1789
1799
  return logContext.run(where, () => this.call(name, input, options));
1790
- if ((options.expect === "query" || currentAccess()?.readOnly) && method.kind === "mutation") {
1800
+ if ((options.expect === "read" || currentAccess()?.readOnly) && method.effect !== "read") {
1791
1801
  throw new MethodError("FORBIDDEN", `${name} changes data, so it only runs when the user acts.`);
1792
1802
  }
1793
1803
  const raw = input ?? {};
1794
1804
  const parsed = method.input.parse(raw);
1795
- if (method.confirm && (options.confirmed === false || workflowScope.getStore()))
1796
- throw new MethodError("CONFIRM", fillConfirm(method.confirm, parsed));
1797
- if (method.kind === "stream")
1805
+ if (method.approve && (options.confirmed === false || workflowScope.getStore()))
1806
+ throw new MethodError("CONFIRM", fillQuestion(method.approve, parsed));
1807
+ if (method.stream)
1798
1808
  return { result: await this.sample(name, input), reads: [], invalidates: [] };
1799
1809
  const confirmed = this.callConfirmed.getStore() ?? false;
1800
- const run = await tracked(method.kind === "query", (tags) => this.notifyInvalidated(tags), () => this.callConfirmed.run(confirmed || method.confirm !== undefined, async () => {
1810
+ const run = await tracked(method.effect === "read", (tags) => this.notifyInvalidated(tags), () => this.callConfirmed.run(confirmed || method.approve !== undefined, async () => {
1801
1811
  const result = await method.run(parsed, raw);
1802
1812
  await this.events.emit(name, { input: parsed, result });
1803
1813
  return result;
@@ -1816,8 +1826,8 @@ class Runtime {
1816
1826
  const method = this.methods.get(name);
1817
1827
  if (!method)
1818
1828
  throw new MethodError("NOT_FOUND", `There is no method ${name}.`);
1819
- if (method.kind !== "stream")
1820
- throw new MethodError("VALIDATION", `${name} is a ${method.kind}, not a stream.`);
1829
+ if (!method.stream)
1830
+ throw new MethodError("VALIDATION", `${name} is not a stream.`);
1821
1831
  const raw = input ?? {};
1822
1832
  const parsed = method.input.parse(raw);
1823
1833
  const root = options.root ?? this.callRoot.getStore() ?? this.root;
@@ -1872,7 +1882,7 @@ class Runtime {
1872
1882
  const statuses = [];
1873
1883
  for (const entry of entries) {
1874
1884
  const timezone = entry.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
1875
- const signature = `${entry.plugin}.${entry.method} ${entry.schedule} ${timezone}`;
1885
+ const signature = `${entry.plugin}.${entry.method} ${entry.schedule} ${timezone} ${entry.root ?? ""}`;
1876
1886
  try {
1877
1887
  const job = kept.get(signature) ?? this.cronJob(entry, timezone, signature);
1878
1888
  jobs.push(job);
@@ -1904,9 +1914,9 @@ class Runtime {
1904
1914
  const method = this.methods.get(name);
1905
1915
  if (!method || method.plugin !== entry.plugin)
1906
1916
  throw new Error(`${entry.method} isn't one of ${entry.plugin}'s methods`);
1907
- if (method.kind === "stream")
1908
- throw new Error(`${name} is a stream; a cron runs a query or a mutation`);
1909
- if (method.confirm)
1917
+ if (method.stream)
1918
+ throw new Error(`${name} is a stream; a cron runs a read or a write`);
1919
+ if (method.approve)
1910
1920
  throw new Error(`${name} asks before it runs, so nothing may run it on a schedule`);
1911
1921
  if (!method.input.safeParse({}).success)
1912
1922
  throw new Error(`${name} needs input; a cron calls it with {}`);
@@ -1922,6 +1932,7 @@ class Runtime {
1922
1932
  return {
1923
1933
  signature,
1924
1934
  plugin: entry.plugin,
1935
+ root: entry.root,
1925
1936
  method: name,
1926
1937
  schedule: entry.schedule,
1927
1938
  timezone,
@@ -1946,7 +1957,7 @@ class Runtime {
1946
1957
  job.running = true;
1947
1958
  job.lastRunAt = now;
1948
1959
  const startedAt = Date.now();
1949
- started.push(this.call(job.method, {}, { caller: "cron" }).then(() => {
1960
+ started.push(this.call(job.method, {}, { caller: "cron", root: job.root }).then(() => {
1950
1961
  job.lastError = null;
1951
1962
  }, (error) => {
1952
1963
  job.lastError = toCallError(error).message;
@@ -2007,9 +2018,11 @@ class Runtime {
2007
2018
  description: plugin.description ?? null,
2008
2019
  methods: [...this.methods.values()].filter((method) => method.plugin === name).map((method) => ({
2009
2020
  name: method.name,
2010
- kind: method.kind,
2021
+ effect: method.effect,
2022
+ stream: method.stream ?? false,
2011
2023
  description: method.description ?? null,
2012
- confirm: method.confirm ?? null,
2024
+ approve: method.approve ?? null,
2025
+ approveUpTo: method.approve ? method.approveUpTo ?? "full-access" : null,
2013
2026
  http: method.http ?? null,
2014
2027
  input: z5.toJSONSchema(method.input, { io: "input", unrepresentable: "any" }),
2015
2028
  output: method.output ? z5.toJSONSchema(method.output, { io: "output", unrepresentable: "any" }) : null
@@ -2083,6 +2096,9 @@ class Runtime {
2083
2096
  register(method) {
2084
2097
  if (this.methods.has(method.name))
2085
2098
  throw new Error(`${method.name} is defined twice; rename the method or the data`);
2099
+ if (method.effect === "destructive" && !method.approve) {
2100
+ throw new Error(`${method.name} is destructive, so it needs an approve question, such as { approve: "Delete {{id}}?" }`);
2101
+ }
2086
2102
  this.methods.set(method.name, method);
2087
2103
  }
2088
2104
  registerGenerated(plugin, name, methods) {
@@ -2099,32 +2115,32 @@ class Runtime {
2099
2115
  const prefix = `${plugin}.${name}`;
2100
2116
  const id = z5.object({ id: z5.string() });
2101
2117
  const record2 = schema.extend({ id: z5.string(), createdAt: z5.string(), updatedAt: z5.string() });
2102
- const crud = (method, kind, input, output, description, run, confirm) => this.register({
2118
+ const crud = (method, effect, input, output, description, run, approve) => this.register({
2103
2119
  name: `${prefix}.${method}`,
2104
2120
  plugin,
2105
- kind,
2121
+ effect,
2106
2122
  description,
2107
- confirm,
2123
+ approve,
2108
2124
  input,
2109
2125
  output,
2110
2126
  run: async (value, raw) => run(value, raw)
2111
2127
  });
2112
- crud("list", "query", z5.object({
2128
+ crud("list", "read", z5.object({
2113
2129
  limit: z5.number().int().positive().max(500).optional(),
2114
2130
  offset: z5.number().int().min(0).optional(),
2115
2131
  orderBy: z5.string().optional(),
2116
2132
  order: z5.enum(["asc", "desc"]).optional()
2117
2133
  }), z5.array(record2), `List ${name} records, newest first unless orderBy says`, (input) => collection.list(input));
2118
- crud("get", "query", id, record2.nullable(), `Get one ${name} record by id, or null`, (input) => collection.get(input.id));
2119
- crud("create", "mutation", schema, record2, `Create a ${name} record`, (input) => collection.create(input));
2120
- crud("update", "mutation", id.extend(schema.partial().shape), record2, `Update fields on a ${name} record`, ({ id: id2, ...fields }, raw) => collection.update(id2, Object.fromEntries(Object.entries(fields).filter(([key]) => Object.hasOwn(raw ?? {}, key)))));
2121
- crud("delete", "mutation", id, z5.null(), `Delete a ${name} record by id`, async (input) => {
2134
+ crud("get", "read", id, record2.nullable(), `Get one ${name} record by id, or null`, (input) => collection.get(input.id));
2135
+ crud("create", "write", schema, record2, `Create a ${name} record`, (input) => collection.create(input));
2136
+ crud("update", "write", id.extend(schema.partial().shape), record2, `Update fields on a ${name} record`, ({ id: id2, ...fields }, raw) => collection.update(id2, Object.fromEntries(Object.entries(fields).filter(([key]) => Object.hasOwn(raw ?? {}, key)))));
2137
+ crud("delete", "destructive", id, z5.null(), `Delete a ${name} record by id`, async (input) => {
2122
2138
  await collection.delete(input.id);
2123
2139
  return null;
2124
2140
  }, "Delete this record?");
2125
2141
  }
2126
2142
  }
2127
- function fillConfirm(question, input) {
2143
+ function fillQuestion(question, input) {
2128
2144
  const fields = input ?? {};
2129
2145
  return question.replace(/\{\{\s*([A-Za-z0-9_]+)\s*\}\}/g, (_, field2) => {
2130
2146
  const value = Object.hasOwn(fields, field2) ? fields[field2] : undefined;
@@ -2147,9 +2163,9 @@ function cronState(job) {
2147
2163
  function mcpFailure(server, tool, error) {
2148
2164
  switch (error.code) {
2149
2165
  case "NOT_READ_ONLY":
2150
- return new MethodError("FORBIDDEN", `${server}.${tool} changes data, so it runs from a mutation, not a query.`);
2166
+ return new MethodError("FORBIDDEN", `${server}.${tool} changes data, so it runs from a write, not a read.`);
2151
2167
  case "CONFIRM":
2152
- return new MethodError("FORBIDDEN", `${server}.${tool} may destroy data, so it runs only from a method with a confirm.`);
2168
+ return new MethodError("FORBIDDEN", `${server}.${tool} may destroy data, so it runs only from a method with an approve.`);
2153
2169
  }
2154
2170
  return new MethodError("INTERNAL", error.message);
2155
2171
  }
@@ -35,7 +35,7 @@ export type WorkflowTarget = {
35
35
  export type WorkflowRequest = WorkflowTarget & {
36
36
  operation: "start" | "list" | "get" | "cancel" | "cancelAll" | "retry" | "restart";
37
37
  input: Record<string, unknown>;
38
- caller?: "card" | "agent" | "cron" | "code" | "http";
38
+ caller?: "card" | "agent" | "cron" | "code" | "http" | "device";
39
39
  settings?: {
40
40
  timeoutMs: number;
41
41
  maxOfflineMs: number;
@@ -55,6 +55,7 @@ export declare const RunMetadataSchema: z.ZodObject<{
55
55
  cron: "cron";
56
56
  code: "code";
57
57
  http: "http";
58
+ device: "device";
58
59
  }>;
59
60
  workflow: z.ZodString;
60
61
  input: z.ZodJSONSchema;
@@ -79,6 +80,7 @@ export declare const RunLocationSchema: z.ZodObject<{
79
80
  cron: "cron";
80
81
  code: "code";
81
82
  http: "http";
83
+ device: "device";
82
84
  }>;
83
85
  }, z.core.$strict>;
84
86
  export type RunMetadata = z.infer<typeof RunMetadataSchema>;
@@ -23,7 +23,7 @@ export declare function workflowContext(base: Context, run: RunContext & {
23
23
  export type WorkflowOptions<O extends z.ZodType = z.ZodType> = {
24
24
  description?: string;
25
25
  output?: O;
26
- confirm?: string;
26
+ approve?: string;
27
27
  timeout?: Duration;
28
28
  maxOffline?: Duration;
29
29
  retention?: Duration;
@@ -24,6 +24,7 @@ export declare const EventInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
24
24
  cron: "cron";
25
25
  code: "code";
26
26
  http: "http";
27
+ device: "device";
27
28
  }>;
28
29
  }, z.core.$strict>>;
29
30
  }, z.core.$strict>, z.ZodObject<{