@agwab/pi-workflow 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/compiler.d.ts +4 -6
- package/dist/compiler.js +70 -39
- package/dist/dynamic-decision.d.ts +0 -1
- package/dist/dynamic-decision.js +0 -7
- package/dist/dynamic-generated-task-runtime.d.ts +2 -0
- package/dist/dynamic-generated-task-runtime.js +21 -8
- package/dist/dynamic-profiles.d.ts +0 -1
- package/dist/dynamic-profiles.js +0 -3
- package/dist/engine-run-graph.d.ts +1 -0
- package/dist/engine-run-graph.js +142 -2
- package/dist/engine.d.ts +10 -6
- package/dist/engine.js +146 -77
- package/dist/extension.d.ts +2 -1
- package/dist/extension.js +38 -15
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -1
- package/dist/store.d.ts +3 -1
- package/dist/store.js +189 -49
- package/dist/subagent-backend.d.ts +4 -0
- package/dist/subagent-backend.js +281 -31
- package/dist/types.d.ts +9 -1
- package/dist/workflow-runtime.d.ts +2 -0
- package/dist/workflow-runtime.js +40 -1
- package/dist/workflow-view.js +3 -1
- package/dist/workflow-web-source-extension.js +167 -48
- package/dist/workflow-web-source.d.ts +2 -1
- package/dist/workflow-web-source.js +84 -19
- package/docs/usage.md +11 -0
- package/node_modules/@agwab/pi-subagent/README.md +3 -3
- package/node_modules/@agwab/pi-subagent/api.mjs +1 -0
- package/node_modules/@agwab/pi-subagent/docs/usage.md +63 -12
- package/node_modules/@agwab/pi-subagent/package.json +2 -2
- package/node_modules/@agwab/pi-subagent/src/api.ts +54 -1
- package/node_modules/@agwab/pi-subagent/src/artifacts/registry.ts +9 -4
- package/node_modules/@agwab/pi-subagent/src/artifacts/result.ts +8 -0
- package/node_modules/@agwab/pi-subagent/src/core/constants.ts +9 -0
- package/node_modules/@agwab/pi-subagent/src/core/validation.ts +21 -0
- package/node_modules/@agwab/pi-subagent/src/index.ts +995 -573
- package/node_modules/@agwab/pi-subagent/src/orchestrate/async.ts +279 -156
- package/node_modules/@agwab/pi-subagent/src/orchestrate/interrupt.ts +165 -89
- package/node_modules/@agwab/pi-subagent/src/orchestrate/reconcile.ts +111 -65
- package/node_modules/@agwab/pi-subagent/src/orchestrate/run-ref.ts +219 -0
- package/node_modules/@agwab/pi-subagent/src/orchestrate/run.ts +88 -8
- package/node_modules/@agwab/pi-subagent/src/orchestrate/status.ts +614 -298
- package/node_modules/@agwab/pi-subagent/src/panel.ts +1352 -560
- package/node_modules/@agwab/pi-subagent/src/runners/headless-model.ts +53 -5
- package/node_modules/@agwab/pi-subagent/src/runners/tmux.ts +13 -6
- package/package.json +2 -2
- package/src/compiler.ts +127 -66
- package/src/dynamic-decision.ts +0 -11
- package/src/dynamic-generated-task-runtime.ts +47 -12
- package/src/dynamic-profiles.ts +0 -4
- package/src/engine-run-graph.ts +185 -2
- package/src/engine.ts +192 -107
- package/src/extension.ts +50 -17
- package/src/index.ts +3 -1
- package/src/store.ts +253 -55
- package/src/subagent-backend.ts +369 -32
- package/src/types.ts +13 -1
- package/src/workflow-runtime.ts +53 -2
- package/src/workflow-view.ts +2 -1
- package/src/workflow-web-source-extension.ts +621 -228
- package/src/workflow-web-source.ts +118 -28
- package/workflows/deep-research/helpers/claim-evidence-gate.mjs +56 -16
- package/workflows/deep-research/helpers/final-audit-packet.mjs +1 -4
- package/workflows/deep-research/helpers/normalize-input-packet.mjs +1 -1
- package/workflows/deep-research/helpers/render-executive.mjs +8 -21
- package/workflows/deep-research/helpers/sanitize-verification-candidates.mjs +89 -15
- package/workflows/deep-research/schemas/deep-research-executive-render-control.schema.json +0 -1
- package/workflows/deep-research/schemas/deep-research-verify-claims-control.schema.json +4 -1
- package/workflows/impact-review/spec.json +3 -3
- package/workflows/spec-review/helpers/spec-review-pipeline.mjs +1 -8
- package/dist/dynamic-loader.d.ts +0 -25
- package/dist/dynamic-loader.js +0 -13
- package/src/dynamic-loader.ts +0 -49
- package/workflows/impact-review/schemas/docs-release-impact-control.schema.json +0 -42
- package/workflows/impact-review/schemas/security-performance-impact-control.schema.json +0 -42
- package/workflows/impact-review/schemas/state-data-impact-control.schema.json +0 -42
package/src/engine-run-graph.ts
CHANGED
|
@@ -127,6 +127,135 @@ export function reconcileDynamicGeneratedRunRecords(
|
|
|
127
127
|
return changed;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
export function reconcileForeachGeneratedRunRecords(
|
|
131
|
+
cwd: string,
|
|
132
|
+
run: WorkflowRunRecord,
|
|
133
|
+
compiledFlow: CompiledWorkflow,
|
|
134
|
+
): boolean {
|
|
135
|
+
let changed = false;
|
|
136
|
+
const compiledSpecIds = new Set(
|
|
137
|
+
compiledFlow.tasks.map((task) => compiledTaskSpecId(task)),
|
|
138
|
+
);
|
|
139
|
+
const placeholderToGeneratedSpecIds = new Map<string, string[]>();
|
|
140
|
+
|
|
141
|
+
for (const compiledTask of compiledFlow.tasks) {
|
|
142
|
+
const specId = compiledTaskSpecId(compiledTask);
|
|
143
|
+
const placeholderSpecId = foreachGeneratedPlaceholderSpecId(
|
|
144
|
+
compiledTask,
|
|
145
|
+
compiledFlow,
|
|
146
|
+
specId,
|
|
147
|
+
);
|
|
148
|
+
if (!placeholderSpecId) continue;
|
|
149
|
+
if (
|
|
150
|
+
compiledTask.foreachGenerated?.placeholderSpecId !== placeholderSpecId
|
|
151
|
+
) {
|
|
152
|
+
compiledTask.foreachGenerated = { placeholderSpecId };
|
|
153
|
+
changed = true;
|
|
154
|
+
}
|
|
155
|
+
const generated =
|
|
156
|
+
placeholderToGeneratedSpecIds.get(placeholderSpecId) ?? [];
|
|
157
|
+
generated.push(specId);
|
|
158
|
+
placeholderToGeneratedSpecIds.set(placeholderSpecId, generated);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (placeholderToGeneratedSpecIds.size === 0) return changed;
|
|
162
|
+
|
|
163
|
+
const filteredRunTasks: WorkflowTaskRunRecord[] = [];
|
|
164
|
+
const seenGeneratedSpecIds = new Set<string>();
|
|
165
|
+
for (const task of run.tasks) {
|
|
166
|
+
const generatedSpecIds = placeholderToGeneratedSpecIds.get(task.specId);
|
|
167
|
+
let placeholderSpecId = foreachGeneratedPlaceholderSpecId(
|
|
168
|
+
task,
|
|
169
|
+
compiledFlow,
|
|
170
|
+
task.specId,
|
|
171
|
+
);
|
|
172
|
+
if (generatedSpecIds && !placeholderSpecId) {
|
|
173
|
+
if (generatedSpecIds.includes(task.specId)) {
|
|
174
|
+
placeholderSpecId = task.specId;
|
|
175
|
+
task.foreachGenerated = { placeholderSpecId };
|
|
176
|
+
changed = true;
|
|
177
|
+
} else {
|
|
178
|
+
changed = true;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (placeholderSpecId && !compiledSpecIds.has(task.specId)) {
|
|
183
|
+
changed = true;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (placeholderSpecId && seenGeneratedSpecIds.has(task.specId)) {
|
|
187
|
+
changed = true;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (placeholderSpecId) {
|
|
191
|
+
seenGeneratedSpecIds.add(task.specId);
|
|
192
|
+
if (task.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
|
|
193
|
+
task.foreachGenerated = { placeholderSpecId };
|
|
194
|
+
changed = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
filteredRunTasks.push(task);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const runTaskBySpecId = new Map<string, WorkflowTaskRunRecord>();
|
|
201
|
+
for (const task of filteredRunTasks) {
|
|
202
|
+
if (!runTaskBySpecId.has(task.specId))
|
|
203
|
+
runTaskBySpecId.set(task.specId, task);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const reordered: WorkflowTaskRunRecord[] = [];
|
|
207
|
+
const usedSpecIds = new Set<string>();
|
|
208
|
+
let nextIndex = nextTaskRecordIndex({ ...run, tasks: filteredRunTasks });
|
|
209
|
+
for (const compiledTask of compiledFlow.tasks) {
|
|
210
|
+
const specId = compiledTaskSpecId(compiledTask);
|
|
211
|
+
const existing = runTaskBySpecId.get(specId);
|
|
212
|
+
if (existing) {
|
|
213
|
+
const placeholderSpecId =
|
|
214
|
+
compiledTask.foreachGenerated?.placeholderSpecId;
|
|
215
|
+
if (
|
|
216
|
+
placeholderSpecId &&
|
|
217
|
+
existing.foreachGenerated?.placeholderSpecId !== placeholderSpecId
|
|
218
|
+
) {
|
|
219
|
+
existing.foreachGenerated = { placeholderSpecId };
|
|
220
|
+
changed = true;
|
|
221
|
+
}
|
|
222
|
+
reordered.push(existing);
|
|
223
|
+
usedSpecIds.add(specId);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (!compiledTask.foreachGenerated) continue;
|
|
227
|
+
const created = createTaskRunRecord(
|
|
228
|
+
cwd,
|
|
229
|
+
run.runId,
|
|
230
|
+
compiledTask,
|
|
231
|
+
nextIndex,
|
|
232
|
+
);
|
|
233
|
+
nextIndex += 1;
|
|
234
|
+
reordered.push(created);
|
|
235
|
+
usedSpecIds.add(specId);
|
|
236
|
+
changed = true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (const task of filteredRunTasks) {
|
|
240
|
+
if (!usedSpecIds.has(task.specId)) reordered.push(task);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!sameTaskRecordOrder(run.tasks, reordered)) changed = true;
|
|
244
|
+
for (const task of reordered) {
|
|
245
|
+
if (!task.dependsOn) continue;
|
|
246
|
+
const replaced = replaceForeachGeneratedDependencies(
|
|
247
|
+
task.dependsOn,
|
|
248
|
+
placeholderToGeneratedSpecIds,
|
|
249
|
+
);
|
|
250
|
+
if (!sameStringList(task.dependsOn, replaced)) {
|
|
251
|
+
task.dependsOn = replaced;
|
|
252
|
+
changed = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (changed) run.tasks = reordered;
|
|
256
|
+
return changed;
|
|
257
|
+
}
|
|
258
|
+
|
|
130
259
|
export function assertRunTaskPositionalAlignment(
|
|
131
260
|
run: WorkflowRunRecord,
|
|
132
261
|
compiledFlow: CompiledWorkflow,
|
|
@@ -209,6 +338,54 @@ export function compiledTaskSpecId(task: CompiledTask): string {
|
|
|
209
338
|
return typeof specId === "string" && specId.trim() !== "" ? specId : task.id;
|
|
210
339
|
}
|
|
211
340
|
|
|
341
|
+
function foreachGeneratedPlaceholderSpecId(
|
|
342
|
+
task: CompiledTask | WorkflowTaskRunRecord,
|
|
343
|
+
compiledFlow: CompiledWorkflow,
|
|
344
|
+
specId: string,
|
|
345
|
+
): string | undefined {
|
|
346
|
+
const explicit = task.foreachGenerated?.placeholderSpecId;
|
|
347
|
+
if (typeof explicit === "string" && explicit.trim() !== "") return explicit;
|
|
348
|
+
if ((task as CompiledTask).foreach) return undefined;
|
|
349
|
+
if (task.kind !== "foreach" || !task.stageId) return undefined;
|
|
350
|
+
const placeholderSpecId = foreachPlaceholderSpecId(
|
|
351
|
+
compiledFlow,
|
|
352
|
+
task.stageId,
|
|
353
|
+
);
|
|
354
|
+
if (!placeholderSpecId || specId === placeholderSpecId) return undefined;
|
|
355
|
+
return placeholderSpecId;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function foreachPlaceholderSpecId(
|
|
359
|
+
compiledFlow: CompiledWorkflow,
|
|
360
|
+
stageId: string,
|
|
361
|
+
): string | undefined {
|
|
362
|
+
const stage = ((compiledFlow as any).stages ?? []).find(
|
|
363
|
+
(candidate: any) => candidate?.id === stageId,
|
|
364
|
+
);
|
|
365
|
+
if (stage?.type !== "foreach") return undefined;
|
|
366
|
+
return `${stageId}.item`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function replaceForeachGeneratedDependencies(
|
|
370
|
+
dependsOn: string[],
|
|
371
|
+
placeholderToGeneratedSpecIds: Map<string, string[]>,
|
|
372
|
+
): string[] {
|
|
373
|
+
const replaced: string[] = [];
|
|
374
|
+
for (const dep of dependsOn) {
|
|
375
|
+
const generatedSpecIds = placeholderToGeneratedSpecIds.get(dep);
|
|
376
|
+
if (generatedSpecIds) replaced.push(...generatedSpecIds);
|
|
377
|
+
else replaced.push(dep);
|
|
378
|
+
}
|
|
379
|
+
return [...new Set(replaced)];
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function sameStringList(left: string[], right: string[]): boolean {
|
|
383
|
+
return (
|
|
384
|
+
left.length === right.length &&
|
|
385
|
+
left.every((value, index) => value === right[index])
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
212
389
|
function isLoopGeneratedCompiledTask(
|
|
213
390
|
task: CompiledTask,
|
|
214
391
|
loopIds: Set<string>,
|
|
@@ -330,7 +507,7 @@ export function buildForeachGeneratedTasks(
|
|
|
330
507
|
const itemText = formatForeachItem(item);
|
|
331
508
|
const instructions = template.foreach!.prompt.replace(
|
|
332
509
|
/\$\{item\}/g,
|
|
333
|
-
itemText,
|
|
510
|
+
escapeReplacementText(itemText),
|
|
334
511
|
);
|
|
335
512
|
const compiledPrompt = [
|
|
336
513
|
template.foreach!.injectRuntimeTask && runtimeTask
|
|
@@ -352,6 +529,7 @@ export function buildForeachGeneratedTasks(
|
|
|
352
529
|
compiledPrompt,
|
|
353
530
|
dependsOn: [...(template.dependsOn ?? [])],
|
|
354
531
|
foreach: undefined,
|
|
532
|
+
foreachGenerated: { placeholderSpecId: template.id },
|
|
355
533
|
} as CompiledTask);
|
|
356
534
|
}
|
|
357
535
|
return { tasks };
|
|
@@ -382,6 +560,10 @@ function formatForeachItem(item: unknown): string {
|
|
|
382
560
|
return typeof item === "string" ? item : JSON.stringify(item);
|
|
383
561
|
}
|
|
384
562
|
|
|
563
|
+
function escapeReplacementText(value: string): string {
|
|
564
|
+
return value.replace(/\$/g, "$$$$");
|
|
565
|
+
}
|
|
566
|
+
|
|
385
567
|
export function sourceStageIdsForFrom(from: unknown): string[] {
|
|
386
568
|
if (Array.isArray(from))
|
|
387
569
|
return from.filter((item): item is string => typeof item === "string");
|
|
@@ -453,7 +635,8 @@ export function markDagDependentsSkipped(
|
|
|
453
635
|
return (
|
|
454
636
|
status === "failed" ||
|
|
455
637
|
status === "interrupted" ||
|
|
456
|
-
status === "skipped"
|
|
638
|
+
status === "skipped" ||
|
|
639
|
+
status === "blocked"
|
|
457
640
|
);
|
|
458
641
|
});
|
|
459
642
|
if (!failedDep) continue;
|