@agwab/pi-workflow 0.1.2 → 0.2.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/README.md +9 -13
- package/dist/compiler.d.ts +5 -5
- package/dist/compiler.js +82 -24
- package/dist/dynamic-generated-task-runtime.d.ts +2 -0
- package/dist/dynamic-generated-task-runtime.js +21 -8
- package/dist/engine.d.ts +6 -5
- package/dist/engine.js +39 -54
- package/dist/extension.js +211 -24
- package/dist/store.d.ts +3 -1
- package/dist/store.js +135 -38
- package/dist/subagent-backend.d.ts +4 -0
- package/dist/subagent-backend.js +128 -4
- package/dist/types.d.ts +5 -0
- package/dist/workflow-progress-health.d.ts +37 -0
- package/dist/workflow-progress-health.js +296 -0
- package/dist/workflow-runtime.d.ts +8 -0
- package/dist/workflow-runtime.js +63 -10
- package/dist/workflow-view.d.ts +2 -0
- package/dist/workflow-view.js +97 -18
- package/dist/workflow-web-source.js +32 -14
- package/docs/usage.md +12 -1
- package/package.json +6 -6
- package/src/compiler.ts +136 -41
- package/src/dynamic-generated-task-runtime.ts +47 -12
- package/src/engine.ts +55 -100
- package/src/extension.ts +270 -34
- package/src/store.ts +180 -44
- package/src/subagent-backend.ts +170 -6
- package/src/types.ts +10 -0
- package/src/workflow-progress-health.ts +461 -0
- package/src/workflow-runtime.ts +85 -13
- package/src/workflow-view.ts +186 -41
- package/src/workflow-web-source.ts +192 -69
- package/workflows/deep-research/helpers/claim-evidence-gate.mjs +111 -37
- package/workflows/deep-research/helpers/final-audit-packet.mjs +191 -14
- package/workflows/deep-research/helpers/normalize-input-packet.mjs +159 -50
- package/workflows/deep-research/helpers/render-executive.mjs +671 -37
- package/workflows/deep-research/helpers/sanitize-verification-candidates.mjs +624 -0
- package/workflows/deep-research/schemas/deep-research-executive-render-control.schema.json +2 -0
- package/workflows/deep-research/schemas/deep-research-final-synthesis-control.schema.json +110 -0
- package/workflows/deep-research/spec.json +41 -11
package/src/engine.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
dirname,
|
|
4
|
-
extname,
|
|
5
|
-
join,
|
|
6
|
-
relative,
|
|
7
|
-
resolve,
|
|
8
|
-
} from "node:path";
|
|
1
|
+
import { appendFile, mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, extname, join, resolve } from "node:path";
|
|
9
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
4
|
import { Worker } from "node:worker_threads";
|
|
11
5
|
|
|
@@ -29,7 +23,7 @@ import {
|
|
|
29
23
|
toProjectPath,
|
|
30
24
|
updateIndex,
|
|
31
25
|
withRunLease,
|
|
32
|
-
|
|
26
|
+
workflowRunPath,
|
|
33
27
|
writeJsonAtomic,
|
|
34
28
|
writeRunRecord,
|
|
35
29
|
writeCompiledRunArtifact,
|
|
@@ -43,7 +37,11 @@ import {
|
|
|
43
37
|
workflowBundleFingerprint,
|
|
44
38
|
workflowBundleSpecPath,
|
|
45
39
|
} from "./workflow-source-context-runtime.js";
|
|
46
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
readSimpleJsonPath,
|
|
42
|
+
type WorkflowModelInfo,
|
|
43
|
+
type WorkflowRuntimeDefaults,
|
|
44
|
+
} from "./workflow-runtime.js";
|
|
47
45
|
import {
|
|
48
46
|
dynamicRunDir,
|
|
49
47
|
hashDynamicRequest,
|
|
@@ -77,7 +75,6 @@ import {
|
|
|
77
75
|
isDynamicCompiledTaskPayload,
|
|
78
76
|
normalizeDynamicAgentRequest,
|
|
79
77
|
readDynamicGeneratedTaskResult,
|
|
80
|
-
type DynamicAgentRequest,
|
|
81
78
|
} from "./dynamic-generated-task-runtime.js";
|
|
82
79
|
import {
|
|
83
80
|
optionalEventString,
|
|
@@ -119,10 +116,6 @@ import {
|
|
|
119
116
|
readSupportSources,
|
|
120
117
|
writeArtifactGraphDynamicResult,
|
|
121
118
|
} from "./artifact-graph-runtime.js";
|
|
122
|
-
import {
|
|
123
|
-
isDynamicOutputProfile,
|
|
124
|
-
type DynamicOutputProfile,
|
|
125
|
-
} from "./dynamic-profiles.js";
|
|
126
119
|
import {
|
|
127
120
|
DIRECT_DYNAMIC_RUNTIME_VERSION,
|
|
128
121
|
ensureDirectDynamicRuntimeBundle,
|
|
@@ -131,7 +124,6 @@ import {
|
|
|
131
124
|
type CompiledDynamicWorkflowTask,
|
|
132
125
|
type CompiledTask,
|
|
133
126
|
type CompiledWorkflow,
|
|
134
|
-
type ThinkingLevel,
|
|
135
127
|
WORKFLOW_RUN_TYPE,
|
|
136
128
|
type WorkflowIndexRecord,
|
|
137
129
|
type WorkflowRunRecord,
|
|
@@ -154,10 +146,13 @@ const DYNAMIC_CONTROLLER_ENGINE_CAPABILITIES = Object.freeze({
|
|
|
154
146
|
const DYNAMIC_CONTROLLER_ENGINE_INTEGRITY_ERROR_MESSAGE =
|
|
155
147
|
"incompatible or stale pi-workflow engine: dynamic controller context is missing runDecisionLoop (rebuild dist / reload workflow engine)";
|
|
156
148
|
const supervisorTimers = new Map<string, ReturnType<typeof setInterval>>();
|
|
149
|
+
const supervisorRunMtimes = new Map<string, number>();
|
|
157
150
|
|
|
158
151
|
export interface WorkflowRunOptions {
|
|
159
152
|
task?: string;
|
|
160
|
-
|
|
153
|
+
runtimeOverrides?: WorkflowRuntimeDefaults;
|
|
154
|
+
runtimeDefaults?: WorkflowRuntimeDefaults;
|
|
155
|
+
availableModels?: WorkflowModelInfo[];
|
|
161
156
|
dynamicUi?: DynamicWorkflowUi;
|
|
162
157
|
runId?: string;
|
|
163
158
|
parentRunId?: string;
|
|
@@ -165,6 +160,7 @@ export interface WorkflowRunOptions {
|
|
|
165
160
|
|
|
166
161
|
interface WorkflowScheduleOptions {
|
|
167
162
|
dynamicUi?: DynamicWorkflowUi;
|
|
163
|
+
availableModels?: WorkflowModelInfo[];
|
|
168
164
|
}
|
|
169
165
|
|
|
170
166
|
export async function runWorkflowSpec(
|
|
@@ -209,7 +205,9 @@ async function runLoadedWorkflowSpec(
|
|
|
209
205
|
cwd,
|
|
210
206
|
specPath,
|
|
211
207
|
task: options.task,
|
|
208
|
+
runtimeOverrides: options.runtimeOverrides,
|
|
212
209
|
runtimeDefaults: options.runtimeDefaults,
|
|
210
|
+
availableModels: options.availableModels,
|
|
213
211
|
});
|
|
214
212
|
|
|
215
213
|
const { run } = await createRunRecord(cwd, compiled, specPath, {
|
|
@@ -223,12 +221,15 @@ async function runLoadedWorkflowSpec(
|
|
|
223
221
|
await writeRunRecord(cwd, run);
|
|
224
222
|
});
|
|
225
223
|
|
|
224
|
+
const scheduleOptions = {
|
|
225
|
+
dynamicUi: options.dynamicUi,
|
|
226
|
+
availableModels: options.availableModels,
|
|
227
|
+
};
|
|
226
228
|
const scheduled =
|
|
227
|
-
(await scheduleRun(cwd, run.runId, compiled,
|
|
228
|
-
|
|
229
|
-
})) ?? (await readRunRecord(cwd, run.runId));
|
|
229
|
+
(await scheduleRun(cwd, run.runId, compiled, scheduleOptions)) ??
|
|
230
|
+
(await readRunRecord(cwd, run.runId));
|
|
230
231
|
if (scheduled.status === "running")
|
|
231
|
-
watchRun(cwd, scheduled.runId,
|
|
232
|
+
watchRun(cwd, scheduled.runId, scheduleOptions);
|
|
232
233
|
return scheduled;
|
|
233
234
|
}
|
|
234
235
|
|
|
@@ -367,15 +368,27 @@ export function watchRun(
|
|
|
367
368
|
|
|
368
369
|
const timer = setInterval(() => {
|
|
369
370
|
void (async () => {
|
|
371
|
+
const previousMtime = supervisorRunMtimes.get(key);
|
|
372
|
+
const beforeMtime = await readRunMtimeMs(cwd, runId);
|
|
370
373
|
const refreshed = await refreshRun(cwd, runId);
|
|
374
|
+
const afterMtime = await readRunMtimeMs(cwd, runId);
|
|
375
|
+
const currentMtime = afterMtime ?? beforeMtime;
|
|
376
|
+
if (currentMtime !== undefined)
|
|
377
|
+
supervisorRunMtimes.set(key, currentMtime);
|
|
378
|
+
|
|
371
379
|
if (refreshed.status === "running") {
|
|
372
|
-
|
|
380
|
+
const unchanged =
|
|
381
|
+
previousMtime !== undefined &&
|
|
382
|
+
currentMtime !== undefined &&
|
|
383
|
+
currentMtime <= previousMtime;
|
|
384
|
+
if (!unchanged) await scheduleRun(cwd, runId, undefined, options);
|
|
373
385
|
return;
|
|
374
386
|
}
|
|
375
387
|
|
|
376
388
|
const existing = supervisorTimers.get(key);
|
|
377
389
|
if (existing) clearInterval(existing);
|
|
378
390
|
supervisorTimers.delete(key);
|
|
391
|
+
supervisorRunMtimes.delete(key);
|
|
379
392
|
})().catch((error) => {
|
|
380
393
|
void recordSupervisorError(cwd, runId, error);
|
|
381
394
|
});
|
|
@@ -385,6 +398,18 @@ export function watchRun(
|
|
|
385
398
|
supervisorTimers.set(key, timer);
|
|
386
399
|
}
|
|
387
400
|
|
|
401
|
+
async function readRunMtimeMs(
|
|
402
|
+
cwd: string,
|
|
403
|
+
runId: string,
|
|
404
|
+
): Promise<number | undefined> {
|
|
405
|
+
try {
|
|
406
|
+
return (await stat(workflowRunPath(cwd, runId))).mtimeMs;
|
|
407
|
+
} catch (error) {
|
|
408
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
388
413
|
export async function scheduleRun(
|
|
389
414
|
cwd: string,
|
|
390
415
|
runId: string,
|
|
@@ -861,7 +886,6 @@ async function extractArtifactGraphForeachItems(
|
|
|
861
886
|
return { items };
|
|
862
887
|
}
|
|
863
888
|
|
|
864
|
-
|
|
865
889
|
async function launchPendingTaskAt(
|
|
866
890
|
cwd: string,
|
|
867
891
|
run: WorkflowRunRecord,
|
|
@@ -1049,6 +1073,7 @@ async function executeDynamicControllerTask(
|
|
|
1049
1073
|
sources,
|
|
1050
1074
|
dynamic: compiledTask.dynamic,
|
|
1051
1075
|
dynamicUi: options.dynamicUi,
|
|
1076
|
+
availableModels: options.availableModels,
|
|
1052
1077
|
});
|
|
1053
1078
|
await assertDynamicGeneratedTasksSettled({
|
|
1054
1079
|
cwd,
|
|
@@ -1058,6 +1083,7 @@ async function executeDynamicControllerTask(
|
|
|
1058
1083
|
controllerTask: task,
|
|
1059
1084
|
controllerCompiledTask: compiledTask,
|
|
1060
1085
|
dynamic: compiledTask.dynamic,
|
|
1086
|
+
availableModels: options.availableModels,
|
|
1061
1087
|
});
|
|
1062
1088
|
await recordActiveRuntime();
|
|
1063
1089
|
const unrunBranchBlockers = await dynamicUnrunBranchBlockers(
|
|
@@ -1190,6 +1216,7 @@ async function runDynamicControllerWorker(input: {
|
|
|
1190
1216
|
sources: Record<string, unknown>;
|
|
1191
1217
|
dynamic: CompiledDynamicWorkflowTask;
|
|
1192
1218
|
dynamicUi?: DynamicWorkflowUi;
|
|
1219
|
+
availableModels?: WorkflowModelInfo[];
|
|
1193
1220
|
}): Promise<unknown> {
|
|
1194
1221
|
const resolved = await resolveWorkflowHelperRef(
|
|
1195
1222
|
input.dynamic.uses,
|
|
@@ -1801,7 +1828,6 @@ function isDynamicReplayInvariantError(error: unknown): boolean {
|
|
|
1801
1828
|
);
|
|
1802
1829
|
}
|
|
1803
1830
|
|
|
1804
|
-
|
|
1805
1831
|
function requiredDynamicString(
|
|
1806
1832
|
value: unknown,
|
|
1807
1833
|
field: string,
|
|
@@ -1813,65 +1839,6 @@ function requiredDynamicString(
|
|
|
1813
1839
|
return value.trim();
|
|
1814
1840
|
}
|
|
1815
1841
|
|
|
1816
|
-
function optionalDynamicString(
|
|
1817
|
-
value: unknown,
|
|
1818
|
-
field: string,
|
|
1819
|
-
): string | undefined {
|
|
1820
|
-
if (value === undefined) return undefined;
|
|
1821
|
-
return requiredDynamicString(value, field);
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
function optionalDynamicStringArray(
|
|
1825
|
-
value: unknown,
|
|
1826
|
-
field: string,
|
|
1827
|
-
): string[] | undefined {
|
|
1828
|
-
if (value === undefined) return undefined;
|
|
1829
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
1830
|
-
throw new Error(`ctx.agent() ${field} must be an array of strings`);
|
|
1831
|
-
}
|
|
1832
|
-
return value.map((item) => item.trim()).filter(Boolean);
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
function isPlainDynamicRecord(
|
|
1836
|
-
value: unknown,
|
|
1837
|
-
): value is Record<string, unknown> {
|
|
1838
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
function optionalDynamicPositiveInteger(
|
|
1842
|
-
value: unknown,
|
|
1843
|
-
field: string,
|
|
1844
|
-
): number | undefined {
|
|
1845
|
-
if (value === undefined) return undefined;
|
|
1846
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
1847
|
-
throw new Error(`ctx.agent() ${field} must be a positive integer`);
|
|
1848
|
-
}
|
|
1849
|
-
return value;
|
|
1850
|
-
}
|
|
1851
|
-
|
|
1852
|
-
function requiredDynamicOutputProfile(
|
|
1853
|
-
value: unknown,
|
|
1854
|
-
field: string,
|
|
1855
|
-
api: string,
|
|
1856
|
-
): DynamicOutputProfile {
|
|
1857
|
-
const profile = requiredDynamicString(value, field, api);
|
|
1858
|
-
if (!isDynamicOutputProfile(profile)) {
|
|
1859
|
-
throw new Error(`${api} ${field} has an unsupported output profile`);
|
|
1860
|
-
}
|
|
1861
|
-
return profile;
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
|
-
function requiredDynamicNonNegativeInteger(
|
|
1865
|
-
value: unknown,
|
|
1866
|
-
field: string,
|
|
1867
|
-
api: string,
|
|
1868
|
-
): number {
|
|
1869
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
1870
|
-
throw new Error(`${api} ${field} must be a non-negative integer`);
|
|
1871
|
-
}
|
|
1872
|
-
return value;
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
1842
|
function requiredDynamicPositiveInteger(
|
|
1876
1843
|
value: unknown,
|
|
1877
1844
|
field: string,
|
|
@@ -1883,17 +1850,6 @@ function requiredDynamicPositiveInteger(
|
|
|
1883
1850
|
return value;
|
|
1884
1851
|
}
|
|
1885
1852
|
|
|
1886
|
-
function optionalDynamicStringField(value: unknown): string | undefined {
|
|
1887
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
function optionalDynamicOutputProfile(
|
|
1891
|
-
value: unknown,
|
|
1892
|
-
): DynamicOutputProfile | undefined {
|
|
1893
|
-
if (value === undefined) return undefined;
|
|
1894
|
-
return requiredDynamicOutputProfile(value, "outputProfile", "ctx.agent()");
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
1853
|
async function currentDynamicBudgetRemaining(input: {
|
|
1898
1854
|
cwd: string;
|
|
1899
1855
|
run: WorkflowRunRecord;
|
|
@@ -2266,6 +2222,7 @@ async function assertDynamicGeneratedTasksSettled(input: {
|
|
|
2266
2222
|
controllerTask: WorkflowTaskRunRecord;
|
|
2267
2223
|
controllerCompiledTask: CompiledTask;
|
|
2268
2224
|
dynamic: CompiledDynamicWorkflowTask;
|
|
2225
|
+
availableModels?: WorkflowModelInfo[];
|
|
2269
2226
|
}): Promise<void> {
|
|
2270
2227
|
const state = await readOrRebuildDynamicState(input.cwd, input.run.runId);
|
|
2271
2228
|
const generatedTaskIds =
|
|
@@ -2292,6 +2249,7 @@ async function repairMissingDynamicGeneratedTask(
|
|
|
2292
2249
|
controllerTask: WorkflowTaskRunRecord;
|
|
2293
2250
|
controllerCompiledTask: CompiledTask;
|
|
2294
2251
|
dynamic: CompiledDynamicWorkflowTask;
|
|
2252
|
+
availableModels?: WorkflowModelInfo[];
|
|
2295
2253
|
},
|
|
2296
2254
|
specId: string,
|
|
2297
2255
|
): Promise<WorkflowTaskRunRecord> {
|
|
@@ -2328,6 +2286,7 @@ async function repairMissingDynamicGeneratedTask(
|
|
|
2328
2286
|
branchId: optionalEventString(event.payload.branchId),
|
|
2329
2287
|
request,
|
|
2330
2288
|
dynamic: input.dynamic,
|
|
2289
|
+
availableModels: input.availableModels,
|
|
2331
2290
|
});
|
|
2332
2291
|
assertDynamicGeneratedMetadataMatches(compiledTask, {
|
|
2333
2292
|
controllerSpecId: input.controllerTask.specId,
|
|
@@ -2377,6 +2336,7 @@ async function runDynamicAgentRequest(input: {
|
|
|
2377
2336
|
request: unknown;
|
|
2378
2337
|
generatedTaskIds: string[];
|
|
2379
2338
|
isSettled?: () => boolean;
|
|
2339
|
+
availableModels?: WorkflowModelInfo[];
|
|
2380
2340
|
}): Promise<unknown> {
|
|
2381
2341
|
await assertDynamicRuntimeBudgetAvailable({
|
|
2382
2342
|
cwd: input.cwd,
|
|
@@ -2462,6 +2422,7 @@ async function runDynamicAgentRequest(input: {
|
|
|
2462
2422
|
branchId: generationBranchId,
|
|
2463
2423
|
request: generationRequest,
|
|
2464
2424
|
dynamic: input.dynamic,
|
|
2425
|
+
availableModels: input.availableModels,
|
|
2465
2426
|
});
|
|
2466
2427
|
assertDynamicGeneratedMetadataMatches(compiledTask, {
|
|
2467
2428
|
controllerSpecId: input.controllerTask.specId,
|
|
@@ -2534,9 +2495,6 @@ async function runDynamicAgentRequest(input: {
|
|
|
2534
2495
|
);
|
|
2535
2496
|
}
|
|
2536
2497
|
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
2498
|
interface DynamicControllerOutcome {
|
|
2541
2499
|
taskStatus: "completed" | "blocked" | "failed";
|
|
2542
2500
|
statusDetail: string;
|
|
@@ -2676,7 +2634,6 @@ function dynamicControllerIssueMessage(
|
|
|
2676
2634
|
return `${prefix}: ${first}${suffix}`;
|
|
2677
2635
|
}
|
|
2678
2636
|
|
|
2679
|
-
|
|
2680
2637
|
function applyExistingLoopWorktree(
|
|
2681
2638
|
run: WorkflowRunRecord,
|
|
2682
2639
|
task: WorkflowTaskRunRecord,
|
|
@@ -2724,12 +2681,10 @@ function recordCreatedLoopWorktree(
|
|
|
2724
2681
|
else run.loopWorktrees[index] = record;
|
|
2725
2682
|
}
|
|
2726
2683
|
|
|
2727
|
-
|
|
2728
2684
|
function uniqueStrings(values: readonly string[]): string[] {
|
|
2729
2685
|
return [...new Set(values.filter((value) => value.trim().length > 0))];
|
|
2730
2686
|
}
|
|
2731
2687
|
|
|
2732
|
-
|
|
2733
2688
|
async function readCompiledWorkflow(
|
|
2734
2689
|
cwd: string,
|
|
2735
2690
|
runId: string,
|