@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
|
@@ -4,185 +4,308 @@ import { writeFile } from "node:fs/promises";
|
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
appendRunEvent,
|
|
8
|
+
beginRunRecord,
|
|
9
|
+
createAttemptArtifactStore,
|
|
10
|
+
createAttemptId,
|
|
11
|
+
createRunId,
|
|
12
|
+
finishAttemptFromResult,
|
|
13
|
+
updateAttemptProcess,
|
|
14
|
+
type ResultEnvelope,
|
|
15
15
|
} from "../artifacts/index.ts";
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
ExecutionMode,
|
|
18
|
+
ResolveInput,
|
|
19
|
+
ResolvedBackend,
|
|
20
|
+
SubagentTaskInput,
|
|
21
|
+
} from "../core/constants.ts";
|
|
17
22
|
import { resolveBackend } from "../core/resolver.ts";
|
|
18
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
DEFAULT_PARALLEL_CONCURRENCY,
|
|
25
|
+
MAX_PARALLEL_CONCURRENCY,
|
|
26
|
+
MAX_PARALLEL_TASKS,
|
|
27
|
+
SubagentToolAuthorityError,
|
|
28
|
+
type ParallelRunResult,
|
|
29
|
+
} from "./run.ts";
|
|
30
|
+
import { writeRunLocator } from "./run-ref.ts";
|
|
19
31
|
import { readRunResult, waitForRun } from "./status.ts";
|
|
20
32
|
|
|
21
33
|
export interface StartAsyncSubagentRunOptions {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
input: ResolveInput;
|
|
35
|
+
cwd: string;
|
|
36
|
+
backend: ResolvedBackend;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
runId?: string;
|
|
39
|
+
attemptId?: string;
|
|
40
|
+
onComplete?: (
|
|
41
|
+
result: ResultEnvelope,
|
|
42
|
+
mode: ExecutionMode,
|
|
43
|
+
) => number | Promise<number>;
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
function executionMode(input: ResolveInput): ExecutionMode {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
if (input.mode !== undefined) return input.mode;
|
|
48
|
+
if (input.tasks !== undefined) return "parallel";
|
|
49
|
+
return "single";
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
function parallelConcurrency(input: ResolveInput): number {
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
const requested = input.concurrency ?? DEFAULT_PARALLEL_CONCURRENCY;
|
|
54
|
+
return Math.max(1, Math.min(MAX_PARALLEL_CONCURRENCY, requested));
|
|
40
55
|
}
|
|
41
56
|
|
|
42
|
-
function mergeTaskInput(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
function mergeTaskInput(
|
|
58
|
+
parent: ResolveInput,
|
|
59
|
+
task: SubagentTaskInput,
|
|
60
|
+
): ResolveInput {
|
|
61
|
+
return {
|
|
62
|
+
...parent,
|
|
63
|
+
...task,
|
|
64
|
+
tasks: undefined,
|
|
65
|
+
mode: "single",
|
|
66
|
+
workspace: parent.workspace,
|
|
67
|
+
worktree: parent.worktree,
|
|
68
|
+
worktreePolicy: parent.worktreePolicy,
|
|
69
|
+
concurrency: undefined,
|
|
70
|
+
failFast: undefined,
|
|
71
|
+
cancelSiblingsOnFailure: undefined,
|
|
72
|
+
asyncDependency: parent.asyncDependency,
|
|
73
|
+
runsDir: parent.runsDir,
|
|
74
|
+
correlationId: parent.correlationId,
|
|
75
|
+
parentSessionId: parent.parentSessionId,
|
|
76
|
+
};
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
function sandboxEnabled(input: ResolveInput): boolean {
|
|
60
|
-
|
|
80
|
+
return input.sandbox !== undefined && input.sandbox !== null;
|
|
61
81
|
}
|
|
62
82
|
|
|
63
|
-
function armCompletionMonitor(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
function armCompletionMonitor(
|
|
84
|
+
options: StartAsyncSubagentRunOptions & {
|
|
85
|
+
runId: string;
|
|
86
|
+
attemptId: string;
|
|
87
|
+
mode: ExecutionMode;
|
|
88
|
+
store: Awaited<ReturnType<typeof createAttemptArtifactStore>>;
|
|
89
|
+
},
|
|
90
|
+
): void {
|
|
91
|
+
if (options.onComplete === undefined || options.input.onComplete !== "notify")
|
|
92
|
+
return;
|
|
93
|
+
void (async () => {
|
|
94
|
+
const waited = await waitForRun({
|
|
95
|
+
cwd: options.cwd,
|
|
96
|
+
runsDir: options.input.runsDir,
|
|
97
|
+
runId: options.runId,
|
|
98
|
+
attemptId: options.attemptId,
|
|
99
|
+
timeoutMs: options.input.timeoutMs ?? 86_400_000,
|
|
100
|
+
pollIntervalMs: 500,
|
|
101
|
+
});
|
|
102
|
+
if (waited.status !== "completed") return;
|
|
103
|
+
const result = await readRunResult({
|
|
104
|
+
cwd: options.cwd,
|
|
105
|
+
runsDir: options.input.runsDir,
|
|
106
|
+
runId: options.runId,
|
|
107
|
+
attemptId: options.attemptId,
|
|
108
|
+
});
|
|
109
|
+
if (result === null) return;
|
|
110
|
+
const updatesSent = await options.onComplete!(result, options.mode);
|
|
111
|
+
const completed = await options.store.writeResult({
|
|
112
|
+
...result,
|
|
113
|
+
completion: {
|
|
114
|
+
onComplete: options.input.onComplete ?? null,
|
|
115
|
+
notified: true,
|
|
116
|
+
updatesSent,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
await finishAttemptFromResult(
|
|
120
|
+
{
|
|
121
|
+
cwd: options.cwd,
|
|
122
|
+
runsDir: options.input.runsDir,
|
|
123
|
+
runId: options.runId,
|
|
124
|
+
},
|
|
125
|
+
completed,
|
|
126
|
+
);
|
|
127
|
+
})().catch(() => undefined);
|
|
77
128
|
}
|
|
78
129
|
|
|
79
130
|
function workerPath(): string {
|
|
80
|
-
|
|
131
|
+
return join(
|
|
132
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
133
|
+
"../workers/durable-worker.mjs",
|
|
134
|
+
);
|
|
81
135
|
}
|
|
82
136
|
|
|
83
|
-
export async function startAsyncParallelSubagentRuns(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
137
|
+
export async function startAsyncParallelSubagentRuns(
|
|
138
|
+
input: ResolveInput,
|
|
139
|
+
cwd: string,
|
|
140
|
+
signal?: AbortSignal,
|
|
141
|
+
onComplete?: StartAsyncSubagentRunOptions["onComplete"],
|
|
142
|
+
): Promise<ParallelRunResult> {
|
|
143
|
+
if (!input.tasks || input.tasks.length === 0)
|
|
144
|
+
throw new SubagentToolAuthorityError(
|
|
145
|
+
"parallel mode requires a non-empty tasks array.",
|
|
146
|
+
);
|
|
147
|
+
if (input.tasks.length > MAX_PARALLEL_TASKS)
|
|
148
|
+
throw new SubagentToolAuthorityError(
|
|
149
|
+
`too many parallel tasks (${input.tasks.length}); max is ${MAX_PARALLEL_TASKS}.`,
|
|
150
|
+
);
|
|
151
|
+
for (const [index, task] of input.tasks.entries()) {
|
|
152
|
+
if (task.task === undefined)
|
|
153
|
+
throw new SubagentToolAuthorityError(
|
|
154
|
+
`parallel tasks[${index}] requires a non-empty task.`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const concurrency = Math.min(parallelConcurrency(input), input.tasks.length);
|
|
159
|
+
const results: ResultEnvelope[] = new Array(input.tasks.length);
|
|
160
|
+
let nextIndex = 0;
|
|
161
|
+
|
|
162
|
+
async function worker(): Promise<void> {
|
|
163
|
+
while (true) {
|
|
164
|
+
const index = nextIndex;
|
|
165
|
+
nextIndex += 1;
|
|
166
|
+
if (index >= input.tasks!.length) return;
|
|
167
|
+
const taskInput = mergeTaskInput(input, input.tasks![index]);
|
|
168
|
+
const resolved = resolveBackend(taskInput);
|
|
169
|
+
if (resolved.status === "failed")
|
|
170
|
+
throw new SubagentToolAuthorityError(resolved.error);
|
|
171
|
+
results[index] = await startAsyncSubagentRun({
|
|
172
|
+
input: taskInput,
|
|
173
|
+
cwd: taskInput.cwd ?? cwd,
|
|
174
|
+
backend: resolved.backend,
|
|
175
|
+
signal,
|
|
176
|
+
onComplete,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await Promise.all(Array.from({ length: concurrency }, () => worker()));
|
|
182
|
+
return {
|
|
183
|
+
mode: "parallel",
|
|
184
|
+
runIds: results.map((result) => result.runId),
|
|
185
|
+
results,
|
|
186
|
+
concurrency,
|
|
187
|
+
totalTasks: input.tasks.length,
|
|
188
|
+
startedCount: results.length,
|
|
189
|
+
skippedCount: 0,
|
|
190
|
+
failFastTriggered: false,
|
|
191
|
+
};
|
|
108
192
|
}
|
|
109
193
|
|
|
110
|
-
export async function startAsyncSubagentRun(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
194
|
+
export async function startAsyncSubagentRun(
|
|
195
|
+
options: StartAsyncSubagentRunOptions,
|
|
196
|
+
): Promise<ResultEnvelope> {
|
|
197
|
+
const input = options.input;
|
|
198
|
+
const startedAt = new Date();
|
|
199
|
+
const runId = options.runId ?? createRunId(startedAt);
|
|
200
|
+
const attemptId = options.attemptId ?? createAttemptId(startedAt);
|
|
201
|
+
const mode = executionMode(input);
|
|
202
|
+
if (mode === "parallel") {
|
|
203
|
+
throw new SubagentToolAuthorityError(
|
|
204
|
+
"startAsyncSubagentRun handles one run; use startAsyncParallelSubagentRuns for parallel inputs.",
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const dependency = input.asyncDependency ?? "unclassified";
|
|
208
|
+
const store = await createAttemptArtifactStore({
|
|
209
|
+
cwd: options.cwd,
|
|
210
|
+
runId,
|
|
211
|
+
attemptId,
|
|
212
|
+
runsDir: input.runsDir,
|
|
213
|
+
});
|
|
214
|
+
const payloadPath = store.pathFor("worker");
|
|
215
|
+
const payloadText = `${JSON.stringify({ input, cwd: options.cwd, backend: options.backend, runId, attemptId, startedAt: startedAt.toISOString() }, null, 2)}\n`;
|
|
216
|
+
await writeFile(payloadPath, payloadText);
|
|
217
|
+
const workerRef = store.refFor(
|
|
218
|
+
"worker",
|
|
219
|
+
Buffer.byteLength(payloadText, "utf8"),
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const running = await store.writeResult({
|
|
223
|
+
backend: options.backend,
|
|
224
|
+
status: "running",
|
|
225
|
+
failureKind: null,
|
|
226
|
+
cwd: options.cwd,
|
|
227
|
+
startedAt,
|
|
228
|
+
completedAt: null,
|
|
229
|
+
workspace: { mode: "shared", cwd: options.cwd },
|
|
230
|
+
sandbox: { enabled: sandboxEnabled(input) },
|
|
231
|
+
exitCode: null,
|
|
232
|
+
signal: null,
|
|
233
|
+
artifacts: [workerRef],
|
|
234
|
+
correlationId: input.correlationId,
|
|
235
|
+
metadata: { contextLengthExceeded: false },
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
await beginRunRecord({
|
|
239
|
+
cwd: options.cwd,
|
|
240
|
+
runsDir: input.runsDir,
|
|
241
|
+
runId,
|
|
242
|
+
mode,
|
|
243
|
+
backend: options.backend,
|
|
244
|
+
startedAt,
|
|
245
|
+
dependency,
|
|
246
|
+
correlationId: input.correlationId,
|
|
247
|
+
parentSessionId: input.parentSessionId,
|
|
248
|
+
activeAttemptId: attemptId,
|
|
249
|
+
attempts: [
|
|
250
|
+
{
|
|
251
|
+
attemptId,
|
|
252
|
+
status: "running",
|
|
253
|
+
backend: options.backend,
|
|
254
|
+
startedAt: startedAt.toISOString(),
|
|
255
|
+
artifactCwd: options.cwd,
|
|
256
|
+
resultPath: running.artifacts.find(
|
|
257
|
+
(artifact) => artifact.type === "result",
|
|
258
|
+
)?.path,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
});
|
|
262
|
+
await writeRunLocator({
|
|
263
|
+
cwd: options.cwd,
|
|
264
|
+
runsDir: input.runsDir,
|
|
265
|
+
runId,
|
|
266
|
+
parentSessionId: input.parentSessionId,
|
|
267
|
+
correlationId: input.correlationId,
|
|
268
|
+
}).catch(() => undefined);
|
|
269
|
+
await appendRunEvent(
|
|
270
|
+
{ cwd: options.cwd, runsDir: input.runsDir, runId },
|
|
271
|
+
{
|
|
272
|
+
type: "run.started",
|
|
273
|
+
status: "running",
|
|
274
|
+
message: `${mode} durable async run started`,
|
|
275
|
+
data: { dependency, attemptId },
|
|
276
|
+
},
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const workerLogFd = openSync(join(store.attemptDir, "worker.log"), "a");
|
|
280
|
+
let child;
|
|
281
|
+
try {
|
|
282
|
+
child = spawn(process.execPath, [workerPath(), payloadPath], {
|
|
283
|
+
cwd: options.cwd,
|
|
284
|
+
detached: process.platform !== "win32",
|
|
285
|
+
stdio: ["ignore", workerLogFd, workerLogFd],
|
|
286
|
+
});
|
|
287
|
+
} finally {
|
|
288
|
+
closeSync(workerLogFd);
|
|
289
|
+
}
|
|
290
|
+
child.unref();
|
|
291
|
+
|
|
292
|
+
if (child.pid !== undefined) {
|
|
293
|
+
await updateAttemptProcess({
|
|
294
|
+
cwd: options.cwd,
|
|
295
|
+
runsDir: input.runsDir,
|
|
296
|
+
runId,
|
|
297
|
+
attemptId,
|
|
298
|
+
process: {
|
|
299
|
+
pid: child.pid,
|
|
300
|
+
processGroupId: process.platform === "win32" ? undefined : child.pid,
|
|
301
|
+
command: process.execPath,
|
|
302
|
+
workerPid: child.pid,
|
|
303
|
+
workerProcessGroupId:
|
|
304
|
+
process.platform === "win32" ? undefined : child.pid,
|
|
305
|
+
},
|
|
306
|
+
}).catch(() => undefined);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
armCompletionMonitor({ ...options, runId, attemptId, mode, store });
|
|
310
|
+
return running;
|
|
188
311
|
}
|