@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/README.md
CHANGED
|
@@ -64,6 +64,8 @@ If you want deterministic manual control, use the slash command form:
|
|
|
64
64
|
/workflow run deep-research "Research this repository and summarize the architecture tradeoffs."
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
For opt-in lower-latency runs, add `--thinking low`; defaults remain conservative pending holdout evidence. See [`docs/usage.md`](./docs/usage.md).
|
|
68
|
+
|
|
67
69
|
For a one-off adaptive workflow that should plan, fan out, and synthesize without choosing a saved workflow, use:
|
|
68
70
|
|
|
69
71
|
```text
|
package/dist/compiler.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ArtifactGraphWorkflowSpec
|
|
2
|
-
import { type WorkflowModelInfo } from "./workflow-runtime.js";
|
|
1
|
+
import { type ArtifactGraphWorkflowSpec } from "./types.js";
|
|
2
|
+
import { type WorkflowModelInfo, type WorkflowRuntimeDefaults } from "./workflow-runtime.js";
|
|
3
3
|
interface CompileOptions {
|
|
4
4
|
cwd: string;
|
|
5
5
|
specPath?: string;
|
|
@@ -7,9 +7,7 @@ interface CompileOptions {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function compileWorkflow(spec: ArtifactGraphWorkflowSpec, options: CompileOptions & {
|
|
9
9
|
task?: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
thinking?: ThinkingLevel;
|
|
13
|
-
};
|
|
10
|
+
runtimeOverrides?: WorkflowRuntimeDefaults;
|
|
11
|
+
runtimeDefaults?: WorkflowRuntimeDefaults;
|
|
14
12
|
}): Promise<any>;
|
|
15
13
|
export {};
|
package/dist/compiler.js
CHANGED
|
@@ -2,9 +2,10 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
3
|
import { loadAgentByName } from "./agents.js";
|
|
4
4
|
import { DYNAMIC_OUTPUT_PROFILES } from "./dynamic-profiles.js";
|
|
5
|
+
import { compileRole } from "./roles.js";
|
|
5
6
|
import { classifyToolCapability, effectiveToolClassification, providersForSelectedTools, resolveToolSelection, TOOL_NAME_PATTERN, toolAllowedByAuthorityCeiling, toolNameForSpec, } from "./tool-metadata.js";
|
|
6
7
|
import { WorkflowValidationError, WORKFLOW_RUN_TYPE, } from "./types.js";
|
|
7
|
-
import { resolveWorkflowRuntime, } from "./workflow-runtime.js";
|
|
8
|
+
import { resolveWorkflowRuntime, selectWorkflowRuntime, } from "./workflow-runtime.js";
|
|
8
9
|
const DELEGATION_TOOLS = new Set([
|
|
9
10
|
"skill_test_subagent",
|
|
10
11
|
"workflow",
|
|
@@ -413,6 +414,17 @@ async function collectForeachPathWarnings(stages, specDir) {
|
|
|
413
414
|
}
|
|
414
415
|
return warnings;
|
|
415
416
|
}
|
|
417
|
+
function runtimeSettings(value) {
|
|
418
|
+
if (!isPlainRecord(value))
|
|
419
|
+
return undefined;
|
|
420
|
+
const model = typeof value.model === "string" && value.model.trim()
|
|
421
|
+
? value.model.trim()
|
|
422
|
+
: undefined;
|
|
423
|
+
const thinking = typeof value.thinking === "string" && value.thinking.trim()
|
|
424
|
+
? value.thinking.trim()
|
|
425
|
+
: undefined;
|
|
426
|
+
return model || thinking ? { model, thinking } : undefined;
|
|
427
|
+
}
|
|
416
428
|
async function compileArtifactGraphPlan(spec, options) {
|
|
417
429
|
const stages = spec.stages;
|
|
418
430
|
if (!Array.isArray(stages)) {
|
|
@@ -431,14 +443,11 @@ async function compileArtifactGraphPlan(spec, options) {
|
|
|
431
443
|
return defaultAgent;
|
|
432
444
|
};
|
|
433
445
|
const roleEntries = Object.entries(spec.roles ?? {});
|
|
434
|
-
const roles = roleEntries.map(([name, role]) =>
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
truncated: false,
|
|
440
|
-
includedSections: [],
|
|
441
|
-
excludedSections: [],
|
|
446
|
+
const roles = await Promise.all(roleEntries.map(async ([name, role]) => {
|
|
447
|
+
const sourceAgent = role.fromAgent
|
|
448
|
+
? await loadWorkflowAgent(role.fromAgent, options.cwd, agentCache, `$.roles.${name}.fromAgent`)
|
|
449
|
+
: undefined;
|
|
450
|
+
return compileRole(name, role, sourceAgent);
|
|
442
451
|
}));
|
|
443
452
|
const roleText = roles.length
|
|
444
453
|
? `# Role Context\n\n${roles.map((r) => `## Role: ${r.name}\n${r.content}`).join("\n\n")}`
|
|
@@ -450,8 +459,9 @@ async function compileArtifactGraphPlan(spec, options) {
|
|
|
450
459
|
Object.keys(workflowInput).length > 0
|
|
451
460
|
? `# Workflow Input\n\n${JSON.stringify(workflowInput, null, 2)}`
|
|
452
461
|
: "";
|
|
453
|
-
const
|
|
454
|
-
const
|
|
462
|
+
const runtimeOverrides = options.runtimeOverrides;
|
|
463
|
+
const runtimeDefaults = options.runtimeDefaults;
|
|
464
|
+
const specRuntimeDefaults = runtimeSettings(spec.defaults);
|
|
455
465
|
const tasks = [];
|
|
456
466
|
const stageRecords = [];
|
|
457
467
|
const issues = [];
|
|
@@ -475,17 +485,26 @@ async function compileArtifactGraphPlan(spec, options) {
|
|
|
475
485
|
: `$.artifactGraph.stages.${jsonKey(stage.id)}.dynamic`;
|
|
476
486
|
validateDelegationBoundary(rawDynamicToolSelection.tools, issues, dynamicToolPath);
|
|
477
487
|
const dynamicToolSelection = filterToolSelection(rawDynamicToolSelection);
|
|
478
|
-
const
|
|
479
|
-
const resolvedDynamicRuntime = await resolveWorkflowRuntime(
|
|
488
|
+
const requestedRuntime = selectWorkflowRuntime(runtimeOverrides, runtimeSettings(stage), runtimeDefaults, specRuntimeDefaults);
|
|
489
|
+
const resolvedDynamicRuntime = await resolveWorkflowRuntime(requestedRuntime, {
|
|
480
490
|
taskKey: key,
|
|
481
491
|
stageId: stage.id,
|
|
482
492
|
taskId,
|
|
483
493
|
agent: "dynamic",
|
|
484
494
|
}, { availableModels: options.availableModels });
|
|
495
|
+
const dynamicTask = buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, options.cwd, specDir, workflowInputText, options.task, resolvedDynamicRuntime, {
|
|
496
|
+
runtimeOverrides,
|
|
497
|
+
runtimeDefaults,
|
|
498
|
+
specRuntimeDefaults,
|
|
499
|
+
stageRuntime: runtimeSettings(stage),
|
|
500
|
+
}, overrides);
|
|
485
501
|
dynamicTask.runtime = {
|
|
486
502
|
...dynamicTask.runtime,
|
|
487
503
|
...resolvedDynamicRuntime,
|
|
488
504
|
};
|
|
505
|
+
if (options.availableModels?.length) {
|
|
506
|
+
dynamicTask.dynamic.availableModels = options.availableModels;
|
|
507
|
+
}
|
|
489
508
|
if (dynamicToolSelection.tools || dynamicToolSelection.toolProviders) {
|
|
490
509
|
dynamicTask.runtime = {
|
|
491
510
|
...dynamicTask.runtime,
|
|
@@ -539,13 +558,7 @@ async function compileArtifactGraphPlan(spec, options) {
|
|
|
539
558
|
validateToolSubset(toolSelection.tools, stageAgent, issues, toolPath);
|
|
540
559
|
validateDelegationBoundary(toolSelection.tools, issues, toolPath);
|
|
541
560
|
const filteredToolSelection = filterToolSelection(toolSelection);
|
|
542
|
-
|
|
543
|
-
const requestedRuntime = {
|
|
544
|
-
model: options.runtimeDefaults?.model ?? stage.model ?? spec.defaults?.model,
|
|
545
|
-
thinking: options.runtimeDefaults?.thinking ??
|
|
546
|
-
stage.thinking ??
|
|
547
|
-
spec.defaults?.thinking,
|
|
548
|
-
};
|
|
561
|
+
const requestedRuntime = selectWorkflowRuntime(runtimeOverrides, runtimeSettings(stage), runtimeDefaults, specRuntimeDefaults);
|
|
549
562
|
const resolvedRuntime = await resolveWorkflowRuntime(requestedRuntime, {
|
|
550
563
|
taskKey: key,
|
|
551
564
|
stageId: stage.id,
|
|
@@ -825,11 +838,33 @@ async function compileArtifactGraphPlan(spec, options) {
|
|
|
825
838
|
tasks,
|
|
826
839
|
warnings,
|
|
827
840
|
budget: {
|
|
828
|
-
models:
|
|
841
|
+
models: budgetModelRows(tasks),
|
|
829
842
|
unratedModels: [],
|
|
830
843
|
},
|
|
831
844
|
};
|
|
832
845
|
}
|
|
846
|
+
function budgetModelRows(tasks) {
|
|
847
|
+
const models = new Set();
|
|
848
|
+
for (const task of tasks) {
|
|
849
|
+
if (typeof task?.runtime?.model === "string" && task.runtime.model.trim()) {
|
|
850
|
+
models.add(task.runtime.model.trim());
|
|
851
|
+
}
|
|
852
|
+
const loop = task?.dynamic?.decisionLoop;
|
|
853
|
+
if (!loop || typeof loop !== "object")
|
|
854
|
+
continue;
|
|
855
|
+
for (const profile of [
|
|
856
|
+
loop.planner,
|
|
857
|
+
loop.workerDefaults,
|
|
858
|
+
loop.verifier,
|
|
859
|
+
loop.synthesis,
|
|
860
|
+
]) {
|
|
861
|
+
if (typeof profile?.model === "string" && profile.model.trim()) {
|
|
862
|
+
models.add(profile.model.trim());
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return [...models].sort().map((model) => ({ model }));
|
|
867
|
+
}
|
|
833
868
|
function isSupportStage(stage) {
|
|
834
869
|
return stage?.support !== undefined && stage?.type === undefined;
|
|
835
870
|
}
|
|
@@ -889,7 +924,7 @@ function buildSupportTask(stage, taskId, key, prompt, dependencyKeys, cwd, workf
|
|
|
889
924
|
...overrides,
|
|
890
925
|
};
|
|
891
926
|
}
|
|
892
|
-
function buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, cwd, specDir, workflowInputText, runtimeTask,
|
|
927
|
+
function buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, cwd, specDir, workflowInputText, runtimeTask, controllerRuntime, runtimePriority, overrides) {
|
|
893
928
|
const dynamic = stage.dynamic ?? {};
|
|
894
929
|
const uses = String(dynamic.uses);
|
|
895
930
|
const normalizedPrompt = String(prompt ?? "").replace(/\$\{item\}/g, "the relevant item from the dependency context");
|
|
@@ -942,7 +977,7 @@ function buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, cwd, specD
|
|
|
942
977
|
usesPath: resolve(specDir, String(workflow.uses)),
|
|
943
978
|
};
|
|
944
979
|
}
|
|
945
|
-
const decisionLoop = compileDynamicDecisionLoop(dynamic.decisionLoop,
|
|
980
|
+
const decisionLoop = compileDynamicDecisionLoop(dynamic.decisionLoop, runtimePriority);
|
|
946
981
|
return {
|
|
947
982
|
key,
|
|
948
983
|
id: key,
|
|
@@ -960,8 +995,7 @@ function buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, cwd, specD
|
|
|
960
995
|
explicitWorktreePolicy: false,
|
|
961
996
|
runtime: {
|
|
962
997
|
approvalMode: "non-interactive",
|
|
963
|
-
|
|
964
|
-
thinking: defaultThinking,
|
|
998
|
+
...controllerRuntime,
|
|
965
999
|
maxRuntimeMs: dynamic.budget?.maxRuntimeMs ?? DEFAULT_DYNAMIC_MAX_RUNTIME_MS,
|
|
966
1000
|
},
|
|
967
1001
|
safety: {
|
|
@@ -999,21 +1033,24 @@ function buildDynamicTask(stage, taskId, key, prompt, dependencyKeys, cwd, specD
|
|
|
999
1033
|
helpers,
|
|
1000
1034
|
workflows,
|
|
1001
1035
|
...(decisionLoop ? { decisionLoop } : {}),
|
|
1036
|
+
...(runtimePriority.runtimeOverrides
|
|
1037
|
+
? { runtimeOverrides: runtimePriority.runtimeOverrides }
|
|
1038
|
+
: {}),
|
|
1002
1039
|
},
|
|
1003
1040
|
...overrides,
|
|
1004
1041
|
};
|
|
1005
1042
|
}
|
|
1006
|
-
function compileDynamicDecisionLoop(value,
|
|
1043
|
+
function compileDynamicDecisionLoop(value, runtimePriority) {
|
|
1007
1044
|
if (!isPlainRecord(value))
|
|
1008
1045
|
return undefined;
|
|
1009
1046
|
const allowedToolSelection = filterToolSelection(resolveToolSelection([Array.isArray(value.allowedTools) ? value.allowedTools : undefined], undefined));
|
|
1010
1047
|
const maxFindings = positiveInteger(recordValue(value.stateIndex, "maxFindings"));
|
|
1011
1048
|
const deprecatedRequiredFindingIds = stringArray(recordValue(value.stateIndex, "requiredFindingIds"));
|
|
1012
1049
|
return {
|
|
1013
|
-
planner: compileDynamicDecisionLoopProfile(value.planner,
|
|
1014
|
-
workerDefaults: compileDynamicDecisionLoopProfile(value.workerDefaults,
|
|
1015
|
-
verifier: compileDynamicDecisionLoopProfile(value.verifier,
|
|
1016
|
-
synthesis: compileDynamicDecisionLoopProfile(value.synthesis,
|
|
1050
|
+
planner: compileDynamicDecisionLoopProfile(value.planner, runtimePriority),
|
|
1051
|
+
workerDefaults: compileDynamicDecisionLoopProfile(value.workerDefaults, runtimePriority),
|
|
1052
|
+
verifier: compileDynamicDecisionLoopProfile(value.verifier, runtimePriority),
|
|
1053
|
+
synthesis: compileDynamicDecisionLoopProfile(value.synthesis, runtimePriority),
|
|
1017
1054
|
allowedAgents: stringArray(value.allowedAgents),
|
|
1018
1055
|
...(allowedToolSelection.tools
|
|
1019
1056
|
? { allowedTools: allowedToolSelection.tools }
|
|
@@ -1054,22 +1091,16 @@ function compileDynamicDecisionLoop(value, defaultModel, defaultThinking) {
|
|
|
1054
1091
|
},
|
|
1055
1092
|
};
|
|
1056
1093
|
}
|
|
1057
|
-
function compileDynamicDecisionLoopProfile(value,
|
|
1094
|
+
function compileDynamicDecisionLoopProfile(value, runtimePriority) {
|
|
1058
1095
|
if (!isPlainRecord(value))
|
|
1059
1096
|
return undefined;
|
|
1060
1097
|
const toolSelection = filterToolSelection(resolveToolSelection([Array.isArray(value.tools) ? value.tools : undefined], undefined));
|
|
1061
|
-
const
|
|
1062
|
-
? value.model.trim()
|
|
1063
|
-
: defaultModel;
|
|
1064
|
-
const thinking = typeof value.thinking === "string" && value.thinking.trim()
|
|
1065
|
-
? value.thinking.trim()
|
|
1066
|
-
: defaultThinking;
|
|
1098
|
+
const runtime = selectWorkflowRuntime(runtimePriority.runtimeOverrides, runtimeSettings(value), runtimePriority.stageRuntime, runtimePriority.runtimeDefaults, runtimePriority.specRuntimeDefaults);
|
|
1067
1099
|
return {
|
|
1068
1100
|
...(typeof value.agent === "string" && value.agent.trim()
|
|
1069
1101
|
? { agent: value.agent.trim() }
|
|
1070
1102
|
: {}),
|
|
1071
|
-
...
|
|
1072
|
-
...(thinking ? { thinking } : {}),
|
|
1103
|
+
...runtime,
|
|
1073
1104
|
...(toolSelection.tools ? { tools: toolSelection.tools } : {}),
|
|
1074
1105
|
...(toolSelection.toolProviders
|
|
1075
1106
|
? { toolProviders: toolSelection.toolProviders }
|
|
@@ -97,7 +97,6 @@ export interface DynamicDecisionArtifactWriteResult {
|
|
|
97
97
|
hash?: string;
|
|
98
98
|
}
|
|
99
99
|
export declare function validateDynamicDecision(value: unknown, context?: DynamicDecisionValidationContext): DynamicDecisionValidationResult;
|
|
100
|
-
export declare function assertValidDynamicDecision(value: unknown, context?: DynamicDecisionValidationContext): NormalizedDynamicDecision;
|
|
101
100
|
export declare function hashDynamicDecision(value: unknown): string;
|
|
102
101
|
export declare function dynamicLoopSignature(decision: NormalizedDynamicDecision): string;
|
|
103
102
|
export declare function writeDynamicDecisionArtifacts(input: DynamicDecisionArtifactWriteInput): Promise<DynamicDecisionArtifactWriteResult>;
|
package/dist/dynamic-decision.js
CHANGED
|
@@ -121,13 +121,6 @@ export function validateDynamicDecision(value, context = {}) {
|
|
|
121
121
|
hash: hashDynamicDecision(decision),
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
-
export function assertValidDynamicDecision(value, context = {}) {
|
|
125
|
-
const result = validateDynamicDecision(value, context);
|
|
126
|
-
if (!result.ok || !result.decision) {
|
|
127
|
-
throw new Error(`invalid dynamic decision: ${result.errors.join("; ")}`);
|
|
128
|
-
}
|
|
129
|
-
return result.decision;
|
|
130
|
-
}
|
|
131
124
|
export function hashDynamicDecision(value) {
|
|
132
125
|
return createHash("sha256")
|
|
133
126
|
.update(stableStringify(toJsonNormalizedValue(value)))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CompiledDynamicWorkflowTask, CompiledTask, CompiledWorkflow, ThinkingLevel, WorkflowRunRecord, WorkflowTaskRunRecord } from "./types.js";
|
|
2
|
+
import { type WorkflowModelInfo } from "./workflow-runtime.js";
|
|
2
3
|
export interface DynamicArtifactInput {
|
|
3
4
|
kind: "workflow-artifact-ref";
|
|
4
5
|
name: string;
|
|
@@ -41,6 +42,7 @@ export declare function buildDynamicGeneratedCompiledTask(input: {
|
|
|
41
42
|
branchId?: string;
|
|
42
43
|
request: DynamicAgentRequest;
|
|
43
44
|
dynamic: CompiledDynamicWorkflowTask;
|
|
45
|
+
availableModels?: WorkflowModelInfo[];
|
|
44
46
|
}): Promise<CompiledTask>;
|
|
45
47
|
export declare function isDynamicCompiledTaskPayload(value: unknown): value is CompiledTask;
|
|
46
48
|
export declare function assertDynamicGeneratedMetadataMatches(compiledTask: CompiledTask, expected: {
|
|
@@ -6,6 +6,7 @@ import { readOrRebuildDynamicState } from "./dynamic-state.js";
|
|
|
6
6
|
import { sanitizeTaskId } from "./engine-run-graph.js";
|
|
7
7
|
import { fromProjectPath, isTerminalTaskStatus, readJson } from "./store.js";
|
|
8
8
|
import { classifyToolCapability, effectiveToolClassification, providersForSelectedTools, toolAllowedByAuthorityCeiling, } from "./tool-metadata.js";
|
|
9
|
+
import { resolveWorkflowRuntime, selectWorkflowRuntime, } from "./workflow-runtime.js";
|
|
9
10
|
const DYNAMIC_OUTPUT_MAX_DIGEST_CHARS = 1000;
|
|
10
11
|
const DYNAMIC_DELEGATION_TOOLS = new Set([
|
|
11
12
|
"skill_test_subagent",
|
|
@@ -69,6 +70,13 @@ export async function buildDynamicGeneratedCompiledTask(input) {
|
|
|
69
70
|
}
|
|
70
71
|
const toolProviders = executionProfile?.toolProviders ??
|
|
71
72
|
providersForSelectedTools(tools, new Map(Object.entries(input.controllerCompiledTask.runtime.toolProviders ?? {})));
|
|
73
|
+
const selectedRuntime = selectWorkflowRuntime(input.dynamic.runtimeOverrides, runtimeSettings(input.request), runtimeSettings(executionProfile), runtimeSettings(input.controllerCompiledTask.runtime), runtimeSettings(agentDefinition));
|
|
74
|
+
const resolvedRuntime = await resolveWorkflowRuntime(selectedRuntime, {
|
|
75
|
+
taskKey: input.generatedSpecId,
|
|
76
|
+
stageId: input.controllerStageId,
|
|
77
|
+
taskId: input.request.id,
|
|
78
|
+
agent: requestedAgent,
|
|
79
|
+
}, { availableModels: input.availableModels ?? input.dynamic.availableModels });
|
|
72
80
|
const unknownTools = (tools ?? []).filter((tool) => effectiveToolClassification(tool, toolProviders) === undefined);
|
|
73
81
|
if (unknownTools.length > 0) {
|
|
74
82
|
throw new Error(`dynamic agent requested tools without trusted classification metadata: ${unknownTools.join(", ")}`);
|
|
@@ -135,14 +143,7 @@ export async function buildDynamicGeneratedCompiledTask(input) {
|
|
|
135
143
|
explicitWorktreePolicy: requiresWorktree,
|
|
136
144
|
runtime: {
|
|
137
145
|
approvalMode: "non-interactive",
|
|
138
|
-
|
|
139
|
-
executionProfile?.model ??
|
|
140
|
-
input.controllerCompiledTask.runtime.model ??
|
|
141
|
-
agentDefinition.model,
|
|
142
|
-
thinking: input.request.thinking ??
|
|
143
|
-
executionProfile?.thinking ??
|
|
144
|
-
input.controllerCompiledTask.runtime.thinking ??
|
|
145
|
-
agentDefinition.thinking,
|
|
146
|
+
...resolvedRuntime,
|
|
146
147
|
tools,
|
|
147
148
|
...(toolProviders ? { toolProviders } : {}),
|
|
148
149
|
maxRuntimeMs: input.request.maxRuntimeMs ??
|
|
@@ -461,6 +462,18 @@ function requiredDynamicString(value, field, api = "ctx.agent()") {
|
|
|
461
462
|
}
|
|
462
463
|
return value.trim();
|
|
463
464
|
}
|
|
465
|
+
function runtimeSettings(value) {
|
|
466
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
467
|
+
return undefined;
|
|
468
|
+
const record = value;
|
|
469
|
+
const model = typeof record.model === "string" && record.model.trim()
|
|
470
|
+
? record.model.trim()
|
|
471
|
+
: undefined;
|
|
472
|
+
const thinking = typeof record.thinking === "string" && record.thinking.trim()
|
|
473
|
+
? record.thinking.trim()
|
|
474
|
+
: undefined;
|
|
475
|
+
return model || thinking ? { model, thinking } : undefined;
|
|
476
|
+
}
|
|
464
477
|
function optionalDynamicString(value, field) {
|
|
465
478
|
if (value === undefined)
|
|
466
479
|
return undefined;
|
|
@@ -5,4 +5,3 @@ export declare const DYNAMIC_TERMINAL_OUTPUT_PROFILES: readonly ["synthesis_v1"]
|
|
|
5
5
|
export declare function isDynamicOutputProfile(value: unknown): value is DynamicOutputProfile;
|
|
6
6
|
export declare function isExtractableDynamicOutputProfile(value: unknown): value is (typeof DYNAMIC_EXTRACTABLE_OUTPUT_PROFILES)[number];
|
|
7
7
|
export declare function isTerminalDynamicOutputProfile(value: unknown): value is (typeof DYNAMIC_TERMINAL_OUTPUT_PROFILES)[number];
|
|
8
|
-
export declare function dynamicOutputProfileValues(): string[];
|
package/dist/dynamic-profiles.js
CHANGED
|
@@ -26,6 +26,3 @@ export function isExtractableDynamicOutputProfile(value) {
|
|
|
26
26
|
export function isTerminalDynamicOutputProfile(value) {
|
|
27
27
|
return typeof value === "string" && TERMINAL_OUTPUT_PROFILE_SET.has(value);
|
|
28
28
|
}
|
|
29
|
-
export function dynamicOutputProfileValues() {
|
|
30
|
-
return [...DYNAMIC_OUTPUT_PROFILES];
|
|
31
|
-
}
|
|
@@ -2,6 +2,7 @@ import type { CompiledTask, CompiledWorkflow, WorkflowRunRecord, WorkflowTaskRun
|
|
|
2
2
|
export declare function reconcileLoopTaskRecordsInMemory(cwd: string, run: WorkflowRunRecord, compiledFlow: CompiledWorkflow, loopIds: Set<string>): boolean;
|
|
3
3
|
export declare function recoverStaleRunningDynamicControllers(run: WorkflowRunRecord, compiledFlow: CompiledWorkflow): boolean;
|
|
4
4
|
export declare function reconcileDynamicGeneratedRunRecords(cwd: string, run: WorkflowRunRecord, compiledFlow: CompiledWorkflow): boolean;
|
|
5
|
+
export declare function reconcileForeachGeneratedRunRecords(cwd: string, run: WorkflowRunRecord, compiledFlow: CompiledWorkflow): boolean;
|
|
5
6
|
export declare function assertRunTaskPositionalAlignment(run: WorkflowRunRecord, compiledFlow: CompiledWorkflow): void;
|
|
6
7
|
export declare function assertLoopTaskPositionalAlignment(run: WorkflowRunRecord, compiledFlow: CompiledWorkflow, loopIds?: Set<string>): void;
|
|
7
8
|
export declare function upsertCompiledLoopTasksAtInsertion(compiledFlow: CompiledWorkflow, loopId: string, placeholderIndex: number, tasks: CompiledTask[]): void;
|
package/dist/engine-run-graph.js
CHANGED
|
@@ -92,6 +92,107 @@ export function reconcileDynamicGeneratedRunRecords(cwd, run, compiledFlow) {
|
|
|
92
92
|
}
|
|
93
93
|
return changed;
|
|
94
94
|
}
|
|
95
|
+
export function reconcileForeachGeneratedRunRecords(cwd, run, compiledFlow) {
|
|
96
|
+
let changed = false;
|
|
97
|
+
const compiledSpecIds = new Set(compiledFlow.tasks.map((task) => compiledTaskSpecId(task)));
|
|
98
|
+
const placeholderToGeneratedSpecIds = new Map();
|
|
99
|
+
for (const compiledTask of compiledFlow.tasks) {
|
|
100
|
+
const specId = compiledTaskSpecId(compiledTask);
|
|
101
|
+
const placeholderSpecId = foreachGeneratedPlaceholderSpecId(compiledTask, compiledFlow, specId);
|
|
102
|
+
if (!placeholderSpecId)
|
|
103
|
+
continue;
|
|
104
|
+
if (compiledTask.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
|
|
105
|
+
compiledTask.foreachGenerated = { placeholderSpecId };
|
|
106
|
+
changed = true;
|
|
107
|
+
}
|
|
108
|
+
const generated = placeholderToGeneratedSpecIds.get(placeholderSpecId) ?? [];
|
|
109
|
+
generated.push(specId);
|
|
110
|
+
placeholderToGeneratedSpecIds.set(placeholderSpecId, generated);
|
|
111
|
+
}
|
|
112
|
+
if (placeholderToGeneratedSpecIds.size === 0)
|
|
113
|
+
return changed;
|
|
114
|
+
const filteredRunTasks = [];
|
|
115
|
+
const seenGeneratedSpecIds = new Set();
|
|
116
|
+
for (const task of run.tasks) {
|
|
117
|
+
const generatedSpecIds = placeholderToGeneratedSpecIds.get(task.specId);
|
|
118
|
+
let placeholderSpecId = foreachGeneratedPlaceholderSpecId(task, compiledFlow, task.specId);
|
|
119
|
+
if (generatedSpecIds && !placeholderSpecId) {
|
|
120
|
+
if (generatedSpecIds.includes(task.specId)) {
|
|
121
|
+
placeholderSpecId = task.specId;
|
|
122
|
+
task.foreachGenerated = { placeholderSpecId };
|
|
123
|
+
changed = true;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
changed = true;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (placeholderSpecId && !compiledSpecIds.has(task.specId)) {
|
|
131
|
+
changed = true;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (placeholderSpecId && seenGeneratedSpecIds.has(task.specId)) {
|
|
135
|
+
changed = true;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (placeholderSpecId) {
|
|
139
|
+
seenGeneratedSpecIds.add(task.specId);
|
|
140
|
+
if (task.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
|
|
141
|
+
task.foreachGenerated = { placeholderSpecId };
|
|
142
|
+
changed = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
filteredRunTasks.push(task);
|
|
146
|
+
}
|
|
147
|
+
const runTaskBySpecId = new Map();
|
|
148
|
+
for (const task of filteredRunTasks) {
|
|
149
|
+
if (!runTaskBySpecId.has(task.specId))
|
|
150
|
+
runTaskBySpecId.set(task.specId, task);
|
|
151
|
+
}
|
|
152
|
+
const reordered = [];
|
|
153
|
+
const usedSpecIds = new Set();
|
|
154
|
+
let nextIndex = nextTaskRecordIndex({ ...run, tasks: filteredRunTasks });
|
|
155
|
+
for (const compiledTask of compiledFlow.tasks) {
|
|
156
|
+
const specId = compiledTaskSpecId(compiledTask);
|
|
157
|
+
const existing = runTaskBySpecId.get(specId);
|
|
158
|
+
if (existing) {
|
|
159
|
+
const placeholderSpecId = compiledTask.foreachGenerated?.placeholderSpecId;
|
|
160
|
+
if (placeholderSpecId &&
|
|
161
|
+
existing.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
|
|
162
|
+
existing.foreachGenerated = { placeholderSpecId };
|
|
163
|
+
changed = true;
|
|
164
|
+
}
|
|
165
|
+
reordered.push(existing);
|
|
166
|
+
usedSpecIds.add(specId);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (!compiledTask.foreachGenerated)
|
|
170
|
+
continue;
|
|
171
|
+
const created = createTaskRunRecord(cwd, run.runId, compiledTask, nextIndex);
|
|
172
|
+
nextIndex += 1;
|
|
173
|
+
reordered.push(created);
|
|
174
|
+
usedSpecIds.add(specId);
|
|
175
|
+
changed = true;
|
|
176
|
+
}
|
|
177
|
+
for (const task of filteredRunTasks) {
|
|
178
|
+
if (!usedSpecIds.has(task.specId))
|
|
179
|
+
reordered.push(task);
|
|
180
|
+
}
|
|
181
|
+
if (!sameTaskRecordOrder(run.tasks, reordered))
|
|
182
|
+
changed = true;
|
|
183
|
+
for (const task of reordered) {
|
|
184
|
+
if (!task.dependsOn)
|
|
185
|
+
continue;
|
|
186
|
+
const replaced = replaceForeachGeneratedDependencies(task.dependsOn, placeholderToGeneratedSpecIds);
|
|
187
|
+
if (!sameStringList(task.dependsOn, replaced)) {
|
|
188
|
+
task.dependsOn = replaced;
|
|
189
|
+
changed = true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (changed)
|
|
193
|
+
run.tasks = reordered;
|
|
194
|
+
return changed;
|
|
195
|
+
}
|
|
95
196
|
export function assertRunTaskPositionalAlignment(run, compiledFlow) {
|
|
96
197
|
const maxLength = Math.max(run.tasks.length, compiledFlow.tasks.length);
|
|
97
198
|
for (let index = 0; index < maxLength; index += 1) {
|
|
@@ -141,6 +242,40 @@ export function compiledTaskSpecId(task) {
|
|
|
141
242
|
const specId = task.specId;
|
|
142
243
|
return typeof specId === "string" && specId.trim() !== "" ? specId : task.id;
|
|
143
244
|
}
|
|
245
|
+
function foreachGeneratedPlaceholderSpecId(task, compiledFlow, specId) {
|
|
246
|
+
const explicit = task.foreachGenerated?.placeholderSpecId;
|
|
247
|
+
if (typeof explicit === "string" && explicit.trim() !== "")
|
|
248
|
+
return explicit;
|
|
249
|
+
if (task.foreach)
|
|
250
|
+
return undefined;
|
|
251
|
+
if (task.kind !== "foreach" || !task.stageId)
|
|
252
|
+
return undefined;
|
|
253
|
+
const placeholderSpecId = foreachPlaceholderSpecId(compiledFlow, task.stageId);
|
|
254
|
+
if (!placeholderSpecId || specId === placeholderSpecId)
|
|
255
|
+
return undefined;
|
|
256
|
+
return placeholderSpecId;
|
|
257
|
+
}
|
|
258
|
+
function foreachPlaceholderSpecId(compiledFlow, stageId) {
|
|
259
|
+
const stage = (compiledFlow.stages ?? []).find((candidate) => candidate?.id === stageId);
|
|
260
|
+
if (stage?.type !== "foreach")
|
|
261
|
+
return undefined;
|
|
262
|
+
return `${stageId}.item`;
|
|
263
|
+
}
|
|
264
|
+
function replaceForeachGeneratedDependencies(dependsOn, placeholderToGeneratedSpecIds) {
|
|
265
|
+
const replaced = [];
|
|
266
|
+
for (const dep of dependsOn) {
|
|
267
|
+
const generatedSpecIds = placeholderToGeneratedSpecIds.get(dep);
|
|
268
|
+
if (generatedSpecIds)
|
|
269
|
+
replaced.push(...generatedSpecIds);
|
|
270
|
+
else
|
|
271
|
+
replaced.push(dep);
|
|
272
|
+
}
|
|
273
|
+
return [...new Set(replaced)];
|
|
274
|
+
}
|
|
275
|
+
function sameStringList(left, right) {
|
|
276
|
+
return (left.length === right.length &&
|
|
277
|
+
left.every((value, index) => value === right[index]));
|
|
278
|
+
}
|
|
144
279
|
function isLoopGeneratedCompiledTask(task, loopIds) {
|
|
145
280
|
return Boolean((task.loopChild?.loopId && loopIds.has(task.loopChild.loopId)) ||
|
|
146
281
|
(task.loopExhausted?.loopId && loopIds.has(task.loopExhausted.loopId)));
|
|
@@ -228,7 +363,7 @@ export function buildForeachGeneratedTasks(template, runtimeTask, items) {
|
|
|
228
363
|
seen.add(taskId);
|
|
229
364
|
const specId = `${template.stageId}.${taskId}`;
|
|
230
365
|
const itemText = formatForeachItem(item);
|
|
231
|
-
const instructions = template.foreach.prompt.replace(/\$\{item\}/g, itemText);
|
|
366
|
+
const instructions = template.foreach.prompt.replace(/\$\{item\}/g, escapeReplacementText(itemText));
|
|
232
367
|
const compiledPrompt = [
|
|
233
368
|
template.foreach.injectRuntimeTask && runtimeTask
|
|
234
369
|
? `# Task\n\n${runtimeTask}`
|
|
@@ -249,6 +384,7 @@ export function buildForeachGeneratedTasks(template, runtimeTask, items) {
|
|
|
249
384
|
compiledPrompt,
|
|
250
385
|
dependsOn: [...(template.dependsOn ?? [])],
|
|
251
386
|
foreach: undefined,
|
|
387
|
+
foreachGenerated: { placeholderSpecId: template.id },
|
|
252
388
|
});
|
|
253
389
|
}
|
|
254
390
|
return { tasks };
|
|
@@ -274,6 +410,9 @@ export function sanitizeTaskId(value) {
|
|
|
274
410
|
function formatForeachItem(item) {
|
|
275
411
|
return typeof item === "string" ? item : JSON.stringify(item);
|
|
276
412
|
}
|
|
413
|
+
function escapeReplacementText(value) {
|
|
414
|
+
return value.replace(/\$/g, "$$$$");
|
|
415
|
+
}
|
|
277
416
|
export function sourceStageIdsForFrom(from) {
|
|
278
417
|
if (Array.isArray(from))
|
|
279
418
|
return from.filter((item) => typeof item === "string");
|
|
@@ -321,7 +460,8 @@ export function markDagDependentsSkipped(run, compiledFlow) {
|
|
|
321
460
|
const status = bySpecId.get(dep)?.status;
|
|
322
461
|
return (status === "failed" ||
|
|
323
462
|
status === "interrupted" ||
|
|
324
|
-
status === "skipped"
|
|
463
|
+
status === "skipped" ||
|
|
464
|
+
status === "blocked");
|
|
325
465
|
});
|
|
326
466
|
if (!failedDep)
|
|
327
467
|
continue;
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { type WorkflowModelInfo } from "./workflow-runtime.js";
|
|
1
|
+
import { type WorkflowModelInfo, type WorkflowRuntimeDefaults } from "./workflow-runtime.js";
|
|
2
2
|
import { type DynamicWorkflowUi } from "./dynamic-controller-policy.js";
|
|
3
|
-
import { type CompiledWorkflow, type
|
|
3
|
+
import { type CompiledWorkflow, type WorkflowRunRecord } from "./types.js";
|
|
4
4
|
export { buildRunSourceContext } from "./workflow-source-context-runtime.js";
|
|
5
5
|
export { evaluateLoopUntilCondition } from "./loop-runtime.js";
|
|
6
6
|
export type { DynamicWorkflowUi } from "./dynamic-controller-policy.js";
|
|
7
7
|
export interface WorkflowRunOptions {
|
|
8
8
|
task?: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
thinking?: ThinkingLevel;
|
|
12
|
-
};
|
|
9
|
+
runtimeOverrides?: WorkflowRuntimeDefaults;
|
|
10
|
+
runtimeDefaults?: WorkflowRuntimeDefaults;
|
|
13
11
|
availableModels?: WorkflowModelInfo[];
|
|
14
12
|
dynamicUi?: DynamicWorkflowUi;
|
|
15
13
|
runId?: string;
|
|
@@ -17,6 +15,7 @@ export interface WorkflowRunOptions {
|
|
|
17
15
|
}
|
|
18
16
|
interface WorkflowScheduleOptions {
|
|
19
17
|
dynamicUi?: DynamicWorkflowUi;
|
|
18
|
+
availableModels?: WorkflowModelInfo[];
|
|
20
19
|
}
|
|
21
20
|
export declare function runWorkflowSpec(specPath: string, cwd: string, options?: WorkflowRunOptions): Promise<WorkflowRunRecord>;
|
|
22
21
|
export declare function runDynamicTask(cwd: string, options?: WorkflowRunOptions): Promise<WorkflowRunRecord>;
|
|
@@ -26,6 +25,11 @@ export interface ResumeRunSummary {
|
|
|
26
25
|
run: WorkflowRunRecord;
|
|
27
26
|
resetTaskIds: string[];
|
|
28
27
|
}
|
|
28
|
+
export interface StopRunSummary {
|
|
29
|
+
run: WorkflowRunRecord;
|
|
30
|
+
interruptedTaskIds: string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function stopRun(cwd: string, runIdOrPrefix: string): Promise<StopRunSummary>;
|
|
29
33
|
export declare function resumeRun(cwd: string, runIdOrPrefix: string, options?: WorkflowScheduleOptions): Promise<ResumeRunSummary>;
|
|
30
34
|
export declare function resumeSupervisors(cwd: string, options?: WorkflowScheduleOptions): Promise<void>;
|
|
31
35
|
export declare function watchRun(cwd: string, runId: string, options?: WorkflowScheduleOptions): void;
|