@boboddy/sdk 0.4.2 → 0.5.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/dist/client.js +0 -23
- package/dist/definitions/advancement-policies/define-advancement-policy.d.ts +30 -5
- package/dist/definitions/advancement-policies/index.js +11 -1
- package/dist/definitions/pipelines/bindings.d.ts +62 -0
- package/dist/definitions/pipelines/builder-helpers.d.ts +36 -94
- package/dist/definitions/pipelines/chain-graph.d.ts +15 -14
- package/dist/definitions/pipelines/compile-node-definitions.d.ts +27 -0
- package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +64 -14
- package/dist/definitions/pipelines/define-pipeline.d.ts +101 -154
- package/dist/definitions/pipelines/index.d.ts +1 -2
- package/dist/definitions/pipelines/index.js +485 -585
- package/dist/definitions/pipelines/node-input-ctx.d.ts +31 -0
- package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +42 -12
- package/dist/definitions/pipelines/pipeline-states.d.ts +104 -0
- package/dist/definitions/pipelines/work-item-fields.d.ts +98 -0
- package/dist/definitions/steps/define-code-step.d.ts +50 -0
- package/dist/definitions/steps/define-step.d.ts +40 -8
- package/dist/definitions/steps/index.d.ts +1 -0
- package/dist/definitions/steps/index.js +41 -24
- package/dist/definitions/steps/step-definitions-client.d.ts +47 -11
- package/dist/definitions/validation/index.js +15148 -94
- package/dist/definitions/validation/validate-definition-specs.d.ts +19 -1
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/sdk.gen.d.ts +1 -4
- package/dist/generated/types.gen.d.ts +469 -875
- package/dist/index.js +525 -585
- package/dist/push/collect-definitions.d.ts +40 -1
- package/dist/push/index.d.ts +2 -2
- package/dist/push/index.js +756 -664
- package/dist/step-execution-plane-client.d.ts +9 -4
- package/package.json +2 -2
- package/dist/definitions/pipelines/builder.d.ts +0 -80
- package/dist/definitions/pipelines/fan-out-builder.d.ts +0 -66
- package/dist/definitions/pipelines/input-accessor.d.ts +0 -25
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ZodType } from "zod";
|
|
2
|
+
import type { DotPaths } from "../steps/define-step";
|
|
3
|
+
import { type WorkItemAccessor } from "./builder-helpers";
|
|
4
|
+
import type { FanOutItemBinding, LiteralBinding, PipelineInputBinding, SignalsListBinding, StepOutputBinding, StepSignalBinding } from "./bindings";
|
|
5
|
+
/**
|
|
6
|
+
* The `input:` mapper ctx every `step`/`fanOut`/`loop`/parallel-branch
|
|
7
|
+
* state receives (see docs/research/flat-pipeline-sdk-and-visual-designer.md
|
|
8
|
+
* §4). Nodes are addressed by their plain string state key rather than a
|
|
9
|
+
* typed step reference — the flat, forward-only authoring model has no
|
|
10
|
+
* "tuple of prior steps" to statically check a binding's source/signal
|
|
11
|
+
* key against (cross-node static proof is explicitly out of scope; see
|
|
12
|
+
* that doc's §1).
|
|
13
|
+
*/
|
|
14
|
+
export type NodeInputCtx<TInput extends ZodType = ZodType> = {
|
|
15
|
+
/** Reads a value from the pipeline's own input, by dot-path. */
|
|
16
|
+
pipelineInput: (path: DotPaths<TInput["_output"]>) => PipelineInputBinding;
|
|
17
|
+
workItem: WorkItemAccessor;
|
|
18
|
+
/** Reads a signal declared by an earlier node, addressed by its state key. */
|
|
19
|
+
signal: (nodeKey: string, signalKey: string) => StepSignalBinding;
|
|
20
|
+
/** Reads an earlier node's whole result output, addressed by its state key. */
|
|
21
|
+
output: (nodeKey: string) => StepOutputBinding;
|
|
22
|
+
/** Reaches a fan-out's whole cohort (every terminal branch's signals + output). */
|
|
23
|
+
signalsList: (nodeKey: string) => SignalsListBinding;
|
|
24
|
+
literal: (value: unknown) => LiteralBinding;
|
|
25
|
+
};
|
|
26
|
+
/** `NodeInputCtx`, plus `item` — the current fan-out branch's own item. */
|
|
27
|
+
export type FanOutNodeInputCtx<TInput extends ZodType = ZodType> = NodeInputCtx<TInput> & {
|
|
28
|
+
item: FanOutItemBinding;
|
|
29
|
+
};
|
|
30
|
+
export declare function makeNodeInputCtx<TInput extends ZodType>(): NodeInputCtx<TInput>;
|
|
31
|
+
export declare function makeFanOutNodeInputCtx<TInput extends ZodType>(): FanOutNodeInputCtx<TInput>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PipelineDefinitions } from "../../generated/sdk.gen";
|
|
2
2
|
import type { PutApiPipelineDefinitionsData } from "../../generated/types.gen";
|
|
3
|
-
import type
|
|
3
|
+
import { type PipelineDefinitionSpec } from "./define-pipeline";
|
|
4
4
|
type RequestOptions = {
|
|
5
5
|
headers?: Record<string, unknown> | undefined;
|
|
6
6
|
};
|
|
@@ -20,10 +20,13 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
20
20
|
description: string | unknown;
|
|
21
21
|
status: "draft" | "active" | "archived";
|
|
22
22
|
archivedAt: string | unknown;
|
|
23
|
-
inputSchemaJson:
|
|
23
|
+
inputSchemaJson: {
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
} | unknown;
|
|
24
26
|
stepDefinitions: Array<{
|
|
25
27
|
id: string;
|
|
26
28
|
pipelineDefinitionId: string;
|
|
29
|
+
kind: "step" | "fanOut" | "cohortGate" | "choice" | "parallel" | "loop" | "succeed" | "fail";
|
|
27
30
|
stepDefinitionId: string;
|
|
28
31
|
stepDefinitionVersion: number;
|
|
29
32
|
key: string;
|
|
@@ -51,7 +54,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
51
54
|
};
|
|
52
55
|
} | unknown;
|
|
53
56
|
timeoutSeconds: number | unknown;
|
|
54
|
-
retryPolicyJson:
|
|
57
|
+
retryPolicyJson: {
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
} | unknown;
|
|
55
60
|
advancementPolicyDefinition: {
|
|
56
61
|
id: string;
|
|
57
62
|
pipelineStepDefinitionId: string;
|
|
@@ -100,7 +105,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
100
105
|
}>;
|
|
101
106
|
};
|
|
102
107
|
defaultEventType: "continue" | "block" | "complete" | "route";
|
|
103
|
-
defaultEventParamsJson:
|
|
108
|
+
defaultEventParamsJson: {
|
|
109
|
+
[key: string]: unknown;
|
|
110
|
+
} | unknown;
|
|
104
111
|
allowedEventTypes: Array<"continue" | "block" | "complete" | "route">;
|
|
105
112
|
createdAt: string;
|
|
106
113
|
updatedAt: string;
|
|
@@ -110,7 +117,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
110
117
|
key: string;
|
|
111
118
|
type: "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
|
|
112
119
|
inputSignalKeys: Array<string>;
|
|
113
|
-
configJson:
|
|
120
|
+
configJson: {
|
|
121
|
+
[key: string]: unknown;
|
|
122
|
+
} | unknown;
|
|
114
123
|
availableWhenResultStatusIn: Array<string> | unknown;
|
|
115
124
|
createdAt: string;
|
|
116
125
|
updatedAt: string;
|
|
@@ -123,11 +132,23 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
123
132
|
}[]>;
|
|
124
133
|
/**
|
|
125
134
|
* Upserts a pipeline definition keyed by (projectId, key). Accepts the
|
|
126
|
-
* `PipelineDefinitionSpec` produced by `
|
|
135
|
+
* `PipelineDefinitionSpec` produced by `definePipeline()`, along with the
|
|
127
136
|
* list of pushed step definitions (used to resolve `stepDefinitionId` for
|
|
128
|
-
* each
|
|
137
|
+
* each node/branch referencing a step by key).
|
|
138
|
+
*
|
|
139
|
+
* Pushes via the richer `nodeDefinitions[]`/`dependencyEdges[]` graph
|
|
140
|
+
* shape (see `buildGraphNodeInput`) rather than the old flat,
|
|
141
|
+
* `position`-ordered `stepDefinitions[]` shape — every node kind
|
|
142
|
+
* `definePipeline()` can produce (`choice`/`fanOut`/`cohortGate`/
|
|
143
|
+
* `parallel`/`loop`/`succeed`/`fail`, not just `step`) is representable
|
|
144
|
+
* this way; the flat shape could only ever represent a `step`-only
|
|
145
|
+
* chain. The generated `UpsertPipelineDefinitionInput` type doesn't yet
|
|
146
|
+
* reflect this (it's OpenAPI-codegen'd from the pre-existing flat
|
|
147
|
+
* contract), so the body is cast at the boundary — the server's zod
|
|
148
|
+
* schema (`createPipelineDefinitionInputSchema`, extended to accept
|
|
149
|
+
* either shape) is the real, enforced contract.
|
|
129
150
|
*
|
|
130
|
-
* Throws if any
|
|
151
|
+
* Throws if any node/branch references a step key/version that isn't
|
|
131
152
|
* present in `stepDefs`.
|
|
132
153
|
*/
|
|
133
154
|
upsertFromSpec: (projectId: string, spec: PipelineDefinitionSpec, stepDefs: ReadonlyArray<StepDefinitionRef>, options?: RequestOptions) => Promise<{
|
|
@@ -138,10 +159,13 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
138
159
|
description: string | unknown;
|
|
139
160
|
status: "draft" | "active" | "archived";
|
|
140
161
|
archivedAt: string | unknown;
|
|
141
|
-
inputSchemaJson:
|
|
162
|
+
inputSchemaJson: {
|
|
163
|
+
[key: string]: unknown;
|
|
164
|
+
} | unknown;
|
|
142
165
|
stepDefinitions: Array<{
|
|
143
166
|
id: string;
|
|
144
167
|
pipelineDefinitionId: string;
|
|
168
|
+
kind: "step" | "fanOut" | "cohortGate" | "choice" | "parallel" | "loop" | "succeed" | "fail";
|
|
145
169
|
stepDefinitionId: string;
|
|
146
170
|
stepDefinitionVersion: number;
|
|
147
171
|
key: string;
|
|
@@ -169,7 +193,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
169
193
|
};
|
|
170
194
|
} | unknown;
|
|
171
195
|
timeoutSeconds: number | unknown;
|
|
172
|
-
retryPolicyJson:
|
|
196
|
+
retryPolicyJson: {
|
|
197
|
+
[key: string]: unknown;
|
|
198
|
+
} | unknown;
|
|
173
199
|
advancementPolicyDefinition: {
|
|
174
200
|
id: string;
|
|
175
201
|
pipelineStepDefinitionId: string;
|
|
@@ -218,7 +244,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
218
244
|
}>;
|
|
219
245
|
};
|
|
220
246
|
defaultEventType: "continue" | "block" | "complete" | "route";
|
|
221
|
-
defaultEventParamsJson:
|
|
247
|
+
defaultEventParamsJson: {
|
|
248
|
+
[key: string]: unknown;
|
|
249
|
+
} | unknown;
|
|
222
250
|
allowedEventTypes: Array<"continue" | "block" | "complete" | "route">;
|
|
223
251
|
createdAt: string;
|
|
224
252
|
updatedAt: string;
|
|
@@ -228,7 +256,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
228
256
|
key: string;
|
|
229
257
|
type: "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
|
|
230
258
|
inputSignalKeys: Array<string>;
|
|
231
|
-
configJson:
|
|
259
|
+
configJson: {
|
|
260
|
+
[key: string]: unknown;
|
|
261
|
+
} | unknown;
|
|
232
262
|
availableWhenResultStatusIn: Array<string> | unknown;
|
|
233
263
|
createdAt: string;
|
|
234
264
|
updatedAt: string;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { ZodType } from "zod";
|
|
2
|
+
import type { RuleCondition } from "../advancement-policies/define-advancement-policy";
|
|
3
|
+
import type { AdvanceAllCtx, AdvanceAllResult, AdvanceEachCtx, AdvanceEachResult } from "../advancement-policies/cohort-fluent-rules";
|
|
4
|
+
import type { AnyTypedStep } from "./builder-helpers";
|
|
5
|
+
import type { AnyBinding } from "./bindings";
|
|
6
|
+
import type { FanOutNodeInputCtx, NodeInputCtx } from "./node-input-ctx";
|
|
7
|
+
/**
|
|
8
|
+
* The 7 authoring state kinds (see
|
|
9
|
+
* docs/research/flat-pipeline-sdk-and-visual-designer.md §4/§5). Every
|
|
10
|
+
* kind besides `choice`/`succeed`/`fail` does its own work (a `step`) and
|
|
11
|
+
* therefore declares exactly one authored `input`/`timeout`; `choice` and
|
|
12
|
+
* `loop` are the only kinds with more than one possible exit.
|
|
13
|
+
*/
|
|
14
|
+
/** `next: "otherStateKey"`, or a special cross-pipeline route target. */
|
|
15
|
+
export type NextTarget = string | {
|
|
16
|
+
routeToPipeline: string;
|
|
17
|
+
input?: Record<string, unknown> | null;
|
|
18
|
+
};
|
|
19
|
+
export type StepState = {
|
|
20
|
+
kind: "step";
|
|
21
|
+
step: AnyTypedStep;
|
|
22
|
+
input?: (ctx: NodeInputCtx) => Partial<Record<string, AnyBinding>>;
|
|
23
|
+
timeout?: number | null;
|
|
24
|
+
/**
|
|
25
|
+
* A single-condition "pause for human review" gate — the narrow
|
|
26
|
+
* replacement for the old per-step rules-engine policy object (see §5's
|
|
27
|
+
* `complete`/`route`/`block` migration notes). When the condition
|
|
28
|
+
* matches, the node run blocks instead of advancing to `next`.
|
|
29
|
+
*/
|
|
30
|
+
blockWhen?: RuleCondition;
|
|
31
|
+
next: NextTarget;
|
|
32
|
+
};
|
|
33
|
+
export type ChoiceCase = {
|
|
34
|
+
when: RuleCondition;
|
|
35
|
+
next: string;
|
|
36
|
+
};
|
|
37
|
+
export type ChoiceState = {
|
|
38
|
+
kind: "choice";
|
|
39
|
+
/** At least one of `choices`/`default` is required — see `compileChoiceState`. */
|
|
40
|
+
choices?: ReadonlyArray<ChoiceCase>;
|
|
41
|
+
default?: string | null;
|
|
42
|
+
};
|
|
43
|
+
export type FanOutState = {
|
|
44
|
+
kind: "fanOut";
|
|
45
|
+
step: AnyTypedStep;
|
|
46
|
+
/**
|
|
47
|
+
* The signal to resolve branch cardinality (and, in array mode, each
|
|
48
|
+
* branch's own item) from. A bare signal key (`"changedFiles"`) or a
|
|
49
|
+
* `"stateKey.signalKey"` dotted convenience form — the dotted prefix is
|
|
50
|
+
* author-facing documentation only; the runtime resolves the signal by
|
|
51
|
+
* scanning every upstream node's own signals for a matching key (see
|
|
52
|
+
* `resolveFanOutCardinality`), not by an explicit node reference.
|
|
53
|
+
*/
|
|
54
|
+
over: string;
|
|
55
|
+
maxConcurrency?: number | null;
|
|
56
|
+
input?: (ctx: FanOutNodeInputCtx) => Partial<Record<string, AnyBinding>>;
|
|
57
|
+
timeout?: number | null;
|
|
58
|
+
advanceEach: (ctx: AdvanceEachCtx) => AdvanceEachResult;
|
|
59
|
+
advanceAll: (ctx: AdvanceAllCtx) => AdvanceAllResult;
|
|
60
|
+
next: string;
|
|
61
|
+
};
|
|
62
|
+
export type ParallelBranchConfig = {
|
|
63
|
+
step: AnyTypedStep;
|
|
64
|
+
input?: (ctx: NodeInputCtx) => Partial<Record<string, AnyBinding>>;
|
|
65
|
+
timeout?: number | null;
|
|
66
|
+
};
|
|
67
|
+
export type ParallelState = {
|
|
68
|
+
kind: "parallel";
|
|
69
|
+
/** Named branches (v1: single-step only — see decision 5). */
|
|
70
|
+
branches: Record<string, ParallelBranchConfig>;
|
|
71
|
+
/** Defaults to "continue iff every branch continued" when omitted. */
|
|
72
|
+
advanceAll?: (ctx: AdvanceAllCtx) => AdvanceAllResult;
|
|
73
|
+
next: string;
|
|
74
|
+
};
|
|
75
|
+
export type LoopState = {
|
|
76
|
+
kind: "loop";
|
|
77
|
+
step: AnyTypedStep;
|
|
78
|
+
maxIterations: number;
|
|
79
|
+
input?: (ctx: NodeInputCtx) => Partial<Record<string, AnyBinding>>;
|
|
80
|
+
timeout?: number | null;
|
|
81
|
+
until: RuleCondition;
|
|
82
|
+
next: string;
|
|
83
|
+
onExhausted: string;
|
|
84
|
+
};
|
|
85
|
+
export type SucceedState = {
|
|
86
|
+
kind: "succeed";
|
|
87
|
+
};
|
|
88
|
+
export type FailState = {
|
|
89
|
+
kind: "fail";
|
|
90
|
+
};
|
|
91
|
+
export type PipelineState = StepState | ChoiceState | FanOutState | ParallelState | LoopState | SucceedState | FailState;
|
|
92
|
+
export type DefinePipelineInput<TInput extends ZodType = ZodType> = {
|
|
93
|
+
key: string;
|
|
94
|
+
name?: string;
|
|
95
|
+
description?: string | null;
|
|
96
|
+
version?: number;
|
|
97
|
+
status?: "draft" | "active";
|
|
98
|
+
/** The pipeline's own input schema — drives `ctx.pipelineInput(path)`'s typing and `inputSchemaJson`. */
|
|
99
|
+
input?: TInput;
|
|
100
|
+
/** The entry state's key. Must not name a `choice`/`succeed`/`fail` state. */
|
|
101
|
+
startAt: string;
|
|
102
|
+
/** Every state in the pipeline, keyed by its unique node key. */
|
|
103
|
+
states: Record<string, PipelineState>;
|
|
104
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { GetApiWorkItemsByWorkItemIdResponses } from "../../generated/types.gen";
|
|
2
|
+
/**
|
|
3
|
+
* Top-level work-item properties addressable by every work-item binding
|
|
4
|
+
* mechanism in the SDK: the default-pipeline-assignment DSL's
|
|
5
|
+
* `workItem.<field>` accessor (`define-default-pipeline-assignment.ts`) and
|
|
6
|
+
* the regular pipeline/step `workItem.<field>` accessor
|
|
7
|
+
* (`builder-helpers.ts`'s `WorkItemAccessor`) — and, reversed, both
|
|
8
|
+
* `boboddy pipelines pull` file generators
|
|
9
|
+
* (`default-pipeline-assignment-file-generator.ts`,
|
|
10
|
+
* `pipeline-file-generator.ts`). `fields` is deliberately excluded from this
|
|
11
|
+
* list: it's reached via `.field(name)` on every one of those accessors, not
|
|
12
|
+
* as a top-level property.
|
|
13
|
+
*
|
|
14
|
+
* This is the single source of truth for the list — it must stay in sync
|
|
15
|
+
* with the `workItem` fact/context shape every corresponding server-side
|
|
16
|
+
* resolver publishes (`buildFacts` in
|
|
17
|
+
* `evaluate-default-pipeline-assignment.ts`; `buildResolvedWorkItemContext`
|
|
18
|
+
* in `resolve-node-input.ts`).
|
|
19
|
+
*/
|
|
20
|
+
export declare const WORK_ITEM_TOP_LEVEL_FIELDS: readonly ["id", "projectId", "platform", "platformId", "platformKey", "url", "title", "description", "sourceCreatedAt", "sourceUpdatedAt", "createdByUserId", "parentWorkItemId", "createdAt", "updatedAt"];
|
|
21
|
+
export type WorkItemTopLevelField = (typeof WORK_ITEM_TOP_LEVEL_FIELDS)[number];
|
|
22
|
+
/**
|
|
23
|
+
* The literal union of valid work-item platforms, sourced from the generated
|
|
24
|
+
* OpenAPI response type (`GetApiWorkItemsByWorkItemIdResponses[200]["platform"]`)
|
|
25
|
+
* rather than hand-duplicated, so it cannot drift from the API contract. It
|
|
26
|
+
* must mirror `WorkItemPlatform` in
|
|
27
|
+
* `packages/core/src/work-items/work-item/domain/work-item-platform.ts`.
|
|
28
|
+
*/
|
|
29
|
+
type WorkItemPlatformLiteral = GetApiWorkItemsByWorkItemIdResponses[200]["platform"];
|
|
30
|
+
/**
|
|
31
|
+
* Per-field value types for every member of `WORK_ITEM_TOP_LEVEL_FIELDS`,
|
|
32
|
+
* mirroring exactly what the server-side resolvers publish at evaluation/
|
|
33
|
+
* resolution time (`buildFacts` for default-pipeline-assignment;
|
|
34
|
+
* `buildResolvedWorkItemContext` for regular pipeline/step input bindings).
|
|
35
|
+
* Notably, `sourceCreatedAt`/`sourceUpdatedAt`/`createdAt`/`updatedAt` are
|
|
36
|
+
* serialized as ISO date strings (or `null`), never `Date` objects.
|
|
37
|
+
*/
|
|
38
|
+
export type WorkItemTopLevelFieldTypeMap = {
|
|
39
|
+
id: string;
|
|
40
|
+
projectId: string;
|
|
41
|
+
platform: WorkItemPlatformLiteral;
|
|
42
|
+
platformId: string | null;
|
|
43
|
+
platformKey: string;
|
|
44
|
+
url: string | null;
|
|
45
|
+
title: string;
|
|
46
|
+
description: string | null;
|
|
47
|
+
sourceCreatedAt: string | null;
|
|
48
|
+
sourceUpdatedAt: string | null;
|
|
49
|
+
createdByUserId: string | null;
|
|
50
|
+
parentWorkItemId: string | null;
|
|
51
|
+
createdAt: string | null;
|
|
52
|
+
updatedAt: string | null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* The path prefix marking a reference into a work item's platform-specific
|
|
56
|
+
* `fields` bag (a Jira custom field, a GitHub label, etc.), as opposed to a
|
|
57
|
+
* `WorkItemTopLevelField`. Shared by every accessor that authors these paths
|
|
58
|
+
* (`workItem.field(name)` in both the default-pipeline-assignment DSL and
|
|
59
|
+
* the regular pipeline/step `WorkItemAccessor`) and every resolver that
|
|
60
|
+
* reads them back (`resolveWorkItemFieldPath` below; the JSONPath-rooted
|
|
61
|
+
* variant in `evaluate-default-pipeline-assignment.ts`, which layers a `$.`
|
|
62
|
+
* prefix on top of this same convention).
|
|
63
|
+
*/
|
|
64
|
+
export declare const WORK_ITEM_FIELDS_PATH_PREFIX = "fields.";
|
|
65
|
+
/**
|
|
66
|
+
* Resolves a work-item path — either a `WorkItemTopLevelField` name (a
|
|
67
|
+
* single, code-controlled segment) or a `fields.<name>` reference into the
|
|
68
|
+
* platform-specific `fields` bag — against a plain object shaped like
|
|
69
|
+
* `WorkItemTopLevelFieldTypeMap & { fields: ... }`.
|
|
70
|
+
*
|
|
71
|
+
* `<name>` in `fields.<name>` is an arbitrary, unescaped, platform-supplied
|
|
72
|
+
* field name (a Jira custom field label, a GitHub key, etc.) that may
|
|
73
|
+
* contain any character, including `.`, `[`, `]`, `~`, `^`, `;`, or even be
|
|
74
|
+
* the empty string. A naive dot-splitting path walker would silently
|
|
75
|
+
* misresolve a field literally named `"a.b"` as nested property access
|
|
76
|
+
* (`fields.a.b`) instead of the flat key `fields["a.b"]` — a silent-wrong-
|
|
77
|
+
* match hazard, not a visible error, since the walker degrades to "no
|
|
78
|
+
* match"/"wrong match" rather than throwing.
|
|
79
|
+
*
|
|
80
|
+
* This resolver sidesteps that hazard entirely: everything after `fields.`
|
|
81
|
+
* is treated as one atomic, unsplit key. Every work-item path resolver in
|
|
82
|
+
* the codebase must use this same convention for a field name to round-trip
|
|
83
|
+
* correctly — see `evaluate-default-pipeline-assignment.ts`'s
|
|
84
|
+
* `resolveWorkItemAssignmentPath` (which layers `$.` path-rooting on top of
|
|
85
|
+
* this function) and `resolve-node-input.ts`'s `work_item` binding
|
|
86
|
+
* resolution (which calls this function directly, replacing what used to be
|
|
87
|
+
* a dot-splitting walker shared with unrelated binding sources and
|
|
88
|
+
* susceptible to the exact hazard described above).
|
|
89
|
+
*
|
|
90
|
+
* `path` is untyped (`string`, not `WorkItemTopLevelField | \`fields.${string}\``)
|
|
91
|
+
* because callers validate membership separately
|
|
92
|
+
* (`WORK_ITEM_TOP_LEVEL_FIELDS`/`isSupportedWorkItemField`) before ever
|
|
93
|
+
* reaching a resolver — this function's contract is purely "resolve
|
|
94
|
+
* whatever path string you hand it, treating `fields.` as atomic," not
|
|
95
|
+
* "validate the path."
|
|
96
|
+
*/
|
|
97
|
+
export declare function resolveWorkItemFieldPath(record: unknown, path: string): unknown;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ZodType } from "zod";
|
|
2
|
+
import type { SignalKeysOf, SignalTypeMapOf, TypedStepDefinitionSpec } from "./define-step";
|
|
3
|
+
/**
|
|
4
|
+
* `codeStep()`'s own signal spec shape — unlike `defineStep()`'s
|
|
5
|
+
* `SignalSpecInput`, `type` is required rather than inferred from the
|
|
6
|
+
* result schema at a dot-path (`resolveZodSchemaAtPath`/
|
|
7
|
+
* `zodTypeToSignalType` are `define-step.ts`-internal, and a code step's
|
|
8
|
+
* result shape is arbitrary application data, not necessarily reflecting
|
|
9
|
+
* one at all) — a small, deliberate simplification over `defineStep`'s own
|
|
10
|
+
* signal authoring surface.
|
|
11
|
+
*/
|
|
12
|
+
export type CodeStepSignalSpec = {
|
|
13
|
+
key?: string;
|
|
14
|
+
sourcePath: string;
|
|
15
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
16
|
+
required?: boolean;
|
|
17
|
+
availableWhenResultStatusIn?: string[] | null;
|
|
18
|
+
};
|
|
19
|
+
export type CodeStepFn<TInput, TResult> = (input: TInput) => TResult | Promise<TResult>;
|
|
20
|
+
export type DefineCodeStepInput<TInput extends ZodType = ZodType, TResult extends ZodType = ZodType> = {
|
|
21
|
+
key: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description?: string | null;
|
|
24
|
+
version?: number;
|
|
25
|
+
/**
|
|
26
|
+
* The step's own implementation — resolved by `collect-definitions.ts`
|
|
27
|
+
* to a portable `{sourceFile, exportName}` pair (by identity-matching
|
|
28
|
+
* this reference against the declaring module's other exports) before
|
|
29
|
+
* the (unserializable) function reference is ever sent over the wire.
|
|
30
|
+
* Must be a plain named export of the same module `codeStep()` is
|
|
31
|
+
* called from (see docs/research/flat-pipeline-sdk-and-visual-designer.md
|
|
32
|
+
* §7.7/§8's "code-step entrypoints resolve against the target repo").
|
|
33
|
+
*/
|
|
34
|
+
fn: CodeStepFn<TInput["_output"], TResult["_output"]>;
|
|
35
|
+
inputSchema?: TInput;
|
|
36
|
+
resultSchema?: TResult;
|
|
37
|
+
signals?: readonly CodeStepSignalSpec[];
|
|
38
|
+
status?: "draft" | "active";
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Defines a `kind: "code"` step: a plain function instead of an LLM
|
|
42
|
+
* prompt. Produces the same phantom-typed `TypedStepDefinitionSpec` shape
|
|
43
|
+
* `defineStep()` does (so it plugs into `definePipeline()`'s
|
|
44
|
+
* `states[key].step` field unchanged), but with no `prompt` and a live
|
|
45
|
+
* `entrypoint.fn` reference attached instead — see `StepDefinitionSpec`'s
|
|
46
|
+
* own doc comment for what happens to it during collection.
|
|
47
|
+
*/
|
|
48
|
+
export declare function codeStep<TInput extends ZodType = ZodType, TResult extends ZodType = ZodType, const TSignals extends ReadonlyArray<CodeStepSignalSpec> = never[]>(config: DefineCodeStepInput<TInput, TResult> & {
|
|
49
|
+
signals?: TSignals;
|
|
50
|
+
}): TypedStepDefinitionSpec<TInput["_output"], TResult["_output"], SignalKeysOf<TSignals>, SignalTypeMapOf<TSignals, TResult["_output"]>>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ZodType } from "zod";
|
|
2
2
|
import type { AnyStepFeature, FeatureResultExtensions, FeatureSignalKeys } from "./step-features";
|
|
3
3
|
import { type PromptTemplateContext } from "./prompt-template";
|
|
4
|
+
import type { LiteralBinding, WorkItemBinding } from "../pipelines/define-pipeline";
|
|
4
5
|
type OpenCodeMcpServers = Record<string, {
|
|
5
6
|
type: "local";
|
|
6
7
|
command: string[];
|
|
@@ -89,20 +90,39 @@ export type DefineStepInput<TInput extends ZodType = ZodType, TResult extends Zo
|
|
|
89
90
|
status?: "draft" | "active";
|
|
90
91
|
executionMode?: "workspace" | "no_workspace";
|
|
91
92
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
/**
|
|
94
|
+
* @deprecated Alias for `LiteralBinding` (`define-pipeline.ts`) — the two
|
|
95
|
+
* used to be independently declared, structurally-identical types. Kept
|
|
96
|
+
* only so existing imports of this name keep working.
|
|
97
|
+
*/
|
|
98
|
+
export type AdditionalStepInputLiteralBinding = LiteralBinding;
|
|
99
|
+
/**
|
|
100
|
+
* The binding sources available to `PipelineMeta.additionalStepInput`'s
|
|
101
|
+
* `bindings` callback (`workItemField(...)`/`literal(...)` in
|
|
102
|
+
* `builder-helpers.ts`'s `resolveAdditionalStepInputBindings`) — the same
|
|
103
|
+
* `WorkItemBinding`/`LiteralBinding` shapes `.step()`'s own `input` mapper
|
|
104
|
+
* uses (`define-pipeline.ts`'s `AnyBinding`), restricted to the subset
|
|
105
|
+
* `resolveAdditionalStepInputBindings` can actually produce. Previously an
|
|
106
|
+
* independently-declared `{ source: "work_item"; field: string }` union
|
|
107
|
+
* member that had drifted apart from `WorkItemBinding` in shape only by
|
|
108
|
+
* coincidence, not by design.
|
|
109
|
+
*/
|
|
110
|
+
export type AdditionalStepInputBinding = WorkItemBinding | LiteralBinding;
|
|
111
|
+
/**
|
|
112
|
+
* A `kind: "code"` step's portable entrypoint, once resolved by
|
|
113
|
+
* `collect-definitions.ts`'s identity-capture pass — see
|
|
114
|
+
* docs/research/flat-pipeline-sdk-and-visual-designer.md §7.7/§8.
|
|
115
|
+
*/
|
|
116
|
+
export type StepDefinitionEntrypointJson = {
|
|
117
|
+
sourceFile: string;
|
|
118
|
+
exportName: string;
|
|
95
119
|
};
|
|
96
|
-
export type AdditionalStepInputBinding = {
|
|
97
|
-
source: "work_item";
|
|
98
|
-
field: string;
|
|
99
|
-
} | AdditionalStepInputLiteralBinding;
|
|
100
120
|
export type StepDefinitionSpec = {
|
|
101
121
|
key: string;
|
|
102
122
|
name: string;
|
|
103
123
|
description: string | null;
|
|
104
124
|
version: number;
|
|
105
|
-
kind: "user_defined";
|
|
125
|
+
kind: "user_defined" | "code";
|
|
106
126
|
status: "draft" | "active" | "archived";
|
|
107
127
|
executionMode?: "workspace" | "no_workspace";
|
|
108
128
|
prompt: string | null;
|
|
@@ -118,6 +138,18 @@ export type StepDefinitionSpec = {
|
|
|
118
138
|
opencodeMcpJson: OpenCodeMcpServers | null;
|
|
119
139
|
opencodePluginJson: OpenCodePlugins | null;
|
|
120
140
|
healthChecksJson: HealthChecks | null;
|
|
141
|
+
/**
|
|
142
|
+
* `kind === "code"` only, and only *before* collection —
|
|
143
|
+
* `collect-definitions.ts` resolves this live `fn` reference down to
|
|
144
|
+
* `entrypointJson` (by identity-matching against the declaring module's
|
|
145
|
+
* other exports) and strips this field before the spec is ever pushed;
|
|
146
|
+
* it can never be serialized into the push request.
|
|
147
|
+
*/
|
|
148
|
+
entrypoint?: {
|
|
149
|
+
fn: (input: unknown) => unknown;
|
|
150
|
+
};
|
|
151
|
+
/** `kind === "code"` only, present after `collect-definitions.ts` has run. */
|
|
152
|
+
entrypointJson?: StepDefinitionEntrypointJson | null;
|
|
121
153
|
};
|
|
122
154
|
export type SignalTypeStrToTs<T extends SignalTypeStr> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : T extends "array" ? unknown[] : T extends "object" ? object : unknown;
|
|
123
155
|
export type SignalTypeMapOf<TSignals extends readonly unknown[], TResult> = Prettify<{
|
|
@@ -12080,6 +12080,32 @@ ${feature._promptAddition}` : feature._promptAddition;
|
|
|
12080
12080
|
};
|
|
12081
12081
|
return spec;
|
|
12082
12082
|
}
|
|
12083
|
+
// src/definitions/steps/define-code-step.ts
|
|
12084
|
+
function codeStep(config2) {
|
|
12085
|
+
const spec = {
|
|
12086
|
+
key: config2.key,
|
|
12087
|
+
name: config2.name,
|
|
12088
|
+
description: config2.description ?? null,
|
|
12089
|
+
version: config2.version ?? 1,
|
|
12090
|
+
kind: "code",
|
|
12091
|
+
status: config2.status ?? "active",
|
|
12092
|
+
prompt: null,
|
|
12093
|
+
inputSchemaJson: config2.inputSchema ? toJSONSchema(config2.inputSchema) : null,
|
|
12094
|
+
resultSchemaJson: config2.resultSchema ? toJSONSchema(config2.resultSchema) : null,
|
|
12095
|
+
signalExtractorDefinitions: (config2.signals ?? []).map((signal) => ({
|
|
12096
|
+
key: signal.key ?? signal.sourcePath,
|
|
12097
|
+
sourcePath: signal.sourcePath,
|
|
12098
|
+
type: signal.type,
|
|
12099
|
+
required: signal.required ?? true,
|
|
12100
|
+
availableWhenResultStatusIn: signal.availableWhenResultStatusIn ?? null
|
|
12101
|
+
})),
|
|
12102
|
+
opencodeMcpJson: null,
|
|
12103
|
+
opencodePluginJson: null,
|
|
12104
|
+
healthChecksJson: null,
|
|
12105
|
+
entrypoint: { fn: config2.fn }
|
|
12106
|
+
};
|
|
12107
|
+
return spec;
|
|
12108
|
+
}
|
|
12083
12109
|
// src/generated/core/bodySerializer.gen.ts
|
|
12084
12110
|
var jsonBodySerializer = {
|
|
12085
12111
|
bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
|
|
@@ -13159,29 +13185,6 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13159
13185
|
unarchivePipelineDefinition(options) {
|
|
13160
13186
|
return (options.client ?? this.client).put({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/unarchive", ...options });
|
|
13161
13187
|
}
|
|
13162
|
-
addPipelineStep(options) {
|
|
13163
|
-
return (options.client ?? this.client).post({
|
|
13164
|
-
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps",
|
|
13165
|
-
...options,
|
|
13166
|
-
headers: {
|
|
13167
|
-
"Content-Type": "application/json",
|
|
13168
|
-
...options.headers
|
|
13169
|
-
}
|
|
13170
|
-
});
|
|
13171
|
-
}
|
|
13172
|
-
removePipelineStep(options) {
|
|
13173
|
-
return (options.client ?? this.client).delete({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}", ...options });
|
|
13174
|
-
}
|
|
13175
|
-
updatePipelineStep(options) {
|
|
13176
|
-
return (options.client ?? this.client).put({
|
|
13177
|
-
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}",
|
|
13178
|
-
...options,
|
|
13179
|
-
headers: {
|
|
13180
|
-
"Content-Type": "application/json",
|
|
13181
|
-
...options.headers
|
|
13182
|
-
}
|
|
13183
|
-
});
|
|
13184
|
-
}
|
|
13185
13188
|
setPipelineStepAdvancementPolicy(options) {
|
|
13186
13189
|
return (options.client ?? this.client).put({
|
|
13187
13190
|
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}/advancement-policy",
|
|
@@ -13710,8 +13713,21 @@ var buildStepDefinitionsClient = (stepDefinitions) => {
|
|
|
13710
13713
|
},
|
|
13711
13714
|
upsertFromSpec: async (projectId, spec, options) => {
|
|
13712
13715
|
const body = {
|
|
13713
|
-
|
|
13716
|
+
key: spec.key,
|
|
13717
|
+
name: spec.name,
|
|
13718
|
+
description: spec.description,
|
|
13714
13719
|
prompt: spec.prompt ?? "",
|
|
13720
|
+
version: spec.version,
|
|
13721
|
+
kind: spec.kind,
|
|
13722
|
+
entrypointJson: spec.entrypointJson ?? null,
|
|
13723
|
+
executionMode: spec.executionMode,
|
|
13724
|
+
inputSchemaJson: spec.inputSchemaJson,
|
|
13725
|
+
resultSchemaJson: spec.resultSchemaJson,
|
|
13726
|
+
opencodeMcpJson: spec.opencodeMcpJson,
|
|
13727
|
+
opencodePluginJson: spec.opencodePluginJson,
|
|
13728
|
+
healthChecksJson: spec.healthChecksJson,
|
|
13729
|
+
status: spec.status,
|
|
13730
|
+
signalExtractorDefinitions: spec.signalExtractorDefinitions,
|
|
13715
13731
|
projectId
|
|
13716
13732
|
};
|
|
13717
13733
|
const result = await stepDefinitions.upsertStepDefinition({
|
|
@@ -16136,5 +16152,6 @@ export {
|
|
|
16136
16152
|
createStepDefinitionsClient,
|
|
16137
16153
|
createPromptTemplateContext,
|
|
16138
16154
|
createPromptInputProxy,
|
|
16155
|
+
codeStep,
|
|
16139
16156
|
Features
|
|
16140
16157
|
};
|