octaflow 0.35.0 → 0.36.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 +9 -79
- package/dist/{core-COMWflJl.js → core-YqnPwR-v.js} +109 -1
- package/dist/{dispatcher-BQErUGy_.d.ts → dispatcher-ltwBJjKc.d.ts} +10 -1
- package/dist/drizzle/index.d.ts +0 -103
- package/dist/drizzle/index.js +2 -105
- package/dist/index.d.ts +56 -4
- package/dist/index.js +18 -3
- package/dist/pg-boss/index.d.ts +1 -2
- package/dist/postgres/index.d.ts +0 -58
- package/dist/postgres/index.js +2 -363
- package/package.json +2 -63
- package/skills/add-a-case-loop/SKILL.md +1 -1
- package/skills/add-a-decision/SKILL.md +1 -1
- package/skills/add-an-ai-proposal-workflow/SKILL.md +8 -6
- package/bin/octaflow-runner.mjs +0 -209
- package/dist/ai/index.d.ts +0 -1018
- package/dist/ai/index.js +0 -1828
- package/dist/ai/providers/index.d.ts +0 -326
- package/dist/ai/providers/index.js +0 -1035
- package/dist/ai/registry.d.ts +0 -2
- package/dist/ai/registry.js +0 -1
- package/dist/ai/runner/index.d.ts +0 -138
- package/dist/ai/runner/index.js +0 -803
- package/dist/gate-BRq-t3K_.js +0 -109
- package/dist/hooks-DHomzpiq.d.ts +0 -56
- package/dist/hub-CTf95SkP.d.ts +0 -125
- package/dist/logger-BCus3AOa.d.ts +0 -10
- package/dist/logger-epkdcXDA.js +0 -18
- package/dist/model-DztyiOGz.js +0 -274
- package/dist/model-providers-DQU57vAf.d.ts +0 -212
- package/dist/model-runner-2ONkybAq.d.ts +0 -194
- package/dist/provider-errors-DZWjl8di.js +0 -422
- package/dist/provider-probe-BDg4c1Rk.d.ts +0 -187
- package/dist/provider-probe-CwZWwFlo.js +0 -271
- package/dist/provider-registry-B91lgOmu.js +0 -217
- package/dist/provider-registry-C_mOfdHH.d.ts +0 -134
- package/skills/serve-a-model-from-a-runner/SKILL.md +0 -154
package/README.md
CHANGED
|
@@ -202,7 +202,6 @@ next to what your steps actually do.
|
|
|
202
202
|
| 💤 | **Durable sleep** — hold a step in the queue for N ms (survives restarts) |
|
|
203
203
|
| 🔀 | **Conditional branching** — `when` guards skip a step and its branch; `join: 'any'` converges |
|
|
204
204
|
| 🎯 | **Decisions** — typed choices with a confidence from a swappable decider (a function, a model, your own); below a threshold a person settles it |
|
|
205
|
-
| 🧭 | **Case loops** — `defineCaseLoop` (`octaflow/ai`): a manager agent chooses every next move of a case, each move its own workflow ending in the same tail (result → decide → next); policy refuses a choice with its reason inside the exit's schema, a move with a step that could fail is refused at definition time, and a manager that cannot decide closes the case for a person |
|
|
206
205
|
| ⏳ | **Deadlines** — a budget on a suspended step (fail, or continue with a stand-in answer) and on a whole run |
|
|
207
206
|
| ♻️ | **Retry a failed run** — `retryWorkflow` resumes from the failure point; completed steps keep their output |
|
|
208
207
|
| 🧹 | **Delete the runs about a record** — `purgeWorkflows({ entityRef })` cancels and deletes them with their sub-workflow runs and steps, for an erasure or a deleted record; refuses only while a step is executing |
|
|
@@ -216,9 +215,7 @@ next to what your steps actually do.
|
|
|
216
215
|
| 🚑 | **Crash recovery** — a step whose worker died is re-queued while its attempt budget lasts |
|
|
217
216
|
| 💓 | **Heartbeats** — a long step proves it is alive, so a dead one is caught in seconds, not minutes |
|
|
218
217
|
| 🔭 | **Observability** — lifecycle events (run history), per-step spans, and `createMeterObserver` turning the events into OpenTelemetry-style metrics — all pluggable, all structural |
|
|
219
|
-
| 🤖 | **
|
|
220
|
-
| 🗂️ | **Model providers an administrator manages** — `createModelProviders` (`octaflow/ai`): providers as rows, each with its kind, server, region, a key that crosses a cipher seam, and its models with declared capabilities (temperature, JSON mode, vision, video, tools, embedding); `createPgModelProviderStore` + `modelProviderDdl` (`octaflow/postgres`), `modelProviderColumns` (`octaflow/drizzle`); `createModelResolver` (`octaflow/ai/providers`) builds the AI SDK model from a row, shapes each call to what the model declares, hands the host its `destination` for the disclosure guard, and rebuilds after a write |
|
|
221
|
-
| 🏃 | **Model runners** — a model the app cannot reach, served by a process that connects *out*: a provider row of kind `runner` carries tags instead of a URL, a runner registered with a token (`octaflow/ai/runner`: `createModelRunnerHub`, shown once, kept as a hash) subscribes with its tags, claims the calls by long-poll through `@octabits-io/server/fetch/octaflow`'s `createModelRunnerHandler` and posts the answers back; the mailbox is three tables (`createPgModelRunnerStore` + `modelRunnerDdl`; `modelRunnerColumns`, `modelRunnerRequestColumns`, `modelRunnerChunkColumns`) whose rows live only while a call is in flight, a streamed answer's parts chunk by chunk among them; nobody online fails the call at once, so the breaker trips and the probe answers in milliseconds; `octaflow-runner` is the runner as a process (Ollama or any OpenAI-compatible server) |
|
|
218
|
+
| 🤖 | **The model layer** — AI steps with token and cost capture, quotas, the model decider, agents that end by choosing an exit, case loops, managed providers and model runners: [`@octabits-io/models`](../models/README.md) (`./octaflow` is its binding to this engine; it was `octaflow/ai` until 0.36) |
|
|
222
219
|
| 🧱 | **Pluggable everything** — `WorkflowStore`, `Dispatcher`, `StepGate`, `FlowObserver`, hooks |
|
|
223
220
|
|
|
224
221
|
---
|
|
@@ -242,8 +239,8 @@ pnpm add drizzle-orm
|
|
|
242
239
|
# pg-boss dispatcher, workers, cron scheduler
|
|
243
240
|
pnpm add pg-boss
|
|
244
241
|
|
|
245
|
-
# the AI
|
|
246
|
-
pnpm add ai @ai-sdk/provider
|
|
242
|
+
# the model layer on this engine: AI steps, agents, case loops (its ./octaflow subpath)
|
|
243
|
+
pnpm add @octabits-io/models ai @ai-sdk/provider
|
|
247
244
|
```
|
|
248
245
|
|
|
249
246
|
> Pure in-memory usage (great for tests and single-process apps) needs **nothing** beyond
|
|
@@ -251,10 +248,10 @@ pnpm add ai @ai-sdk/provider
|
|
|
251
248
|
|
|
252
249
|
### The Postgres tables
|
|
253
250
|
|
|
254
|
-
`octaflow/postgres` owns
|
|
255
|
-
`flow_workflow_step`), `flowEventDdl()` (`flow_step_event`)
|
|
256
|
-
(`flow_rate_bucket`, `flow_step_lease`)
|
|
257
|
-
|
|
251
|
+
`octaflow/postgres` owns five tables and ships their DDL: `flowStoreDdl()` (`flow_workflow`,
|
|
252
|
+
`flow_workflow_step`), `flowEventDdl()` (`flow_step_event`) and `flowGateDdl()`
|
|
253
|
+
(`flow_rate_bucket`, `flow_step_lease`). The model providers' and runners' tables, here until
|
|
254
|
+
0.36, are `@octabits-io/models/postgres`'s. Each is idempotent `CREATE TABLE IF NOT EXISTS`, takes
|
|
258
255
|
a `schema`, and is meant to be pasted into your own migration system; `applySchema(pool, ddl)`
|
|
259
256
|
is the dev and test shortcut.
|
|
260
257
|
|
|
@@ -272,8 +269,7 @@ column set, so a host on Drizzle declares it in its own schema and drizzle-kit o
|
|
|
272
269
|
migration. Where the store's queries are one SQL statement by nature — every one of octaflow's
|
|
273
270
|
is — `./drizzle` ships the columns only, and the store stays the SQL one. So
|
|
274
271
|
`octaflow/drizzle` exports `flowWorkflowColumns`, `flowWorkflowStepColumns`,
|
|
275
|
-
`flowStepEventColumns`, `flowRateBucketColumns
|
|
276
|
-
`modelRunnerColumns`, `modelRunnerRequestColumns` and `modelRunnerChunkColumns` (`drizzle-orm` an
|
|
272
|
+
`flowStepEventColumns`, `flowRateBucketColumns` and `flowStepLeaseColumns` (`drizzle-orm` an
|
|
277
273
|
optional peer) and nothing that runs a query. The foreign keys, the composite keys, the unique
|
|
278
274
|
constraint and the indexes are yours to declare on the `pgTable`; each column set's doc lists
|
|
279
275
|
the ones its DDL creates, and two of them the store relies on:
|
|
@@ -318,71 +314,6 @@ The store stays plain SQL, bound to the `schema` you hand `createPgWorkflowStore
|
|
|
318
314
|
declare the tables under the same schema and names. A test in the package holds every column
|
|
319
315
|
set and its DDL equal, column for column: a column added to one side alone fails the build.
|
|
320
316
|
|
|
321
|
-
### Model runners — a model that connects out
|
|
322
|
-
|
|
323
|
-
A model the app cannot reach: a laptop with the model loaded for a demo, a GPU box behind
|
|
324
|
-
someone's firewall, a machine that is only on when it is needed. The runner never opens a
|
|
325
|
-
port. It connects *out* to the app with a token, subscribes with its tags, claims the model
|
|
326
|
-
calls that carry those tags and posts the answers back — the shape of a self-hosted CI
|
|
327
|
-
runner. The mailbox is Postgres, because the call runs in the worker and the door the runner
|
|
328
|
-
knocks on runs in the API; a request row lives only while the call is in flight.
|
|
329
|
-
|
|
330
|
-
```ts
|
|
331
|
-
// the app — once, beside the providers
|
|
332
|
-
import { createModelRunnerHub } from 'octaflow/ai/runner';
|
|
333
|
-
import { createPgModelRunnerStore } from 'octaflow/postgres';
|
|
334
|
-
|
|
335
|
-
const runners = createModelRunnerHub({ store: createPgModelRunnerStore({ executor }) });
|
|
336
|
-
const resolver = createModelResolver({ providers, runners, wrap });
|
|
337
|
-
|
|
338
|
-
// an administrator: the provider row carries tags, the runner gets its token once
|
|
339
|
-
await providers.save({ id: 'mac', kind: 'runner', label: 'The Mac', region: 'self-hosted', tags: ['qwen'], models: [{ id: 'qwen3:32b', settings: { numCtx: 16_384 } }] });
|
|
340
|
-
const { token } = (await runners.registerRunner({ id: 'dani-mac', label: "Dani's Mac", tags: ['qwen', 'mac'] })).value;
|
|
341
|
-
|
|
342
|
-
// the API: the door, behind the host's rate limit
|
|
343
|
-
import { createModelRunnerHandler } from '@octabits-io/server/fetch/octaflow';
|
|
344
|
-
export const POST = compose(withErrorMapping())(createModelRunnerHandler({ prefix: '/api/model-runner', hub: runners }));
|
|
345
|
-
|
|
346
|
-
// the runner, on the machine with the model — the bin, or the loop in your own process
|
|
347
|
-
// npx octaflow-runner --url https://app.example/api/model-runner --token omr_… --ollama http://localhost:11434
|
|
348
|
-
import { createHttpRunnerClient, runModelRunner } from 'octaflow/ai/runner';
|
|
349
|
-
import { createOllama } from 'octaflow/ai/providers';
|
|
350
|
-
await runModelRunner({
|
|
351
|
-
client: createHttpRunnerClient({ url: 'https://app.example/api/model-runner', token }),
|
|
352
|
-
backend: createOllama({ baseUrl: 'http://localhost:11434' }),
|
|
353
|
-
});
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
**`octaflow-runner`**, the bin, is the runner as a process: `--url` and `--token` (or
|
|
357
|
-
`OCTAFLOW_RUNNER_URL` / `OCTAFLOW_RUNNER_TOKEN`), one backend — `--ollama <url>` for Ollama's
|
|
358
|
-
native API, `--openai-compatible <url>` (with `--api-key`) for mlx_lm.server, vLLM or llama.cpp
|
|
359
|
-
through the optional `@ai-sdk/openai-compatible` peer — and `--concurrency`. At start it says
|
|
360
|
-
who the token belongs to, which models the app's provider rows declare for its tags (the door
|
|
361
|
-
tells it) and which of them the local server has, with the `ollama pull` for a missing one;
|
|
362
|
-
`--check` does that and exits. A door it cannot reach is retried with a backoff, forever.
|
|
363
|
-
The skill `serve-a-model-from-a-runner` walks through the four pieces.
|
|
364
|
-
|
|
365
|
-
A runner may claim a request when it has **every tag** of the request — the provider row's
|
|
366
|
-
tags — as a CI job's labels must all be on the runner. A call with nobody online for its
|
|
367
|
-
tags fails at once with `provider_unreachable`, so `withCircuitBreaker` trips and
|
|
368
|
-
`testProvider` reports it in milliseconds instead of a timeout; whether another provider is
|
|
369
|
-
tried is the host's resolver's choice, through the same disclosure gate. A claim lasts 30 s
|
|
370
|
-
without a heartbeat; an expired claim is requeued once and failed the second time. The
|
|
371
|
-
region is the administrator's declaration about where runners with these tags are, as for
|
|
372
|
-
every provider, and the disclosure gate reads it the same way.
|
|
373
|
-
|
|
374
|
-
The wire is the AI SDK's own call and answer as JSON — binary file data as base64, a URL
|
|
375
|
-
restored on the other side — so the runner's backend is any `LanguageModelV4`: `createOllama`
|
|
376
|
-
from this package, or `@ai-sdk/openai-compatible` for mlx_lm.server, vLLM and llama.cpp.
|
|
377
|
-
`streamText` streams: the runner runs `doStream` and posts the parts in chunks as they come
|
|
378
|
-
(every 100 ms, or 64 parts), a third table carries them, and the app emits each chunk as it
|
|
379
|
-
lands; a chunk the door refuses tells the runner the caller gave up, and it cancels the
|
|
380
|
-
stream. A runner on the older wire answers a stream whole, and the app emits that as parts
|
|
381
|
-
too. Files reach the runner as bytes, since the runner model declares no URL support and the
|
|
382
|
-
SDK downloads on the app's side. Embeddings go the same way.
|
|
383
|
-
|
|
384
|
-
---
|
|
385
|
-
|
|
386
317
|
---
|
|
387
318
|
|
|
388
319
|
## Documentation
|
|
@@ -405,7 +336,7 @@ Full docs — concepts, every feature, production wiring and the API reference
|
|
|
405
336
|
| [Postgres & pg-boss](https://octaflow.octabits.io/running/postgres-and-pg-boss/) | production wiring, workers, DLQ, cron |
|
|
406
337
|
| [Cancellation & recovery](https://octaflow.octabits.io/running/cancellation-and-recovery/) | cancelling a run, sweeping steps a crash left behind, retrying a failed run, and deleting the runs about a record |
|
|
407
338
|
| [Observability](https://octaflow.octabits.io/running/observability/) · [Live progress](https://octaflow.octabits.io/running/live-progress/) | lifecycle events, spans, and streaming them to a browser |
|
|
408
|
-
| [The AI add-on](https://octaflow.octabits.io/extending/ai/) | token/cost capture, quota, usage rollups |
|
|
339
|
+
| [The AI add-on](https://octaflow.octabits.io/extending/ai/) | token/cost capture, quota, usage rollups — `@octabits-io/models/octaflow` |
|
|
409
340
|
| [Extending](https://octaflow.octabits.io/extending/interfaces/) | custom stores, dispatchers and gates |
|
|
410
341
|
| [API reference](https://octaflow.octabits.io/reference/api/) | every export, by entry point |
|
|
411
342
|
|
|
@@ -429,7 +360,6 @@ Runnable, focused examples live in [`examples/`](./examples) — see [`examples/
|
|
|
429
360
|
| 10 | `10-saga-compensation.ts` | reverse-order rollback on failure |
|
|
430
361
|
| 11 | `11-observability.ts` | observer events + tracer spans |
|
|
431
362
|
| 12 | `12-postgres-pgboss-production.ts` | full pg store + gate + event sink + pg-boss + cron |
|
|
432
|
-
| 13 | `13-ai-workflow.ts` | AI add-on (instrumented model + cost) |
|
|
433
363
|
| 14 | `14-live-progress.ts` | `FlowObserver` → SSE fan-out (build your own dashboard) |
|
|
434
364
|
| 15 | `15-conditional-branching.ts` | `when` guards + a `join: 'any'` convergence |
|
|
435
365
|
| 16 | `16-deadlines-and-retry.ts` | wait deadlines, run deadlines, `retryWorkflow`, heartbeats |
|
|
@@ -1,4 +1,112 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
//#region src/core/gate.ts
|
|
3
|
+
/**
|
|
4
|
+
* The rule keys a request is held to, in the order they are checked: the
|
|
5
|
+
* step's type, then each resource it declares, without repeats. The shipped
|
|
6
|
+
* gates look up their `concurrency` and `rateLimit` rules by these keys, so a
|
|
7
|
+
* rule keyed `'llm:local'` holds every step that names that resource, whatever
|
|
8
|
+
* its type, and a rule keyed by a type still holds that type alone. A custom
|
|
9
|
+
* gate that wants the same vocabulary calls this.
|
|
10
|
+
*/
|
|
11
|
+
function gateRuleKeys(req) {
|
|
12
|
+
const keys = [req.stepType];
|
|
13
|
+
for (const resource of req.resources ?? []) if (!keys.includes(resource)) keys.push(resource);
|
|
14
|
+
return keys;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A per-process {@link StepGate}: concurrency caps (held slots) plus token-bucket
|
|
18
|
+
* rate limits (throughput), each keyed by a step type or by a resource a step
|
|
19
|
+
* declares ({@link gateRuleKeys}). Both are optional; a step none of whose keys
|
|
20
|
+
* has a rule is always admitted, and a step with several keys must pass every
|
|
21
|
+
* rule among them.
|
|
22
|
+
*
|
|
23
|
+
* Concurrency is reserved first, then the rate tokens — so a rate denial does not
|
|
24
|
+
* waste a concurrency slot, and a denial by a later rule gives back what earlier
|
|
25
|
+
* ones granted. Good for single-worker deployments; swap in a shared-store gate
|
|
26
|
+
* for multi-worker concurrency control.
|
|
27
|
+
*/
|
|
28
|
+
function createInMemoryStepGate(config = {}) {
|
|
29
|
+
const now = config.now ?? (() => Date.now());
|
|
30
|
+
const concurrencyRetry = Math.max(1, config.concurrencyRetrySeconds ?? 1);
|
|
31
|
+
const running = /* @__PURE__ */ new Map();
|
|
32
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
33
|
+
const capacityOf = (rule) => rule.burst ?? Math.max(1, Math.ceil(rule.perSecond));
|
|
34
|
+
function rateCheck(key) {
|
|
35
|
+
const rule = config.rateLimit?.[key];
|
|
36
|
+
if (!rule) return { ok: true };
|
|
37
|
+
const capacity = capacityOf(rule);
|
|
38
|
+
const tNow = now();
|
|
39
|
+
let b = buckets.get(key);
|
|
40
|
+
if (!b) {
|
|
41
|
+
b = {
|
|
42
|
+
tokens: capacity,
|
|
43
|
+
updatedMs: tNow
|
|
44
|
+
};
|
|
45
|
+
buckets.set(key, b);
|
|
46
|
+
}
|
|
47
|
+
const elapsedSec = Math.max(0, (tNow - b.updatedMs) / 1e3);
|
|
48
|
+
b.tokens = Math.min(capacity, b.tokens + elapsedSec * rule.perSecond);
|
|
49
|
+
b.updatedMs = tNow;
|
|
50
|
+
if (b.tokens >= 1) {
|
|
51
|
+
b.tokens -= 1;
|
|
52
|
+
return { ok: true };
|
|
53
|
+
}
|
|
54
|
+
const needed = 1 - b.tokens;
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
retryAfterSeconds: Math.max(1, Math.ceil(needed / rule.perSecond))
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Give back a token a denied request had already taken from an earlier bucket. */
|
|
61
|
+
function refund(key) {
|
|
62
|
+
const rule = config.rateLimit?.[key];
|
|
63
|
+
const b = buckets.get(key);
|
|
64
|
+
if (rule && b) b.tokens = Math.min(capacityOf(rule), b.tokens + 1);
|
|
65
|
+
}
|
|
66
|
+
return { async acquire(req) {
|
|
67
|
+
const keys = gateRuleKeys(req);
|
|
68
|
+
const held = [];
|
|
69
|
+
let released = false;
|
|
70
|
+
const release = () => {
|
|
71
|
+
if (released) return;
|
|
72
|
+
released = true;
|
|
73
|
+
for (const key of held) running.set(key, Math.max(0, (running.get(key) ?? 1) - 1));
|
|
74
|
+
};
|
|
75
|
+
for (const key of keys) {
|
|
76
|
+
const cRule = config.concurrency?.[key];
|
|
77
|
+
if (!cRule) continue;
|
|
78
|
+
const current = running.get(key) ?? 0;
|
|
79
|
+
if (current >= cRule.maxConcurrent) {
|
|
80
|
+
release();
|
|
81
|
+
return {
|
|
82
|
+
admitted: false,
|
|
83
|
+
retryAfterSeconds: concurrencyRetry
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
running.set(key, current + 1);
|
|
87
|
+
held.push(key);
|
|
88
|
+
}
|
|
89
|
+
const taken = [];
|
|
90
|
+
for (const key of keys) {
|
|
91
|
+
if (!config.rateLimit?.[key]) continue;
|
|
92
|
+
const rate = rateCheck(key);
|
|
93
|
+
if (!rate.ok) {
|
|
94
|
+
for (const t of taken) refund(t);
|
|
95
|
+
release();
|
|
96
|
+
return {
|
|
97
|
+
admitted: false,
|
|
98
|
+
retryAfterSeconds: rate.retryAfterSeconds
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
taken.push(key);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
admitted: true,
|
|
105
|
+
release
|
|
106
|
+
};
|
|
107
|
+
} };
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
2
110
|
//#region src/core/retry.ts
|
|
3
111
|
/**
|
|
4
112
|
* Realm-safe marker for an explicit retryability decision. `Symbol.for` so a
|
|
@@ -882,4 +990,4 @@ function toPublicWorkflow(workflow) {
|
|
|
882
990
|
};
|
|
883
991
|
}
|
|
884
992
|
//#endregion
|
|
885
|
-
export { nonRetryableError as C, markRetryable as S, defineStep as _, WORKFLOW_STATUS_SCHEMA as a, explicitRetryability as b, toPublicWorkflow as c, defineDecisionStep as d, functionDecider as f, defineSleepStep as g, defineMapStep as h, STEP_DISPLAY_STATUS_SCHEMA as i, defineDecisionOutcomeStep as l, buildWorkflow as m, PUBLIC_WORKFLOW_STEP_SCHEMA as n, toDisplayStepStatus as o, resolveDecision as p, STEP_DISPLAY_STATUS as r, toPublicStep as s, PUBLIC_WORKFLOW_SCHEMA as t, defineDecisionReviewStep as u, defineSubWorkflowStep as v, retryableError as w, isRetryableError as x, defineWaitStep as y };
|
|
993
|
+
export { nonRetryableError as C, gateRuleKeys as E, markRetryable as S, createInMemoryStepGate as T, defineStep as _, WORKFLOW_STATUS_SCHEMA as a, explicitRetryability as b, toPublicWorkflow as c, defineDecisionStep as d, functionDecider as f, defineSleepStep as g, defineMapStep as h, STEP_DISPLAY_STATUS_SCHEMA as i, defineDecisionOutcomeStep as l, buildWorkflow as m, PUBLIC_WORKFLOW_STEP_SCHEMA as n, toDisplayStepStatus as o, resolveDecision as p, STEP_DISPLAY_STATUS as r, toPublicStep as s, PUBLIC_WORKFLOW_SCHEMA as t, defineDecisionReviewStep as u, defineSubWorkflowStep as v, retryableError as w, isRetryableError as x, defineWaitStep as y };
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { St as Result, lt as WorkflowId, nt as StepId, xt as FlowErrorShape } from "./index-DZUO24Rz.js";
|
|
2
|
+
//#region src/core/logger.d.ts
|
|
3
|
+
type LogAttributes = Record<string, unknown>;
|
|
4
|
+
interface Logger {
|
|
5
|
+
info(message: string, attributes?: LogAttributes): void;
|
|
6
|
+
warn(message: string, attributes?: LogAttributes): void;
|
|
7
|
+
error(message: string, error?: Error, attributes?: LogAttributes): void;
|
|
8
|
+
}
|
|
9
|
+
declare const noopLogger: Logger;
|
|
10
|
+
//#endregion
|
|
2
11
|
//#region src/core/dispatcher.d.ts
|
|
3
12
|
/**
|
|
4
13
|
* What a step job is for. A queue carries two kinds of work for a step, and
|
|
@@ -61,4 +70,4 @@ interface Dispatcher {
|
|
|
61
70
|
enqueueStepIn?(handle: unknown, payload: DispatchStepPayload, options?: EnqueueOptions): Promise<Result<void, FlowErrorShape>>;
|
|
62
71
|
}
|
|
63
72
|
//#endregion
|
|
64
|
-
export { EnqueueOptions as i, DispatchStepPayload as n, Dispatcher as r, DispatchKind as t };
|
|
73
|
+
export { LogAttributes as a, EnqueueOptions as i, DispatchStepPayload as n, Logger as o, Dispatcher as r, noopLogger as s, DispatchKind as t };
|
package/dist/drizzle/index.d.ts
CHANGED
|
@@ -170,107 +170,4 @@ export declare const flowStepLeaseColumns: {
|
|
|
170
170
|
/** A lease past this instant is reaped on the next acquire. */
|
|
171
171
|
expiresAt: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>>;
|
|
172
172
|
};
|
|
173
|
-
/**
|
|
174
|
-
* `model_provider` — one row per provider an administrator manages
|
|
175
|
-
* (`createModelProviders` in `octaflow/ai`, over `createPgModelProviderStore`).
|
|
176
|
-
* `id` is the primary key; nothing else is declared beyond the columns. A host
|
|
177
|
-
* whose customers bring their own keys adds its scope column beside these and
|
|
178
|
-
* makes the key composite.
|
|
179
|
-
*
|
|
180
|
-
* ```ts
|
|
181
|
-
* import { pgTable } from 'drizzle-orm/pg-core';
|
|
182
|
-
* import { modelProviderColumns } from 'octaflow/drizzle';
|
|
183
|
-
*
|
|
184
|
-
* export const modelProvider = pgTable('model_provider', modelProviderColumns);
|
|
185
|
-
* ```
|
|
186
|
-
*/
|
|
187
|
-
export declare const modelProviderColumns: {
|
|
188
|
-
id: import("drizzle-orm").IsPrimaryKey<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"id", [string, ...string[]]>>>;
|
|
189
|
-
kind: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"kind", [string, ...string[]]>>;
|
|
190
|
-
label: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"label", [string, ...string[]]>>;
|
|
191
|
-
baseUrl: import("drizzle-orm/pg-core").PgTextBuilderInitial<"base_url", [string, ...string[]]>;
|
|
192
|
-
region: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"region", [string, ...string[]]>>;
|
|
193
|
-
apiKey: import("drizzle-orm/pg-core").PgTextBuilderInitial<"api_key", [string, ...string[]]>;
|
|
194
|
-
keyHint: import("drizzle-orm/pg-core").PgTextBuilderInitial<"key_hint", [string, ...string[]]>;
|
|
195
|
-
headers: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm").$Type<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"headers">, Record<string, string>>>>;
|
|
196
|
-
tags: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm").$Type<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"tags">, string[]>>>;
|
|
197
|
-
models: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm").$Type<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"models">, unknown[]>>>;
|
|
198
|
-
defaultModel: import("drizzle-orm/pg-core").PgTextBuilderInitial<"default_model", [string, ...string[]]>;
|
|
199
|
-
enabled: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgBooleanBuilderInitial<"enabled">>>;
|
|
200
|
-
updatedAt: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>>>;
|
|
201
|
-
updatedBy: import("drizzle-orm/pg-core").PgTextBuilderInitial<"updated_by", [string, ...string[]]>;
|
|
202
|
-
};
|
|
203
|
-
/**
|
|
204
|
-
* `model_runner` — one row per runner an administrator registered
|
|
205
|
-
* (`createModelRunnerHub` in `octaflow/ai/runner`, over
|
|
206
|
-
* `createPgModelRunnerStore`). `id` is the primary key; the DDL adds a unique
|
|
207
|
-
* index on `token_hash`, which the host mirrors. No scope column, as for the
|
|
208
|
-
* providers.
|
|
209
|
-
*
|
|
210
|
-
* ```ts
|
|
211
|
-
* import { pgTable, uniqueIndex } from 'drizzle-orm/pg-core';
|
|
212
|
-
* import { modelRunnerColumns } from 'octaflow/drizzle';
|
|
213
|
-
*
|
|
214
|
-
* export const modelRunner = pgTable('model_runner', modelRunnerColumns, (t) => [uniqueIndex('model_runner_token_hash_idx').on(t.tokenHash)]);
|
|
215
|
-
* ```
|
|
216
|
-
*/
|
|
217
|
-
export declare const modelRunnerColumns: {
|
|
218
|
-
id: import("drizzle-orm").IsPrimaryKey<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"id", [string, ...string[]]>>>;
|
|
219
|
-
label: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"label", [string, ...string[]]>>;
|
|
220
|
-
tags: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm").$Type<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"tags">, string[]>>>;
|
|
221
|
-
concurrency: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgIntegerBuilderInitial<"concurrency">>>;
|
|
222
|
-
tokenHash: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"token_hash", [string, ...string[]]>>;
|
|
223
|
-
lastSeenAt: import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>;
|
|
224
|
-
createdAt: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>>>;
|
|
225
|
-
createdBy: import("drizzle-orm/pg-core").PgTextBuilderInitial<"created_by", [string, ...string[]]>;
|
|
226
|
-
};
|
|
227
|
-
/**
|
|
228
|
-
* `model_runner_request` — the mailbox: one row per model call in flight,
|
|
229
|
-
* deleted as soon as the caller read the answer. The DDL's index is the
|
|
230
|
-
* claim's, `(created_at) WHERE status = 'pending'`, which the host mirrors.
|
|
231
|
-
*
|
|
232
|
-
* ```ts
|
|
233
|
-
* import { index, pgTable } from 'drizzle-orm/pg-core';
|
|
234
|
-
* import { modelRunnerRequestColumns } from 'octaflow/drizzle';
|
|
235
|
-
*
|
|
236
|
-
* export const modelRunnerRequest = pgTable('model_runner_request', modelRunnerRequestColumns, (t) => [
|
|
237
|
-
* index('model_runner_request_pending_idx').on(t.createdAt).where(sql`${t.status} = 'pending'`),
|
|
238
|
-
* ]);
|
|
239
|
-
* ```
|
|
240
|
-
*/
|
|
241
|
-
export declare const modelRunnerRequestColumns: {
|
|
242
|
-
id: import("drizzle-orm").IsPrimaryKey<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"id", [string, ...string[]]>>>;
|
|
243
|
-
providerId: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"provider_id", [string, ...string[]]>>;
|
|
244
|
-
tags: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm").$Type<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"tags">, string[]>>>;
|
|
245
|
-
model: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"model", [string, ...string[]]>>;
|
|
246
|
-
kind: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"kind", [string, ...string[]]>>;
|
|
247
|
-
payload: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"payload">>;
|
|
248
|
-
status: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"status", [string, ...string[]]>>>;
|
|
249
|
-
claimedBy: import("drizzle-orm/pg-core").PgTextBuilderInitial<"claimed_by", [string, ...string[]]>;
|
|
250
|
-
claimedAt: import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>;
|
|
251
|
-
leaseUntil: import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>;
|
|
252
|
-
attempts: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgIntegerBuilderInitial<"attempts">>>;
|
|
253
|
-
result: import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"result">;
|
|
254
|
-
error: import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"error">;
|
|
255
|
-
createdAt: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>>>;
|
|
256
|
-
finishedAt: import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>;
|
|
257
|
-
};
|
|
258
|
-
/**
|
|
259
|
-
* `model_runner_chunk` — the parts of a `stream` request as the runner posted
|
|
260
|
-
* them, a batch per row, read and deleted with the request. The key is
|
|
261
|
-
* composite, `(request_id, seq)`, and the host declares it.
|
|
262
|
-
*
|
|
263
|
-
* ```ts
|
|
264
|
-
* import { pgTable, primaryKey } from 'drizzle-orm/pg-core';
|
|
265
|
-
* import { modelRunnerChunkColumns } from 'octaflow/drizzle';
|
|
266
|
-
*
|
|
267
|
-
* export const modelRunnerChunk = pgTable('model_runner_chunk', modelRunnerChunkColumns, (t) => [primaryKey({ columns: [t.requestId, t.seq] })]);
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
export declare const modelRunnerChunkColumns: {
|
|
271
|
-
requestId: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTextBuilderInitial<"request_id", [string, ...string[]]>>;
|
|
272
|
-
seq: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgIntegerBuilderInitial<"seq">>;
|
|
273
|
-
parts: import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgJsonbBuilderInitial<"parts">>;
|
|
274
|
-
createdAt: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/pg-core").PgTimestampBuilderInitial<string>>>;
|
|
275
|
-
};
|
|
276
173
|
//#endregion
|
package/dist/drizzle/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bigint, bigserial,
|
|
1
|
+
import { bigint, bigserial, doublePrecision, integer, jsonb, text, timestamp } from "drizzle-orm/pg-core";
|
|
2
2
|
//#region src/drizzle/index.ts
|
|
3
3
|
/**
|
|
4
4
|
* `octaflow/drizzle` — the engine's tables as Drizzle column sets.
|
|
@@ -195,108 +195,5 @@ const flowStepLeaseColumns = {
|
|
|
195
195
|
/** A lease past this instant is reaped on the next acquire. */
|
|
196
196
|
expiresAt: timestamptz("expires_at").notNull()
|
|
197
197
|
};
|
|
198
|
-
/**
|
|
199
|
-
* `model_provider` — one row per provider an administrator manages
|
|
200
|
-
* (`createModelProviders` in `octaflow/ai`, over `createPgModelProviderStore`).
|
|
201
|
-
* `id` is the primary key; nothing else is declared beyond the columns. A host
|
|
202
|
-
* whose customers bring their own keys adds its scope column beside these and
|
|
203
|
-
* makes the key composite.
|
|
204
|
-
*
|
|
205
|
-
* ```ts
|
|
206
|
-
* import { pgTable } from 'drizzle-orm/pg-core';
|
|
207
|
-
* import { modelProviderColumns } from 'octaflow/drizzle';
|
|
208
|
-
*
|
|
209
|
-
* export const modelProvider = pgTable('model_provider', modelProviderColumns);
|
|
210
|
-
* ```
|
|
211
|
-
*/
|
|
212
|
-
const modelProviderColumns = {
|
|
213
|
-
id: text("id").primaryKey(),
|
|
214
|
-
kind: text("kind").notNull(),
|
|
215
|
-
label: text("label").notNull(),
|
|
216
|
-
baseUrl: text("base_url"),
|
|
217
|
-
region: text("region").notNull(),
|
|
218
|
-
apiKey: text("api_key"),
|
|
219
|
-
keyHint: text("key_hint"),
|
|
220
|
-
headers: jsonb("headers").$type().notNull().default({}),
|
|
221
|
-
tags: jsonb("tags").$type().notNull().default([]),
|
|
222
|
-
models: jsonb("models").$type().notNull().default([]),
|
|
223
|
-
defaultModel: text("default_model"),
|
|
224
|
-
enabled: boolean("enabled").notNull().default(true),
|
|
225
|
-
updatedAt: timestamptz("updated_at").notNull().defaultNow(),
|
|
226
|
-
updatedBy: text("updated_by")
|
|
227
|
-
};
|
|
228
|
-
/**
|
|
229
|
-
* `model_runner` — one row per runner an administrator registered
|
|
230
|
-
* (`createModelRunnerHub` in `octaflow/ai/runner`, over
|
|
231
|
-
* `createPgModelRunnerStore`). `id` is the primary key; the DDL adds a unique
|
|
232
|
-
* index on `token_hash`, which the host mirrors. No scope column, as for the
|
|
233
|
-
* providers.
|
|
234
|
-
*
|
|
235
|
-
* ```ts
|
|
236
|
-
* import { pgTable, uniqueIndex } from 'drizzle-orm/pg-core';
|
|
237
|
-
* import { modelRunnerColumns } from 'octaflow/drizzle';
|
|
238
|
-
*
|
|
239
|
-
* export const modelRunner = pgTable('model_runner', modelRunnerColumns, (t) => [uniqueIndex('model_runner_token_hash_idx').on(t.tokenHash)]);
|
|
240
|
-
* ```
|
|
241
|
-
*/
|
|
242
|
-
const modelRunnerColumns = {
|
|
243
|
-
id: text("id").primaryKey(),
|
|
244
|
-
label: text("label").notNull(),
|
|
245
|
-
tags: jsonb("tags").$type().notNull().default([]),
|
|
246
|
-
concurrency: integer("concurrency").notNull().default(1),
|
|
247
|
-
tokenHash: text("token_hash").notNull(),
|
|
248
|
-
lastSeenAt: timestamptz("last_seen_at"),
|
|
249
|
-
createdAt: timestamptz("created_at").notNull().defaultNow(),
|
|
250
|
-
createdBy: text("created_by")
|
|
251
|
-
};
|
|
252
|
-
/**
|
|
253
|
-
* `model_runner_request` — the mailbox: one row per model call in flight,
|
|
254
|
-
* deleted as soon as the caller read the answer. The DDL's index is the
|
|
255
|
-
* claim's, `(created_at) WHERE status = 'pending'`, which the host mirrors.
|
|
256
|
-
*
|
|
257
|
-
* ```ts
|
|
258
|
-
* import { index, pgTable } from 'drizzle-orm/pg-core';
|
|
259
|
-
* import { modelRunnerRequestColumns } from 'octaflow/drizzle';
|
|
260
|
-
*
|
|
261
|
-
* export const modelRunnerRequest = pgTable('model_runner_request', modelRunnerRequestColumns, (t) => [
|
|
262
|
-
* index('model_runner_request_pending_idx').on(t.createdAt).where(sql`${t.status} = 'pending'`),
|
|
263
|
-
* ]);
|
|
264
|
-
* ```
|
|
265
|
-
*/
|
|
266
|
-
const modelRunnerRequestColumns = {
|
|
267
|
-
id: text("id").primaryKey(),
|
|
268
|
-
providerId: text("provider_id").notNull(),
|
|
269
|
-
tags: jsonb("tags").$type().notNull().default([]),
|
|
270
|
-
model: text("model").notNull(),
|
|
271
|
-
kind: text("kind").notNull(),
|
|
272
|
-
payload: jsonb("payload").notNull(),
|
|
273
|
-
status: text("status").notNull().default("pending"),
|
|
274
|
-
claimedBy: text("claimed_by"),
|
|
275
|
-
claimedAt: timestamptz("claimed_at"),
|
|
276
|
-
leaseUntil: timestamptz("lease_until"),
|
|
277
|
-
attempts: integer("attempts").notNull().default(0),
|
|
278
|
-
result: jsonb("result"),
|
|
279
|
-
error: jsonb("error"),
|
|
280
|
-
createdAt: timestamptz("created_at").notNull().defaultNow(),
|
|
281
|
-
finishedAt: timestamptz("finished_at")
|
|
282
|
-
};
|
|
283
|
-
/**
|
|
284
|
-
* `model_runner_chunk` — the parts of a `stream` request as the runner posted
|
|
285
|
-
* them, a batch per row, read and deleted with the request. The key is
|
|
286
|
-
* composite, `(request_id, seq)`, and the host declares it.
|
|
287
|
-
*
|
|
288
|
-
* ```ts
|
|
289
|
-
* import { pgTable, primaryKey } from 'drizzle-orm/pg-core';
|
|
290
|
-
* import { modelRunnerChunkColumns } from 'octaflow/drizzle';
|
|
291
|
-
*
|
|
292
|
-
* export const modelRunnerChunk = pgTable('model_runner_chunk', modelRunnerChunkColumns, (t) => [primaryKey({ columns: [t.requestId, t.seq] })]);
|
|
293
|
-
* ```
|
|
294
|
-
*/
|
|
295
|
-
const modelRunnerChunkColumns = {
|
|
296
|
-
requestId: text("request_id").notNull(),
|
|
297
|
-
seq: integer("seq").notNull(),
|
|
298
|
-
parts: jsonb("parts").notNull(),
|
|
299
|
-
createdAt: timestamptz("created_at").notNull().defaultNow()
|
|
300
|
-
};
|
|
301
198
|
//#endregion
|
|
302
|
-
export { flowRateBucketColumns, flowStepEventColumns, flowStepLeaseColumns, flowWorkflowColumns, flowWorkflowStepColumns
|
|
199
|
+
export { flowRateBucketColumns, flowStepEventColumns, flowStepLeaseColumns, flowWorkflowColumns, flowWorkflowStepColumns };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,60 @@
|
|
|
1
1
|
import { $ as StepHandler, A as StepOutput, B as defineWaitStep, C as defineDecisionOutcomeStep, Ct as err, D as resolveDecision, E as functionDecider, F as buildWorkflow, G as StepCompensateHandler, H as InvalidWorkflowDefinitionError, I as defineMapStep, J as StepDefinition, K as StepCompensationContext, L as defineSleepStep, M as TypedStepContext, N as TypedWorkflow, O as DefineStepConfig, P as WorkflowOutput, Q as StepFailurePolicy, R as defineStep, S as DecisionStep, St as Result, T as defineDecisionStep, U as RetryPolicy, V as FlowError, W as StartOptions, X as StepError, Y as StepDelay, Z as StepExecutionContext, _ as DecisionOutput, _t as PlannedSkip, a as STEP_DISPLAY_STATUS, at as StepStatus, b as DecisionResponse, bt as isTerminalStepStatus, c as WORKFLOW_STATUS_SCHEMA, ct as WorkflowDefinition, d as toPublicWorkflow, dt as WorkflowNotRetryableError, et as StepHandlerNotFoundError, f as Decider, ft as WorkflowRecord, g as DecisionOutcome, gt as JoinRule, h as DecisionChoices, ht as WorkflowWithSteps, i as PublicWorkflowStep, it as StepRegistration, j as TypedStep, k as StepDeps, l as toDisplayStepStatus, lt as WorkflowId, m as DecisionAnswers, mt as WorkflowStepRunningError, n as PUBLIC_WORKFLOW_STEP_SCHEMA, nt as StepId, o as STEP_DISPLAY_STATUS_SCHEMA, ot as WaitTimeoutPolicy, p as DecisionAnswer, pt as WorkflowStatus, q as StepConditionHandler, r as PublicWorkflow, rt as StepRecord, s as StepDisplayStatus, st as WorkflowCreatedResult, t as PUBLIC_WORKFLOW_SCHEMA, tt as StepHandlerRegistry, u as toPublicStep, ut as WorkflowNotFoundError, v as DecisionQuestions, vt as ReadinessPlan, w as defineDecisionReviewStep, wt as ok, x as DecisionReview, xt as FlowErrorShape, y as DecisionRequest, yt as computeReadiness, z as defineSubWorkflowStep } from "./index-DZUO24Rz.js";
|
|
2
|
-
import { n as Logger, r as noopLogger, t as
|
|
2
|
+
import { a as LogAttributes, i as EnqueueOptions, n as DispatchStepPayload, o as Logger, r as Dispatcher, s as noopLogger, t as DispatchKind } from "./dispatcher-ltwBJjKc.js";
|
|
3
3
|
import { A as FinishWorkflowParams, C as gateRuleKeys, D as CreateWorkflowStep, E as CreateWorkflowParams, F as WorkflowTreeFilter, M as ReopenWorkflowParams, N as TransactionalScope, O as CreatedWorkflow, P as WorkflowStore, S as createInMemoryStepGate, T as CompleteStepParams, _ as InMemoryStepGateConfig, a as FlowSpan, b as StepGateDecision, c as RecordingObserver, d as createMeterObserver, f as createRecordingObserver, g as ConcurrencyRule, h as noopTracer, i as FlowObserver, j as ListWorkflowsFilters, k as FailStepParams, l as RecordingTracer, m as noopObserver, n as FlowEventType, o as FlowTracer, p as createRecordingTracer, r as FlowMeter, s as RecordedSpan, t as FlowEvent, u as combineObservers, v as RateRule, w as AddChildStep, x as StepGateRequest, y as StepGate } from "./observability-BLUEjdto.js";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
//#region src/core/hooks.d.ts
|
|
5
|
+
export interface BeforeStartArgs {
|
|
6
|
+
definition: WorkflowDefinition;
|
|
7
|
+
input: Record<string, unknown>;
|
|
8
|
+
options?: StartOptions;
|
|
9
|
+
}
|
|
10
|
+
export interface BeforeStartResult {
|
|
11
|
+
/** Extra metadata persisted on the workflow row (merged over `options.metadata`). */
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface BuildStepContextArgs {
|
|
15
|
+
workflowId: WorkflowId;
|
|
16
|
+
stepId: StepId;
|
|
17
|
+
stepKey: string;
|
|
18
|
+
partitionKey: string;
|
|
19
|
+
workflow: WorkflowRecord;
|
|
20
|
+
step: StepRecord;
|
|
21
|
+
}
|
|
22
|
+
export interface AfterStepArgs<TContext> {
|
|
23
|
+
workflowId: WorkflowId;
|
|
24
|
+
stepId: StepId;
|
|
25
|
+
partitionKey: string;
|
|
26
|
+
workflow: WorkflowRecord;
|
|
27
|
+
step: StepRecord;
|
|
28
|
+
output: Record<string, unknown>;
|
|
29
|
+
/** The same context object that was handed to the step handler. */
|
|
30
|
+
context: TContext;
|
|
31
|
+
}
|
|
32
|
+
export interface WorkflowCompletedArgs {
|
|
33
|
+
workflowId: WorkflowId;
|
|
34
|
+
partitionKey: string;
|
|
35
|
+
workflow: WorkflowRecord;
|
|
36
|
+
}
|
|
37
|
+
export interface WorkflowHooks<TContext = unknown> {
|
|
38
|
+
/**
|
|
39
|
+
* Runs before a workflow is created. Return an error to reject the start
|
|
40
|
+
* (e.g. quota exceeded) — the engine passes the error through untouched.
|
|
41
|
+
*/
|
|
42
|
+
onBeforeStart?(args: BeforeStartArgs): Promise<Result<BeforeStartResult, FlowErrorShape>>;
|
|
43
|
+
/**
|
|
44
|
+
* Produces the per-step `context` handed to the handler (and later to
|
|
45
|
+
* `onAfterStep`). This is where the AI add-on resolves and instruments a model.
|
|
46
|
+
* If omitted, handlers receive `undefined` as their context.
|
|
47
|
+
*/
|
|
48
|
+
buildStepContext?(args: BuildStepContextArgs): TContext | Promise<TContext>;
|
|
49
|
+
/**
|
|
50
|
+
* Runs after a step handler succeeds, before the step is marked completed.
|
|
51
|
+
* The AI add-on reads token usage off `context` here and persists cost.
|
|
52
|
+
*/
|
|
53
|
+
onAfterStep?(args: AfterStepArgs<TContext>): Promise<void>;
|
|
54
|
+
/** Runs once when a workflow reaches `completed` (e.g. daily usage rollup). */
|
|
55
|
+
onWorkflowCompleted?(args: WorkflowCompletedArgs): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
6
58
|
//#region src/core/registry.d.ts
|
|
7
59
|
/**
|
|
8
60
|
* Creates an in-memory step handler registry.
|
|
@@ -168,4 +220,4 @@ export declare function createInMemoryWorkflowStore(partitionKey?: string): Work
|
|
|
168
220
|
};
|
|
169
221
|
};
|
|
170
222
|
//#endregion
|
|
171
|
-
export { AddChildStep,
|
|
223
|
+
export { AddChildStep, CompleteStepParams, ConcurrencyRule, CreateWorkflowParams, CreateWorkflowStep, CreatedWorkflow, Decider, DecisionAnswer, DecisionAnswers, DecisionChoices, DecisionOutcome, DecisionOutput, DecisionQuestions, DecisionRequest, DecisionResponse, DecisionReview, DecisionStep, DefineStepConfig, DispatchKind, DispatchStepPayload, Dispatcher, EnqueueOptions, FailStepParams, FinishWorkflowParams, FlowError, FlowErrorShape, FlowEvent, FlowEventType, FlowMeter, FlowObserver, FlowSpan, FlowTracer, InMemoryStepGateConfig, InvalidWorkflowDefinitionError, JoinRule, ListWorkflowsFilters, LogAttributes, Logger, PUBLIC_WORKFLOW_SCHEMA, PUBLIC_WORKFLOW_STEP_SCHEMA, PlannedSkip, PublicWorkflow, PublicWorkflowStep, RateRule, ReadinessPlan, RecordedSpan, RecordingObserver, RecordingTracer, ReopenWorkflowParams, Result, RetryPolicy, STEP_DISPLAY_STATUS, STEP_DISPLAY_STATUS_SCHEMA, StartOptions, StepCompensateHandler, StepCompensationContext, StepConditionHandler, StepDefinition, StepDelay, StepDeps, StepDisplayStatus, StepError, StepExecutionContext, StepFailurePolicy, StepGate, StepGateDecision, StepGateRequest, StepHandler, StepHandlerNotFoundError, StepHandlerRegistry, StepId, StepOutput, StepRecord, StepRegistration, StepStatus, TransactionalScope, TypedStep, TypedStepContext, TypedWorkflow, WORKFLOW_STATUS_SCHEMA, WaitTimeoutPolicy, WorkflowCreatedResult, WorkflowDefinition, WorkflowId, WorkflowNotFoundError, WorkflowNotRetryableError, WorkflowOutput, WorkflowRecord, WorkflowStatus, WorkflowStepRunningError, WorkflowStore, WorkflowTreeFilter, WorkflowWithSteps, buildWorkflow, combineObservers, computeReadiness, createInMemoryStepGate, createMeterObserver, createRecordingObserver, createRecordingTracer, defineDecisionOutcomeStep, defineDecisionReviewStep, defineDecisionStep, defineMapStep, defineSleepStep, defineStep, defineSubWorkflowStep, defineWaitStep, err, functionDecider, gateRuleKeys, isTerminalStepStatus, noopLogger, noopObserver, noopTracer, ok, resolveDecision, toDisplayStepStatus, toPublicStep, toPublicWorkflow };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { C as nonRetryableError, E as gateRuleKeys, S as markRetryable, T as createInMemoryStepGate, _ as defineStep, a as WORKFLOW_STATUS_SCHEMA, b as explicitRetryability, c as toPublicWorkflow, d as defineDecisionStep, f as functionDecider, g as defineSleepStep, h as defineMapStep, i as STEP_DISPLAY_STATUS_SCHEMA, l as defineDecisionOutcomeStep, m as buildWorkflow, n as PUBLIC_WORKFLOW_STEP_SCHEMA, o as toDisplayStepStatus, p as resolveDecision, r as STEP_DISPLAY_STATUS, s as toPublicStep, t as PUBLIC_WORKFLOW_SCHEMA, u as defineDecisionReviewStep, v as defineSubWorkflowStep, w as retryableError, x as isRetryableError, y as defineWaitStep } from "./core-YqnPwR-v.js";
|
|
2
|
+
//#region src/core/result.ts
|
|
3
|
+
const ok = (value) => ({
|
|
4
|
+
ok: true,
|
|
5
|
+
value
|
|
6
|
+
});
|
|
7
|
+
const err = (error) => ({
|
|
8
|
+
ok: false,
|
|
9
|
+
error
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/core/logger.ts
|
|
13
|
+
const noopLogger = {
|
|
14
|
+
info() {},
|
|
15
|
+
warn() {},
|
|
16
|
+
error() {}
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
4
19
|
//#region src/core/readiness.ts
|
|
5
20
|
/** Statuses a step can no longer move out of on its own. */
|
|
6
21
|
const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
package/dist/pg-boss/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import "../index-DZUO24Rz.js";
|
|
2
|
-
import {
|
|
3
|
-
import { r as Dispatcher } from "../dispatcher-BQErUGy_.js";
|
|
2
|
+
import { o as Logger, r as Dispatcher } from "../dispatcher-ltwBJjKc.js";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { PgBoss, Schedule } from "pg-boss";
|
|
6
5
|
//#region src/pg-boss/payload.d.ts
|