singleton-pipeline 0.4.0-beta.0 → 0.4.0-beta.2

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,8 @@
1
- # Singleton Pipeline Builder (v0.4.0-beta.0)
1
+ # Singleton Pipeline Builder (v0.4.0-beta.2)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/singleton-pipeline/beta.svg)](https://www.npmjs.com/package/singleton-pipeline)
4
+ [![npm downloads](https://img.shields.io/npm/dm/singleton-pipeline.svg)](https://www.npmjs.com/package/singleton-pipeline)
5
+ [![license](https://img.shields.io/npm/l/singleton-pipeline.svg)](LICENSE)
2
6
 
3
7
  Build multi-agent pipelines for your codebase, visually.
4
8
 
@@ -57,13 +61,32 @@ This beta focused on multi-provider execution, Copilot support, inspection, and
57
61
 
58
62
  ## Install
59
63
 
64
+ The fastest path is via npm:
65
+
60
66
  ```bash
67
+ npm install -g singleton-pipeline@beta
68
+ singleton --version
69
+ ```
70
+
71
+ Or run it directly without installing globally:
72
+
73
+ ```bash
74
+ npx singleton-pipeline@beta --help
75
+ ```
76
+
77
+ Singleton drives the provider CLIs you already use; install the ones you want in your `$PATH` with a working session: `claude`, `codex`, `copilot`, `opencode`.
78
+
79
+ Requirements: Node 20+.
80
+
81
+ ### From source (development)
82
+
83
+ ```bash
84
+ git clone https://github.com/RomainLENTZ/singleton_pipeline.git
85
+ cd singleton_pipeline
61
86
  npm install
62
87
  npm link # optional, to use `singleton` globally
63
88
  ```
64
89
 
65
- Requirements: Node 20+, plus the provider CLIs you want to use in your `$PATH` with a working session: `claude`, `codex`, `copilot`, and/or `opencode`.
66
-
67
90
  ## Quickstart
68
91
 
69
92
  Run the bundled mixed-provider example end-to-end (uses Claude for scouting/review and Codex for implementation):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "singleton-pipeline",
3
- "version": "0.4.0-beta.0",
3
+ "version": "0.4.0-beta.2",
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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singleton/cli",
3
- "version": "0.4.0-beta.0",
3
+ "version": "0.4.0-beta.2",
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.0';
205
+ const APP_VERSION = 'v0.4.0-beta.2';
206
206
 
207
207
  async function showWelcome(root, shell) {
208
208
  const now = new Date();
@@ -1076,7 +1076,8 @@ function shouldHighlightSecurity({ provider, permissionMode, securityPolicy }) {
1076
1076
 
1077
1077
  function commandExists(command) {
1078
1078
  return new Promise((resolve) => {
1079
- const child = spawn('which', [command], { stdio: 'ignore' });
1079
+ const lookup = process.platform === 'win32' ? 'where' : 'which';
1080
+ const child = spawn(lookup, [command], { stdio: 'ignore' });
1080
1081
  child.on('error', () => resolve(false));
1081
1082
  child.on('close', (code) => resolve(code === 0));
1082
1083
  });
@@ -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.0');
25
+ .version('0.4.0-beta.2');
26
26
 
27
27
  program
28
28
  .command('scan')
@@ -3,6 +3,13 @@
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
+
6
13
  export function safeJsonParse(line) {
7
14
  try {
8
15
  return JSON.parse(line);
@@ -1,4 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
+ import { resolveBinary } from './_shared.js';
2
3
 
3
4
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
4
5
  const ALLOWED_PERMISSION_MODES = new Set(['bypassPermissions']);
@@ -62,7 +63,7 @@ export const claudeRunner = {
62
63
  if (model) args.push('--model', model);
63
64
 
64
65
  const raw = await new Promise((resolve, reject) => {
65
- const child = spawn('claude', args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
66
+ const child = spawn(resolveBinary('claude'), args, { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
66
67
  let stdout = '';
67
68
  let stderr = '';
68
69
  let timedOut = false;
@@ -3,7 +3,7 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { discoverCodexProjectInstructions } from './codex-instructions.js';
6
- import { findUsage, safeJsonParse } from './_shared.js';
6
+ import { findUsage, resolveBinary, 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,7 +79,7 @@ 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('codex', args, {
82
+ const child = spawn(resolveBinary('codex'), args, {
83
83
  cwd,
84
84
  stdio: ['pipe', 'pipe', 'pipe'],
85
85
  env: {
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import path from 'node:path';
3
- import { extractText, safeJsonParse } from './_shared.js';
3
+ import { extractText, resolveBinary, safeJsonParse } from './_shared.js';
4
4
 
5
5
  const DEFAULT_TIMEOUT_MS = Number(process.env.SINGLETON_RUNNER_TIMEOUT_MS) || 10 * 60 * 1000;
6
6
 
@@ -141,7 +141,7 @@ export const copilotRunner = {
141
141
  const args = buildCopilotArgs({ prompt, model, runnerAgent, securityPolicy });
142
142
 
143
143
  const { events, stderr } = await new Promise((resolve, reject) => {
144
- const child = spawn('copilot', args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
144
+ const child = spawn(resolveBinary('copilot'), args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
145
145
  const stdoutChunks = [];
146
146
  let stderrText = '';
147
147
  let timedOut = false;
@@ -1,6 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import path from 'node:path';
3
- import { extractText, findCostUsd, findUsage, safeJsonParse } from './_shared.js';
3
+ import { extractText, findCostUsd, findUsage, resolveBinary, 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('opencode', args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });
202
+ const child = spawn(resolveBinary('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.0",
3
+ "version": "0.4.0-beta.2",
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.0",
3
+ "version": "0.4.0-beta.2",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {