@sanoma-ai/workflows 0.6.0 → 0.7.1

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.
Files changed (166) hide show
  1. package/README.md +52 -14
  2. package/dist/apply.d.ts +2 -1
  3. package/dist/apply.js +29 -7
  4. package/dist/apply.js.map +1 -1
  5. package/dist/approvals.d.ts +27 -2
  6. package/dist/approvals.js +73 -9
  7. package/dist/approvals.js.map +1 -1
  8. package/dist/call.d.ts +3 -2
  9. package/dist/call.js +38 -30
  10. package/dist/call.js.map +1 -1
  11. package/dist/cedar.js +24 -9
  12. package/dist/cedar.js.map +1 -1
  13. package/dist/change.d.ts +219 -0
  14. package/dist/change.js +150 -0
  15. package/dist/change.js.map +1 -0
  16. package/dist/chats.d.ts +43 -0
  17. package/dist/chats.js +48 -0
  18. package/dist/chats.js.map +1 -0
  19. package/dist/client.d.ts +52 -6
  20. package/dist/client.js +88 -47
  21. package/dist/client.js.map +1 -1
  22. package/dist/config.d.ts +75 -8
  23. package/dist/config.js +103 -13
  24. package/dist/config.js.map +1 -1
  25. package/dist/constructors.d.ts +37 -1
  26. package/dist/constructors.js +6 -2
  27. package/dist/constructors.js.map +1 -1
  28. package/dist/database.d.ts +83 -0
  29. package/dist/database.js +92 -0
  30. package/dist/database.js.map +1 -0
  31. package/dist/db.d.ts +19 -1
  32. package/dist/db.js +51 -7
  33. package/dist/db.js.map +1 -1
  34. package/dist/deadlines.d.ts +91 -0
  35. package/dist/deadlines.js +165 -0
  36. package/dist/deadlines.js.map +1 -0
  37. package/dist/define.d.ts +25 -4
  38. package/dist/define.js +40 -0
  39. package/dist/define.js.map +1 -1
  40. package/dist/demo.d.ts +28 -0
  41. package/dist/demo.js +72 -0
  42. package/dist/demo.js.map +1 -0
  43. package/dist/describe.d.ts +5 -2
  44. package/dist/describe.js +10 -6
  45. package/dist/describe.js.map +1 -1
  46. package/dist/errors.d.ts +10 -1
  47. package/dist/errors.js +13 -0
  48. package/dist/errors.js.map +1 -1
  49. package/dist/fake.d.ts +34 -0
  50. package/dist/fake.js +134 -1
  51. package/dist/fake.js.map +1 -1
  52. package/dist/grid.d.ts +34 -0
  53. package/dist/grid.js +62 -0
  54. package/dist/grid.js.map +1 -0
  55. package/dist/host.d.ts +12 -2
  56. package/dist/host.js +2 -2
  57. package/dist/host.js.map +1 -1
  58. package/dist/index.d.ts +15 -8
  59. package/dist/index.js +10 -5
  60. package/dist/index.js.map +1 -1
  61. package/dist/ledger.d.ts +11 -2
  62. package/dist/ledger.js.map +1 -1
  63. package/dist/lint.js +2 -2
  64. package/dist/lint.js.map +1 -1
  65. package/dist/op.d.ts +21 -2
  66. package/dist/op.js.map +1 -1
  67. package/dist/person.d.ts +5 -0
  68. package/dist/person.js +3 -1
  69. package/dist/person.js.map +1 -1
  70. package/dist/policy.d.ts +7 -1
  71. package/dist/policy.js +2 -1
  72. package/dist/policy.js.map +1 -1
  73. package/dist/resource.d.ts +13 -1
  74. package/dist/resource.js +9 -1
  75. package/dist/resource.js.map +1 -1
  76. package/dist/resources.d.ts +2 -0
  77. package/dist/resources.js +15 -4
  78. package/dist/resources.js.map +1 -1
  79. package/dist/run.d.ts +5 -0
  80. package/dist/run.js.map +1 -1
  81. package/dist/sandbox.d.ts +38 -10
  82. package/dist/sandbox.js +66 -35
  83. package/dist/sandbox.js.map +1 -1
  84. package/dist/scenario.d.ts +18 -1
  85. package/dist/scenario.js +77 -27
  86. package/dist/scenario.js.map +1 -1
  87. package/dist/scenarios.d.ts +10 -1
  88. package/dist/scenarios.js +19 -4
  89. package/dist/scenarios.js.map +1 -1
  90. package/dist/schedules.d.ts +66 -0
  91. package/dist/schedules.js +158 -0
  92. package/dist/schedules.js.map +1 -0
  93. package/dist/schema.d.ts +6 -0
  94. package/dist/schema.js +13 -3
  95. package/dist/schema.js.map +1 -1
  96. package/dist/shared.d.ts +30 -2
  97. package/dist/shared.js +42 -4
  98. package/dist/shared.js.map +1 -1
  99. package/dist/source.d.ts +185 -2
  100. package/dist/source.js +9 -0
  101. package/dist/source.js.map +1 -1
  102. package/dist/supervisor.d.ts +39 -0
  103. package/dist/supervisor.js +68 -0
  104. package/dist/supervisor.js.map +1 -0
  105. package/dist/version.d.ts +3 -1
  106. package/dist/version.js +3 -1
  107. package/dist/version.js.map +1 -1
  108. package/dist/wakeup-driver.d.ts +128 -0
  109. package/dist/wakeup-driver.js +216 -0
  110. package/dist/wakeup-driver.js.map +1 -0
  111. package/dist/wakeup-service.d.ts +83 -0
  112. package/dist/wakeup-service.js +415 -0
  113. package/dist/wakeup-service.js.map +1 -0
  114. package/dist/wakeup-type.d.ts +43 -0
  115. package/dist/wakeup-type.js +80 -0
  116. package/dist/wakeup-type.js.map +1 -0
  117. package/dist/wakeup.d.ts +77 -0
  118. package/dist/wakeup.js +78 -0
  119. package/dist/wakeup.js.map +1 -0
  120. package/dist/worker.d.ts +39 -1
  121. package/dist/worker.js +125 -38
  122. package/dist/worker.js.map +1 -1
  123. package/oxlint.json +3 -1
  124. package/package.json +10 -2
  125. package/src/apply.ts +25 -6
  126. package/src/approvals.ts +89 -16
  127. package/src/call.ts +40 -29
  128. package/src/cedar.ts +24 -6
  129. package/src/change.ts +222 -0
  130. package/src/chats.ts +114 -0
  131. package/src/client.ts +145 -55
  132. package/src/config.ts +149 -21
  133. package/src/constructors.ts +8 -2
  134. package/src/database.ts +152 -0
  135. package/src/db.ts +58 -9
  136. package/src/deadlines.ts +228 -0
  137. package/src/define.ts +71 -4
  138. package/src/demo.ts +87 -0
  139. package/src/describe.ts +18 -6
  140. package/src/errors.ts +14 -0
  141. package/src/fake.ts +149 -0
  142. package/src/grid.ts +100 -0
  143. package/src/host.ts +12 -4
  144. package/src/index.ts +66 -3
  145. package/src/ledger.ts +15 -3
  146. package/src/lint.ts +2 -2
  147. package/src/op.ts +22 -2
  148. package/src/person.ts +4 -1
  149. package/src/policy.ts +7 -1
  150. package/src/resource.ts +22 -3
  151. package/src/resources.ts +17 -4
  152. package/src/run.ts +5 -0
  153. package/src/sandbox.ts +97 -37
  154. package/src/scenario.ts +97 -28
  155. package/src/scenarios.ts +21 -5
  156. package/src/schedules.ts +206 -0
  157. package/src/schema.ts +16 -3
  158. package/src/shared.ts +51 -4
  159. package/src/source.ts +176 -3
  160. package/src/supervisor.ts +102 -0
  161. package/src/version.ts +3 -1
  162. package/src/wakeup-driver.ts +270 -0
  163. package/src/wakeup-service.ts +504 -0
  164. package/src/wakeup-type.ts +90 -0
  165. package/src/wakeup.ts +139 -0
  166. package/src/worker.ts +176 -43
