@voltro/plugin-ai-flows 0.85.0 → 0.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  # Third-Party Notices — @voltro/plugin-ai-flows
2
2
 
3
- This package depends on the open-source software listed below. Each is the
3
+ This package uses the open-source software listed below. Each is the
4
4
  property of its respective copyright holders and is used under the terms of
5
5
  its license. This file is provided for attribution; it grants no rights in
6
6
  @voltro/plugin-ai-flows itself, which is proprietary (see LICENSE).
7
7
 
8
- Generated from the resolved runtime dependency closure (62 packages).
8
+ Generated from the resolved runtime dependency closure (61 packages).
9
9
 
10
10
  ---
11
11
 
@@ -4259,34 +4259,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4259
4259
  SOFTWARE.
4260
4260
  ```
4261
4261
 
4262
- ## layerr@3.0.0
4263
-
4264
- License: MIT
4265
-
4266
- ```
4267
- MIT License
4268
-
4269
- Copyright (c) 2020 Perry Mitchell
4270
-
4271
- Permission is hereby granted, free of charge, to any person obtaining a copy
4272
- of this software and associated documentation files (the "Software"), to deal
4273
- in the Software without restriction, including without limitation the rights
4274
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4275
- copies of the Software, and to permit persons to whom the Software is
4276
- furnished to do so, subject to the following conditions:
4277
-
4278
- The above copyright notice and this permission notice shall be included in all
4279
- copies or substantial portions of the Software.
4280
-
4281
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4282
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4283
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4284
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4285
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4286
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4287
- SOFTWARE.
4288
- ```
4289
-
4290
4262
  ## lib0@0.2.117
4291
4263
 
4292
4264
  License: MIT
@@ -4664,14 +4636,14 @@ Apache License
4664
4636
  limitations under the License.
4665
4637
  ```
4666
4638
 
4667
- ## ulidx@2.4.1
4639
+ ## ulid@3.0.2
4668
4640
 
4669
4641
  License: MIT
4670
4642
 
