@xemahq/dsl 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/deliverable-spec/index.d.ts +3 -0
- package/dist/deliverable-spec/index.d.ts.map +1 -0
- package/dist/deliverable-spec/index.js +19 -0
- package/dist/deliverable-spec/index.js.map +1 -0
- package/dist/deliverable-spec/lib/schema.d.ts +151 -0
- package/dist/deliverable-spec/lib/schema.d.ts.map +1 -0
- package/dist/deliverable-spec/lib/schema.js +139 -0
- package/dist/deliverable-spec/lib/schema.js.map +1 -0
- package/dist/deliverable-spec/lib/types.d.ts +8 -0
- package/dist/deliverable-spec/lib/types.d.ts.map +1 -0
- package/dist/deliverable-spec/lib/types.js +3 -0
- package/dist/deliverable-spec/lib/types.js.map +1 -0
- package/dist/payload-codec/index.d.ts +8 -0
- package/dist/payload-codec/index.d.ts.map +1 -0
- package/dist/payload-codec/index.js +27 -0
- package/dist/payload-codec/index.js.map +1 -0
- package/dist/payload-codec/lib/blob-store.d.ts +37 -0
- package/dist/payload-codec/lib/blob-store.d.ts.map +1 -0
- package/dist/payload-codec/lib/blob-store.js +0 -0
- package/dist/payload-codec/lib/blob-store.js.map +1 -0
- package/dist/payload-codec/lib/codec-context.d.ts +6 -0
- package/dist/payload-codec/lib/codec-context.d.ts.map +1 -0
- package/dist/payload-codec/lib/codec-context.js +16 -0
- package/dist/payload-codec/lib/codec-context.js.map +1 -0
- package/dist/payload-codec/lib/codec.d.ts +51 -0
- package/dist/payload-codec/lib/codec.d.ts.map +1 -0
- package/dist/payload-codec/lib/codec.js +330 -0
- package/dist/payload-codec/lib/codec.js.map +1 -0
- package/dist/payload-codec/lib/enums.d.ts +18 -0
- package/dist/payload-codec/lib/enums.d.ts.map +1 -0
- package/dist/payload-codec/lib/enums.js +23 -0
- package/dist/payload-codec/lib/enums.js.map +1 -0
- package/dist/payload-codec/lib/errors.d.ts +18 -0
- package/dist/payload-codec/lib/errors.d.ts.map +1 -0
- package/dist/payload-codec/lib/errors.js +39 -0
- package/dist/payload-codec/lib/errors.js.map +1 -0
- package/dist/payload-codec/lib/http-blob-store.d.ts +21 -0
- package/dist/payload-codec/lib/http-blob-store.d.ts.map +1 -0
- package/dist/payload-codec/lib/http-blob-store.js +139 -0
- package/dist/payload-codec/lib/http-blob-store.js.map +1 -0
- package/dist/payload-codec/lib/lru-cache.d.ts +12 -0
- package/dist/payload-codec/lib/lru-cache.d.ts.map +1 -0
- package/dist/payload-codec/lib/lru-cache.js +59 -0
- package/dist/payload-codec/lib/lru-cache.js.map +1 -0
- package/dist/schema/action.schema.json +181 -0
- package/dist/schema/reusable-workflow.schema.json +46 -0
- package/dist/schema/workflow.schema.json +373 -0
- package/dist/workflow/index.d.ts +14 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +49 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/lib/action-input-validator.d.ts +10 -0
- package/dist/workflow/lib/action-input-validator.d.ts.map +1 -0
- package/dist/workflow/lib/action-input-validator.js +69 -0
- package/dist/workflow/lib/action-input-validator.js.map +1 -0
- package/dist/workflow/lib/compiler/action-shape.d.ts +5 -0
- package/dist/workflow/lib/compiler/action-shape.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/action-shape.js +43 -0
- package/dist/workflow/lib/compiler/action-shape.js.map +1 -0
- package/dist/workflow/lib/compiler/canonical-json.d.ts +3 -0
- package/dist/workflow/lib/compiler/canonical-json.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/canonical-json.js +45 -0
- package/dist/workflow/lib/compiler/canonical-json.js.map +1 -0
- package/dist/workflow/lib/compiler/compile.d.ts +4 -0
- package/dist/workflow/lib/compiler/compile.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/compile.js +794 -0
- package/dist/workflow/lib/compiler/compile.js.map +1 -0
- package/dist/workflow/lib/compiler/concurrency.d.ts +5 -0
- package/dist/workflow/lib/compiler/concurrency.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/concurrency.js +104 -0
- package/dist/workflow/lib/compiler/concurrency.js.map +1 -0
- package/dist/workflow/lib/compiler/dag.d.ts +10 -0
- package/dist/workflow/lib/compiler/dag.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/dag.js +74 -0
- package/dist/workflow/lib/compiler/dag.js.map +1 -0
- package/dist/workflow/lib/compiler/index.d.ts +6 -0
- package/dist/workflow/lib/compiler/index.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/index.js +14 -0
- package/dist/workflow/lib/compiler/index.js.map +1 -0
- package/dist/workflow/lib/compiler/inputs.d.ts +4 -0
- package/dist/workflow/lib/compiler/inputs.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/inputs.js +108 -0
- package/dist/workflow/lib/compiler/inputs.js.map +1 -0
- package/dist/workflow/lib/compiler/installation-resource-validator.d.ts +9 -0
- package/dist/workflow/lib/compiler/installation-resource-validator.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/installation-resource-validator.js +76 -0
- package/dist/workflow/lib/compiler/installation-resource-validator.js.map +1 -0
- package/dist/workflow/lib/compiler/manifest-source.d.ts +4 -0
- package/dist/workflow/lib/compiler/manifest-source.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/manifest-source.js +100 -0
- package/dist/workflow/lib/compiler/manifest-source.js.map +1 -0
- package/dist/workflow/lib/compiler/matrix.d.ts +4 -0
- package/dist/workflow/lib/compiler/matrix.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/matrix.js +76 -0
- package/dist/workflow/lib/compiler/matrix.js.map +1 -0
- package/dist/workflow/lib/compiler/mount-plan.d.ts +4 -0
- package/dist/workflow/lib/compiler/mount-plan.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/mount-plan.js +96 -0
- package/dist/workflow/lib/compiler/mount-plan.js.map +1 -0
- package/dist/workflow/lib/compiler/payload-reach-in.d.ts +14 -0
- package/dist/workflow/lib/compiler/payload-reach-in.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/payload-reach-in.js +273 -0
- package/dist/workflow/lib/compiler/payload-reach-in.js.map +1 -0
- package/dist/workflow/lib/compiler/permissions.d.ts +6 -0
- package/dist/workflow/lib/compiler/permissions.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/permissions.js +43 -0
- package/dist/workflow/lib/compiler/permissions.js.map +1 -0
- package/dist/workflow/lib/compiler/retry-timeout.d.ts +6 -0
- package/dist/workflow/lib/compiler/retry-timeout.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/retry-timeout.js +64 -0
- package/dist/workflow/lib/compiler/retry-timeout.js.map +1 -0
- package/dist/workflow/lib/compiler/review-step.d.ts +18 -0
- package/dist/workflow/lib/compiler/review-step.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/review-step.js +247 -0
- package/dist/workflow/lib/compiler/review-step.js.map +1 -0
- package/dist/workflow/lib/compiler/types.d.ts +42 -0
- package/dist/workflow/lib/compiler/types.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/types.js +3 -0
- package/dist/workflow/lib/compiler/types.js.map +1 -0
- package/dist/workflow/lib/compiler/variable-requirements.d.ts +5 -0
- package/dist/workflow/lib/compiler/variable-requirements.d.ts.map +1 -0
- package/dist/workflow/lib/compiler/variable-requirements.js +119 -0
- package/dist/workflow/lib/compiler/variable-requirements.js.map +1 -0
- package/dist/workflow/lib/deliverable-spec-keys.d.ts +3 -0
- package/dist/workflow/lib/deliverable-spec-keys.d.ts.map +1 -0
- package/dist/workflow/lib/deliverable-spec-keys.js +90 -0
- package/dist/workflow/lib/deliverable-spec-keys.js.map +1 -0
- package/dist/workflow/lib/dispatch-inputs/index.d.ts +23 -0
- package/dist/workflow/lib/dispatch-inputs/index.d.ts.map +1 -0
- package/dist/workflow/lib/dispatch-inputs/index.js +106 -0
- package/dist/workflow/lib/dispatch-inputs/index.js.map +1 -0
- package/dist/workflow/lib/dispatch-inputs/to-json-schema.d.ts +3 -0
- package/dist/workflow/lib/dispatch-inputs/to-json-schema.d.ts.map +1 -0
- package/dist/workflow/lib/dispatch-inputs/to-json-schema.js +43 -0
- package/dist/workflow/lib/dispatch-inputs/to-json-schema.js.map +1 -0
- package/dist/workflow/lib/duration.d.ts +2 -0
- package/dist/workflow/lib/duration.d.ts.map +1 -0
- package/dist/workflow/lib/duration.js +26 -0
- package/dist/workflow/lib/duration.js.map +1 -0
- package/dist/workflow/lib/errors.d.ts +9 -0
- package/dist/workflow/lib/errors.d.ts.map +1 -0
- package/dist/workflow/lib/errors.js +28 -0
- package/dist/workflow/lib/errors.js.map +1 -0
- package/dist/workflow/lib/expression/ast.d.ts +61 -0
- package/dist/workflow/lib/expression/ast.d.ts.map +1 -0
- package/dist/workflow/lib/expression/ast.js +34 -0
- package/dist/workflow/lib/expression/ast.js.map +1 -0
- package/dist/workflow/lib/expression/context.d.ts +63 -0
- package/dist/workflow/lib/expression/context.d.ts.map +1 -0
- package/dist/workflow/lib/expression/context.js +32 -0
- package/dist/workflow/lib/expression/context.js.map +1 -0
- package/dist/workflow/lib/expression/evaluator.d.ts +5 -0
- package/dist/workflow/lib/expression/evaluator.d.ts.map +1 -0
- package/dist/workflow/lib/expression/evaluator.js +291 -0
- package/dist/workflow/lib/expression/evaluator.js.map +1 -0
- package/dist/workflow/lib/expression/index.d.ts +9 -0
- package/dist/workflow/lib/expression/index.d.ts.map +1 -0
- package/dist/workflow/lib/expression/index.js +26 -0
- package/dist/workflow/lib/expression/index.js.map +1 -0
- package/dist/workflow/lib/expression/interpolation.d.ts +9 -0
- package/dist/workflow/lib/expression/interpolation.d.ts.map +1 -0
- package/dist/workflow/lib/expression/interpolation.js +51 -0
- package/dist/workflow/lib/expression/interpolation.js.map +1 -0
- package/dist/workflow/lib/expression/parser.d.ts +4 -0
- package/dist/workflow/lib/expression/parser.d.ts.map +1 -0
- package/dist/workflow/lib/expression/parser.js +203 -0
- package/dist/workflow/lib/expression/parser.js.map +1 -0
- package/dist/workflow/lib/expression/template.d.ts +18 -0
- package/dist/workflow/lib/expression/template.d.ts.map +1 -0
- package/dist/workflow/lib/expression/template.js +63 -0
- package/dist/workflow/lib/expression/template.js.map +1 -0
- package/dist/workflow/lib/expression/tokenizer.d.ts +3 -0
- package/dist/workflow/lib/expression/tokenizer.d.ts.map +1 -0
- package/dist/workflow/lib/expression/tokenizer.js +153 -0
- package/dist/workflow/lib/expression/tokenizer.js.map +1 -0
- package/dist/workflow/lib/expression/tokens.d.ts +25 -0
- package/dist/workflow/lib/expression/tokens.d.ts.map +1 -0
- package/dist/workflow/lib/expression/tokens.js +24 -0
- package/dist/workflow/lib/expression/tokens.js.map +1 -0
- package/dist/workflow/lib/expression/walk-artifact-refs.d.ts +5 -0
- package/dist/workflow/lib/expression/walk-artifact-refs.d.ts.map +1 -0
- package/dist/workflow/lib/expression/walk-artifact-refs.js +138 -0
- package/dist/workflow/lib/expression/walk-artifact-refs.js.map +1 -0
- package/dist/workflow/lib/installation-resource-kind.d.ts +14 -0
- package/dist/workflow/lib/installation-resource-kind.d.ts.map +1 -0
- package/dist/workflow/lib/installation-resource-kind.js +59 -0
- package/dist/workflow/lib/installation-resource-kind.js.map +1 -0
- package/dist/workflow/lib/schemas-loader.d.ts +4 -0
- package/dist/workflow/lib/schemas-loader.d.ts.map +1 -0
- package/dist/workflow/lib/schemas-loader.js +36 -0
- package/dist/workflow/lib/schemas-loader.js.map +1 -0
- package/dist/workflow/lib/serializer.d.ts +3 -0
- package/dist/workflow/lib/serializer.d.ts.map +1 -0
- package/dist/workflow/lib/serializer.js +15 -0
- package/dist/workflow/lib/serializer.js.map +1 -0
- package/dist/workflow/lib/types.d.ts +179 -0
- package/dist/workflow/lib/types.d.ts.map +1 -0
- package/dist/workflow/lib/types.js +3 -0
- package/dist/workflow/lib/types.js.map +1 -0
- package/dist/workflow/lib/validate.d.ts +8 -0
- package/dist/workflow/lib/validate.d.ts.map +1 -0
- package/dist/workflow/lib/validate.js +119 -0
- package/dist/workflow/lib/validate.js.map +1 -0
- package/dist/workspace-manifest/index.d.ts +6 -0
- package/dist/workspace-manifest/index.d.ts.map +1 -0
- package/dist/workspace-manifest/index.js +22 -0
- package/dist/workspace-manifest/index.js.map +1 -0
- package/dist/workspace-manifest/lib/compile.d.ts +8 -0
- package/dist/workspace-manifest/lib/compile.d.ts.map +1 -0
- package/dist/workspace-manifest/lib/compile.js +439 -0
- package/dist/workspace-manifest/lib/compile.js.map +1 -0
- package/dist/workspace-manifest/lib/interpolate.d.ts +12 -0
- package/dist/workspace-manifest/lib/interpolate.d.ts.map +1 -0
- package/dist/workspace-manifest/lib/interpolate.js +81 -0
- package/dist/workspace-manifest/lib/interpolate.js.map +1 -0
- package/dist/workspace-manifest/lib/resolve-extends.d.ts +10 -0
- package/dist/workspace-manifest/lib/resolve-extends.d.ts.map +1 -0
- package/dist/workspace-manifest/lib/resolve-extends.js +108 -0
- package/dist/workspace-manifest/lib/resolve-extends.js.map +1 -0
- package/dist/workspace-manifest/lib/schema.d.ts +710 -0
- package/dist/workspace-manifest/lib/schema.d.ts.map +1 -0
- package/dist/workspace-manifest/lib/schema.js +355 -0
- package/dist/workspace-manifest/lib/schema.js.map +1 -0
- package/dist/workspace-manifest/lib/types.d.ts +153 -0
- package/dist/workspace-manifest/lib/types.d.ts.map +1 -0
- package/dist/workspace-manifest/lib/types.js +10 -0
- package/dist/workspace-manifest/lib/types.js.map +1 -0
- package/package.json +79 -0
- package/schema/action.schema.json +181 -0
- package/schema/reusable-workflow.schema.json +46 -0
- package/schema/workflow.schema.json +373 -0
- package/src/deliverable-spec/index.ts +19 -0
- package/src/deliverable-spec/lib/schema.ts +248 -0
- package/src/deliverable-spec/lib/types.ts +26 -0
- package/src/payload-codec/index.ts +40 -0
- package/src/payload-codec/lib/blob-store.ts +0 -0
- package/src/payload-codec/lib/codec-context.ts +38 -0
- package/src/payload-codec/lib/codec.ts +593 -0
- package/src/payload-codec/lib/enums.ts +58 -0
- package/src/payload-codec/lib/errors.ts +54 -0
- package/src/payload-codec/lib/http-blob-store.ts +257 -0
- package/src/payload-codec/lib/lru-cache.ts +81 -0
- package/src/workflow/index.ts +98 -0
- package/src/workflow/lib/action-input-validator.ts +160 -0
- package/src/workflow/lib/compiler/action-shape.ts +71 -0
- package/src/workflow/lib/compiler/canonical-json.ts +53 -0
- package/src/workflow/lib/compiler/compile.ts +1518 -0
- package/src/workflow/lib/compiler/concurrency.ts +223 -0
- package/src/workflow/lib/compiler/dag.ts +108 -0
- package/src/workflow/lib/compiler/index.ts +10 -0
- package/src/workflow/lib/compiler/inputs.ts +199 -0
- package/src/workflow/lib/compiler/installation-resource-validator.ts +114 -0
- package/src/workflow/lib/compiler/manifest-source.ts +176 -0
- package/src/workflow/lib/compiler/matrix.ts +135 -0
- package/src/workflow/lib/compiler/mount-plan.ts +202 -0
- package/src/workflow/lib/compiler/payload-reach-in.ts +497 -0
- package/src/workflow/lib/compiler/permissions.ts +64 -0
- package/src/workflow/lib/compiler/retry-timeout.ts +105 -0
- package/src/workflow/lib/compiler/review-step.ts +517 -0
- package/src/workflow/lib/compiler/types.ts +170 -0
- package/src/workflow/lib/compiler/variable-requirements.ts +208 -0
- package/src/workflow/lib/deliverable-spec-keys.ts +109 -0
- package/src/workflow/lib/dispatch-inputs/index.ts +160 -0
- package/src/workflow/lib/dispatch-inputs/to-json-schema.ts +60 -0
- package/src/workflow/lib/duration.ts +48 -0
- package/src/workflow/lib/errors.ts +37 -0
- package/src/workflow/lib/expression/ast.ts +108 -0
- package/src/workflow/lib/expression/context.ts +148 -0
- package/src/workflow/lib/expression/evaluator.ts +492 -0
- package/src/workflow/lib/expression/index.ts +28 -0
- package/src/workflow/lib/expression/interpolation.ts +84 -0
- package/src/workflow/lib/expression/parser.ts +264 -0
- package/src/workflow/lib/expression/template.ts +117 -0
- package/src/workflow/lib/expression/tokenizer.ts +200 -0
- package/src/workflow/lib/expression/tokens.ts +30 -0
- package/src/workflow/lib/expression/walk-artifact-refs.ts +232 -0
- package/src/workflow/lib/installation-resource-kind.ts +107 -0
- package/src/workflow/lib/schemas-loader.ts +64 -0
- package/src/workflow/lib/serializer.ts +30 -0
- package/src/workflow/lib/types.ts +361 -0
- package/src/workflow/lib/validate.ts +199 -0
- package/src/workspace-manifest/index.ts +27 -0
- package/src/workspace-manifest/lib/compile.ts +608 -0
- package/src/workspace-manifest/lib/interpolate.ts +140 -0
- package/src/workspace-manifest/lib/resolve-extends.ts +260 -0
- package/src/workspace-manifest/lib/schema.ts +612 -0
- package/src/workspace-manifest/lib/types.ts +392 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import type { ConcurrencyMode, PermissionScope } from '@xemahq/kernel-contracts/workflow';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Authored-shape TypeScript types for a Xema workflow document. These match
|
|
5
|
+
* the JSON Schema at schema/workflow.schema.json — validation is the source
|
|
6
|
+
* of truth, these types are ergonomics for callers that have already
|
|
7
|
+
* validated the input.
|
|
8
|
+
*
|
|
9
|
+
* Do NOT trust unvalidated user input typed as `WorkflowDocument` — always
|
|
10
|
+
* pass through `validateWorkflowDocument(raw)` first, which produces a
|
|
11
|
+
* narrowed value safely typed as this interface.
|
|
12
|
+
*/
|
|
13
|
+
export interface WorkflowDocument {
|
|
14
|
+
readonly apiVersion: 'xema.dev/workflow/v1alpha1';
|
|
15
|
+
readonly kind: 'Workflow';
|
|
16
|
+
readonly metadata: WorkflowMetadata;
|
|
17
|
+
readonly on: WorkflowTriggerDeclarations;
|
|
18
|
+
readonly concurrency?: WorkflowConcurrencyDeclaration;
|
|
19
|
+
readonly defaults?: WorkflowDefaults;
|
|
20
|
+
readonly permissions?: WorkflowPermissions;
|
|
21
|
+
readonly vars?: Readonly<Record<string, unknown>>;
|
|
22
|
+
/**
|
|
23
|
+
* Wallets (variable + secret bundles) the workflow needs at dispatch
|
|
24
|
+
* time. A wallet is a named group of project / org variables managed
|
|
25
|
+
* through `project-registry-api`. The engine resolves each declared
|
|
26
|
+
* wallet to its contents before starting the run; missing wallets or
|
|
27
|
+
* missing keys referenced by `${{ vars.X }}` / `${{ secrets.X }}`
|
|
28
|
+
* surface as
|
|
29
|
+
* `WorkflowErrorCode.WORKFLOW_WALLET_NOT_FOUND` /
|
|
30
|
+
* `WorkflowErrorCode.WORKFLOW_VARIABLES_MISSING` respectively, and
|
|
31
|
+
* the run is never started.
|
|
32
|
+
*
|
|
33
|
+
* Dispatch callers may pass additional wallet names on top of this
|
|
34
|
+
* list — additive only.
|
|
35
|
+
*/
|
|
36
|
+
readonly requires?: WorkflowRequiresDeclaration;
|
|
37
|
+
readonly jobs: Readonly<Record<string, WorkflowJobDeclaration>>;
|
|
38
|
+
/**
|
|
39
|
+
* Workflow-level named outputs. Each entry references a single
|
|
40
|
+
* `(job, outputName)` pair and declares the kind of value it
|
|
41
|
+
* surfaces — deliverable artifact (the most common), structured
|
|
42
|
+
* JSON value, or plain text.
|
|
43
|
+
*
|
|
44
|
+
* Consumers:
|
|
45
|
+
* - Biome `mcpWorkflowTools[].outputProjection.slug` (cross-
|
|
46
|
+
* referenced at biome boot — the slug MUST match a key here).
|
|
47
|
+
* - Future `workflow_call` reusable composition (consumes outputs
|
|
48
|
+
* declared by the called workflow).
|
|
49
|
+
* - Run-detail projections (`RunResponseDto.deliverables`) — built
|
|
50
|
+
* by walking this map against the producing JobRun outputs.
|
|
51
|
+
*
|
|
52
|
+
* Validation at compile time:
|
|
53
|
+
* - `fromJob` MUST exist in `jobs`.
|
|
54
|
+
* - `fromOutput` MUST appear in that job's `outputs:` map.
|
|
55
|
+
* - For `kind: 'deliverable'`, `deliverableSpecRef` MUST resolve
|
|
56
|
+
* through the spec prefetch path.
|
|
57
|
+
*/
|
|
58
|
+
readonly outputs?: Readonly<Record<string, WorkflowOutputDeclaration>>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Per-output declaration shape. Discriminated by `kind`. Lives at the
|
|
63
|
+
* workflow document level (`workflow.outputs.<name>`), NOT on a job.
|
|
64
|
+
* Job-level `outputs:` remain the per-step expressions feeding into
|
|
65
|
+
* workflow outputs via `fromJob` / `fromOutput`.
|
|
66
|
+
*/
|
|
67
|
+
export type WorkflowOutputDeclaration =
|
|
68
|
+
| WorkflowDeliverableOutputDeclaration
|
|
69
|
+
| WorkflowStructuredOutputDeclaration
|
|
70
|
+
| WorkflowTextOutputDeclaration;
|
|
71
|
+
|
|
72
|
+
interface WorkflowOutputDeclarationBase {
|
|
73
|
+
readonly slug: string;
|
|
74
|
+
readonly fromJob: string;
|
|
75
|
+
readonly fromOutput: string;
|
|
76
|
+
readonly description?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface WorkflowDeliverableOutputDeclaration
|
|
80
|
+
extends WorkflowOutputDeclarationBase {
|
|
81
|
+
readonly kind: 'deliverable';
|
|
82
|
+
/** Reference to a published `DeliverableSpec` (slug or slug@version). */
|
|
83
|
+
readonly deliverableSpecRef: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface WorkflowStructuredOutputDeclaration
|
|
87
|
+
extends WorkflowOutputDeclarationBase {
|
|
88
|
+
readonly kind: 'structured';
|
|
89
|
+
/** Optional JSON Schema ref the platform validates the value against. */
|
|
90
|
+
readonly schemaRef?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WorkflowTextOutputDeclaration extends WorkflowOutputDeclarationBase {
|
|
94
|
+
readonly kind: 'text';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface WorkflowRequiresDeclaration {
|
|
98
|
+
/** Wallet names; must match `^[a-z][a-z0-9-]{0,62}$`. */
|
|
99
|
+
readonly wallets?: readonly string[];
|
|
100
|
+
/**
|
|
101
|
+
* Integration adapter kinds the workflow consumes. Biome-shipped
|
|
102
|
+
* workflows declare these so `biome-host-api` can cross-validate
|
|
103
|
+
* them against the biome's manifest `integrationRequirements` at
|
|
104
|
+
* boot. Stand-alone workflows (not biome-owned) may also declare
|
|
105
|
+
* them as documentation; dispatch-time enforcement only kicks in
|
|
106
|
+
* for biome-gated runs.
|
|
107
|
+
*/
|
|
108
|
+
readonly integrations?: readonly WorkflowIntegrationRequirement[];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface WorkflowIntegrationRequirement {
|
|
112
|
+
/** Adapter kind slug (e.g. `scm`, `tracker`, `documentation`). */
|
|
113
|
+
readonly adapterKind: string;
|
|
114
|
+
/** Capability slugs the workflow exercises against the adapter. */
|
|
115
|
+
readonly capabilities: readonly string[];
|
|
116
|
+
/** Whether the workflow can degrade if the integration is unbound. */
|
|
117
|
+
readonly optional?: boolean;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface WorkflowMetadata {
|
|
121
|
+
readonly name: string;
|
|
122
|
+
readonly version: string;
|
|
123
|
+
readonly title?: string;
|
|
124
|
+
readonly description?: string;
|
|
125
|
+
readonly category?: string;
|
|
126
|
+
readonly tags?: readonly string[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface WorkflowTriggerDeclarations {
|
|
130
|
+
readonly workflow_dispatch?: WorkflowDispatchDeclaration;
|
|
131
|
+
readonly schedule?: readonly ScheduleDeclaration[];
|
|
132
|
+
readonly webhook?: readonly WebhookDeclaration[];
|
|
133
|
+
readonly workflow_call?: WorkflowCallDeclaration;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface WorkflowDispatchDeclaration {
|
|
137
|
+
readonly inputs?: Readonly<Record<string, WorkflowInputDeclaration>>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface ScheduleDeclaration {
|
|
141
|
+
readonly cron: string;
|
|
142
|
+
readonly timezone?: string;
|
|
143
|
+
readonly inputs?: Readonly<Record<string, unknown>>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface WebhookDeclaration {
|
|
147
|
+
readonly event: string;
|
|
148
|
+
readonly secretRef?: string;
|
|
149
|
+
readonly filters?: Readonly<Record<string, string>>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface WorkflowCallDeclaration {
|
|
153
|
+
readonly inputs?: Readonly<Record<string, WorkflowInputDeclaration>>;
|
|
154
|
+
readonly outputs?: Readonly<Record<string, string>>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface WorkflowInputDeclaration {
|
|
158
|
+
readonly type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
|
|
159
|
+
readonly required?: boolean;
|
|
160
|
+
readonly default?: unknown;
|
|
161
|
+
readonly description?: string;
|
|
162
|
+
readonly enum?: readonly unknown[];
|
|
163
|
+
readonly items?: Readonly<Record<string, unknown>>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface WorkflowConcurrencyDeclaration {
|
|
167
|
+
readonly group: string;
|
|
168
|
+
readonly mode: ConcurrencyMode;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface WorkflowDefaults {
|
|
172
|
+
readonly retry?: WorkflowRetryDeclaration;
|
|
173
|
+
readonly timeout?: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface WorkflowRetryDeclaration {
|
|
177
|
+
readonly maxAttempts?: number;
|
|
178
|
+
readonly initialInterval?: string;
|
|
179
|
+
readonly backoffCoefficient?: number;
|
|
180
|
+
readonly maximumInterval?: string;
|
|
181
|
+
readonly nonRetryableErrorTypes?: readonly string[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type WorkflowPermissions = Partial<Record<'repos' | 'kb' | 'backlog' | 'integrations' | 'artifacts' | 'memory', PermissionScope>>;
|
|
185
|
+
|
|
186
|
+
export interface WorkflowJobDeclaration {
|
|
187
|
+
readonly title?: string;
|
|
188
|
+
readonly needs?: readonly string[];
|
|
189
|
+
readonly if?: string;
|
|
190
|
+
readonly strategy?: WorkflowStrategyDeclaration;
|
|
191
|
+
readonly matrixGather?: readonly string[];
|
|
192
|
+
readonly uses: string;
|
|
193
|
+
readonly with?: Readonly<Record<string, unknown>>;
|
|
194
|
+
readonly outputs?: Readonly<Record<string, string>>;
|
|
195
|
+
readonly retry?: WorkflowRetryDeclaration;
|
|
196
|
+
readonly timeout?: string;
|
|
197
|
+
readonly permissions?: WorkflowPermissions;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export type WorkflowStrategyDeclaration =
|
|
201
|
+
| { readonly matrix: Readonly<Record<string, readonly unknown[]>>; readonly maxParallel?: number }
|
|
202
|
+
| { readonly dynamic: WorkflowDynamicStrategyDeclaration; readonly maxParallel?: number };
|
|
203
|
+
|
|
204
|
+
export interface WorkflowDynamicStrategyDeclaration {
|
|
205
|
+
readonly from: string;
|
|
206
|
+
readonly as: string;
|
|
207
|
+
readonly maxEntries?: number;
|
|
208
|
+
/**
|
|
209
|
+
* Optional dotted path on each bound entry whose value becomes the
|
|
210
|
+
* entry's key in `needs.<thisJob>.outputs.byKey`. Enables per-CU
|
|
211
|
+
* downstream consumers to write
|
|
212
|
+
* `needs.X.outputs.byKey[matrix.<binding>.<keyBy>].field`. Validated
|
|
213
|
+
* lexically by the schema; resolved against actual entries at
|
|
214
|
+
* dispatch time.
|
|
215
|
+
*/
|
|
216
|
+
readonly keyBy?: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ── Action manifest ─────────────────────────────────────────────────────
|
|
220
|
+
|
|
221
|
+
export interface ActionManifest {
|
|
222
|
+
readonly apiVersion: 'xema.dev/workflow/v1alpha1';
|
|
223
|
+
readonly kind: 'Action';
|
|
224
|
+
readonly metadata: ActionManifestMetadata;
|
|
225
|
+
readonly spec: ActionManifestSpec;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface ActionManifestMetadata {
|
|
229
|
+
readonly id: string;
|
|
230
|
+
readonly version: string;
|
|
231
|
+
readonly title?: string;
|
|
232
|
+
readonly description?: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface ActionManifestSpec {
|
|
236
|
+
readonly executionKind: 'activity' | 'child_workflow';
|
|
237
|
+
readonly taskQueue: 'xema_default' | 'xema_agent' | 'xema_human';
|
|
238
|
+
/**
|
|
239
|
+
* Semantic category — drives consumer presentation (FE canvas
|
|
240
|
+
* shape, badge icon). Optional; omitted manifests fall back to
|
|
241
|
+
* `generic`. Closed values mirror `ActionKind` in
|
|
242
|
+
* `@xemahq/kernel-contracts/workflow`; consumers MUST treat unknown
|
|
243
|
+
* strings as `generic` so newer manifests stay safe with older
|
|
244
|
+
* clients.
|
|
245
|
+
*/
|
|
246
|
+
readonly actionKind?:
|
|
247
|
+
| 'agent'
|
|
248
|
+
| 'review'
|
|
249
|
+
| 'wait'
|
|
250
|
+
| 'timer'
|
|
251
|
+
| 'aggregate'
|
|
252
|
+
| 'dispatch'
|
|
253
|
+
| 'branch'
|
|
254
|
+
| 'loop'
|
|
255
|
+
| 'publish'
|
|
256
|
+
| 'notify'
|
|
257
|
+
| 'inquiry'
|
|
258
|
+
| 'fetch'
|
|
259
|
+
| 'transform'
|
|
260
|
+
| 'validate'
|
|
261
|
+
| 'terminate'
|
|
262
|
+
| 'generic';
|
|
263
|
+
readonly inputs: Readonly<Record<string, unknown>>;
|
|
264
|
+
readonly outputs: Readonly<Record<string, unknown>>;
|
|
265
|
+
/**
|
|
266
|
+
* Per-output deliverable-spec bindings (plan §B per-output bindings).
|
|
267
|
+
* Each entry pins a named output to a deliverable-spec ref like
|
|
268
|
+
* `agent-summary@1.0.0`. The DSL compiler consults this first when
|
|
269
|
+
* resolving typed payload reach-in (`outputs.<name>.<field>`); it
|
|
270
|
+
* falls back to the job-level `with.deliverableSpecRef` only when no
|
|
271
|
+
* per-output binding is declared, preserving the current single-spec
|
|
272
|
+
* agent flow.
|
|
273
|
+
*
|
|
274
|
+
* Optional. Activities with no fixed per-output spec (e.g. the agent
|
|
275
|
+
* activity, whose deliverables spec is workflow-author-chosen) omit
|
|
276
|
+
* this. The compiler always proves at least one of (per-output spec,
|
|
277
|
+
* job-level spec) is set before letting a reach-in compile.
|
|
278
|
+
*/
|
|
279
|
+
readonly outputBindings?: Readonly<Record<string, ActionOutputBinding>>;
|
|
280
|
+
readonly permissions?: WorkflowPermissions;
|
|
281
|
+
readonly allowedMounts?: readonly string[];
|
|
282
|
+
readonly retryDefaults: ActionManifestRetryDefaults;
|
|
283
|
+
readonly timeoutDefaults: ActionManifestTimeoutDefaults;
|
|
284
|
+
readonly auditEventMapping?: Partial<{ started: string; succeeded: string; failed: string }>;
|
|
285
|
+
/**
|
|
286
|
+
* Declarative contracts the action opts into. The DSL compiler reads
|
|
287
|
+
* this list to decide which validation lanes apply — e.g. the
|
|
288
|
+
* `workspace-manifest@v1` entry enables the manifest-source pair
|
|
289
|
+
* (`compositionRef` XOR inline short-form `mounts`) and the frontend
|
|
290
|
+
* canvas Inspector renders the manifest picker. Closed-set
|
|
291
|
+
* `kind`/`version` pair so biome-shipped agent actions inherit the
|
|
292
|
+
* same lanes without per-action-id branching.
|
|
293
|
+
*
|
|
294
|
+
* Today the only kind is `workspace-manifest`. New kinds extend the
|
|
295
|
+
* closed enum (deliverable-spec, knowledge-base-binding, …) with a
|
|
296
|
+
* single PR that fans out across the compiler, canvas, and runtime.
|
|
297
|
+
*/
|
|
298
|
+
readonly consumes?: readonly ActionContract[];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Per-output binding declaration on an action manifest. Today the only
|
|
303
|
+
* binding field is `deliverableSpecRef`; future bindings (e.g. KB-page
|
|
304
|
+
* slug, custom contracts) extend the type.
|
|
305
|
+
*/
|
|
306
|
+
export interface ActionOutputBinding {
|
|
307
|
+
/**
|
|
308
|
+
* Deliverable spec ref governing this output's payload shape, in the
|
|
309
|
+
* canonical `<slug>@<version>` form (e.g. `metrics-snapshot@1.0.0`).
|
|
310
|
+
*/
|
|
311
|
+
readonly deliverableSpecRef?: string;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Versioned consume-contract declaration on an action manifest.
|
|
316
|
+
*
|
|
317
|
+
* `workspace-manifest@v1` — enables the workspace-manifest triplet on
|
|
318
|
+
* `with:` (long-form ref, inline-anonymous envelope, or short-form
|
|
319
|
+
* mounts). Optional fields:
|
|
320
|
+
* - `surfaces`: restricts the surfaces the action can be invoked on
|
|
321
|
+
* (must intersect the manifest's `metadata.surfaceCompat`).
|
|
322
|
+
* - `roleHint`: pins the manifest's `spec.agent.role` to a closed
|
|
323
|
+
* `AgentRunRole`. Compile-time fail when a workflow points the
|
|
324
|
+
* action at a manifest whose role doesn't match.
|
|
325
|
+
*
|
|
326
|
+
* `agent-composition@v1` — enables the `with.composition` field: a
|
|
327
|
+
* `slug@version` reference to an Agent Composition (llm-registry-api
|
|
328
|
+
* composition registry). The composition is the source of truth for the
|
|
329
|
+
* step's agent + sub-agents + skill/tool selection. Resolved at dispatch
|
|
330
|
+
* time by the runtime via the composition resolution endpoint. Optional
|
|
331
|
+
* and additive — existing workflows that point an agent step at a
|
|
332
|
+
* workspace manifest are unaffected.
|
|
333
|
+
*/
|
|
334
|
+
export type ActionContract =
|
|
335
|
+
| WorkspaceManifestActionContract
|
|
336
|
+
| AgentCompositionActionContract;
|
|
337
|
+
|
|
338
|
+
export interface WorkspaceManifestActionContract {
|
|
339
|
+
readonly kind: 'workspace-manifest';
|
|
340
|
+
readonly version: 'v1';
|
|
341
|
+
readonly surfaces?: readonly ('workflow' | 'agent-session')[];
|
|
342
|
+
readonly roleHint?: string;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export interface AgentCompositionActionContract {
|
|
346
|
+
readonly kind: 'agent-composition';
|
|
347
|
+
readonly version: 'v1';
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export interface ActionManifestRetryDefaults {
|
|
351
|
+
readonly maxAttempts: number;
|
|
352
|
+
readonly initialInterval: string;
|
|
353
|
+
readonly backoffCoefficient: number;
|
|
354
|
+
readonly maximumInterval: string;
|
|
355
|
+
readonly nonRetryableErrorTypes?: readonly string[];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export interface ActionManifestTimeoutDefaults {
|
|
359
|
+
readonly startToClose: string;
|
|
360
|
+
readonly heartbeat?: string;
|
|
361
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import Ajv2020, { type ErrorObject, type ValidateFunction } from 'ajv/dist/2020';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import { load as parseYaml } from 'js-yaml';
|
|
4
|
+
import { WorkflowErrorCode } from '@xemahq/kernel-contracts/workflow';
|
|
5
|
+
import { WorkflowDslError } from './errors';
|
|
6
|
+
import {
|
|
7
|
+
ACTION_SCHEMA,
|
|
8
|
+
REUSABLE_WORKFLOW_SCHEMA,
|
|
9
|
+
WORKFLOW_SCHEMA,
|
|
10
|
+
} from './schemas-loader';
|
|
11
|
+
import type { ActionManifest, WorkflowDocument } from './types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Ajv is constructed exactly once per process (module scope). `strict:true`
|
|
15
|
+
* keeps us honest — we catch schema authoring bugs at module-load time
|
|
16
|
+
* instead of silently coercing them at runtime.
|
|
17
|
+
*
|
|
18
|
+
* Per-request validation is a hot path; re-compiling schemas would burn CPU
|
|
19
|
+
* for no correctness gain. Rule 7 (horizontal scalability): this validator
|
|
20
|
+
* is stateless and safe to share across concurrent requests in a NestJS
|
|
21
|
+
* process.
|
|
22
|
+
*
|
|
23
|
+
* `strictRequired` is explicitly disabled: it conflicts with the standard
|
|
24
|
+
* JSON-Schema-2020-12 `oneOf` discrimination idiom (`oneOf: [{required:[a]},
|
|
25
|
+
* {required:[b]}]`) where the referenced properties are declared in the
|
|
26
|
+
* parent subschema's `properties`. The remaining strict flags
|
|
27
|
+
* (`strictSchema`, `strictTypes`, `strictTuples`) plus
|
|
28
|
+
* `additionalProperties:false` in every object schema already catch the
|
|
29
|
+
* typos `strictRequired` would catch, so the safety tradeoff is zero.
|
|
30
|
+
*/
|
|
31
|
+
const ajv = new Ajv2020({
|
|
32
|
+
strict: true,
|
|
33
|
+
strictSchema: true,
|
|
34
|
+
strictTypes: true,
|
|
35
|
+
strictRequired: false,
|
|
36
|
+
strictTuples: true,
|
|
37
|
+
allErrors: true,
|
|
38
|
+
allowUnionTypes: false,
|
|
39
|
+
useDefaults: false,
|
|
40
|
+
validateFormats: true,
|
|
41
|
+
});
|
|
42
|
+
addFormats(ajv);
|
|
43
|
+
|
|
44
|
+
// Register referenced schemas so `$ref` across files resolves. Order
|
|
45
|
+
// matters: reusable-workflow references workflow.schema.json by $id.
|
|
46
|
+
ajv.addSchema(WORKFLOW_SCHEMA);
|
|
47
|
+
ajv.addSchema(REUSABLE_WORKFLOW_SCHEMA);
|
|
48
|
+
ajv.addSchema(ACTION_SCHEMA);
|
|
49
|
+
|
|
50
|
+
const validateWorkflow = compile<WorkflowDocument>(
|
|
51
|
+
'https://xema.dev/schemas/workflow/v1alpha1/Workflow.json',
|
|
52
|
+
);
|
|
53
|
+
const validateReusableWorkflow = compile<WorkflowDocument>(
|
|
54
|
+
'https://xema.dev/schemas/workflow/v1alpha1/ReusableWorkflow.json',
|
|
55
|
+
);
|
|
56
|
+
const validateAction = compile<ActionManifest>(
|
|
57
|
+
'https://xema.dev/schemas/workflow/v1alpha1/Action.json',
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
function compile<T>(schemaId: string): ValidateFunction<T> {
|
|
61
|
+
const fn = ajv.getSchema<T>(schemaId);
|
|
62
|
+
if (!fn) {
|
|
63
|
+
throw new WorkflowDslError(
|
|
64
|
+
WorkflowErrorCode.COMPILE_INTERNAL,
|
|
65
|
+
`Ajv failed to compile schema ${schemaId}. Schema registration order is wrong.`,
|
|
66
|
+
{ schemaId },
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return fn;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Parse a YAML workflow document and validate it against the workflow
|
|
74
|
+
* schema. Returns the narrowed document on success; throws
|
|
75
|
+
* {@link WorkflowDslError} with code DSL_SCHEMA_INVALID on any validation
|
|
76
|
+
* failure (never silent pass-through, never partial validation).
|
|
77
|
+
*/
|
|
78
|
+
export function parseAndValidateWorkflowYaml(yaml: string): WorkflowDocument {
|
|
79
|
+
return parseAndValidate(yaml, validateWorkflow, 'workflow');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Parse a YAML reusable-workflow document and validate it against the
|
|
84
|
+
* reusable-workflow schema.
|
|
85
|
+
*/
|
|
86
|
+
export function parseAndValidateReusableWorkflowYaml(yaml: string): WorkflowDocument {
|
|
87
|
+
return parseAndValidate(yaml, validateReusableWorkflow, 'reusable-workflow');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Parse a YAML action manifest and validate it against the action schema. */
|
|
91
|
+
export function parseAndValidateActionYaml(yaml: string): ActionManifest {
|
|
92
|
+
return parseAndValidate(yaml, validateAction, 'action');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validate an already-parsed document object. Useful for programmatic
|
|
97
|
+
* construction (e.g. tests) and for the engine seeding path that reads
|
|
98
|
+
* JSON directly from the DB.
|
|
99
|
+
*/
|
|
100
|
+
export function validateWorkflowDocument(doc: unknown): WorkflowDocument {
|
|
101
|
+
if (doc !== null && typeof doc === 'object' && !Array.isArray(doc)) {
|
|
102
|
+
normalizeJobNeedsShorthand(doc);
|
|
103
|
+
}
|
|
104
|
+
return runValidator(doc, validateWorkflow, 'workflow');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function validateReusableWorkflowDocument(doc: unknown): WorkflowDocument {
|
|
108
|
+
if (doc !== null && typeof doc === 'object' && !Array.isArray(doc)) {
|
|
109
|
+
normalizeJobNeedsShorthand(doc);
|
|
110
|
+
}
|
|
111
|
+
return runValidator(doc, validateReusableWorkflow, 'reusable-workflow');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function validateActionManifest(doc: unknown): ActionManifest {
|
|
115
|
+
return runValidator(doc, validateAction, 'action');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function parseAndValidate<T>(
|
|
119
|
+
yaml: string,
|
|
120
|
+
validator: ValidateFunction<T>,
|
|
121
|
+
kind: 'workflow' | 'reusable-workflow' | 'action',
|
|
122
|
+
): T {
|
|
123
|
+
let parsed: unknown;
|
|
124
|
+
try {
|
|
125
|
+
parsed = parseYaml(yaml, { schema: undefined, json: false });
|
|
126
|
+
} catch (err) {
|
|
127
|
+
throw new WorkflowDslError(
|
|
128
|
+
WorkflowErrorCode.DSL_SCHEMA_INVALID,
|
|
129
|
+
`YAML parse failure in ${kind} document: ${(err as Error).message}`,
|
|
130
|
+
{ kind },
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
134
|
+
throw new WorkflowDslError(
|
|
135
|
+
WorkflowErrorCode.DSL_SCHEMA_INVALID,
|
|
136
|
+
`Top-level YAML value in ${kind} document must be a mapping.`,
|
|
137
|
+
{ kind },
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
// Plan §G shorthand: `needs: <string>` → `[<string>]`. Normalize
|
|
141
|
+
// BEFORE validation so the schema stays strict (one canonical shape)
|
|
142
|
+
// and the rest of the compiler never branches on shorthand. Workflow +
|
|
143
|
+
// reusable-workflow documents both have `jobs: { <key>: { needs?... } }`;
|
|
144
|
+
// action manifests have no `needs`, so this is a no-op there.
|
|
145
|
+
if (kind !== 'action') {
|
|
146
|
+
normalizeJobNeedsShorthand(parsed);
|
|
147
|
+
}
|
|
148
|
+
return runValidator(parsed, validator, kind);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Mutates `doc.jobs.<key>.needs` from `<string>` to `[<string>]` in
|
|
153
|
+
* place. Authors can write either form; the canonical form is the
|
|
154
|
+
* array. Documented in plan §G under "Simplified DSL".
|
|
155
|
+
*/
|
|
156
|
+
function normalizeJobNeedsShorthand(doc: object): void {
|
|
157
|
+
const jobs = (doc as { jobs?: unknown }).jobs;
|
|
158
|
+
if (!jobs || typeof jobs !== 'object' || Array.isArray(jobs)) return;
|
|
159
|
+
for (const job of Object.values(jobs as Record<string, unknown>)) {
|
|
160
|
+
if (!job || typeof job !== 'object' || Array.isArray(job)) continue;
|
|
161
|
+
const rec = job as Record<string, unknown>;
|
|
162
|
+
if (typeof rec.needs === 'string') {
|
|
163
|
+
rec.needs = [rec.needs];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function runValidator<T>(
|
|
169
|
+
doc: unknown,
|
|
170
|
+
validator: ValidateFunction<T>,
|
|
171
|
+
kind: 'workflow' | 'reusable-workflow' | 'action',
|
|
172
|
+
): T {
|
|
173
|
+
if (validator(doc)) {
|
|
174
|
+
return doc;
|
|
175
|
+
}
|
|
176
|
+
const errors = validator.errors ?? [];
|
|
177
|
+
throw new WorkflowDslError(
|
|
178
|
+
WorkflowErrorCode.DSL_SCHEMA_INVALID,
|
|
179
|
+
`Schema validation failed for ${kind} document: ${formatErrors(errors)}`,
|
|
180
|
+
{ kind, issues: errors.map(formatIssue) },
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function formatIssue(err: ErrorObject): Readonly<Record<string, unknown>> {
|
|
185
|
+
return {
|
|
186
|
+
instancePath: err.instancePath,
|
|
187
|
+
schemaPath: err.schemaPath,
|
|
188
|
+
keyword: err.keyword,
|
|
189
|
+
message: err.message ?? '',
|
|
190
|
+
params: err.params,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function formatErrors(errors: readonly ErrorObject[]): string {
|
|
195
|
+
if (errors.length === 0) return '(no detail)';
|
|
196
|
+
return errors
|
|
197
|
+
.map((e) => `${e.instancePath || '/'} ${e.message ?? ''} [${e.keyword}]`.trim())
|
|
198
|
+
.join('; ');
|
|
199
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// ── @xemahq/workspace-manifest-dsl ──
|
|
3
|
+
//
|
|
4
|
+
// Schema, compiler, and interpolation engine for `WorkspaceManifest`
|
|
5
|
+
// YAMLs. A manifest declares the SHAPE of `/workspace/` for an agent
|
|
6
|
+
// invocation — which user-data slots are populated, which agent runs,
|
|
7
|
+
// which seed files are dropped in.
|
|
8
|
+
//
|
|
9
|
+
// Consumers:
|
|
10
|
+
// - `biomes/agent-runtime/api/llm-registry-api` (composition seeder): compiles each
|
|
11
|
+
// biome-shipped manifest and projects it into a published
|
|
12
|
+
// `Composition` row.
|
|
13
|
+
// - `packages/agent-session-runtime` (composer): turns a compiled
|
|
14
|
+
// manifest + bind inputs into a `WorkspaceMountPlan` that gets
|
|
15
|
+
// applied via workspace-proxy `/workspace/mounts/apply`.
|
|
16
|
+
// - `packages/workflow-dsl`: validates inline `mounts:` blocks on
|
|
17
|
+
// `xema/agent` jobs at workflow compile time.
|
|
18
|
+
//
|
|
19
|
+
// Sibling to `@xemahq/workflow-dsl`. Workflow DSL describes the
|
|
20
|
+
// process; workspace manifest describes the environment shape.
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
|
|
23
|
+
export * from './lib/types';
|
|
24
|
+
export * from './lib/schema';
|
|
25
|
+
export * from './lib/interpolate';
|
|
26
|
+
export * from './lib/compile';
|
|
27
|
+
export * from './lib/resolve-extends';
|