package/dist/wakeup.js ADDED
@@ -0,0 +1,78 @@
1
+ import { hasPath } from "./host.js";
2
+ /** The operations `defineResource` gives a type itself: never its register, or a database's `storeUrl`. */
3
+ export const RESOURCE_OPS = new Set(["read", "import", "plan", "create", "update", "delete"]);
4
+ /**
5
+ * Throws what is wrong with a resource type's `wakeup`: a type apply cannot change (not
6
+ * `writable`), a host (stopped when its wake is due), a `host` that names no field or no
7
+ * reference resolved `by` a field, a `register` that is not an operation of the type's own group
8
+ * or is one of its resource operations, `outputs` that is not a function. Whether the connector
9
+ * has that operation, and the reference names a host, is `checkWakeupOps`'s, which
10
+ * `resolveConfig` runs.
11
+ */
12
+ export function checkWakeup(what, wakeup, type) {
13
+ const problems = [];
14
+ if (!type.writable)
15
+ problems.push("it must be writable, so apply can create and update it");
16
+ if (type.host)
17
+ problems.push("a host cannot be its own wakeup: it is stopped when the wake is due");
18
+ const host = wakeup.inputs?.host;
19
+ const reference = typeof host === "string" ? type.fields.references?.[host] : undefined;
20
+ if (typeof host !== "string" || !hasPath(type.schema, host))
21
+ problems.push(`inputs.host names no field (${host})`);
22
+ else if (!reference)
23
+ problems.push(`inputs.host must be a reference to the host (fields.references), not ${host}`);
24
+ else if (!reference.by?.length)
25
+ problems.push("inputs.host must be resolved `by` the field of the host's state that holds its URL");
26
+ const group = `${type.vendor}.${type.type}.`;
27
+ const register = wakeup.register;
28
+ const name = typeof register === "string" && register.startsWith(group) ? register.slice(group.length) : "";
29
+ if (!/^\w+$/.test(name))
30
+ problems.push(`register must name an operation of its own group, ${group}<op> (${String(register)})`);
31
+ else if (RESOURCE_OPS.has(name))
32
+ problems.push(`register must be an operation of its own, not the type's ${name}`);
33
+ if (typeof wakeup.outputs !== "function")
34
+ problems.push("outputs must be a function of the state");
35
+ if (problems.length)
36
+ throw new Error(`${what}: its wakeup: ${problems.join("; ")}`);
37
+ }
38
+ /** A registration every register operation must take: the input `checkWakeupOps` tries. */
39
+ const SAMPLE = { at: new Date(0).toISOString() };
40
+ /**
41
+ * True when `op`'s input takes `sample` and keeps each of its fields: one that strips a field
42
+ * takes none of it. A wakeup's `register` is checked with it.
43
+ */
44
+ function keepsInput(op, sample) {
45
+ try {
46
+ const parsed = op.input.safeParse(sample);
47
+ const data = parsed.data;
48
+ return parsed.success && Object.keys(sample).every((key) => data?.[key] !== undefined);
49
+ }
50
+ catch {
51
+ // An async refinement, which a sync parse cannot run: no input the runtime can check.
52
+ return false;
53
+ }
54
+ }
55
+ /** The host types a wakeup type may name: its `inputs.host` reference's. */
56
+ export const wakeupHostTypes = (type) => type.wakeup ? [type.fields.references?.[type.wakeup.inputs.host]?.type ?? []].flat() : [];
57
+ /**
58
+ * Throws when a wakeup type's host reference names a type of the config that is no host, or its
59
+ * `register` is not among the config's operations, or does not take
60
+ * `WakeupRegistration`. Here rather than in `defineConnector`, which sees one connector before
61
+ * its package merges in the operations it adds to a resource's group (Supabase's pattern).
62
+ */
63
+ export function checkWakeupOps(types, ops) {
64
+ for (const [id, type] of types) {
65
+ if (!type.wakeup)
66
+ continue;
67
+ // The types it may name that the config has, each a host; one it lacks no data file can declare.
68
+ const notHosts = wakeupHostTypes(type).filter((t) => types.has(t) && !types.get(t).host);
69
+ if (notHosts.length)
70
+ throw new Error(`${id}: its wakeup's host may name ${notHosts.join(", ")}, which is no host`);
71
+ const op = ops.get(type.wakeup.register);
72
+ if (!op)
73
+ throw new Error(`${id}: its wakeup's register, ${type.wakeup.register}, is no operation of its connector`);
74
+ if (!keepsInput(op, { ...SAMPLE }))
75
+ throw new Error(`${id}: its wakeup's register, ${op.id}, must take { at }`);
76
+ }
77
+ }
78
+ //# sourceMappingURL=wakeup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wakeup.js","sourceRoot":"","sources":["../src/wakeup.ts"],"names":[],"mappings":"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"}
package/dist/worker.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { type SanomaConfig } from "./config.ts";
1
+ import { type ResolvedConfig, type SanomaConfig } from "./config.ts";
2
+ import { type Deadlines, type SelfStop } from "./deadlines.ts";
2
3
  import type { Source } from "./source.ts";
