@voltro/plugin-ai-flows 0.71.0 → 0.72.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/CHANGELOG.md +435 -0
- package/THIRD-PARTY-NOTICES.md +29 -1
- package/dist/errors.d.ts +18 -0
- package/dist/errors.js +6 -1
- package/dist/index.d.ts +136 -25
- package/dist/index.js +695 -476
- package/dist/{ir-B0rox9qW.js → ir-BP8rOTuf.js} +13 -11
- package/dist/ir.d.ts +17 -0
- package/dist/ir.js +2 -2
- package/dist/web.d.ts +11 -0
- package/package.json +11 -11
package/dist/errors.js
CHANGED
|
@@ -28,6 +28,11 @@ var t = class extends e.TaggedError()("FlowNotFound", {
|
|
|
28
28
|
}) {}, c = class extends e.TaggedError()("FlowCapabilityMissing", {
|
|
29
29
|
capability: e.String,
|
|
30
30
|
message: e.String
|
|
31
|
+
}) {}, l = class extends e.TaggedError()("FlowAgentUnavailable", {
|
|
32
|
+
agentRef: e.String,
|
|
33
|
+
reason: e.Literal("not-found", "access-revoked", "model-unusable"),
|
|
34
|
+
message: e.String,
|
|
35
|
+
publicMessage: e.optional(e.String)
|
|
31
36
|
}) {};
|
|
32
37
|
//#endregion
|
|
33
|
-
export { a as FlowBriefIncomplete, c as FlowCapabilityMissing, i as FlowDependencyError, o as FlowNotAwaitingResponse, t as FlowNotFound, s as FlowReviewDeliveryError, n as FlowRunNotFound, r as FlowValidationError };
|
|
38
|
+
export { l as FlowAgentUnavailable, a as FlowBriefIncomplete, c as FlowCapabilityMissing, i as FlowDependencyError, o as FlowNotAwaitingResponse, t as FlowNotFound, s as FlowReviewDeliveryError, n as FlowRunNotFound, r as FlowValidationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ import { TableLike } from '@voltro/database';
|
|
|
12
12
|
import { VoltroPlugin } from '@voltro/protocol';
|
|
13
13
|
import { WorkflowEngine } from '@effect/workflow/WorkflowEngine';
|
|
14
14
|
import { WorkflowInstance } from '@effect/workflow/WorkflowEngine';
|
|
15
|
+
import { WorkflowRunHandle } from '@voltro/protocol';
|
|
16
|
+
|
|
17
|
+
/** The handle a flow row records for an ADMITTED start: the execution the
|
|
18
|
+
* engine owns. `id` is that execution too — the stable handle callers pass on. */
|
|
19
|
+
export declare const admittedStartHandle: (executionId: string) => WorkflowRunHandle;
|
|
15
20
|
|
|
16
21
|
/** An `agent` step's resolved persona. */
|
|
17
22
|
export declare interface AgentResolution {
|
|
@@ -76,6 +81,8 @@ export declare const aiFlowRunsTable: Table<"_voltro_ai_flow_runs", FieldDefinit
|
|
|
76
81
|
readonly chainRefusal: ColumnBuilder<string | null, "text", boolean>;
|
|
77
82
|
/** Accumulated cost in micro-USD (app view projects to €/cents). */
|
|
78
83
|
readonly costMicroUsd: ColumnBuilder<number, "integer", true>;
|
|
84
|
+
/** `actual` | `estimated` | `incomplete` | `unknown` — whether `costMicroUsd` can be booked as spend, or only read as a floor. */
|
|
85
|
+
readonly costCompleteness: ColumnBuilder<string, "text", true>;
|
|
79
86
|
readonly durationMs: ColumnBuilder<number | null, "integer", boolean>;
|
|
80
87
|
readonly error: ColumnBuilder<string | null, "text", boolean>;
|
|
81
88
|
readonly errorMessage: ColumnBuilder<string | null, "text", boolean>;
|
|
@@ -285,13 +292,25 @@ export declare const buildFlowRunExecute: (ctx: AppContext, deps?: EngineDeps) =
|
|
|
285
292
|
*/
|
|
286
293
|
export declare const cadenceMatches: (cadence: FlowCadence, now: Date) => boolean;
|
|
287
294
|
|
|
288
|
-
/**
|
|
289
|
-
*
|
|
295
|
+
/**
|
|
296
|
+
* Cancel a run on BOTH sides in one operation: the row (what the UI and the
|
|
297
|
+
* cadence read) and the workflow execution (what actually runs, or waits at a
|
|
298
|
+
* human step). Either half alone drifts — a row marked cancelled over a
|
|
299
|
+
* suspended execution, or a cancelled execution under a row that still says
|
|
300
|
+
* `waiting` — and a reader of one side never learns about the other.
|
|
301
|
+
*
|
|
302
|
+
* The row is patched first, so a cooperative check between steps sees it even
|
|
303
|
+
* if the engine's interrupt is slow; the execution's own interrupt handler
|
|
304
|
+
* (`buildFlowRunExecute`) writes the same terminal fields again, harmlessly.
|
|
305
|
+
* An execution that cannot be reached (no runtime, not started) leaves the row
|
|
306
|
+
* cancelled and says so in `engine`.
|
|
307
|
+
*/
|
|
290
308
|
export declare const cancelFlow: (ctx: AppContext, args: {
|
|
291
309
|
runId: string;
|
|
292
310
|
}) => Effect.Effect<{
|
|
293
311
|
runId: string;
|
|
294
312
|
status: RunStatus;
|
|
313
|
+
engine: "unreachable" | "cancelled";
|
|
295
314
|
}, FlowRunNotFound, never>;
|
|
296
315
|
|
|
297
316
|
/** Staged follow-up when `chainTo.requireConfirmation` is set. */
|
|
@@ -321,6 +340,16 @@ export declare const ConditionOp: Schema.Literal<["truthy", "falsy", "eq", "neq"
|
|
|
321
340
|
|
|
322
341
|
export declare type ConditionOp = typeof ConditionOp.Type;
|
|
323
342
|
|
|
343
|
+
/** A run's cost verdict over its steps: every step gateway-priced → `actual`; none unpriced → `estimated`; any unpriced → `incomplete`; no priced step → `unknown`. */
|
|
344
|
+
export declare const CostCompleteness: Schema.Literal<["actual", "estimated", "incomplete", "unknown"]>;
|
|
345
|
+
|
|
346
|
+
export declare type CostCompleteness = typeof CostCompleteness.Type;
|
|
347
|
+
|
|
348
|
+
/** Where a cost figure came from. `unpriced` means the number beside it is a placeholder, not a price. */
|
|
349
|
+
export declare const CostSource: Schema.Literal<["gateway", "estimated", "unpriced"]>;
|
|
350
|
+
|
|
351
|
+
export declare type CostSource = typeof CostSource.Type;
|
|
352
|
+
|
|
324
353
|
/** Create a flow row. Generates an id when absent; tenant/audit columns are
|
|
325
354
|
* auto-stamped by the runtime. */
|
|
326
355
|
export declare const createFlow: (ctx: AppContext, fields: Record<string, unknown>) => Effect.Effect<Readonly<Record<string, unknown>>, never, never>;
|
|
@@ -364,13 +393,27 @@ export declare const describeCondition: (condition: StepCondition) => string;
|
|
|
364
393
|
export declare interface EngineDeps {
|
|
365
394
|
/** Resolve an agent in the durable run's tenant, in deterministic steps AND
|
|
366
395
|
* the agentic `run_agent` tool. Do not infer tenancy from the current subject:
|
|
367
|
-
* a crash resume may run as system. Absent → FlowCapabilityMissing.
|
|
368
|
-
|
|
396
|
+
* a crash resume may run as system. Absent → FlowCapabilityMissing.
|
|
397
|
+
*
|
|
398
|
+
* Refuse with `FlowAgentUnavailable` for anything that is not "no such
|
|
399
|
+
* agent" — revoked access, a model the host cannot serve. Its `message` is
|
|
400
|
+
* for the HOST (the step's error, the run's log); what the MODEL sees in the
|
|
401
|
+
* agentic planner is `publicMessage`, or a generic "agent unavailable" — a
|
|
402
|
+
* resolver's words are tool output, so never say anything private in
|
|
403
|
+
* `publicMessage`. */
|
|
404
|
+
readonly resolveAgent?: (agentRef: string, run: FlowRunContext) => Effect.Effect<AgentResolution, FlowNotFound | FlowAgentUnavailable, unknown>;
|
|
369
405
|
/** Additional tools for the agentic planner, resolved inside its durable step.
|
|
370
406
|
* The original flow reference and durable tenant are scope, not authorization.
|
|
371
407
|
* Enforce current access in this callback and the tools. Internal planner names
|
|
372
|
-
* cannot be replaced. Deterministic agent tools belong to AgentResolution.
|
|
373
|
-
|
|
408
|
+
* cannot be replaced. Deterministic agent tools belong to AgentResolution.
|
|
409
|
+
* `planner.provider()` is the provider the planner will run on — a host that
|
|
410
|
+
* offers a provider-native search (web search on OpenAI, Google, Anthropic)
|
|
411
|
+
* picks the matching tool from it. A thunk: resolved only when asked, so a
|
|
412
|
+
* resolver that fails never resolves the model. A failure here fails the planner with
|
|
413
|
+
* the resolver's own message. */
|
|
414
|
+
readonly resolveTools?: (flowRef: string, run: FlowRunContext, planner: {
|
|
415
|
+
readonly provider: () => ProviderConfig | undefined;
|
|
416
|
+
}) => Effect.Effect<Record<string, AnyTool>, FlowCapabilityMissing, unknown>;
|
|
374
417
|
/** Media generator for image/video/audio steps (`makeMediaGenerator` in
|
|
375
418
|
* `mediaAdapter.ts` is the @voltro/ai-backed implementation). */
|
|
376
419
|
readonly generateMedia?: MediaGenerator;
|
|
@@ -425,6 +468,24 @@ export declare const FLOW_RUNS_TTL_ENV = "VOLTRO_AI_FLOW_RUNS_TTL_HOURS";
|
|
|
425
468
|
* runs. Only TERMINAL runs are swept — see `index.ts`. */
|
|
426
469
|
export declare const FLOW_RUNS_TTL_HOURS_DEFAULT: number;
|
|
427
470
|
|
|
471
|
+
/**
|
|
472
|
+
* An agent the host will not serve for this run: access revoked, a model it
|
|
473
|
+
* cannot run, or nothing under that reference. `message` is for the host —
|
|
474
|
+
* the step's error and the run's log. `publicMessage` is the ONLY sentence
|
|
475
|
+
* the agentic planner's model sees; leave it out for a generic line.
|
|
476
|
+
*/
|
|
477
|
+
declare class FlowAgentUnavailable extends FlowAgentUnavailable_base {
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
declare const FlowAgentUnavailable_base: Schema.TaggedErrorClass<FlowAgentUnavailable, "FlowAgentUnavailable", {
|
|
481
|
+
readonly _tag: Schema.tag<"FlowAgentUnavailable">;
|
|
482
|
+
} & {
|
|
483
|
+
agentRef: typeof Schema.String;
|
|
484
|
+
reason: Schema.Literal<["not-found", "access-revoked", "model-unusable"]>;
|
|
485
|
+
message: typeof Schema.String;
|
|
486
|
+
publicMessage: Schema.optional<typeof Schema.String>;
|
|
487
|
+
}>;
|
|
488
|
+
|
|
428
489
|
/** A required brief field was blank at launch. */
|
|
429
490
|
declare class FlowBriefIncomplete extends FlowBriefIncomplete_base {
|
|
430
491
|
}
|
|
@@ -618,6 +679,24 @@ export declare const FlowReviewReceipt: Schema.Struct<{
|
|
|
618
679
|
|
|
619
680
|
export declare type FlowReviewReceipt = typeof FlowReviewReceipt.Type;
|
|
620
681
|
|
|
682
|
+
/** The run an agent or media step executes within, resolved from the durable RUN ROW —
|
|
683
|
+
* not the caller subject. This is the difference between a normal call and a
|
|
684
|
+
* resume: a BOOTSTRAP/crash resume runs under a tenant-less `SYSTEM_SUBJECT`,
|
|
685
|
+
* so a host that persists artifacts per tenant cannot read the tenant from
|
|
686
|
+
* `ctx.request.subject` (it isn't there) and would either fail closed or, worse
|
|
687
|
+
* under the old fallback, write into the wrong tenant. The engine reads the run
|
|
688
|
+
* row it already loads and hands the original tenant down here, so persistence
|
|
689
|
+
* continues in the right place on replay. */
|
|
690
|
+
export declare interface FlowRunContext {
|
|
691
|
+
readonly runId: string;
|
|
692
|
+
/** The run's tenant as stamped when it was created, or `null` for a
|
|
693
|
+
* single-tenant app. Authoritative on resume, where the subject has none. */
|
|
694
|
+
readonly tenantId: string | null;
|
|
695
|
+
/** The run's owner as stored on its row, or `null`. Every host used to load
|
|
696
|
+
* the row again for this; a cadence run has none. */
|
|
697
|
+
readonly ownerId: string | null;
|
|
698
|
+
}
|
|
699
|
+
|
|
621
700
|
/** A flow run row could not be found. */
|
|
622
701
|
declare class FlowRunNotFound extends FlowRunNotFound_base {
|
|
623
702
|
}
|
|
@@ -684,6 +763,22 @@ export declare const FlowStartReceipt: Schema.Struct<{
|
|
|
684
763
|
|
|
685
764
|
export declare type FlowStartReceipt = typeof FlowStartReceipt.Type;
|
|
686
765
|
|
|
766
|
+
export declare interface FlowStartReconciliation {
|
|
767
|
+
/** Rows read with a queued handle. */
|
|
768
|
+
readonly examined: number;
|
|
769
|
+
/** Rows now `running` under the execution the engine accepted. */
|
|
770
|
+
readonly accepted: number;
|
|
771
|
+
/** Rows now `failed` because their start will never run. */
|
|
772
|
+
readonly notExecuted: number;
|
|
773
|
+
/** Rows still queued. */
|
|
774
|
+
readonly pending: number;
|
|
775
|
+
/** Per-row read or write failures; the other rows were still reconciled. */
|
|
776
|
+
readonly failures: ReadonlyArray<{
|
|
777
|
+
readonly runId: string;
|
|
778
|
+
readonly cause: unknown;
|
|
779
|
+
}>;
|
|
780
|
+
}
|
|
781
|
+
|
|
687
782
|
/** Flow-definition lifecycle. */
|
|
688
783
|
export declare const FlowStatus: Schema.Literal<["draft", "active", "archived"]>;
|
|
689
784
|
|
|
@@ -711,6 +806,7 @@ export declare const FlowStep: Schema.Struct<{
|
|
|
711
806
|
mediaInputs: Schema.optional<Schema.Record$<typeof Schema.String, Schema.Union<[Schema.Struct<{
|
|
712
807
|
from: Schema.Literal<["upload"]>;
|
|
713
808
|
url: typeof Schema.String;
|
|
809
|
+
mediaType: Schema.optional<typeof Schema.NonEmptyString>;
|
|
714
810
|
}>, Schema.Struct<{
|
|
715
811
|
from: Schema.Literal<["step"]>;
|
|
716
812
|
ref: typeof Schema.String;
|
|
@@ -1038,14 +1134,21 @@ export declare type MediaGenerator = (args: {
|
|
|
1038
1134
|
readonly prompt: string;
|
|
1039
1135
|
readonly params?: Record<string, unknown>;
|
|
1040
1136
|
readonly inputs?: ResolvedMediaInputs;
|
|
1137
|
+
/** The same slots as TYPED references, for the models that require one
|
|
1138
|
+
* (`inputReferences: [{ type: 'url', url, mediaType }]`): an upload that
|
|
1139
|
+
* declared its `mediaType`, and a prior step's artifact, whose type the
|
|
1140
|
+
* engine already knows. A slot without a known type is in `inputs` only —
|
|
1141
|
+
* a type is never guessed from a URL. */
|
|
1142
|
+
readonly inputRefs?: ResolvedMediaInputRefs;
|
|
1041
1143
|
/** The run this artifact belongs to — pin persistence to `run.tenantId` rather
|
|
1042
1144
|
* than the current subject, so a system/bootstrap resume stores it correctly. */
|
|
1043
|
-
readonly run:
|
|
1145
|
+
readonly run: FlowRunContext;
|
|
1044
1146
|
}) => Effect.Effect<MediaResult, FlowCapabilityMissing, unknown>;
|
|
1045
1147
|
|
|
1046
1148
|
export declare const MediaInputs: Schema.Record$<typeof Schema.String, Schema.Union<[Schema.Struct<{
|
|
1047
1149
|
from: Schema.Literal<["upload"]>;
|
|
1048
1150
|
url: typeof Schema.String;
|
|
1151
|
+
mediaType: Schema.optional<typeof Schema.NonEmptyString>;
|
|
1049
1152
|
}>, Schema.Struct<{
|
|
1050
1153
|
from: Schema.Literal<["step"]>;
|
|
1051
1154
|
ref: typeof Schema.String;
|
|
@@ -1060,6 +1163,7 @@ export declare type MediaInputs = typeof MediaInputs.Type;
|
|
|
1060
1163
|
export declare const MediaInputSlot: Schema.Union<[Schema.Struct<{
|
|
1061
1164
|
from: Schema.Literal<["upload"]>;
|
|
1062
1165
|
url: typeof Schema.String;
|
|
1166
|
+
mediaType: Schema.optional<typeof Schema.NonEmptyString>;
|
|
1063
1167
|
}>, Schema.Struct<{
|
|
1064
1168
|
from: Schema.Literal<["step"]>;
|
|
1065
1169
|
ref: typeof Schema.String;
|
|
@@ -1071,7 +1175,7 @@ export declare type MediaInputSlot = typeof MediaInputSlot.Type;
|
|
|
1071
1175
|
/** Host-supplied persistence (from @voltro/plugin-storage's StorageService).
|
|
1072
1176
|
*
|
|
1073
1177
|
* Both hooks receive the `run` — its `tenantId` is the durable, resume-safe
|
|
1074
|
-
* tenant (see `
|
|
1178
|
+
* tenant (see `FlowRunContext`). Pass it to `storage.put`/`ingestUrl` as the
|
|
1075
1179
|
* scope so a BOOTSTRAP resume, whose subject has no tenant, still writes into
|
|
1076
1180
|
* the run's own tenant instead of failing or defaulting. */
|
|
1077
1181
|
export declare interface MediaPersist {
|
|
@@ -1079,11 +1183,11 @@ export declare interface MediaPersist {
|
|
|
1079
1183
|
readonly put: (args: {
|
|
1080
1184
|
data: Uint8Array | string;
|
|
1081
1185
|
mediaType: string;
|
|
1082
|
-
run:
|
|
1186
|
+
run: FlowRunContext;
|
|
1083
1187
|
}) => Effect.Effect<StoredMedia, unknown, unknown>;
|
|
1084
1188
|
/** Re-host a provider URL (StorageService.ingestUrl). If absent, a provider
|
|
1085
1189
|
* video URL is used as-is (no re-hosting). */
|
|
1086
|
-
readonly ingestUrl?: (url: string, run:
|
|
1190
|
+
readonly ingestUrl?: (url: string, run: FlowRunContext) => Effect.Effect<StoredMedia, unknown, unknown>;
|
|
1087
1191
|
}
|
|
1088
1192
|
|
|
1089
1193
|
export declare const MediaResult: Schema.Struct<{
|
|
@@ -1095,27 +1199,13 @@ export declare const MediaResult: Schema.Struct<{
|
|
|
1095
1199
|
providerMetadata: Schema.optional<typeof Schema.Unknown>;
|
|
1096
1200
|
}>>>;
|
|
1097
1201
|
costMicroUsd: Schema.optional<Schema.filter<typeof Schema.Finite>>;
|
|
1202
|
+
costSource: Schema.optional<Schema.Literal<["gateway", "estimated", "unpriced"]>>;
|
|
1098
1203
|
/** A provider/usage correlation only, never a storage reference. */
|
|
1099
1204
|
requestId: Schema.optional<typeof Schema.NonEmptyString>;
|
|
1100
1205
|
}>;
|
|
1101
1206
|
|
|
1102
1207
|
export declare type MediaResult = typeof MediaResult.Type;
|
|
1103
1208
|
|
|
1104
|
-
/** The run an agent or media step executes within, resolved from the durable RUN ROW —
|
|
1105
|
-
* not the caller subject. This is the difference between a normal call and a
|
|
1106
|
-
* resume: a BOOTSTRAP/crash resume runs under a tenant-less `SYSTEM_SUBJECT`,
|
|
1107
|
-
* so a host that persists artifacts per tenant cannot read the tenant from
|
|
1108
|
-
* `ctx.request.subject` (it isn't there) and would either fail closed or, worse
|
|
1109
|
-
* under the old fallback, write into the wrong tenant. The engine reads the run
|
|
1110
|
-
* row it already loads and hands the original tenant down here, so persistence
|
|
1111
|
-
* continues in the right place on replay. */
|
|
1112
|
-
export declare interface MediaRunContext {
|
|
1113
|
-
readonly runId: string;
|
|
1114
|
-
/** The run's tenant as stamped when it was created, or `null` for a
|
|
1115
|
-
* single-tenant app. Authoritative on resume, where the subject has none. */
|
|
1116
|
-
readonly tenantId: string | null;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
1209
|
export declare const Modality: Schema.Literal<["text", "image", "video", "audio"]>;
|
|
1120
1210
|
|
|
1121
1211
|
export declare type Modality = typeof Modality.Type;
|
|
@@ -1137,6 +1227,15 @@ export declare const nonContiguousGroups: (segments: ReadonlyArray<FlowSegment>)
|
|
|
1137
1227
|
*/
|
|
1138
1228
|
export declare const normalizeFlow: (def: FlowDefinitionInput) => FlowIR;
|
|
1139
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* Converge every pending flow run whose start was recorded as `queued` onto
|
|
1232
|
+
* what that start has become. Bounded by `take` (newest-first is not needed:
|
|
1233
|
+
* a pending row is pending until it converges, so any order visits it).
|
|
1234
|
+
*/
|
|
1235
|
+
export declare const reconcileFlowStarts: (ctx: AppContext, options?: {
|
|
1236
|
+
readonly take?: number;
|
|
1237
|
+
}) => Promise<FlowStartReconciliation>;
|
|
1238
|
+
|
|
1140
1239
|
/** Register (or replace) a code-defined flow by its IR name. Called by
|
|
1141
1240
|
* `defineFlow` when the module is loaded. */
|
|
1142
1241
|
export declare const registerFlow: (ir: FlowIR) => void;
|
|
@@ -1144,6 +1243,13 @@ export declare const registerFlow: (ir: FlowIR) => void;
|
|
|
1144
1243
|
/** Test seam — forget the recorded tunables. */
|
|
1145
1244
|
export declare const resetAiFlowsDefaults: () => void;
|
|
1146
1245
|
|
|
1246
|
+
declare const ResolvedMediaInputRefs: Schema.Record$<typeof Schema.String, Schema.Struct<{
|
|
1247
|
+
url: Schema.filter<typeof Schema.String>;
|
|
1248
|
+
mediaType: typeof Schema.NonEmptyString;
|
|
1249
|
+
}>>;
|
|
1250
|
+
|
|
1251
|
+
declare type ResolvedMediaInputRefs = typeof ResolvedMediaInputRefs.Type;
|
|
1252
|
+
|
|
1147
1253
|
declare const ResolvedMediaInputs: Schema.Record$<typeof Schema.String, Schema.filter<typeof Schema.String>>;
|
|
1148
1254
|
|
|
1149
1255
|
declare type ResolvedMediaInputs = typeof ResolvedMediaInputs.Type;
|
|
@@ -1236,6 +1342,7 @@ export declare type ReviewOption = typeof ReviewOption.Type;
|
|
|
1236
1342
|
export declare const runCadenceTick: (ctx: AppContext, now?: Date) => Promise<{
|
|
1237
1343
|
readonly matched: number;
|
|
1238
1344
|
readonly started: ReadonlyArray<string>;
|
|
1345
|
+
readonly reconciled: FlowStartReconciliation;
|
|
1239
1346
|
}>;
|
|
1240
1347
|
|
|
1241
1348
|
/** Human-review config projected onto a `waiting` run step. */
|
|
@@ -1272,6 +1379,9 @@ export declare const RunStep: Schema.Struct<{
|
|
|
1272
1379
|
completedAt: Schema.optional<typeof Schema.String>;
|
|
1273
1380
|
/** Per-step cost in micro-USD (the app view projects to €/cents). */
|
|
1274
1381
|
costMicroUsd: Schema.optional<typeof Schema.Number>;
|
|
1382
|
+
/** Where that number came from — the gateway's actual charge, a price-table
|
|
1383
|
+
* estimate, or nothing (`unpriced`: the 0 above is not a price). */
|
|
1384
|
+
costSource: Schema.optional<Schema.Literal<["gateway", "estimated", "unpriced"]>>;
|
|
1275
1385
|
/** Links a media step to its generation/usage record. */
|
|
1276
1386
|
requestId: Schema.optional<typeof Schema.String>;
|
|
1277
1387
|
/** Hosted media artifact URL (image/video/audio), via storage. */
|
|
@@ -1314,6 +1424,7 @@ export declare interface RunStep {
|
|
|
1314
1424
|
readonly startedAt?: string | undefined;
|
|
1315
1425
|
readonly completedAt?: string | undefined;
|
|
1316
1426
|
readonly costMicroUsd?: number | undefined;
|
|
1427
|
+
readonly costSource?: CostSource | undefined;
|
|
1317
1428
|
readonly requestId?: string | undefined;
|
|
1318
1429
|
readonly url?: string | undefined;
|
|
1319
1430
|
readonly artifacts?: ReadonlyArray<MediaArtifact> | undefined;
|