singleton-pipeline 0.4.0-beta.3 → 0.4.0-beta.5

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 CHANGED
@@ -1,4 +1,4 @@
1
- # Singleton Pipeline Builder (v0.4.0-beta.3)
1
+ # Singleton Pipeline Builder (v0.4.0-beta.5)
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/singleton-pipeline/beta.svg)](https://www.npmjs.com/package/singleton-pipeline)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/singleton-pipeline.svg)](https://www.npmjs.com/package/singleton-pipeline)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "singleton-pipeline",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0-beta.5",
4
4
  "description": "Visual pipeline builder for multi-agent AI workflows. Orchestrates Claude Code, Codex, Copilot, and OpenCode under a unified security policy.",
5
5
  "keywords": [
6
6
  "ai",
@@ -53,6 +53,7 @@
53
53
  "chalk": "^5.6.2",
54
54
  "commander": "^12.1.0",
55
55
  "cors": "^2.8.5",
56
+ "cross-spawn": "^7.0.6",
56
57
  "express": "^4.21.2",
57
58
  "fast-glob": "^3.3.2",
58
59
  "figlet": "^1.11.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singleton/cli",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0-beta.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "singleton": "./src/index.js"
@@ -202,7 +202,7 @@ const SINGLETON_RAW = [
202
202
  ];
203
203
 
204
204
  const ART_WIDTH = Math.max(...SINGLETON_RAW.map((l) => l.length));
205
- const APP_VERSION = 'v0.4.0-beta.3';
205
+ const APP_VERSION = 'v0.4.0-beta.5';
206
206
 
207
207
  async function showWelcome(root, shell) {
208
208
  const now = new Date();
@@ -22,7 +22,7 @@ function groupAgentsByProvider(agents) {
22
22
  program
23
23
  .name('singleton')
24
24
  .description('Singleton Pipeline Builder — scan agents and build pipelines')
25
- .version('0.4.0-beta.3');
25
+ .version('0.4.0-beta.5');
26
26
 
27
27
  program
28
28
  .command('scan')
@@ -3,13 +3,6 @@
3
3
  // normalize the common patterns: parsing lines, walking nested events to find
4
4
  // usage/cost, and extracting assistant text from messages with varying schemas.
5
5
 
6
- // On Windows, npm-installed CLI binaries are shipped as .cmd wrappers (claude.cmd,
7
- // copilot.cmd, codex.cmd, opencode.cmd). Node's spawn does not append the extension
8
- // automatically, so we resolve the platform-specific name here.
9
- export function resolveBinary(command) {
10
- return process.platform === 'win32' ? `${command}.cmd` : command;
11
- }
12
-
13
6
  export function safeJsonParse(line) {
14
7
  try {
15
8
  return JSON.parse(line);
@@ -1,5 +1,4 @@
1
- import { spawn } from 'node:child_process';
2
- import { resolveBinary } from './_shared.js';
1
+ import spawn from 'cross-spawn';
3
2
 
4
3
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
5
4
  const ALLOWED_PERMISSION_MODES = new Set(['bypassPermissions']);
@@ -63,7 +62,7 @@ export const claudeRunner = {
63
62
  if (model) args.push('--model', model);
64
63
 
65
64
  const raw = await new Promise((resolve, reject) => {
66
- const child = spawn(resolveBinary('claude'), args, { cwd, stdio: ['pipe', 'pipe', 'pipe'], shell: process.platform === 'win32' });
65
+ const child = spawn('claude', args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
67
66
  let stdout = '';
68
67
  let stderr = '';
69
68
  let timedOut = false;
@@ -1,9 +1,9 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
- import { spawn } from 'node:child_process';
4
+ import spawn from 'cross-spawn';
5
5
  import { discoverCodexProjectInstructions } from './codex-instructions.js';
6
- import { findUsage, resolveBinary, safeJsonParse } from './_shared.js';
6
+ import { findUsage, safeJsonParse } from './_shared.js';
7
7
 
8
8
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
9
9
 
@@ -79,10 +79,9 @@ export const codexRunner = {
79
79
  const args = buildCodexArgs({ prompt, model, outputFile, securityPolicy });
80
80
 
81
81
  const { events, stderr } = await new Promise((resolve, reject) => {
82
- const child = spawn(resolveBinary('codex'), args, {
82
+ const child = spawn('codex', args, {
83
83
  cwd,
84
84
  stdio: ['pipe', 'pipe', 'pipe'],
85
- shell: process.platform === 'win32',
86
85
  env: {
87
86
  ...process.env,
88
87
  CODEX_HOME: process.env.CODEX_HOME || path.join(os.homedir(), '.codex'),
@@ -1,6 +1,6 @@
1
- import { spawn } from 'node:child_process';
1
+ import spawn from 'cross-spawn';
2
2
  import path from 'node:path';
3
- import { extractText, resolveBinary, safeJsonParse } from './_shared.js';
3
+ import { extractText, safeJsonParse } from './_shared.js';
4
4
 
5
5
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
6
6
 
@@ -76,10 +76,14 @@ export function buildCopilotPermissionArgs(securityPolicy = {}) {
76
76
  return args;
77
77
  }
78
78
 
79
- export function buildCopilotArgs({ prompt, model, runnerAgent, securityPolicy = {} } = {}) {
79
+ export function buildCopilotArgs({ model, runnerAgent, securityPolicy = {} } = {}) {
80
+ // Prompt is written to stdin (see copilotRunner.run) instead of being passed
81
+ // as `-p <prompt>`. This avoids the Windows command-line length limit (~32KB)
82
+ // that hits as soon as the scout's context.md is injected into downstream
83
+ // prompts.
80
84
  const args = [
81
85
  '-p',
82
- prompt,
86
+ '-',
83
87
  '--output-format',
84
88
  'json',
85
89
  ...buildCopilotPermissionArgs(securityPolicy),
@@ -138,10 +142,10 @@ export const copilotRunner = {
138
142
  timeoutMs = DEFAULT_TIMEOUT_MS,
139
143
  }) {
140
144
  const prompt = buildPrompt(systemPrompt, userPrompt);
141
- const args = buildCopilotArgs({ prompt, model, runnerAgent, securityPolicy });
145
+ const args = buildCopilotArgs({ model, runnerAgent, securityPolicy });
142
146
 
143
147
  const { events, stderr } = await new Promise((resolve, reject) => {
144
- const child = spawn(resolveBinary('copilot'), args, { cwd, stdio: ['ignore', 'pipe', 'pipe'], shell: process.platform === 'win32' });
148
+ const child = spawn('copilot', args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
145
149
  const stdoutChunks = [];
146
150
  let stderrText = '';
147
151
  let timedOut = false;
@@ -152,6 +156,9 @@ export const copilotRunner = {
152
156
  setTimeout(() => child.kill('SIGKILL'), 5000).unref();
153
157
  }, timeoutMs);
154
158
 
159
+ child.stdin.write(prompt);
160
+ child.stdin.end();
161
+
155
162
  child.stdout.on('data', (d) => stdoutChunks.push(d.toString()));
156
163
  child.stderr.on('data', (d) => (stderrText += d.toString()));
157
164
  child.on('error', (err) => {
@@ -1,6 +1,6 @@
1
- import { spawn } from 'node:child_process';
1
+ import spawn from 'cross-spawn';
2
2
  import path from 'node:path';
3
- import { extractText, findCostUsd, findUsage, resolveBinary, safeJsonParse } from './_shared.js';
3
+ import { extractText, findCostUsd, findUsage, safeJsonParse } from './_shared.js';
4
4
 
5
5
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
6
6
 
@@ -199,7 +199,7 @@ export const opencodeRunner = {
199
199
  });
200
200
 
201
201
  const runResult = await new Promise((resolve, reject) => {
202
- const child = spawn(resolveBinary('opencode'), args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'], shell: process.platform === 'win32' });
202
+ const child = spawn('opencode', args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });
203
203
  const stdoutChunks = [];
204
204
  let stderrText = '';
205
205
  let timedOut = false;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singleton/server",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0-beta.5",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singleton/web",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0-beta.5",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {