@osolmaz/pi-workflows 0.9.1 → 0.11.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/README.md +64 -19
- package/dist/builtins/autodoc.workflow.d.ts +58 -0
- package/dist/builtins/autodoc.workflow.js +266 -0
- package/dist/builtins/autodoc.workflow.js.map +1 -0
- package/dist/builtins/autoimplement.workflow.d.ts +353 -0
- package/dist/builtins/autoimplement.workflow.js +961 -0
- package/dist/builtins/autoimplement.workflow.js.map +1 -0
- package/dist/builtins/autoplan.workflow.d.ts +58 -0
- package/dist/builtins/autoplan.workflow.js +190 -0
- package/dist/builtins/autoplan.workflow.js.map +1 -0
- package/dist/builtins/catalog.js +9 -1
- package/dist/builtins/catalog.js.map +1 -1
- package/dist/builtins/index.d.ts +6 -0
- package/dist/builtins/index.js +7 -0
- package/dist/builtins/index.js.map +1 -0
- package/dist/builtins/monitor.workflow.d.ts +29 -3
- package/dist/builtins/monitor.workflow.js +325 -13
- package/dist/builtins/monitor.workflow.js.map +1 -1
- package/dist/builtins/plan-approval.workflow.d.ts +83 -0
- package/dist/builtins/plan-approval.workflow.js +148 -0
- package/dist/builtins/plan-approval.workflow.js.map +1 -0
- package/dist/builtins/plan-presentation.d.ts +7 -0
- package/dist/builtins/plan-presentation.js +44 -0
- package/dist/builtins/plan-presentation.js.map +1 -0
- package/dist/extension/decision-channels.d.ts +132 -0
- package/dist/extension/decision-channels.js +1082 -0
- package/dist/extension/decision-channels.js.map +1 -0
- package/dist/extension/index.d.ts +1 -0
- package/dist/extension/index.js +426 -11
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/widget.js +26 -2
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-tool.d.ts +1 -37
- package/dist/extension/workflow-tool.js +1 -42
- package/dist/extension/workflow-tool.js.map +1 -1
- package/dist/host/rpc-bridge.js +4 -21
- package/dist/host/rpc-bridge.js.map +1 -1
- package/dist/render/graph-render.js +46 -10
- package/dist/render/graph-render.js.map +1 -1
- package/dist/viewer/render.js +36 -2
- package/dist/viewer/render.js.map +1 -1
- package/dist/workflows/catalog.d.ts +1 -0
- package/dist/workflows/catalog.js +6 -0
- package/dist/workflows/catalog.js.map +1 -1
- package/dist/workflows/composition.d.ts +45 -0
- package/dist/workflows/composition.js +485 -0
- package/dist/workflows/composition.js.map +1 -0
- package/dist/workflows/decision-presentation.d.ts +18 -0
- package/dist/workflows/decision-presentation.js +417 -0
- package/dist/workflows/decision-presentation.js.map +1 -0
- package/dist/workflows/decision.d.ts +11 -5
- package/dist/workflows/decision.js.map +1 -1
- package/dist/workflows/definition.d.ts +22 -3
- package/dist/workflows/definition.js +46 -3
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.d.ts +2 -1
- package/dist/workflows/engine.js +199 -18
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/graph.js +8 -6
- package/dist/workflows/graph.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +87 -0
- package/dist/workflows/human-decision.js +583 -0
- package/dist/workflows/human-decision.js.map +1 -0
- package/dist/workflows/index.d.ts +5 -2
- package/dist/workflows/index.js +4 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/loader.d.ts +5 -4
- package/dist/workflows/loader.js +118 -18
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/schema.d.ts +3 -1
- package/dist/workflows/schema.js +64 -2
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/store.js +39 -2
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/tool-input.d.ts +72 -0
- package/dist/workflows/tool-input.js +141 -0
- package/dist/workflows/tool-input.js.map +1 -0
- package/dist/workflows/types.d.ts +300 -2
- package/docs/CONTROLLERS.md +1 -1
- package/docs/DESIGN_PHILOSOPHY.md +1 -1
- package/docs/HUMAN_DECISIONS.md +371 -0
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +323 -0
- package/docs/MONITOR.md +46 -18
- package/docs/WORKFLOW_COMPOSITION.md +333 -0
- package/docs/plans/2026-08-19-human-decision-gates-plan.md +296 -0
- package/docs/plans/2026-08-19-human-decision-presentations-plan.md +172 -0
- package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +45 -0
- package/docs/plans/2026-08-19-workflow-composition-plan.md +308 -0
- package/docs/run-bundles.md +45 -10
- package/docs/workflows.md +106 -15
- package/examples/workflows/approved-plan.workflow.ts +58 -0
- package/examples/workflows/autoimplement.workflow.ts +1 -92
- package/examples/workflows/autoplan.workflow.ts +1 -0
- package/examples/workflows/human-decision.workflow.ts +62 -0
- package/herdr-plugin.toml +1 -1
- package/package.json +6 -1
- package/schemas/decision-presentation-v1.schema.json +83 -0
- package/schemas/human-decision-accepted-v1.schema.json +44 -0
- package/schemas/human-decision-accepted-v2.schema.json +50 -0
- package/schemas/human-decision-answer-attempt-v1.schema.json +37 -0
- package/schemas/human-decision-cancellation-v1.schema.json +15 -0
- package/schemas/human-decision-continuation-v1.schema.json +16 -0
- package/schemas/human-decision-delivery-v1.schema.json +28 -0
- package/schemas/human-decision-delivery-v2.schema.json +36 -0
- package/schemas/human-decision-receipt-v1.schema.json +33 -0
- package/schemas/human-decision-receipt-v2.schema.json +39 -0
- package/schemas/human-decision-request-v1.schema.json +59 -0
- package/schemas/human-decision-request-v2.schema.json +69 -0
- package/schemas/human-decision-resolution-v1.schema.json +27 -0
- package/schemas/human-decision-resolution-v2.schema.json +27 -0
- package/schemas/human-decision-settlement-v1.schema.json +28 -0
- package/skills/autodoc/SKILL.md +43 -0
- package/skills/autoimplement/SKILL.md +58 -0
- package/skills/autoimplement/agents/openai.yaml +4 -0
- package/skills/autoplan/SKILL.md +25 -0
- package/skills/monitor/SKILL.md +8 -1
- package/skills/pi-workflows/SKILL.md +5 -3
- package/src/builtins/autodoc.workflow.ts +325 -0
- package/src/builtins/autoimplement.workflow.ts +1123 -0
- package/src/builtins/autoplan.workflow.ts +231 -0
- package/src/builtins/catalog.ts +9 -1
- package/src/builtins/index.ts +32 -0
- package/src/builtins/monitor.workflow.ts +396 -15
- package/src/builtins/plan-approval.workflow.ts +190 -0
- package/src/builtins/plan-presentation.ts +57 -0
- package/src/extension/decision-channels.ts +1533 -0
- package/src/extension/index.ts +499 -9
- package/src/extension/widget.ts +39 -2
- package/src/extension/workflow-tool.ts +5 -81
- package/src/host/rpc-bridge.ts +7 -30
- package/src/render/graph-render.ts +54 -5
- package/src/viewer/render.ts +56 -3
- package/src/workflows/catalog.ts +7 -0
- package/src/workflows/composition.ts +642 -0
- package/src/workflows/decision-presentation.ts +501 -0
- package/src/workflows/decision.ts +12 -5
- package/src/workflows/definition.ts +118 -8
- package/src/workflows/engine.ts +257 -20
- package/src/workflows/graph.ts +8 -6
- package/src/workflows/human-decision.ts +819 -0
- package/src/workflows/index.ts +89 -0
- package/src/workflows/loader.ts +186 -18
- package/src/workflows/schema.ts +79 -2
- package/src/workflows/store.ts +45 -2
- package/src/workflows/tool-input.ts +202 -0
- package/src/workflows/types.ts +374 -2
- package/examples/workflows/elegant-solution.workflow.ts +0 -95
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Type, type Static, type TObject, type TProperties, type TSchema } from "typebox";
|
|
2
|
+
import { Parse, ParseError } from "typebox/value";
|
|
3
|
+
|
|
4
|
+
const noExtraProperties = { additionalProperties: false } as const;
|
|
5
|
+
|
|
6
|
+
const offsetSchema = Type.Integer({ minimum: 0, description: "Workflow list offset" });
|
|
7
|
+
const workflowSchema = Type.String({
|
|
8
|
+
description: "Discovered workflow name or workflow file path; required when action is start",
|
|
9
|
+
});
|
|
10
|
+
const inputSchema = Type.Unknown({
|
|
11
|
+
description: "Checkpoint answer for answer; optional structured workflow input for start",
|
|
12
|
+
});
|
|
13
|
+
const runIdSchema = Type.String({
|
|
14
|
+
description: "Run id; optional for status and answer",
|
|
15
|
+
});
|
|
16
|
+
const stepSchema = Type.String({
|
|
17
|
+
description: "Workflow step id; required when action is update or submit",
|
|
18
|
+
});
|
|
19
|
+
const attemptSchema = Type.String({
|
|
20
|
+
description: "Workflow attempt id; required when action is update or submit",
|
|
21
|
+
});
|
|
22
|
+
const updateSchema = Type.Object(
|
|
23
|
+
{
|
|
24
|
+
type: Type.String(),
|
|
25
|
+
key: Type.String(),
|
|
26
|
+
data: Type.Record(Type.String(), Type.Unknown()),
|
|
27
|
+
},
|
|
28
|
+
noExtraProperties,
|
|
29
|
+
);
|
|
30
|
+
const outputSchema = Type.Unknown({
|
|
31
|
+
description: "Step output matching the expected shape; required when action is submit",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const WorkflowActionSchemas = {
|
|
35
|
+
list: Type.Object(
|
|
36
|
+
{ action: Type.Literal("list"), offset: Type.Optional(offsetSchema) },
|
|
37
|
+
noExtraProperties,
|
|
38
|
+
),
|
|
39
|
+
start: Type.Object(
|
|
40
|
+
{
|
|
41
|
+
action: Type.Literal("start"),
|
|
42
|
+
workflow: workflowSchema,
|
|
43
|
+
input: Type.Optional(inputSchema),
|
|
44
|
+
},
|
|
45
|
+
noExtraProperties,
|
|
46
|
+
),
|
|
47
|
+
status: Type.Object(
|
|
48
|
+
{ action: Type.Literal("status"), runId: Type.Optional(runIdSchema) },
|
|
49
|
+
noExtraProperties,
|
|
50
|
+
),
|
|
51
|
+
pause: Type.Object({ action: Type.Literal("pause") }, noExtraProperties),
|
|
52
|
+
resume: Type.Object({ action: Type.Literal("resume") }, noExtraProperties),
|
|
53
|
+
cancel: Type.Object({ action: Type.Literal("cancel") }, noExtraProperties),
|
|
54
|
+
answer: Type.Object(
|
|
55
|
+
{
|
|
56
|
+
action: Type.Literal("answer"),
|
|
57
|
+
input: inputSchema,
|
|
58
|
+
runId: Type.Optional(runIdSchema),
|
|
59
|
+
},
|
|
60
|
+
noExtraProperties,
|
|
61
|
+
),
|
|
62
|
+
update: Type.Object(
|
|
63
|
+
{
|
|
64
|
+
action: Type.Literal("update"),
|
|
65
|
+
step: stepSchema,
|
|
66
|
+
attempt: attemptSchema,
|
|
67
|
+
update: updateSchema,
|
|
68
|
+
},
|
|
69
|
+
noExtraProperties,
|
|
70
|
+
),
|
|
71
|
+
submit: Type.Object(
|
|
72
|
+
{
|
|
73
|
+
action: Type.Literal("submit"),
|
|
74
|
+
step: stepSchema,
|
|
75
|
+
attempt: attemptSchema,
|
|
76
|
+
output: outputSchema,
|
|
77
|
+
},
|
|
78
|
+
noExtraProperties,
|
|
79
|
+
),
|
|
80
|
+
} as const;
|
|
81
|
+
|
|
82
|
+
const WorkflowSubmissionActionSchemas = {
|
|
83
|
+
update: WorkflowActionSchemas.update,
|
|
84
|
+
submit: WorkflowActionSchemas.submit,
|
|
85
|
+
} as const;
|
|
86
|
+
|
|
87
|
+
type SchemaValue<Schemas extends Record<string, TSchema>> = Schemas[keyof Schemas];
|
|
88
|
+
|
|
89
|
+
export type WorkflowToolInput = Static<SchemaValue<typeof WorkflowActionSchemas>>;
|
|
90
|
+
export type WorkflowSubmissionInput = Static<SchemaValue<typeof WorkflowSubmissionActionSchemas>>;
|
|
91
|
+
|
|
92
|
+
export const WorkflowToolParameters = providerObjectSchema(Object.values(WorkflowActionSchemas));
|
|
93
|
+
export const WorkflowSubmissionToolParameters = providerObjectSchema(
|
|
94
|
+
Object.values(WorkflowSubmissionActionSchemas),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
type ToolInputParser<Output> = (value: unknown) => Output;
|
|
98
|
+
|
|
99
|
+
const workflowInputParsers = {
|
|
100
|
+
list: (value) => parseToolInput(WorkflowActionSchemas.list, value, "workflow"),
|
|
101
|
+
start: (value) => parseToolInput(WorkflowActionSchemas.start, value, "workflow"),
|
|
102
|
+
status: (value) => parseToolInput(WorkflowActionSchemas.status, value, "workflow"),
|
|
103
|
+
pause: (value) => parseToolInput(WorkflowActionSchemas.pause, value, "workflow"),
|
|
104
|
+
resume: (value) => parseToolInput(WorkflowActionSchemas.resume, value, "workflow"),
|
|
105
|
+
cancel: (value) => parseToolInput(WorkflowActionSchemas.cancel, value, "workflow"),
|
|
106
|
+
answer: (value) => parseToolInput(WorkflowActionSchemas.answer, value, "workflow"),
|
|
107
|
+
update: (value) => parseToolInput(WorkflowActionSchemas.update, value, "workflow"),
|
|
108
|
+
submit: (value) => parseToolInput(WorkflowActionSchemas.submit, value, "workflow"),
|
|
109
|
+
} satisfies Record<keyof typeof WorkflowActionSchemas, ToolInputParser<WorkflowToolInput>>;
|
|
110
|
+
|
|
111
|
+
const workflowSubmissionInputParsers = {
|
|
112
|
+
update: (value) =>
|
|
113
|
+
parseToolInput(WorkflowSubmissionActionSchemas.update, value, "workflow submission"),
|
|
114
|
+
submit: (value) =>
|
|
115
|
+
parseToolInput(WorkflowSubmissionActionSchemas.submit, value, "workflow submission"),
|
|
116
|
+
} satisfies Record<
|
|
117
|
+
keyof typeof WorkflowSubmissionActionSchemas,
|
|
118
|
+
ToolInputParser<WorkflowSubmissionInput>
|
|
119
|
+
>;
|
|
120
|
+
|
|
121
|
+
export function parseWorkflowToolInput(value: unknown): WorkflowToolInput {
|
|
122
|
+
return parseSelectedAction<WorkflowToolInput>(workflowInputParsers, value, "workflow");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function parseWorkflowSubmissionInput(value: unknown): WorkflowSubmissionInput {
|
|
126
|
+
return parseSelectedAction<WorkflowSubmissionInput>(
|
|
127
|
+
workflowSubmissionInputParsers,
|
|
128
|
+
value,
|
|
129
|
+
"workflow submission",
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function providerObjectSchema(variants: readonly TObject[]): TObject {
|
|
134
|
+
const actions: string[] = [];
|
|
135
|
+
const properties: TProperties = {};
|
|
136
|
+
|
|
137
|
+
for (const variant of variants) {
|
|
138
|
+
const action = variant.properties.action;
|
|
139
|
+
if (!isRecord(action) || typeof action.const !== "string") {
|
|
140
|
+
throw new Error("Workflow action schema must have a string action literal.");
|
|
141
|
+
}
|
|
142
|
+
actions.push(action.const);
|
|
143
|
+
|
|
144
|
+
for (const [name, schema] of Object.entries(variant.properties)) {
|
|
145
|
+
if (name === "action") continue;
|
|
146
|
+
const optionalSchema = Type.Optional(schema);
|
|
147
|
+
const current = properties[name];
|
|
148
|
+
if (current !== undefined && JSON.stringify(current) !== JSON.stringify(optionalSchema)) {
|
|
149
|
+
throw new Error(`Workflow property ${JSON.stringify(name)} has incompatible schemas.`);
|
|
150
|
+
}
|
|
151
|
+
properties[name] = optionalSchema;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return Type.Object(
|
|
156
|
+
{
|
|
157
|
+
action: Type.String({ enum: actions }),
|
|
158
|
+
...properties,
|
|
159
|
+
},
|
|
160
|
+
noExtraProperties,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function parseSelectedAction<Output>(
|
|
165
|
+
parsers: Readonly<Record<string, ToolInputParser<Output>>>,
|
|
166
|
+
value: unknown,
|
|
167
|
+
label: string,
|
|
168
|
+
): Output {
|
|
169
|
+
if (!isRecord(value) || typeof value.action !== "string") throw unknownAction(label);
|
|
170
|
+
const parser = parsers[value.action];
|
|
171
|
+
if (parser === undefined) throw unknownAction(label);
|
|
172
|
+
return parser(value);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function unknownAction(label: string): Error {
|
|
176
|
+
return new Error(`Invalid ${label} tool input: action is missing or unknown.`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
180
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function parseToolInput<const Schema extends TSchema>(
|
|
184
|
+
schema: Schema,
|
|
185
|
+
value: unknown,
|
|
186
|
+
label: string,
|
|
187
|
+
): Static<Schema> {
|
|
188
|
+
try {
|
|
189
|
+
return Parse(schema, value);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
if (!(error instanceof ParseError)) throw error;
|
|
192
|
+
const details = error.cause.errors
|
|
193
|
+
.slice(0, 3)
|
|
194
|
+
.map(({ instancePath, message }) => {
|
|
195
|
+
const field = instancePath.replace(/^\//u, "").replaceAll("/", ".");
|
|
196
|
+
const clearMessage = message === "must be integer" ? "must be an integer" : message;
|
|
197
|
+
return `${field ? `${field} ` : ""}${clearMessage}`;
|
|
198
|
+
})
|
|
199
|
+
.join("; ");
|
|
200
|
+
throw new Error(`Invalid ${label} tool input: ${details}`, { cause: error });
|
|
201
|
+
}
|
|
202
|
+
}
|
package/src/workflows/types.ts
CHANGED
|
@@ -177,6 +177,262 @@ export type ShellActionNodeDefinition = WorkflowNodeCommon & {
|
|
|
177
177
|
|
|
178
178
|
export type ActionNodeDefinition = FunctionActionNodeDefinition | ShellActionNodeDefinition;
|
|
179
179
|
|
|
180
|
+
export type HumanDecisionTextInput = {
|
|
181
|
+
kind: "text";
|
|
182
|
+
name: string;
|
|
183
|
+
prompt: string;
|
|
184
|
+
minLength: number;
|
|
185
|
+
maxLength: number;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
export type HumanDecisionChoice = {
|
|
189
|
+
label: string;
|
|
190
|
+
input?: HumanDecisionTextInput;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export type HumanDecisionChoiceMap = Record<string, HumanDecisionChoice>;
|
|
194
|
+
|
|
195
|
+
export type DecisionPresentationParagraph = {
|
|
196
|
+
kind: "paragraph";
|
|
197
|
+
text: string;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export type DecisionPresentationSection = {
|
|
201
|
+
kind: "section";
|
|
202
|
+
title: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type DecisionPresentationBullets = {
|
|
206
|
+
kind: "bullets";
|
|
207
|
+
items: string[];
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export type DecisionPresentationFields = {
|
|
211
|
+
kind: "fields";
|
|
212
|
+
items: Array<{ label: string; value: string }>;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export type DecisionPresentationPreformatted = {
|
|
216
|
+
kind: "preformatted";
|
|
217
|
+
text: string;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export type DecisionPresentationBlock =
|
|
221
|
+
| DecisionPresentationParagraph
|
|
222
|
+
| DecisionPresentationSection
|
|
223
|
+
| DecisionPresentationBullets
|
|
224
|
+
| DecisionPresentationFields
|
|
225
|
+
| DecisionPresentationPreformatted;
|
|
226
|
+
|
|
227
|
+
export type DecisionPresentation = {
|
|
228
|
+
schema: "pi-workflows.decision-presentation.v1";
|
|
229
|
+
summary: string;
|
|
230
|
+
blocks: DecisionPresentationBlock[];
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export type LegacyHumanDecisionPrompt = {
|
|
234
|
+
title: string;
|
|
235
|
+
body: unknown;
|
|
236
|
+
subject?: never;
|
|
237
|
+
presentation?: never;
|
|
238
|
+
revision?: never;
|
|
239
|
+
/** Optional absolute expiry. An expired request cannot accept an answer. */
|
|
240
|
+
expiresAt?: string;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export type PresentedHumanDecisionPrompt<TSubject = unknown> = {
|
|
244
|
+
title: string;
|
|
245
|
+
subject: TSubject;
|
|
246
|
+
presentation: DecisionPresentation;
|
|
247
|
+
body?: never;
|
|
248
|
+
/** Positive revision of the decision subject and presentation. Defaults to 1. */
|
|
249
|
+
revision?: number;
|
|
250
|
+
/** Optional absolute expiry. An expired request cannot accept an answer. */
|
|
251
|
+
expiresAt?: string;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export type HumanDecisionPrompt = LegacyHumanDecisionPrompt | PresentedHumanDecisionPrompt;
|
|
255
|
+
|
|
256
|
+
export type HumanDecisionAudience =
|
|
257
|
+
| string
|
|
258
|
+
| ((context: WorkflowNodeContext) => MaybePromise<string>);
|
|
259
|
+
|
|
260
|
+
export type HumanDecisionNodeContract = {
|
|
261
|
+
audience: HumanDecisionAudience;
|
|
262
|
+
choices: HumanDecisionChoiceMap;
|
|
263
|
+
request: (context: WorkflowNodeContext) => MaybePromise<HumanDecisionPrompt>;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
type HumanDecisionRequestCommon = {
|
|
267
|
+
decisionId: string;
|
|
268
|
+
requestDigest: string;
|
|
269
|
+
runId: string;
|
|
270
|
+
workflowName: string;
|
|
271
|
+
nodeId: string;
|
|
272
|
+
attemptId: string;
|
|
273
|
+
audience: string;
|
|
274
|
+
title: string;
|
|
275
|
+
choices: HumanDecisionChoiceMap;
|
|
276
|
+
createdAt: string;
|
|
277
|
+
expiresAt?: string;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
export type HumanDecisionRequestV1 = HumanDecisionRequestCommon & {
|
|
281
|
+
schema: "pi-workflows.human-decision-request.v1";
|
|
282
|
+
body: unknown;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
export type HumanDecisionRequestV2 = HumanDecisionRequestCommon & {
|
|
286
|
+
schema: "pi-workflows.human-decision-request.v2";
|
|
287
|
+
subject: unknown;
|
|
288
|
+
presentation: DecisionPresentation;
|
|
289
|
+
revision: number;
|
|
290
|
+
subjectDigest: string;
|
|
291
|
+
presentationDigest: string;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export type HumanDecisionRequest = HumanDecisionRequestV1 | HumanDecisionRequestV2;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Complete operator-facing request passed to a decision channel. It excludes
|
|
298
|
+
* the canonical subject and legacy body by design.
|
|
299
|
+
*/
|
|
300
|
+
export type HumanDecisionChannelRequest = HumanDecisionRequestCommon & {
|
|
301
|
+
schema: "pi-workflows.human-decision-channel-request.v1";
|
|
302
|
+
sourceSchema: HumanDecisionRequest["schema"];
|
|
303
|
+
presentation: DecisionPresentation;
|
|
304
|
+
presentationDigest: string;
|
|
305
|
+
revision: number;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export type HumanDecisionResponse = {
|
|
309
|
+
choice: string;
|
|
310
|
+
input?: Record<string, string>;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
export type HumanDecisionAnswerSource = {
|
|
314
|
+
channel: string;
|
|
315
|
+
actorId: string;
|
|
316
|
+
eventId: string;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export type HumanDecisionSubmission = HumanDecisionResponse & {
|
|
320
|
+
decisionId: string;
|
|
321
|
+
requestDigest: string;
|
|
322
|
+
source: HumanDecisionAnswerSource;
|
|
323
|
+
idempotencyKey: string;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
type AcceptedHumanDecisionCommon = {
|
|
327
|
+
decisionId: string;
|
|
328
|
+
requestDigest: string;
|
|
329
|
+
response: HumanDecisionResponse;
|
|
330
|
+
source: HumanDecisionAnswerSource;
|
|
331
|
+
idempotencyKey: string;
|
|
332
|
+
acceptedAt: string;
|
|
333
|
+
answerDigest: string;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
export type AcceptedHumanDecisionV1 = AcceptedHumanDecisionCommon & {
|
|
337
|
+
schema: "pi-workflows.human-decision-accepted.v1";
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export type AcceptedHumanDecisionV2 = AcceptedHumanDecisionCommon & {
|
|
341
|
+
schema: "pi-workflows.human-decision-accepted.v2";
|
|
342
|
+
subjectDigest: string;
|
|
343
|
+
presentationDigest: string;
|
|
344
|
+
revision: number;
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
export type AcceptedHumanDecision = AcceptedHumanDecisionV1 | AcceptedHumanDecisionV2;
|
|
348
|
+
|
|
349
|
+
type HumanDecisionReceiptCommon = {
|
|
350
|
+
decisionId: string;
|
|
351
|
+
requestDigest: string;
|
|
352
|
+
nodeId: string;
|
|
353
|
+
response: HumanDecisionResponse;
|
|
354
|
+
acceptedAt: string;
|
|
355
|
+
answerDigest: string;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
export type HumanDecisionReceiptV1 = HumanDecisionReceiptCommon & {
|
|
359
|
+
schema: "pi-workflows.human-decision-receipt.v1";
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export type HumanDecisionReceiptV2 = HumanDecisionReceiptCommon & {
|
|
363
|
+
schema: "pi-workflows.human-decision-receipt.v2";
|
|
364
|
+
subjectDigest: string;
|
|
365
|
+
presentationDigest: string;
|
|
366
|
+
revision: number;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export type HumanDecisionReceipt = HumanDecisionReceiptV1 | HumanDecisionReceiptV2;
|
|
370
|
+
|
|
371
|
+
export type HumanDecisionDeliveryRecordV1 = {
|
|
372
|
+
schema: "pi-workflows.human-decision-delivery.v1";
|
|
373
|
+
attemptId: string;
|
|
374
|
+
decisionId: string;
|
|
375
|
+
requestDigest: string;
|
|
376
|
+
channel: string;
|
|
377
|
+
state: "intent" | "confirmed" | "failed" | "unknown";
|
|
378
|
+
createdAt: string;
|
|
379
|
+
finishedAt?: string;
|
|
380
|
+
messageCount?: number;
|
|
381
|
+
errorCode?: string;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
export type HumanDecisionDeliveryRecordV2 = {
|
|
385
|
+
schema: "pi-workflows.human-decision-delivery.v2";
|
|
386
|
+
attemptId: string;
|
|
387
|
+
decisionId: string;
|
|
388
|
+
requestDigest: string;
|
|
389
|
+
presentationDigest: string;
|
|
390
|
+
channel: string;
|
|
391
|
+
phase: "intent" | "part" | "complete";
|
|
392
|
+
state: "intent" | "confirmed" | "failed" | "unknown";
|
|
393
|
+
createdAt: string;
|
|
394
|
+
finishedAt?: string;
|
|
395
|
+
recipientIndex?: number;
|
|
396
|
+
partIndex?: number;
|
|
397
|
+
partCount?: number;
|
|
398
|
+
contentDigest?: string;
|
|
399
|
+
messageCount?: number;
|
|
400
|
+
errorCode?: string;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
export type HumanDecisionDeliveryRecord =
|
|
404
|
+
| HumanDecisionDeliveryRecordV1
|
|
405
|
+
| HumanDecisionDeliveryRecordV2;
|
|
406
|
+
|
|
407
|
+
export type HumanDecisionSettlementRecord = {
|
|
408
|
+
schema: "pi-workflows.human-decision-settlement.v1";
|
|
409
|
+
attemptId: string;
|
|
410
|
+
decisionId: string;
|
|
411
|
+
requestDigest: string;
|
|
412
|
+
channel: string;
|
|
413
|
+
state: "confirmed" | "failed";
|
|
414
|
+
createdAt: string;
|
|
415
|
+
finishedAt: string;
|
|
416
|
+
errorCode?: string;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
export type HumanDecisionCancellationRecord = {
|
|
420
|
+
schema: "pi-workflows.human-decision-cancellation.v1";
|
|
421
|
+
decisionId: string;
|
|
422
|
+
requestDigest: string;
|
|
423
|
+
cancelledAt: string;
|
|
424
|
+
reason: "cancelled" | "expired";
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
export type HumanDecisionContinuationRecord = {
|
|
428
|
+
schema: "pi-workflows.human-decision-continuation.v1";
|
|
429
|
+
decisionId: string;
|
|
430
|
+
requestDigest: string;
|
|
431
|
+
parentRunId: string;
|
|
432
|
+
runId: string;
|
|
433
|
+
createdAt: string;
|
|
434
|
+
};
|
|
435
|
+
|
|
180
436
|
/**
|
|
181
437
|
* A pause point. The run terminates with status `waiting` so a human (or an
|
|
182
438
|
* external trigger) can decide how to continue. The optional `run` callback
|
|
@@ -186,6 +442,8 @@ export type CheckpointNodeDefinition = WorkflowNodeCommon & {
|
|
|
186
442
|
nodeType: "checkpoint";
|
|
187
443
|
summary?: string;
|
|
188
444
|
run?: (context: WorkflowNodeContext) => MaybePromise<unknown>;
|
|
445
|
+
/** Typed verified-human request. Still executes as a checkpoint node. */
|
|
446
|
+
humanDecision?: HumanDecisionNodeContract;
|
|
189
447
|
};
|
|
190
448
|
|
|
191
449
|
export type WorkflowNodeDefinition =
|
|
@@ -204,12 +462,88 @@ export type WorkflowPresentationContext = {
|
|
|
204
462
|
signal: AbortSignal;
|
|
205
463
|
};
|
|
206
464
|
|
|
207
|
-
|
|
465
|
+
/** Runtime parser that also carries its normalized TypeScript result type. */
|
|
466
|
+
export type WorkflowValueParser<T> = (value: unknown) => MaybePromise<T>;
|
|
467
|
+
|
|
468
|
+
export type WorkflowExitDefinition<TOutput = unknown> = {
|
|
469
|
+
/** Successful terminal node whose output leaves through this exit. */
|
|
470
|
+
from: string;
|
|
471
|
+
/** Optional runtime output normalizer and validator. */
|
|
472
|
+
validate?: WorkflowValueParser<TOutput>;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
export type WorkflowExitMap = Record<string, WorkflowExitDefinition>;
|
|
476
|
+
|
|
477
|
+
export type WorkflowInputOf<TWorkflow> =
|
|
478
|
+
TWorkflow extends WorkflowDefinition<infer TInput, any, any> ? TInput : unknown;
|
|
479
|
+
|
|
480
|
+
export type WorkflowExitOutputs<TWorkflow> =
|
|
481
|
+
TWorkflow extends WorkflowDefinition<any, infer TExits, any>
|
|
482
|
+
? {
|
|
483
|
+
[K in keyof TExits]: TExits[K] extends WorkflowExitDefinition<infer TOutput>
|
|
484
|
+
? TOutput
|
|
485
|
+
: unknown;
|
|
486
|
+
}
|
|
487
|
+
: Record<string, unknown>;
|
|
488
|
+
|
|
489
|
+
export type WorkflowIncludedResult<TWorkflow> = {
|
|
490
|
+
[K in keyof WorkflowExitOutputs<TWorkflow>]: {
|
|
491
|
+
exit: K;
|
|
492
|
+
output: WorkflowExitOutputs<TWorkflow>[K];
|
|
493
|
+
};
|
|
494
|
+
}[keyof WorkflowExitOutputs<TWorkflow>];
|
|
495
|
+
|
|
496
|
+
export type WorkflowIncludeDefinition<
|
|
497
|
+
TWorkflow extends WorkflowDefinition<any, any, any> = WorkflowDefinition<any, any, any>,
|
|
498
|
+
> = {
|
|
499
|
+
/** Imported child definition or dynamic discovered name/path. */
|
|
500
|
+
workflow: TWorkflow | string;
|
|
501
|
+
/** Pure parent-to-child input mapping, evaluated on every mount entry. */
|
|
502
|
+
input?: (context: WorkflowNodeContext) => MaybePromise<WorkflowInputOf<TWorkflow>>;
|
|
503
|
+
/** Optional direct definition that supplies the contract for a dynamic reference. */
|
|
504
|
+
contract?: TWorkflow;
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
export type WorkflowIncludeMap = Record<string, WorkflowIncludeDefinition>;
|
|
508
|
+
|
|
509
|
+
export type WorkflowIncludeExitReference<TIncludes extends WorkflowIncludeMap> = {
|
|
510
|
+
[K in keyof TIncludes & string]: TIncludes[K] extends WorkflowIncludeDefinition<infer TWorkflow>
|
|
511
|
+
? `${K}.${Extract<keyof WorkflowExitOutputs<TWorkflow>, string>}`
|
|
512
|
+
: never;
|
|
513
|
+
}[keyof TIncludes & string];
|
|
514
|
+
|
|
515
|
+
export type WorkflowTypedEdge<
|
|
516
|
+
TNodes extends Record<string, WorkflowNodeDefinition>,
|
|
517
|
+
TIncludes extends WorkflowIncludeMap,
|
|
518
|
+
> =
|
|
519
|
+
| {
|
|
520
|
+
from: (keyof TNodes & string) | WorkflowIncludeExitReference<TIncludes>;
|
|
521
|
+
to: (keyof TNodes & string) | (keyof TIncludes & string);
|
|
522
|
+
}
|
|
523
|
+
| {
|
|
524
|
+
from: keyof TNodes & string;
|
|
525
|
+
switch: {
|
|
526
|
+
on: string;
|
|
527
|
+
cases: Record<string, (keyof TNodes & string) | (keyof TIncludes & string)>;
|
|
528
|
+
};
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
export type WorkflowDefinition<
|
|
532
|
+
TInput = any,
|
|
533
|
+
TExits extends WorkflowExitMap = WorkflowExitMap,
|
|
534
|
+
TIncludes extends WorkflowIncludeMap = WorkflowIncludeMap,
|
|
535
|
+
> = {
|
|
208
536
|
name: string;
|
|
537
|
+
/** Module URL used to attest directly imported child workflow files. */
|
|
538
|
+
source?: string;
|
|
539
|
+
/** Stable public input-and-exit contract identity for compatible overrides. */
|
|
540
|
+
contractId?: string;
|
|
541
|
+
/** Optional runtime input normalizer and validator. */
|
|
542
|
+
input?: WorkflowValueParser<TInput>;
|
|
209
543
|
/** Optional human-readable run title (static or derived from input). */
|
|
210
544
|
title?:
|
|
211
545
|
| string
|
|
212
|
-
| ((context: { input:
|
|
546
|
+
| ((context: { input: TInput; workflowName: string }) => MaybePromise<string | undefined>);
|
|
213
547
|
/**
|
|
214
548
|
* Optional instructions for a normal assistant response after the run ends.
|
|
215
549
|
* The Pi extension resolves this only after the final state is persisted;
|
|
@@ -220,6 +554,8 @@ export type WorkflowDefinition = {
|
|
|
220
554
|
| ((context: WorkflowPresentationContext) => MaybePromise<string | undefined>);
|
|
221
555
|
startAt: string;
|
|
222
556
|
nodes: Record<string, WorkflowNodeDefinition>;
|
|
557
|
+
includes?: TIncludes;
|
|
558
|
+
exits?: TExits;
|
|
223
559
|
edges: WorkflowEdge[];
|
|
224
560
|
/** Guard against unbounded loops. Defaults to the engine's maxSteps. */
|
|
225
561
|
maxSteps?: number;
|
|
@@ -308,6 +644,24 @@ export type WorkflowSource =
|
|
|
308
644
|
| { kind: "builtin"; id: string; revision: string }
|
|
309
645
|
| { kind: "file"; path: string; hash: string };
|
|
310
646
|
|
|
647
|
+
export type WorkflowMountedSource = {
|
|
648
|
+
mountPath: string[];
|
|
649
|
+
workflowName: string;
|
|
650
|
+
source: WorkflowSource;
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
export type WorkflowMountSnapshot = {
|
|
654
|
+
mountPath: string[];
|
|
655
|
+
workflowName: string;
|
|
656
|
+
entryNode: string;
|
|
657
|
+
exits: Record<string, string>;
|
|
658
|
+
maxSteps?: number;
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
export type WorkflowCompositionSnapshot = {
|
|
662
|
+
mounts: WorkflowMountSnapshot[];
|
|
663
|
+
};
|
|
664
|
+
|
|
311
665
|
export type WorkflowRunState = {
|
|
312
666
|
schema: "pi-workflows.run-state.v1";
|
|
313
667
|
/**
|
|
@@ -329,6 +683,10 @@ export type WorkflowRunState = {
|
|
|
329
683
|
runTitle?: string;
|
|
330
684
|
/** Stable built-in identity or immutable file source used by this run. */
|
|
331
685
|
workflowSource?: WorkflowSource;
|
|
686
|
+
/** Sorted immutable sources used by included workflow mounts. */
|
|
687
|
+
workflowSources?: WorkflowMountedSource[];
|
|
688
|
+
/** SHA-256 of the fully resolved definition snapshot. */
|
|
689
|
+
definitionDigest?: string;
|
|
332
690
|
/** Legacy fields accepted only by the bounded built-in migration. */
|
|
333
691
|
workflowPath?: string;
|
|
334
692
|
workflowHash?: string;
|
|
@@ -346,6 +704,8 @@ export type WorkflowRunState = {
|
|
|
346
704
|
currentAttemptId?: string;
|
|
347
705
|
currentNodeStartedAt?: string;
|
|
348
706
|
statusDetail?: string;
|
|
707
|
+
/** Redacted verified-human receipt carried by a continuation run. */
|
|
708
|
+
humanDecision?: HumanDecisionReceipt;
|
|
349
709
|
/** True while the run is held at a step boundary by a pause request. */
|
|
350
710
|
paused?: boolean;
|
|
351
711
|
waitingOn?: string;
|
|
@@ -360,14 +720,24 @@ export type WorkflowNodeSnapshot = {
|
|
|
360
720
|
summary?: string;
|
|
361
721
|
expectedOutput?: string;
|
|
362
722
|
actionExecution?: "function" | "shell";
|
|
723
|
+
mountPath?: string[];
|
|
724
|
+
localNodeId?: string;
|
|
725
|
+
includeTransition?: "entry" | "exit";
|
|
726
|
+
humanDecision?: {
|
|
727
|
+
audience: string;
|
|
728
|
+
dynamicAudience?: boolean;
|
|
729
|
+
choices: HumanDecisionChoiceMap;
|
|
730
|
+
};
|
|
363
731
|
};
|
|
364
732
|
|
|
365
733
|
export type WorkflowDefinitionSnapshot = {
|
|
366
734
|
schema: "pi-workflows.definition-snapshot.v1";
|
|
367
735
|
name: string;
|
|
736
|
+
contractId?: string;
|
|
368
737
|
startAt: string;
|
|
369
738
|
nodes: Record<string, WorkflowNodeSnapshot>;
|
|
370
739
|
edges: WorkflowEdge[];
|
|
740
|
+
composition?: WorkflowCompositionSnapshot;
|
|
371
741
|
};
|
|
372
742
|
|
|
373
743
|
export type WorkflowTraceEvent = {
|
|
@@ -460,6 +830,8 @@ export type WorkflowRunManifest = {
|
|
|
460
830
|
workflowName: string;
|
|
461
831
|
runTitle?: string;
|
|
462
832
|
workflowSource?: WorkflowSource;
|
|
833
|
+
workflowSources?: WorkflowMountedSource[];
|
|
834
|
+
definitionDigest?: string;
|
|
463
835
|
startedAt: string;
|
|
464
836
|
finishedAt?: string;
|
|
465
837
|
status: WorkflowRunStatus;
|