4671
4643
  ```
4672
- MIT License
4644
+ The MIT License (MIT)
4673
4645
 
4674
- Copyright (c) 2021 Perry Mitchell
4646
+ Copyright (c) 2017 Alizain Feerasta
4675
4647
 
4676
4648
  Permission is hereby granted, free of charge, to any person obtaining a copy
4677
4649
  of this software and associated documentation files (the "Software"), to deal
@@ -37,4 +37,4 @@ var e = (e) => (e.getDay() + 6) % 7, t = (e) => Math.ceil(e.getDate() / 7), n =
37
37
  return r;
38
38
  };
39
39
  //#endregion
40
- export { o as n, a as t };
40
+ export { a as cadenceMatches, o as nextRuns };
@@ -0,0 +1,80 @@
1
+ import { listRegisteredFlows as e } from "./registry.js";
2
+ import { flowRunWorkflow as t } from "./workflow.js";
3
+ import { reconcileFlowStarts as n } from "./startReconcile.js";
4
+ import { cadenceMatches as r } from "./cadence.js";
5
+ import { recordFlowStartReceipt as i } from "./startReceipt.js";
6
+ import { Schema as a } from "effect";
7
+ import { createHash as o } from "node:crypto";
8
+ //#region src/cadenceTick.ts
9
+ var s = (e, t, n) => {
10
+ if (!Number.isFinite(t.getTime())) throw Error("cadence timestamp must be valid");
11
+ return `cron-${o("sha256").update(JSON.stringify([
12
+ n,
13
+ e,
14
+ Math.floor(t.getTime() / 6e4)
15
+ ])).digest("hex")}`;
16
+ }, c = async (t) => {
17
+ let n = [];
18
+ for (let r of e()) r.cadence && (r.cadence.repeats?.length ?? 0) > 0 && n.push({
19
+ tenantId: t.request.subject.tenantId,
20
+ flowRef: r.name,
21
+ cadence: r.cadence,
22
+ defaultInput: r.cadence.defaultInput ?? {}
23
+ });
24
+ let r = await t.store.select("_voltro_ai_flows").where("isEnabled", !0).all();
25
+ for (let e of r) e.id && e.cadence && (e.cadence.repeats?.length ?? 0) > 0 && n.push({
26
+ tenantId: e.tenantId ?? t.request.subject.tenantId,
27
+ flowRef: e.id,
28
+ cadence: e.cadence,
29
+ defaultInput: e.cadence.defaultInput ?? {}
30
+ });
31
+ return n;
32
+ }, l = async (e, o = /* @__PURE__ */ new Date()) => {
33
+ let l = [], u = 0, d = [], f = e.workflows ? await n(e) : {
34
+ examined: 0,
35
+ accepted: 0,
36
+ notExecuted: 0,
37
+ pending: 0,
38
+ failures: []
39
+ };
40
+ d.push(...f.failures.map((e) => Error(`flow run ${e.runId}: start reconciliation failed`, { cause: e.cause })));
41
+ let p = await c(e);
42
+ for (let n of p) {
43
+ if (!r(n.cadence, o)) continue;
44
+ u += 1;
45
+ let c = s(n.flowRef, o, n.tenantId), f = `run-${c}`;
46
+ try {
47
+ if (!e.workflows) throw Error("workflow runtime unavailable; no cadence start was submitted");
48
+ (await e.transaction(async (e) => {
49
+ let r = e.workflows;
50
+ if (!r) throw Error("workflow runtime unavailable in transaction; no cadence start was submitted");
51
+ await e.store.insertIgnoreWithOutcome("_voltro_ai_flow_runs", {
52
+ id: f,
53
+ flowRef: n.flowRef,
54
+ flowName: n.flowRef,
55
+ status: "pending",
56
+ source: "cron",
57
+ requestId: c,
58
+ input: n.defaultInput
59
+ }, { conflictColumns: ["id"] });
60
+ let o = await e.store.select("_voltro_ai_flow_runs").where("id", f).first();
61
+ if (!o) throw Error("cadence run is not readable after persistence");
62
+ let s = a.decodeUnknownSync(t.payloadSchema.pipe(a.check(a.makeFilter((e) => e.runId === f && e.flowRef === n.flowRef && e.requestId === c && e.source === "cron"))))({
63
+ ...o,
64
+ runId: o.id
65
+ });
66
+ return i(e, f, await r.start("flow.run", s));
67
+ }, n.tenantId === null ? void 0 : { tenantId: n.tenantId })).status === "running" && l.push(c);
68
+ } catch (e) {
69
+ d.push(e);
70
+ }
71
+ }
72
+ if (d.length > 0) throw AggregateError(d, `${d.length} cadence submission(s) failed`);
73
+ return {
74
+ matched: u,
75
+ started: l,
76
+ reconciled: f
77
+ };
78
+ };
79
+ //#endregion
80
+ export { s as cronRequestId, l as runCadenceTick };
@@ -0,0 +1,46 @@
1
+ import { Schema as e } from "effect";
2
+ //#region src/condition.ts
3
+ var t = e.Literals([
4
+ "truthy",
5
+ "falsy",
6
+ "eq",
7
+ "neq",
8
+ "contains"
9
+ ]), n = e.Struct({
10
+ ref: e.String,
11
+ op: t,
12
+ value: e.optional(e.Unknown)
13
+ }), r = (e) => e == null ? !1 : typeof e == "boolean" ? e : !Array.isArray(e) || e.length > 0, i = (e, t) => {
14
+ if (e === t) return !0;
15
+ if (e === null || t === null || e === void 0 || t === void 0) return !1;
16
+ if (typeof e == "object" || typeof t == "object") try {
17
+ return JSON.stringify(e) === JSON.stringify(t);
18
+ } catch {
19
+ return !1;
20
+ }
21
+ return String(e) === String(t);
22
+ }, a = (e, t) => {
23
+ let n = t[e.ref];
24
+ switch (e.op) {
25
+ case "truthy": return r(n);
26
+ case "falsy": return !r(n);
27
+ case "eq": return i(n, e.value);
28
+ case "neq": return !i(n, e.value);
29
+ case "contains": {
30
+ if (n == null) return !1;
31
+ if (Array.isArray(n)) return n.some((t) => i(t, e.value));
32
+ let t = e.value;
33
+ return typeof t != "string" && typeof t != "number" ? !1 : String(n).includes(String(t));
34
+ }
35
+ }
36
+ }, o = (e) => {
37
+ switch (e.op) {
38
+ case "truthy": return `{{${e.ref}}} is set`;
39
+ case "falsy": return `{{${e.ref}}} is not set`;
40
+ case "eq": return `{{${e.ref}}} equals ${JSON.stringify(e.value)}`;
41
+ case "neq": return `{{${e.ref}}} does not equal ${JSON.stringify(e.value)}`;
42
+ case "contains": return `{{${e.ref}}} contains ${JSON.stringify(e.value)}`;
43
+ }
44
+ };
45
+ //#endregion
46
+ export { t as ConditionOp, n as StepCondition, o as describeCondition, a as evaluateCondition, r as isTruthy };
@@ -0,0 +1,18 @@
1
+ //#region src/defaults.ts
2
+ var e = 168, t = "VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS", n = 2160, r = "VOLTRO_AI_FLOW_RUNS_TTL_HOURS", i = 5, a = "VOLTRO_AI_FLOW_MAX_CHAIN_DEPTH", o = { current: {} }, s = (e) => {
3
+ o.current = e;
4
+ }, c = () => o.current, l = () => {
5
+ o.current = {};
6
+ }, u = (e, t) => {
7
+ if (e === void 0 || e.trim() === "") return t * 36e5;
8
+ let n = Number(e);
9
+ return !Number.isFinite(n) || n < 0 ? t * 36e5 : n * 36e5;
10
+ }, d = (e) => Number.isFinite(e) && e > 0 ? e : Infinity, f = (e) => {
11
+ let t = e.env ?? process.env;
12
+ return d(e.step?.timeoutMs ?? e.flow?.humanTimeoutMs ?? e.deps?.humanReviewTimeoutMs ?? c().humanReviewTimeoutMs ?? u(t.VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS, 168));
13
+ }, p = (e) => {
14
+ let t = e?.env ?? process.env, n = Number(t[a]), r = e?.maxChainDepth ?? c().maxChainDepth ?? (Number.isFinite(n) && n >= 1 ? n : 5);
15
+ return Number.isFinite(r) && r >= 1 ? r : 5;
16
+ };
17
+ //#endregion
18
+ export { r as FLOW_RUNS_TTL_ENV, n as FLOW_RUNS_TTL_HOURS_DEFAULT, t as HUMAN_REVIEW_TIMEOUT_ENV, e as HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT, i as MAX_CHAIN_DEPTH_DEFAULT, a as MAX_CHAIN_DEPTH_ENV, c as getAiFlowsDefaults, u as msFromHoursEnv, l as resetAiFlowsDefaults, f as resolveHumanReviewTimeoutMs, p as resolveMaxChainDepth, s as setAiFlowsDefaults, d as toTimeoutMs };
package/dist/define.js ADDED
@@ -0,0 +1,71 @@
1
+ import { registerFlow as e } from "./registry.js";
2
+ import { normalizeFlow as t, sanitizeOutputKey as n } from "./ir.js";
3
+ import { collectRefs as r } from "./interpolate.js";
4
+ import { flowSegments as i, nonContiguousGroups as a } from "./segments.js";
5
+ import { FlowValidationError as o } from "./errors.js";
6
+ //#region src/define.ts
7
+ var s = {
8
+ text: (e) => ({
9
+ type: "generate",
10
+ modality: "text",
11
+ ...e
12
+ }),
13
+ media: (e, t) => ({
14
+ type: "generate",
15
+ modality: e,
16
+ ...t
17
+ }),
18
+ agent: (e) => ({
19
+ type: "agent",
20
+ ...e
21
+ }),
22
+ structured: (e) => ({
23
+ type: "structured",
24
+ ...e
25
+ }),
26
+ note: (e) => ({
27
+ type: "note",
28
+ ...e
29
+ }),
30
+ human: (e) => ({
31
+ type: "human",
32
+ ...e
33
+ })
34
+ }, c = (e) => e.map((e, t) => "id" in e && e.id ? e : {
35
+ id: `step-${t}`,
36
+ ...e
37
+ }), l = (e) => {
38
+ let t = [], s = i(e.steps);
39
+ for (let e of a(s)) t.push(`group "${e}" is not contiguous — only CONSECUTIVE steps sharing a group run concurrently, so this would execute as two separate fan-outs`);
40
+ let c = new Set(e.brief.map((e) => e.key));
41
+ for (let e of s) {
42
+ for (let { step: n } of e.steps) {
43
+ n.type === "human" && n.group !== void 0 && t.push(`step "${n.id}" is a human review inside group "${n.group}" — a review SUSPENDS the whole run, which one branch of a fan-out cannot do`);
44
+ for (let i of r(n.prompt ?? "")) c.has(i) || t.push(e.steps.length > 1 ? `step "${n.id}" references {{${i}}} which is produced inside its OWN group "${n.group}" or does not exist — grouped steps run concurrently, so they cannot read each other` : `step "${n.id}" references {{${i}}} which is not a brief field or a prior step outputKey`);
45
+ for (let [e, r] of Object.entries(n.mediaInputs ?? {})) r.from === "step" && !c.has(r.ref) && t.push(`step "${n.id}" media input "${e}" references "${r.ref}" which is not a brief field or an earlier segment's outputKey`);
46
+ n.when !== void 0 && !c.has(n.when.ref) && t.push(`step "${n.id}" has a when-condition on {{${n.when.ref}}} which is not a brief field or a prior step outputKey — it would never run`);
47
+ }
48
+ for (let { step: t } of e.steps) t.outputKey && c.add(n(t.outputKey));
49
+ }
50
+ if (t.length > 0) throw new o({
51
+ flowRef: e.name,
52
+ message: `flow "${e.name}" has ${t.length} problem(s)`,
53
+ issues: t
54
+ });
55
+ }, u = (n) => {
56
+ let r = t({
57
+ name: n.name,
58
+ mode: n.mode,
59
+ steps: c(n.steps),
60
+ maxSteps: n.maxSteps,
61
+ brief: n.brief,
62
+ orchestratorModel: n.orchestrator?.model,
63
+ orchestratorInstructions: n.orchestrator?.instructions,
64
+ chain: n.chain,
65
+ cadence: n.cadence,
66
+ humanTimeoutMs: n.humanTimeoutMs
67
+ });
68
+ return l(r), e(r), r;
69
+ };
70
+ //#endregion
71
+ export { u as defineFlow, s as flowStep, l as validateFlow };