@ryanfw/prompt-orchestration-pipeline 0.4.0 → 0.5.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/package.json +1 -1
- package/src/core/orchestrator.js +92 -78
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanfw/prompt-orchestration-pipeline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A Prompt-orchestration pipeline (POP) is a framework for building, running, and experimenting with complex chains of LLM tasks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/ui/server.js",
|
package/src/core/orchestrator.js
CHANGED
|
@@ -220,97 +220,111 @@ export async function startOrchestrator(opts) {
|
|
|
220
220
|
* @param {Object} seed - Seed data containing pipeline information
|
|
221
221
|
*/
|
|
222
222
|
function spawnRunner(jobId, dirs, running, spawn, testMode, seed) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
"core",
|
|
227
|
-
"pipeline-runner.js"
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
const configSnapshot = getConfig();
|
|
231
|
-
const availablePipelines = Object.keys(configSnapshot?.pipelines ?? {});
|
|
232
|
-
const pipelineSlug = seed?.pipeline;
|
|
233
|
-
|
|
234
|
-
console.log("[Orchestrator] spawnRunner invoked", {
|
|
235
|
-
jobId,
|
|
236
|
-
pipelineSlug: pipelineSlug ?? null,
|
|
237
|
-
availablePipelines,
|
|
238
|
-
seedKeys: seed ? Object.keys(seed) : null,
|
|
239
|
-
});
|
|
223
|
+
// Use path relative to this file to avoid process.cwd() issues
|
|
224
|
+
const orchestratorDir = path.dirname(new URL(import.meta.url).pathname);
|
|
225
|
+
const runnerPath = path.join(orchestratorDir, "pipeline-runner.js");
|
|
240
226
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} else if (!availablePipelines.includes(pipelineSlug)) {
|
|
246
|
-
console.warn(
|
|
247
|
-
"[Orchestrator] Requested pipeline slug missing from registry snapshot",
|
|
248
|
-
{
|
|
249
|
-
jobId,
|
|
250
|
-
pipelineSlug,
|
|
251
|
-
availablePipelines,
|
|
252
|
-
}
|
|
253
|
-
);
|
|
254
|
-
}
|
|
227
|
+
// Set PO_ROOT for the orchestrator process to match what the runner will use
|
|
228
|
+
const originalPoRoot = process.env.PO_ROOT;
|
|
229
|
+
const poRoot = path.resolve(dirs.dataDir, "..");
|
|
230
|
+
process.env.PO_ROOT = poRoot;
|
|
255
231
|
|
|
256
|
-
|
|
257
|
-
|
|
232
|
+
try {
|
|
233
|
+
const configSnapshot = getConfig();
|
|
234
|
+
const availablePipelines = Object.keys(configSnapshot?.pipelines ?? {});
|
|
235
|
+
const pipelineSlug = seed?.pipeline;
|
|
236
|
+
|
|
237
|
+
console.log("[Orchestrator] spawnRunner invoked", {
|
|
258
238
|
jobId,
|
|
259
|
-
|
|
239
|
+
pipelineSlug: pipelineSlug ?? null,
|
|
260
240
|
availablePipelines,
|
|
241
|
+
seedKeys: seed ? Object.keys(seed) : null,
|
|
261
242
|
});
|
|
262
|
-
throw new Error(
|
|
263
|
-
"Pipeline slug is required in seed data. Include a 'pipeline' field in your seed."
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
243
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
244
|
+
if (!availablePipelines.length) {
|
|
245
|
+
console.warn(
|
|
246
|
+
"[Orchestrator] No pipelines registered in config() when spawnRunner invoked"
|
|
247
|
+
);
|
|
248
|
+
} else if (!availablePipelines.includes(pipelineSlug)) {
|
|
249
|
+
console.warn(
|
|
250
|
+
"[Orchestrator] Requested pipeline slug missing from registry snapshot",
|
|
251
|
+
{
|
|
252
|
+
jobId,
|
|
253
|
+
pipelineSlug,
|
|
254
|
+
availablePipelines,
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!pipelineSlug) {
|
|
260
|
+
console.error("[Orchestrator] Missing pipeline slug in seed", {
|
|
261
|
+
jobId,
|
|
262
|
+
seed,
|
|
263
|
+
availablePipelines,
|
|
264
|
+
});
|
|
265
|
+
throw new Error(
|
|
266
|
+
"Pipeline slug is required in seed data. Include a 'pipeline' field in your seed."
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let pipelineConfig;
|
|
271
|
+
try {
|
|
272
|
+
pipelineConfig = getPipelineConfig(pipelineSlug);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error("[Orchestrator] Pipeline lookup failed", {
|
|
275
|
+
jobId,
|
|
276
|
+
pipelineSlug,
|
|
277
|
+
availablePipelines,
|
|
278
|
+
});
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Use environment variables with explicit slug propagation
|
|
283
|
+
// PO_ROOT should point to the directory containing pipeline-config
|
|
284
|
+
// In our case, it's the parent of pipeline-data directory
|
|
285
|
+
const env = {
|
|
286
|
+
...process.env,
|
|
287
|
+
PO_ROOT: poRoot,
|
|
288
|
+
PO_DATA_DIR: dirs.dataDir,
|
|
289
|
+
PO_PENDING_DIR: dirs.pending,
|
|
290
|
+
PO_CURRENT_DIR: dirs.current,
|
|
291
|
+
PO_COMPLETE_DIR: dirs.complete,
|
|
292
|
+
PO_PIPELINE_SLUG: pipelineSlug,
|
|
293
|
+
// Force mock provider for testing
|
|
294
|
+
PO_DEFAULT_PROVIDER: "mock",
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Always call spawn so tests can capture it
|
|
298
|
+
const child = spawn(process.execPath, [runnerPath, jobId], {
|
|
299
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
300
|
+
env,
|
|
301
|
+
cwd: process.cwd(),
|
|
275
302
|
});
|
|
276
|
-
throw error;
|
|
277
|
-
}
|
|
278
303
|
|
|
279
|
-
|
|
280
|
-
const env = {
|
|
281
|
-
...process.env,
|
|
282
|
-
PO_DATA_DIR: dirs.dataDir,
|
|
283
|
-
PO_PENDING_DIR: dirs.pending,
|
|
284
|
-
PO_CURRENT_DIR: dirs.current,
|
|
285
|
-
PO_COMPLETE_DIR: dirs.complete,
|
|
286
|
-
PO_PIPELINE_SLUG: pipelineSlug,
|
|
287
|
-
// Force mock provider for testing
|
|
288
|
-
PO_DEFAULT_PROVIDER: "mock",
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
// Always call spawn so tests can capture it
|
|
292
|
-
const child = spawn(process.execPath, [runnerPath, jobId], {
|
|
293
|
-
stdio: ["ignore", "inherit", "inherit"],
|
|
294
|
-
env,
|
|
295
|
-
cwd: process.cwd(),
|
|
296
|
-
});
|
|
304
|
+
running.set(jobId, child);
|
|
297
305
|
|
|
298
|
-
|
|
306
|
+
child.on("exit", () => {
|
|
307
|
+
running.delete(jobId);
|
|
308
|
+
});
|
|
309
|
+
child.on("error", () => {
|
|
310
|
+
running.delete(jobId);
|
|
311
|
+
});
|
|
299
312
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
running.delete(jobId);
|
|
305
|
-
});
|
|
313
|
+
// In test mode: return immediately; in real mode you might await readiness
|
|
314
|
+
if (testMode) {
|
|
315
|
+
return child;
|
|
316
|
+
}
|
|
306
317
|
|
|
307
|
-
|
|
308
|
-
if (testMode) {
|
|
318
|
+
// Non-test: we can consider "started" immediately for simplicity
|
|
309
319
|
return child;
|
|
320
|
+
} finally {
|
|
321
|
+
// Restore original PO_ROOT
|
|
322
|
+
if (originalPoRoot) {
|
|
323
|
+
process.env.PO_ROOT = originalPoRoot;
|
|
324
|
+
} else {
|
|
325
|
+
delete process.env.PO_ROOT;
|
|
326
|
+
}
|
|
310
327
|
}
|
|
311
|
-
|
|
312
|
-
// Non-test: we can consider "started" immediately for simplicity
|
|
313
|
-
return child;
|
|
314
328
|
}
|
|
315
329
|
|
|
316
330
|
export default { startOrchestrator };
|