@reaatech/media-pipeline-mcp-core 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Media Pipeline MCP Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,446 @@
1
+ # @reaatech/media-pipeline-mcp-core
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@reaatech/media-pipeline-mcp-core.svg)](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-core)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/reaatech/media-pipeline-mcp/blob/main/LICENSE)
5
+ [![CI](https://img.shields.io/github/actions/workflow/status/reaatech/media-pipeline-mcp/ci.yml?branch=main&label=CI)](https://github.com/reaatech/media-pipeline-mcp/actions/workflows/ci.yml)
6
+
7
+ > **Status:** Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.
8
+
9
+ Core framework for media pipeline orchestration. Provides the complete type system (Zod-validated), pipeline execution engine with variable interpolation, validation with provider availability checks, quality gate evaluation (threshold, dimension-check, LLM-judge, custom), artifact registry, budget enforcement, persistence-based resume, cost tracking, event bus, and a configurable mock provider for testing.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @reaatech/media-pipeline-mcp-core
15
+ # or
16
+ pnpm add @reaatech/media-pipeline-mcp-core
17
+ ```
18
+
19
+ ## Feature Overview
20
+
21
+ - **Pipeline execution engine** — sequential step processing with `{{step_id.output}}` variable interpolation, timeout handling, budget preflight, persistence-based resume, and run lifecycle management
22
+ - **Zod-validated type system** — 20+ schemas for `Pipeline`, `Step`, `Artifact`, `QualityGate`, `CostRecord`, `PipelineEvent`, `VariantsConfig`, `RunContext`, and more
23
+ - **Quality gate evaluation** — `threshold` (numeric checks on metadata fields), `dimension-check` (output dimensions with tolerance), `llm-judge` (LLM evaluates quality), and `custom` (user-provided function) with retry/gating/fail/warn actions
24
+ - **Artifact registry** — in-memory artifact tracking with CRUD operations, source-step lookup, batch deletion by source step, and latest-artifact retrieval
25
+ - **Pipeline validation** — Zod schema validation, duplicate step detection, path-traversal checks, circular/forward reference detection, provider availability verification, quality gate config validation, budget and variants config validation
26
+ - **Pipeline estimation** — dry-run cost estimation with per-step `usdLow`/`usdHigh` bands, provider-specific pricing, router-spread warnings, and prior-step dependency detection
27
+ - **Mock provider** — configurable simulated provider with delay, failure rate, base cost, and operation-specific artifact type/mime generation for development and testing
28
+ - **Event bus** — typed event emitter with `kind`-based subscription, promise-based `await`, and optional timeout
29
+ - **Budget enforcement** — `abort`/`suspend` on budget exceed with configurable warning thresholds
30
+ - **Persistence integration** — `PipelineStateStore` and `CostLedger` injection for run durability and cost recording
31
+ - **Provenance signing** — C2PA manifest callback with pipeline definition hash and ingredient tracking
32
+ - **Extensible provider interface** — `Provider` contract with `execute`, `healthCheck`, and optional `estimateCost`
33
+ - **Stateful resume (F3)** — persistence-backed resume from any step with lock acquisition and step state tracking
34
+ - **Adapter injection callbacks** — route-based provider selection, variants execution, ratio fan-out, context resolution, gate evaluation, and tenant policy enforcement via injected callbacks
35
+ - **30+ typed error classes** — categorized errors with `code`, `retryable` flags, and structured payloads for `BudgetExceededError`, `ArtifactNotFoundError`, `VariantsAllRejectedError`, `SafetyGateRejectedError`, and more
36
+
37
+ ## Quick Start
38
+
39
+ ```typescript
40
+ import {
41
+ PipelineExecutor,
42
+ PipelineValidator,
43
+ ArtifactRegistry,
44
+ MockProvider,
45
+ } from "@reaatech/media-pipeline-mcp-core";
46
+
47
+ const executor = new PipelineExecutor({
48
+ providers: [new MockProvider()],
49
+ defaultStepTimeoutMs: 60000,
50
+ });
51
+
52
+ const result = await executor.execute({
53
+ id: "product-photo",
54
+ steps: [
55
+ {
56
+ id: "generate",
57
+ operation: "mock.generate",
58
+ inputs: { prompt: "A sunset over mountains" },
59
+ config: { dimensions: "1024x1024" },
60
+ qualityGate: {
61
+ type: "threshold",
62
+ config: { checks: [{ field: "metadata.width", operator: ">=", value: 1024 }] },
63
+ action: "retry",
64
+ maxRetries: 2,
65
+ },
66
+ },
67
+ {
68
+ id: "upscale",
69
+ operation: "mock.transform",
70
+ inputs: { artifact_id: "{{generate.output}}" },
71
+ config: { scale: "4x" },
72
+ },
73
+ ],
74
+ budget: {
75
+ maxUsd: 1.0,
76
+ onExceed: "abort",
77
+ warnAtPct: 0.8,
78
+ },
79
+ });
80
+
81
+ console.log(result.status); // "completed"
82
+ console.log(result.artifacts.size); // 2
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### `PipelineExecutor`
88
+
89
+ The core execution engine for running pipelines with step-by-step processing, quality gate evaluation, budget enforcement, and variable interpolation.
90
+
91
+ ```typescript
92
+ class PipelineExecutor {
93
+ constructor(options: PipelineExecutorOptions);
94
+ execute(definition: PipelineDefinition, options?: { runId?: string }): Promise<Pipeline>;
95
+ resume(runId: string, fromStepId?: string): Promise<Pipeline>;
96
+ resume(pipeline: Pipeline, action: 'retry' | 'skip' | 'abort'): Promise<Pipeline>;
97
+ estimate(definition: PipelineDefinition): Promise<PipelineEstimate>;
98
+ getRegistry(): ArtifactRegistry;
99
+ }
100
+ ```
101
+
102
+ #### `PipelineExecutorOptions`
103
+
104
+ | Property | Type | Default | Description |
105
+ |----------|------|---------|-------------|
106
+ | `providers` | `Provider[]` | **required** | Provider instances registered by operation |
107
+ | `defaultPipelineTimeoutMs` | `number` | `300000` | Max pipeline wall-clock time |
108
+ | `defaultStepTimeoutMs` | `number` | — | Max per-step execution time |
109
+ | `llmJudgeFn` | `(prompt, artifact) => Promise<{pass,reasoning,score?}>` | — | LLM-based quality evaluation |
110
+ | `customCheckFn` | `(artifact, config) => boolean \| Promise<boolean>` | — | Custom quality gate check |
111
+ | `prepareInputs` | `(op, inputs) => Promise<Record>` | — | Pre-execution input transformation |
112
+ | `persistArtifact` | `({artifactId,data,...}) => Promise<{uri?}>` | — | Storage persistence callback |
113
+ | `onEvent` | `(event: PipelineEvent) => void` | — | Lifecycle event listener |
114
+ | `onCost` | `(record: CostRecord) => void` | — | Per-operation cost callback |
115
+ | `persistence` | `PipelineStateStore` | — | Run state persistence (enables resume) |
116
+ | `ledger` | `CostLedger` | — | Cost accounting ledger |
117
+ | `routeStepFn` | `RouteStepFn` | — | Route-based provider selection |
118
+ | `variantsStepFn` | `VariantsStepFn` | — | Variants execution callback |
119
+ | `ratiosStepFn` | `RatiosStepFn` | — | Aspect-ratio fan-out callback |
120
+ | `context` | `RunContext` | — | Run context (voices, styles, brand kit) |
121
+ | `contextResolveFn` | `ContextResolveFn` | — | Context reference resolution |
122
+ | `gateEvalFn` | `GateEvalFn` | — | Custom gate evaluation (loudness, safety) |
123
+ | `tenantPolicyEnforceFn` | `(provider?, model?) => void` | — | Per-tenant allow-list enforcement |
124
+ | `signProvenance` | `({artifactId, runId, ...}) => Promise<{signedArtifactId,manifestUri}>` | — | C2PA provenance signing |
125
+
126
+ #### Provider Interface
127
+
128
+ ```typescript
129
+ interface Provider {
130
+ readonly name: string;
131
+ readonly supportedOperations: string[];
132
+ execute(operation: string, inputs: Record<string, unknown>, config: Record<string, unknown>): Promise<{
133
+ data?: Buffer | NodeJS.ReadableStream;
134
+ artifact: Omit<Artifact, 'id' | 'createdAt'>;
135
+ cost_usd?: number;
136
+ duration_ms?: number;
137
+ }>;
138
+ healthCheck(): Promise<boolean>;
139
+ estimateCost?(input: { operation: string; params: Record<string, unknown>; config: Record<string, unknown> }): Promise<{ costUsd: number; estimatedDurationMs?: number }>;
140
+ }
141
+ ```
142
+
143
+ ### `PipelineValidator`
144
+
145
+ Validates pipeline definitions with schema checks, reference integrity, provider availability, and config warnings.
146
+
147
+ ```typescript
148
+ class PipelineValidator {
149
+ constructor(providerAvailability: ProviderAvailability);
150
+ validate(definition: PipelineDefinition): ValidationResult;
151
+ }
152
+ ```
153
+
154
+ Validation checks performed:
155
+ 1. Zod schema validation against `PipelineDefinitionSchema`
156
+ 2. Duplicate step ID and path-traversal character detection
157
+ 3. Circular/forward reference detection in `{{step_id.output}}` patterns
158
+ 4. Provider availability for each operation
159
+ 5. Quality gate configuration completeness (retry without `maxRetries`, `llm-judge` without prompt, etc.)
160
+ 6. Budget config validity (`maxUsd > 0`, `onExceed` must be `'abort'` or `'suspend'`)
161
+ 7. Variants config validity (n between 2-16, valid `seedStrategy`, judge configured)
162
+ 8. Run context validity (valid voice providers, clean style names)
163
+
164
+ ### `PipelineEstimator`
165
+
166
+ Dry-run cost estimation with per-step bands.
167
+
168
+ ```typescript
169
+ class PipelineEstimator {
170
+ constructor(options?: PipelineEstimatorOptions);
171
+ estimate(pipeline: PipelineDefinition): Promise<PipelineEstimate>;
172
+ }
173
+
174
+ interface PipelineEstimate {
175
+ totalUsdLow: number;
176
+ totalUsdHigh: number;
177
+ perStep: StepEstimate[];
178
+ warnings: EstimateWarning[];
179
+ }
180
+ ```
181
+
182
+ ### `ArtifactRegistry`
183
+
184
+ In-memory artifact tracking for pipeline execution.
185
+
186
+ ```typescript
187
+ class ArtifactRegistry {
188
+ register(artifact: Omit<Artifact, 'id'>): Artifact;
189
+ registerWithId(id: string, artifact: Omit<Artifact, 'id'>): Artifact;
190
+ get(id: string): Artifact | undefined;
191
+ delete(id: string): boolean;
192
+ list(): Artifact[];
193
+ findBySourceStep(stepId: string): Artifact | undefined;
194
+ deleteBySourceStep(stepId: string): number;
195
+ clear(): void;
196
+ size(): number;
197
+ }
198
+ ```
199
+
200
+ ### Quality Gates
201
+
202
+ ```typescript
203
+ import {
204
+ createQualityGateEvaluator,
205
+ ThresholdEvaluator,
206
+ DimensionCheckEvaluator,
207
+ LLMJudgeEvaluator,
208
+ CustomEvaluator,
209
+ } from "@reaatech/media-pipeline-mcp-core";
210
+
211
+ const evaluator = createQualityGateEvaluator(
212
+ { type: "threshold", config: { checks: [{ field: "metadata.width", operator: ">=", value: 1024 }] }, action: "fail" },
213
+ llmJudgeFn, // required for llm-judge type
214
+ customCheckFn // required for custom type
215
+ );
216
+
217
+ const result = await evaluator.evaluate(gate, artifact);
218
+ // { passed: boolean, reasoning: string, score?: number, action: 'fail' | 'retry' | 'warn' }
219
+ ```
220
+
221
+ #### Gate Types
222
+
223
+ | Type | Config | Description |
224
+ |------|--------|-------------|
225
+ | `threshold` | `{ checks: [{ field, operator, value }] }` | Numeric checks on artifact metadata fields. Operators: `>=`, `<=`, `>`, `<`, `==`, `!=` |
226
+ | `dimension-check` | `{ expectedWidth, expectedHeight, tolerance? }` | Verify output dimensions within tolerance (0-1) |
227
+ | `llm-judge` | `{ prompt, model?, timeout? }` | LLM evaluates output quality against a prompt. Requires `llmJudgeFn` injection |
228
+ | `custom` | `{ [key: string]: unknown }` | Arbitrary config passed to `customCheckFn` |
229
+
230
+ #### Gate Actions
231
+
232
+ | Action | Behavior |
233
+ |--------|----------|
234
+ | `fail` | Halt pipeline execution immediately |
235
+ | `retry` | Re-execute the step up to `maxRetries` times |
236
+ | `warn` | Log a warning and continue execution |
237
+
238
+ ### `MockProvider`
239
+
240
+ Configurable simulated provider for development and testing.
241
+
242
+ ```typescript
243
+ class MockProvider implements Provider {
244
+ readonly name: string;
245
+ readonly supportedOperations: string[];
246
+
247
+ constructor(config?: {
248
+ name?: string; // default: "mock"
249
+ operations?: string[]; // default: ["mock.generate", "mock.transform", "mock.extract"]
250
+ delay?: number; // Simulated latency in ms (default: 100)
251
+ failureRate?: number; // 0-1 probability of failure (default: 0)
252
+ baseCost?: number; // Cost per operation (default: 0.001)
253
+ alwaysPass?: boolean; // Generate high-quality (0.99) metadata (default: false)
254
+ });
255
+ }
256
+ ```
257
+
258
+ ### Event Bus
259
+
260
+ Typed event bus for pipeline lifecycle events.
261
+
262
+ ```typescript
263
+ import { createEventBus } from "@reaatech/media-pipeline-mcp-core";
264
+
265
+ const bus = createEventBus<{ kind: "step:complete"; stepId: string; artifactId: string }>();
266
+
267
+ const dispose = bus.on("step:complete", (event) => {
268
+ console.log(`Step ${event.stepId} completed: ${event.artifactId}`);
269
+ });
270
+
271
+ bus.emit({ kind: "step:complete", stepId: "generate", artifactId: "artifact-123" });
272
+
273
+ // Promise-based await with optional predicate and timeout
274
+ const event = await bus.await("step:complete", (e) => e.stepId === "generate", 5000);
275
+
276
+ dispose(); // Unsubscribe
277
+ ```
278
+
279
+ ### Core Types
280
+
281
+ | Export | Description |
282
+ |--------|-------------|
283
+ | `PipelineSchema` / `Pipeline` | Full pipeline with steps, status, artifacts, and timing |
284
+ | `PipelineDefinitionSchema` / `PipelineDefinition` | User-supplied pipeline definition with optional budget/context |
285
+ | `PipelineStepSchema` / `PipelineStep` | Step with id, operation, inputs, config, quality gate, variants, cache, route |
286
+ | `ArtifactSchema` / `Artifact` | Pipeline output with id, type, uri, mimeType, metadata, sourceStep |
287
+ | `QualityGateSchema` / `QualityGate` | Gate with type, config, action, maxRetries |
288
+ | `QualityGateResultSchema` / `QualityGateResult` | Evaluation result with passed, reasoning, score, action |
289
+ | `CostRecordSchema` / `CostRecord` | Per-operation cost entry with operation, provider, model, cost_usd |
290
+ | `CostSummarySchema` / `CostSummary` | Aggregated costs by operation, provider, pipeline |
291
+ | `PipelineEventSchema` / `PipelineEvent` | Lifecycle event with type, pipelineId, stepId, timestamp, data |
292
+ | `PipelineStatus` | `"pending" \| "running" \| "completed" \| "failed" \| "gated" \| "cancelled"` |
293
+ | `PipelineRunRecord` | Persistence-layer run record with runId, definition, stepStates, cost |
294
+ | `StepStateRecord` | Per-step state in persistence: status, artifactId, attempts, timing |
295
+ | `PipelineStateStore` | Persistence interface: createRun, getRun, updateRun, acquireLock, releaseLock, listRuns |
296
+ | `CostLedger` | Cost interface: charge, getRunCost, getTotalCost |
297
+ | `BudgetConfig` | Budget with maxUsd, onExceed, warnAtPct |
298
+ | `PipelineEstimate` / `StepEstimate` / `EstimateWarning` | Dry-run estimation results |
299
+ | `RunContext` / `VoiceRef` / `StyleRef` / `BrandKit` | Run context for voice/style/brand resolution |
300
+ | `VariantsConfig` / `VariantResult` / `VariantsStepOutput` | Variants configuration and results |
301
+ | `JudgeConfig` / `JudgeRubric` | Variants judge types (llm-judge, image-judge, rule, custom) |
302
+ | `ArtifactMetaSchema` / `ArtifactMeta` | Storage-level artifact metadata |
303
+ | `ValidationResultSchema` / `ValidationResult` | Validator output with valid, errors, warnings, estimates |
304
+
305
+ ### Error Classes
306
+
307
+ All errors extend `A2AError` and carry `code` and `retryable` properties.
308
+
309
+ | Error Class | Code | Retryable | Description |
310
+ |-------------|------|-----------|-------------|
311
+ | `IdempotencyConflictError` | `IDEMPOTENCY_CONFLICT` | No | Duplicate idempotency key with in-flight or body-mismatch |
312
+ | `BudgetExceededError` | `BUDGET_EXCEEDED` | No | Budget cap reached (run, tenant-daily, or tenant-monthly) |
313
+ | `RunNotFoundError` | `RUN_NOT_FOUND` | No | Persisted run not found for resume |
314
+ | `RunInProgressError` | `RUN_IN_PROGRESS` | Yes | Run lock held by another process |
315
+ | `RunNotResumableError` | `RUN_NOT_RESUMABLE` | No | Run in terminal state or `resumable: false` |
316
+ | `WebhookSignatureInvalidError` | `WEBHOOK_SIGNATURE_INVALID` | No | Webhook HMAC verification failed |
317
+ | `WebhookProviderUnknownError` | `WEBHOOK_PROVIDER_UNKNOWN` | No | Webhook provider not recognized |
318
+ | `StateStoreUnavailableError` | `STATE_STORE_UNAVAILABLE` | Yes | Persistence backend unreachable |
319
+ | `EstimateUnsupportedError` | `ESTIMATE_UNSUPPORTED` | No | Cost estimation not available for operation |
320
+ | `ArtifactNotFoundError` | `ARTIFACT_NOT_FOUND` | No | Referenced artifact missing from registry |
321
+ | `RouterAllCandidatesFailedError` | `ROUTER_ALL_CANDIDATES_FAILED` | No | All routing candidates exhausted |
322
+ | `RouterNoCandidatesError` | `ROUTER_NO_CANDIDATES` | No | Empty candidate list for routing |
323
+ | `RouterFastestIneligibleError` | `ROUTER_FASTEST_INELIGIBLE` | No | Candidate exceeds fastest strategy duration cap |
324
+ | `SafetyGateRejectedError` | `SAFETY_GATE_REJECTED` | No | Content safety check blocked artifact |
325
+ | `TenantNotFoundError` | `TENANT_NOT_FOUND` | No | Tenant not found in multi-tenant deployment |
326
+ | `KeyVaultUnavailableError` | `KEY_VAULT_UNAVAILABLE` | Yes | Key vault service unreachable |
327
+ | `FfmpegUnavailableError` | `FFMPEG_UNAVAILABLE` | No | ffmpeg not found for audio/video processing |
328
+ | `VariantsAllRejectedError` | `VARIANTS_ALL_REJECTED` | No | All variants failed (safety, judge-low, generation-error) |
329
+ | `JudgeUnavailableError` | `JUDGE_UNAVAILABLE` | Yes | LLM judge service unreachable |
330
+ | `WorkflowNotFoundError` | `WORKFLOW_NOT_FOUND` | No | ComfyUI workflow not found |
331
+ | `WorkflowExpiredError` | `WORKFLOW_EXPIRED` | No | ComfyUI workflow exceeded retention period |
332
+ | `ContextRefUnknownError` | `CONTEXT_REF_UNKNOWN` | No | Context reference (voice/style/brand) not found |
333
+ | `ContextRefTypeError` | `CONTEXT_REF_TYPE_MISMATCH` | No | Context reference type mismatch for operation |
334
+ | `LoudnessGateFailedError` | `LOUDNESS_GATE_FAILED` | No | Audio loudness gate out of tolerance |
335
+ | `TenantPolicyViolationError` | `TENANT_POLICY_VIOLATION` | No | Provider/model blocked by tenant allow-list |
336
+ | `ProvenanceSigningFailedError` | `PROVENANCE_SIGNING_FAILED` | No | C2PA manifest signing failed |
337
+ | `SafetyProviderUnavailableError` | `SAFETY_PROVIDER_UNAVAILABLE` | Yes | Safety classifier unreachable |
338
+ | `RatioUnsupportedError` | `RATIO_UNSUPPORTED` | No | Aspect ratio not natively supported by provider |
339
+ | `InvalidInputError` | `INVALID_INPUT` | No | Invalid step input |
340
+ | `FormatUnsupportedError` | `FORMAT_UNSUPPORTED` | No | Output format not supported for operation |
341
+ | `ArtifactAccessDeniedError` | `ARTIFACT_ACCESS_DENIED` | No | Tenant-scoped access denied |
342
+ | `InvalidResourceUriError` | `INVALID_RESOURCE_URI` | No | Invalid resource URI format |
343
+
344
+ ## Usage Patterns
345
+
346
+ ### Pipeline with Persistence and Resume
347
+
348
+ ```typescript
349
+ const executor = new PipelineExecutor({
350
+ providers: [new MockProvider()],
351
+ persistence: stateStore, // PipelineStateStore for durability
352
+ ledger: costLedger, // CostLedger for cost tracking
353
+ onEvent: (event) => console.log(event.type, event.pipelineId),
354
+ onCost: (record) => console.log(`Cost: $${record.cost_usd}`),
355
+ });
356
+
357
+ // Execute with a specific runId for idempotency
358
+ const result = await executor.execute(definition, { runId: "run-001" });
359
+
360
+ // Resume from persistence
361
+ const resumed = await executor.resume("run-001");
362
+ // Or resume from a specific step
363
+ const resumedFrom = await executor.resume("run-001", "upscale");
364
+ ```
365
+
366
+ ### Dry-Run Estimation
367
+
368
+ ```typescript
369
+ const estimator = new PipelineEstimator({
370
+ estimateOperation: async (operation, config) => {
371
+ return { usdLow: 0.001, usdHigh: 0.01 };
372
+ },
373
+ ledger: costLedger,
374
+ });
375
+
376
+ const estimate = await estimator.estimate(definition);
377
+ console.log(`Cost range: $${estimate.totalUsdLow} - $${estimate.totalUsdHigh}`);
378
+ ```
379
+
380
+ ### Validation with Provider Checks
381
+
382
+ ```typescript
383
+ const validator = new PipelineValidator({
384
+ isAvailable: (op) => providers.has(op),
385
+ getEstimatedCost: (op) => 0.01,
386
+ getEstimatedDuration: (op) => 5000,
387
+ });
388
+
389
+ const result = validator.validate(definition);
390
+ if (!result.valid) {
391
+ result.errors.forEach(e => console.error(e));
392
+ }
393
+ result.warnings.forEach(w => console.warn(w));
394
+ ```
395
+
396
+ ### LLM-Judge Quality Gate
397
+
398
+ ```typescript
399
+ const executor = new PipelineExecutor({
400
+ providers: [new MockProvider()],
401
+ llmJudgeFn: async (prompt, artifact) => {
402
+ const response = await callLLM(prompt, artifact.uri);
403
+ return { pass: response.score >= 7, reasoning: response.explanation, score: response.score };
404
+ },
405
+ });
406
+
407
+ // Step with llm-judge:
408
+ {
409
+ id: "generate",
410
+ operation: "image.generate",
411
+ inputs: { prompt: "..." },
412
+ config: {},
413
+ qualityGate: {
414
+ type: "llm-judge",
415
+ config: { prompt: "Rate image quality from 1-10", timeout: 30000 },
416
+ action: "retry",
417
+ maxRetries: 2,
418
+ },
419
+ }
420
+ ```
421
+
422
+ ### Event Bus Usage
423
+
424
+ ```typescript
425
+ const bus = createEventBus<{ kind: "pipeline:complete"; pipelineId: string; artifacts: string[] }>();
426
+
427
+ bus.on("pipeline:complete", (event) => {
428
+ console.log(`Pipeline ${event.pipelineId} done with ${event.artifacts.length} artifacts`);
429
+ });
430
+
431
+ // Await an event
432
+ const completed = await bus.await("pipeline:complete", (e) => e.pipelineId === "my-pipeline", 60000);
433
+ ```
434
+
435
+ ## Related Packages
436
+
437
+ - [`@reaatech/media-pipeline-mcp-provider-core`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-provider-core) — Abstract provider base class and router
438
+ - [`@reaatech/media-pipeline-mcp-pipeline`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-pipeline) — Pipeline templates, variants, batches, ratios
439
+ - [`@reaatech/media-pipeline-mcp-storage`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-storage) — Artifact persistence (local, S3, GCS)
440
+ - [`@reaatech/media-pipeline-mcp-resilience`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-resilience) — Circuit breaker and retry policies
441
+ - [`@reaatech/media-pipeline-mcp-security`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-security) — Auth, RBAC, rate limiting, audit logging
442
+ - [`@reaatech/media-pipeline-mcp-observability`](https://www.npmjs.com/package/@reaatech/media-pipeline-mcp-observability) — Tracing, metrics, structured logging
443
+
444
+ ## License
445
+
446
+ [MIT](https://github.com/reaatech/media-pipeline-mcp/blob/main/LICENSE)