@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanfw/prompt-orchestration-pipeline",
3
- "version": "0.4.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",
@@ -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
- const runnerPath = path.join(
224
- process.cwd(),
225
- "src",
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
- if (!availablePipelines.length) {
242
- console.warn(
243
- "[Orchestrator] No pipelines registered in config() when spawnRunner invoked"
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
- if (!pipelineSlug) {
257
- console.error("[Orchestrator] Missing pipeline slug in seed", {
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
- seed,
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
- let pipelineConfig;
268
- try {
269
- pipelineConfig = getPipelineConfig(pipelineSlug);
270
- } catch (error) {
271
- console.error("[Orchestrator] Pipeline lookup failed", {
272
- jobId,
273
- pipelineSlug,
274
- availablePipelines,
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
- // Use environment variables with explicit slug propagation
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
- running.set(jobId, child);
306
+ child.on("exit", () => {
307
+ running.delete(jobId);
308
+ });
309
+ child.on("error", () => {
310
+ running.delete(jobId);
311
+ });
299
312
 
300
- child.on("exit", () => {
301
- running.delete(jobId);
302
- });
303
- child.on("error", () => {
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
- // In test mode: return immediately; in real mode you might await readiness
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 };