3
4
  export interface Worker {
4
5
  /**
@@ -7,6 +8,18 @@ export interface Worker {
7
8
  * The worker names them in one line at start, unless started `quiet`.
8
9
  */
9
10
  readonly unconfigured: readonly string[];
11
+ /**
12
+ * Its runs' deadlines: each sleeping run's, and the sources added here (a schedule's next
13
+ * fire), which a stop registers the earliest of with the wakeup.
14
+ */
15
+ readonly deadlines: Deadlines;
16
+ /**
17
+ * True when nothing this worker would run can run soon (`idle` in deadlines.ts): no run executing,
18
+ * none queued, every unfinished one blocked in a sleep or an approval, the next deadline past
19
+ * `idleHorizonMs`. False once stopped.
20
+ */
21
+ idle(): Promise<boolean>;
22
+ /** Stops the worker; a second call waits for the first. */
10
23
  stop(): Promise<void>;
11
24
  }
12
25
  export interface WorkerOptions {
@@ -27,6 +40,31 @@ export interface WorkerOptions {
27
40
  promote?: boolean;
28
41
  /** The company's repository, which apply commits the lockfile to; the launcher passes its checkout. */
29
42
  source?: Source;
43
+ /**
44
+ * How soon a deadline keeps the worker up (`idle`): 60 s by default, so apply's short sleeps
45
+ * and other short waits never stop it.
46
+ */
47
+ idleHorizonMs?: number;
48
+ /** How often a worker whose data files declare a wakeup checks whether it may stop: every 15 s by default. */
49
+ stopCheckMs?: number;
50
+ /**
51
+ * Given, and with a wakeup declared, the worker stops itself when idle (`stopCheckMs`); without
52
+ * it, nobody would start another, so it never does. Called once the worker has stopped itself, with the deadline it registered with the
53
+ * wakeup (null for none): a supervisor starts a fresh worker on the next write or wake, since a
54
+ * stopped one cannot launch again.
55
+ */
56
+ onStopped?: (stopped: SelfStop) => void;
57
+ /**
58
+ * Apply the workflows' schedules (`trigger: { schedule }`): on by default. `runScenarios` turns
59
+ * it off, on a database of its own, so no schedule is applied there to start a live run.
60
+ */
61
+ schedules?: boolean;
62
+ /**
63
+ * The config as the caller resolved it (`resolveConfig(config, options)`), for a worker that
64
+ * shares its drivers with the caller: the instance fakes of `fakes: "instance"`, which a demo's
65
+ * client and reseed call too. The caller closes its `dataStore`, as it made it.
66
+ */
67
+ resolved?: ResolvedConfig;
30
68
  }
31
69
  /**
32
70
  * Registers the workflows, connects to Postgres and recovers any runs that were interrupted.
package/dist/worker.js CHANGED
@@ -2,9 +2,10 @@ import { DBOS } from "@dbos-inc/dbos-sdk";
2
2
  import { awaitApproval } from "./approvals.js";
3
3
  import { buildCtx, decideStart, isInfrastructureError, startHoldOf } from "./call.js";
4
4
  import { dbosStatusesOf } from "./client.js";
5
- import { resolveConfig } from "./config.js";
5
+ import { declaredWakeup, resolveConfig } from "./config.js";
6
6
  import { storedSecrets, watchCredentials } from "./credentials.js";
7
7
  import { DBOS_DATABASE_OPTIONS, lazyPool, prepareDatabase } from "./db.js";
8
+ import { deadlineRegistry, idle, onOwnQueue, stopWhenIdle } from "./deadlines.js";
8
9
  import { credentialsOf, unconfigured, unconfiguredSummary } from "./env.js";
9
10
  import { errorInfo, parseOrThrow, PolicyDeniedError } from "./errors.js";
10
11
  import { entry, ownedLedger, skipped, write, writeFailure } from "./ledger.js";
@@ -12,12 +13,22 @@ import { dbosLogger, quietIfSandbox, setLogLevel, warn } from "./log.js";
12
13
  import { lineStartsOf, readSource } from "./ast.js";
13
14
  import { callsOf, outlineWithSource } from "./outline.js";
14
15
  import { currentRun } from "./run.js";
15
- import { errorMessage, WORKFLOW_ACTION } from "./shared.js";
16
+ import { applyScheduled, nextScheduledFire, scheduledStarter } from "./schedules.js";
17
+ import { approverLabel, errorMessage, WORKFLOW_ACTION } from "./shared.js";
18
+ /**
19
+ * How many times DBOS may start a run again before it gives up on it
20
+ * (`MAX_RECOVERY_ATTEMPTS_EXCEEDED`). Every start of a worker counts one for each unfinished run
21
+ * of its version, and a worker that stops when idle starts again at each wake and each request:
22
+ * at one every five minutes, DBOS's default of 100 would fail a run waiting on an approval within
23
+ * nine hours. 100,000 is a year of that; a run that crashes its process at every recovery is still
24
+ * given up on, after as many restarts.
25
+ */
26
+ const MAX_RECOVERY_ATTEMPTS = 100_000;
16
27
  // DBOS registrations are process-wide and survive shutdown, so a name is registered once, and
17
28
  // its function reads the state of the worker running when a run starts, definition and all; the
18
- // run keeps that state.
29
+ // run keeps that state. Each registered function, by name, is what a schedule fires.
19
30
  let current;
20
- const registered = new Set();
31
+ const registered = new Map();
21
32
  /**
22
33
  * Registers the workflows, connects to Postgres and recovers any runs that were interrupted.
23
34
  * When a driver declares variables the environment leaves unset, it first loads their stored
@@ -27,16 +38,27 @@ const registered = new Set();
27
38
  */
28
39
  export async function startWorker(config, options = {}) {
29
40
  // Check everything before touching the state a running worker reads.
30
- const resolved = resolveConfig(config);
41
+ const resolved = options.resolved ?? resolveConfig(config);
31
42
  setLogLevel(options.logLevel);
43
+ // Read once, when it matters: a worker stops itself, registering its next deadline there, only
44
+ // when its caller hears it stop (`onStopped`).
45
+ const wakeup = options.onStopped || config.wakeup === true ? await declaredWakeup(config) : undefined;
46
+ // The wakeup service wakes the instances that stop: one that runs it must not stop with its worker.
47
+ if (config.wakeup === true && wakeup) {
48
+ throw new Error("The config runs the wakeup service (`wakeup: true`) and declares a wakeup of its own: an instance that runs the service must not stop, so leave out one of them");
49
+ }
32
50
  // The config's own, or a Postgres store made for this worker, which `stop` then closes.
33
51
  const ledger = ownedLedger(resolved);
34
52
  const secrets = lazyPool(resolved.databaseUrl, "secrets");
53
+ let stopRule;
54
+ let stopping;
55
+ const horizonMs = options.idleHorizonMs ?? 60_000;
35
56
  const state = {
36
57
  app: resolved.appName,
37
58
  ops: resolved.ops,
38
59
  drivers: resolved.drivers,
39
60
  fakes: resolved.fakes,
61
+ ...(resolved.instanceFakes && { instanceFakes: resolved.instanceFakes }),
40
62
  ...(resolved.scenarios && { scenarios: resolved.scenarios }),
41
63
  ...(options.source && { source: options.source }),
42
64
  types: resolved.types,
@@ -49,27 +71,38 @@ export async function startWorker(config, options = {}) {
49
71
  workflows: resolved.workflows,
50
72
  outlines: new Map([...resolved.workflows].map(([name, wf]) => [name, outlineOf(wf)])),
51
73
  stopped: false,
74
+ deadlines: deadlineRegistry(),
52
75
  };
53
76
  const credentials = await watchCredentials(resolved.databaseUrl, resolved.driversByVendor);
54
77
  const worker = {
55
78
  unconfigured: [...credentialsOf(resolved.driversByVendor, (name) => process.env[name])]
56
79
  .filter(([vendor, statuses]) => unconfigured(vendor, statuses))
57
80
  .map(([vendor]) => vendor),
58
- async stop() {
59
- state.stopped = true;
60
- // Each is closed whatever the one before did; the first failure is what stop throws.
61
- let failed;
62
- for (const close of [
63
- () => DBOS.shutdown(),
64
- () => credentials.close(),
65
- () => secrets.close(),
66
- () => ledger.close(),
67
- async () => resolved.dataStore?.close(),
68
- ]) {
69
- await close().catch((error) => (failed ??= { error }));
70
- }
71
- if (failed)
72
- throw failed.error;
81
+ deadlines: state.deadlines,
82
+ async idle() {
83
+ return !state.stopped && idle(state.deadlines, resolved, horizonMs);
84
+ },
85
+ stop() {
86
+ // A stop that failed may be tried again.
87
+ return (stopping ??= (async () => {
88
+ state.stopped = true;
89
+ stopRule?.close();
90
+ // Each is closed whatever the one before did; the first failure is what stop throws.
91
+ let failed;
92
+ for (const close of [
93
+ () => DBOS.shutdown(),
94
+ () => credentials.close(),
95
+ () => secrets.close(),
96
+ () => ledger.close(),
97
+ async () => (options.resolved ? undefined : resolved.dataStore?.close()),
98
+ ]) {
99
+ await close().catch((error) => (failed ??= { error }));
100
+ }
101
+ if (failed) {
102
+ stopping = undefined;
103
+ throw failed.error;
104
+ }
105
+ })());
73
106
  },
74
107
  };
75
108
  // Runs recovered during launch start before it returns, so they must already find this
@@ -79,10 +112,8 @@ export async function startWorker(config, options = {}) {
79
112
  let launched = false;
80
113
  try {
81
114
  for (const name of resolved.workflows.keys()) {
82
- if (!registered.has(name)) {
83
- register(name);
84
- registered.add(name);
85
- }
115
+ if (!registered.has(name))
116
+ registered.set(name, register(name));
86
117
  }
87
118
  current = state;
88
119
  // Before DBOS's pool connects, so its connections start with the database's idle-transaction
@@ -102,6 +133,7 @@ export async function startWorker(config, options = {}) {
102
133
  // DBOS gives runs queued without a version only to the app's latest version, which is the
103
134
  // newest one registered. A worker started on code seen before (a rollback) is not it.
104
135
  const latest = (await DBOS.getLatestApplicationVersion()).versionName;
136
+ const isLatest = latest === resolved.version || options.promote === true;
105
137
  if (latest !== resolved.version) {
106
138
  if (options.promote)
107
139
  await DBOS.setLatestApplicationVersion(resolved.version);
@@ -111,6 +143,12 @@ export async function startWorker(config, options = {}) {
111
143
  }
112
144
  }
113
145
  await DBOS.registerQueue(resolved.queueName);
146
+ // The schedules are the latest version's: an older worker leaves them as the newer set them.
147
+ if (isLatest && options.schedules !== false) {
148
+ await applyScheduled(resolved, registered, () => secrets.db());
149
+ // A schedule's next tick is a deadline: a worker that stops when quiet registers it with its wakeup.
150
+ state.deadlines.addSource(() => nextScheduledFire(resolved, new Date()));
151
+ }
114
152
  await warnAboutStrandedRuns(resolved);
115
153
  const summary = unconfiguredSummary(worker.unconfigured, resolved.driversByVendor.size);
116
154
  if (summary && !options.quiet)
@@ -118,6 +156,22 @@ export async function startWorker(config, options = {}) {
118
156
  if (resolved.policyProblems.length && !options.quiet) {
119
157
  warn(`the policies do not hold, so every call and start is refused:\n ${resolved.policyProblems.join("\n ")}`);
120
158
  }
159
+ if (wakeup && options.onStopped) {
160
+ const registerId = wakeup.type.wakeup.register;
161
+ stopRule = stopWhenIdle({
162
+ // The row is one more of the runtime's tables: the secrets' pool, on the same database.
163
+ db: () => secrets.db(),
164
+ wakeup: wakeup.binding ?? wakeup.id,
165
+ // `resolveConfig` checked the operation is the config's (`checkWakeupOps`).
166
+ register: { op: resolved.ops.get(registerId), fn: resolved.drivers.get(registerId) },
167
+ secrets: state.secrets,
168
+ deadlines: state.deadlines,
169
+ idle: () => worker.idle(),
170
+ everyMs: options.stopCheckMs ?? 15_000,
171
+ stop: () => worker.stop(),
172
+ onStopped: options.onStopped,
173
+ });
174
+ }
121
175
  }
122
176
  catch (err) {
123
177
  // Once DBOS is launched, the caller gets no worker to stop: stop it here, so no run goes on
@@ -163,7 +217,7 @@ async function warnAboutStrandedRuns({ appName, version, queueName }) {
163
217
  });
164
218
  const otherVersion = runs.filter((r) => r.applicationVersion && r.applicationVersion !== version);
165
219
  // Recovery moves a worker's own runs to DBOS's internal queues, which are fine.
166
- const otherQueue = runs.filter((r) => !otherVersion.includes(r) && r.queueName && r.queueName !== queueName && !r.queueName.startsWith("_dbos_"));
220
+ const otherQueue = runs.filter((r) => !otherVersion.includes(r) && !onOwnQueue(r.queueName, queueName));
167
221
  if (!otherVersion.length && !otherQueue.length)
168
222
  return;
169
223
  const ids = [...otherVersion, ...otherQueue].map((r) => r.workflowID);
@@ -173,23 +227,44 @@ async function warnAboutStrandedRuns({ appName, version, queueName }) {
173
227
  `with DBOSClient.forkWorkflow(id, step, { applicationVersion: "${version}", queueName: "${queueName}" }) ` +
174
228
  `and cancel the original; resumeWorkflow(id, { queueName: "${queueName}" }) moves a run on this version to this queue.`);
175
229
  }
176
- /** Registers the name with DBOS: its runs take the definition of that name from the running worker. */
230
+ /**
231
+ * Registers the name with DBOS: its runs take the definition of that name from the running worker.
232
+ * A start passes its `RunArgs`; a schedule's tick passes the time it is for (and DBOS's context).
233
+ */
177
234
  function register(name) {
178
- DBOS.registerWorkflow((args) => quietIfSandbox(args.sandbox !== undefined, () => runWorkflow(name, args)), {
179
- name,
180
- });
235
+ const fn = DBOS.registerWorkflow((start) => start instanceof Date
236
+ ? runWorkflow(name, start)
237
+ : quietIfSandbox(start.sandbox !== undefined, () => runWorkflow(name, start)), { name, maxRecoveryAttempts: MAX_RECOVERY_ATTEMPTS });
238
+ return fn;
181
239
  }
182
- /** One run of the workflow registered as `name`, on the state of the worker running when it starts. */
183
- async function runWorkflow(name, { input, startedBy, sandbox, hold }) {
240
+ /**
241
+ * One run of the workflow registered as `name`, on the state of the worker running when it
242
+ * starts, counted busy in its deadlines but while it waits: started with its `RunArgs`, or by its
243
+ * schedule for the time `start`, as the `schedule` agent with the input `{}`, the policy deciding
244
+ * that start at the top of the run.
245
+ */
246
+ async function runWorkflow(name, start) {
184
247
  const state = current;
185
248
  // A stopped worker's state stays current while DBOS shuts down.
186
249
  if (!state || state.stopped)
187
250
  throw new Error(`Run of "${name}" started with no worker running`);
251
+ return state.deadlines.running(DBOS.workflowID, () => runOn(state, name, start));
252
+ }
253
+ async function runOn(state, name, start) {
188
254
  const wf = state.workflows.get(name);
189
255
  const outline = state.outlines.get(name);
190
256
  // Registered by an earlier worker in this process, whose config had it; this one's has not.
191
257
  if (!wf || !outline)
192
258
  throw new Error(`Run of "${name}" refused: this worker's config has no workflow of that name`);
259
+ let scheduled;
260
+ let args;
261
+ if (start instanceof Date) {
262
+ scheduled = { at: start, ...(await scheduledStarter(state)) };
263
+ args = { input: {}, startedBy: scheduled.startedBy };
264
+ }
265
+ else
266
+ args = start;
267
+ const { input, startedBy, sandbox, hold } = args;
193
268
  const run = {
194
269
  id: DBOS.workflowID,
195
270
  workflow: wf.name,
@@ -203,23 +278,35 @@ async function runWorkflow(name, { input, startedBy, sandbox, hold }) {
203
278
  outline,
204
279
  state,
205
280
  };
206
- await write(run, entry(run, { type: "run.started", input }));
281
+ await write(run, entry(run, { type: "run.started", input, ...(scheduled && { scheduledFor: scheduled.at.toISOString() }) }));
207
282
  let output;
208
283
  try {
209
284
  try {
210
285
  // The one parse of the input: the client checked it, but sent it as given.
211
286
  const parsed = parseOrThrow(wf.input, input, `The input does not match ${wf.name}'s schema`);
287
+ const action = `${WORKFLOW_ACTION}${wf.name}`;
288
+ /** The policy's answer to this start, in a step; a deny fails the run. */
289
+ const decide = async () => {
290
+ const decision = await DBOS.runStep(async () => decideStart(state.policy, wf.name, parsed, startedBy, run.approvals), { name: `policy:${action}` });
291
+ if (decision.kind === "deny")
292
+ throw new PolicyDeniedError(action, decision.reason);
293
+ return decision;
294
+ };
295
+ if (scheduled) {
296
+ if (scheduled.refused)
297
+ throw new Error(`The schedule agent was not admitted: ${scheduled.refused}`);
298
+ // A schedule has no one to wait for, and its next tick would start another run meanwhile.
299
+ const decision = await decide();
300
+ if (decision.kind === "approve") {
301
+ throw new PolicyDeniedError(action, `it needs ${approverLabel(decision.approver)} to approve it, and a scheduled start waits for no approval`);
302
+ }
303
+ }
212
304
  // The policy held the start: the body waits for each hold's approval in turn, the policy
213
305
  // asked again once one is approved, and a rejection or a deny fails the run.
214
- const action = `${WORKFLOW_ACTION}${wf.name}`;
215
306
  for (let next = hold; next;) {
216
307
  const held = { op: action, input, reasons: next.reasons };
217
308
  await awaitApproval(run, next.title, { approver: next.approver, covers: [action] }, undefined, held);
218
- const decision = await DBOS.runStep(async () => decideStart(state.policy, wf.name, parsed, startedBy, run.approvals), {
219
- name: `policy:${action}`,
220
- });
221
- if (decision.kind === "deny")
222
- throw new PolicyDeniedError(action, decision.reason);
309
+ const decision = await decide();
223
310
  next = decision.kind === "approve" ? startHoldOf(wf.name, decision) : undefined;
224
311
  }
225
312
  if (sandbox !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/oxlint.json CHANGED
@@ -93,11 +93,13 @@
93
93
  "group": [
94
94
  "@sanoma-ai/connector-*/fake",
95
95
  "@sanoma-ai/connector-*/driver",
96
+ "@sanoma-ai/connector-*/remote",
96
97
  "@sanoma-ai/workflows/describe",
97
98
  "@sanoma-ai/workflows/fake",
98
99
  "@sanoma-ai/workflows/plugin",
99
100
  "@sanoma-ai/workflows/scenario",
100
- "@sanoma-ai/workflows/scenarios"
101
+ "@sanoma-ai/workflows/scenarios",
102
+ "@sanoma-ai/workflows/wakeup-service"
101
103
  ],
102
104
  "message": "A workflow must call vendors through ctx, so the policy sees every call: import the connector itself, `@sanoma-ai/connector-<vendor>`."
103
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanoma-ai/workflows",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Business processes as TypeScript functions, run durably on DBOS",
5
5
  "keywords": [
6
6
  "approvals",
@@ -66,12 +66,17 @@
66
66
  "./shared": {
67
67
  "types": "./dist/shared.d.ts",
68
68
  "default": "./dist/shared.js"
69
+ },
70
+ "./wakeup-service": {
71
+ "types": "./dist/wakeup-service.d.ts",
72
+ "default": "./dist/wakeup-service.js"
69
73
  }
70
74
  },
71
75
  "publishConfig": {
72
76
  "access": "public"
73
77
  },
74
78
  "dependencies": {
79
+ "@ai-sdk/provider": "4.0.34",
75
80
  "@cedar-policy/cedar-wasm": "4.14.0",
76
81
  "@cucumber/cucumber": "13.3.0",
77
82
  "@cucumber/cucumber-expressions": "^20.1.0",
@@ -79,6 +84,7 @@
79
84
  "@cucumber/query": "16.1.1",
80
85
  "@dbos-inc/dbos-sdk": "^5.2.11",
81
86
  "@faker-js/faker": "^10.6.0",
87
+ "ai": "7.0.153",
82
88
  "oxc-parser": "^0.153.0",
83
89
  "oxfmt": "^0.72.0",
84
90
  "pg": "^8.23.1",
@@ -87,13 +93,15 @@
87
93
  },
88
94
  "devDependencies": {
89
95
  "@types/pg": "^8.23.1",
96
+ "msw": "^3.0.2",
97
+ "srvx": "^0.11.22",
90
98
  "zod": "^4.6.5"
91
99
  },
92
100
  "peerDependencies": {
93
101
  "zod": "^4"
94
102
  },
95
103
  "engines": {
96
- "node": "24 || >=26"
104
+ "node": ">=26"
97
105
  },
98
106
  "//": "randexp is a dependency only because zod-schema-faker, which makes up scenario inputs, needs it as a peer.",
99
107
  "scripts": {
package/src/apply.ts CHANGED
@@ -178,15 +178,17 @@ function inDependencyOrder<T extends { id: string; refs: Record<string, string>
178
178
  /**
179
179
  * What a change operation is given of a declaration: its fields, where it names a resource the
180
180
  * vendor may hold by another field (`by`, as a repository's node id), that resource's binding id
181
- * when it has one, made in this run or before.
181
+ * when it has one, made in this run or before; a wakeup's `host`, the URL its host answers at
182
+ * (`urls`, by the host's declared id) once its state says.
182
183
  */
183
184
  function desiredOf(
184
185
  r: Declaration,
185
186
  types: ReadonlyMap<string, Resource>,
186
187
  bindings: Bindings,
187
188
  hosts: ReadonlyMap<string, { source: string; revision: string }>,
189
+ urls: ReadonlyMap<string, string>,
188
190
  ): State {
189
- const { fields, host } = types.get(`${r.vendor}.${r.type}`)!;
191
+ const { fields, host, wakeup } = types.get(`${r.vendor}.${r.type}`)!;
190
192
  const { references = {} } = fields;
191
193
  const out = structuredClone(r.desired);
192
194
  for (const [at, target] of Object.entries(r.refs)) {
@@ -194,6 +196,11 @@ function desiredOf(
194
196
  const place = holderOf(out, at);
195
197
  if (references[fieldPathOf(at)]?.by?.length && bound !== undefined && place) place.holder[place.key] = bound;
196
198
  }
199
+ if (wakeup) {
200
+ const url = urls.get(r.refs[wakeup.inputs.host] ?? "");
201
+ const named = holderOf(out, wakeup.inputs.host);
202
+ if (url && named) named.holder[named.key] = url;
203
+ }
197
204
  // A host is given its source's clone URL and the commit its ref names now.
198
205
  const run = hosts.get(r.id);
199
206
  if (host && run) {
@@ -406,7 +413,8 @@ function messageOf(step: PlanStep, before: Binding | undefined, after: Binding |
406
413
  * and right after one that changes a binding, the lockfile written and committed
407
414
  * (`steps.write`), so an object made is never left unbound. An update is given the plan's action
408
415
  * and replace (`expect`), and refuses (`plan_changed`) when the vendor now plans otherwise; a
409
- * reference to a resource made in this run is given its new binding. A failed step is reported
416
+ * reference to a resource made in this run is given its new binding, and a wakeup's `host` the
417
+ * URL its host's state gives (`outputs(state).url`), found or made in this run. A failed step is reported
410
418
  * and the run goes on; a failure that ends the run (`isRunControlError`) ends it.
411
419
  */
412
420
  export function applyWorkflow(
@@ -467,6 +475,16 @@ export function applyWorkflow(
467
475
  }
468
476
  }
469
477
  }
478
+ // Where each declared host answers, as its state says, found now or made below: a wakeup is given it.
479
+ const urls = new Map<string, string>();
480
+ const answersAt = (r: Declaration, state: State) => {
481
+ const url = types.get(`${r.vendor}.${r.type}`)?.host?.outputs(state).url;
482
+ if (url) urls.set(r.id, url);
483
+ };
484
+ for (const resource of resources) {
485
+ const now = found.get(resource.id);
486
+ if (now && "state" in now) answersAt(resource, now.state);
487
+ }
470
488
  // A host wanted runs the commit its ref names now, resolved before planning: a merge is a change
471
489
  // to it. One bound by the input needs none.
472
490
  const revisions = new Map<string, Revision>();
@@ -492,7 +510,7 @@ export function applyWorkflow(
492
510
  }
493
511
  }
494
512
  const drift = new Map(compare(types, resources, found, revisions).map((result) => [result.id, result]));
495
- const desired = new Map(resources.map((r) => [r.id, desiredOf(r, types, locked, hosts)]));
513
+ const desired = new Map(resources.map((r) => [r.id, desiredOf(r, types, locked, hosts, urls)]));
496
514
 
497
515
  const planned: PlanStep[] = [];
498
516
  for (const resource of inDependencyOrder(resources).filter((r) => wanted(r.id))) {
@@ -546,7 +564,7 @@ export function applyWorkflow(
546
564
  try {
547
565
  if (todo === "create") {
548
566
  const made = await ctx[step.vendor]![step.type]!.create({
549
- desired: desiredOf(declared!, types, bindings, hosts),
567
+ desired: desiredOf(declared!, types, bindings, hosts, urls),
550
568
  });
551
569
  bindings[key] = { type, id: made.id };
552
570
  state = made.state;
@@ -554,7 +572,7 @@ export function applyWorkflow(
554
572
  const expect = { action: step.action, replace: step.replace };
555
573
  const changed = await ctx[step.vendor]![step.type]!.update({
556
574
  id: binding,
557
- desired: desiredOf(declared!, types, bindings, hosts),
575
+ desired: desiredOf(declared!, types, bindings, hosts, urls),
558
576
  expect,
559
577
  });
560
578
  bindings[key] = { type, id: changed.id };
@@ -564,6 +582,7 @@ export function applyWorkflow(
564
582
  delete bindings[key];
565
583
  } else if (todo === "bind") bindings[key] = { type, id: binding };
566
584
  else if (todo === "forget") delete bindings[key];
585
+ if (state && declared) answersAt(declared, state);
567
586
  const after = bindings[key];
568
587
  if (after?.id !== before?.id) {
569
588
  const wrote = await steps.write(key, after, messageOf(step, before, after));