@the-agenticflow/openflows 0.1.5 → 0.1.8-dev.230.5aa03a0
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/bin/openflows-dashboard.js +1 -1
- package/bin/openflows-setup.js +1 -1
- package/bin/openflows.js +4 -286
- package/package.json +2 -12
- package/scripts/install.js +47 -209
- package/.env.example +0 -60
- package/README.md +0 -217
- package/bin/LICENSE +0 -21
- package/bin/README.md +0 -535
- package/bin/agentflow-bin +0 -0
- package/bin/agentflow-dashboard-bin +0 -0
- package/bin/agentflow-doctor-bin +0 -0
- package/bin/agentflow-setup-bin +0 -0
- package/bin/orchestration/agent/agents/forge.agent.md +0 -110
- package/bin/orchestration/agent/agents/lore.agent.md +0 -27
- package/bin/orchestration/agent/agents/nexus.agent.md +0 -201
- package/bin/orchestration/agent/agents/sentinel.agent.md +0 -96
- package/bin/orchestration/agent/agents/vessel.agent.md +0 -38
- package/bin/orchestration/agent/registry.json +0 -10
- package/bin/orchestration/agent/standards/CODING.md +0 -22
- package/bin/orchestration/agent/standards/REVIEW.md +0 -15
- package/bin/orchestration/agent/standards/SECURITY.md +0 -72
- package/bin/orchestration/plugin/commands/assign.md +0 -45
- package/bin/orchestration/plugin/commands/check-ci.md +0 -26
- package/bin/orchestration/plugin/commands/document-pr.md +0 -32
- package/bin/orchestration/plugin/commands/gate-approve.md +0 -39
- package/bin/orchestration/plugin/commands/handoff.md +0 -75
- package/bin/orchestration/plugin/commands/merge.md +0 -47
- package/bin/orchestration/plugin/commands/plan.md +0 -66
- package/bin/orchestration/plugin/commands/segment-done.md +0 -50
- package/bin/orchestration/plugin/commands/status-check.md +0 -28
- package/bin/orchestration/plugin/commands/status.md +0 -94
- package/bin/orchestration/plugin/commands/update-changelog.md +0 -37
- package/bin/orchestration/plugin/hooks/forge/post_write_lint.sh +0 -76
- package/bin/orchestration/plugin/hooks/forge/pre_bash_guard.sh +0 -81
- package/bin/orchestration/plugin/hooks/forge/pre_compact_handoff.sh +0 -28
- package/bin/orchestration/plugin/hooks/forge/pre_write_check.sh +0 -77
- package/bin/orchestration/plugin/hooks/forge/session_start.sh +0 -59
- package/bin/orchestration/plugin/hooks/forge/stop_require_artifact.sh +0 -75
- package/bin/orchestration/plugin/hooks/lore/session-start.sh +0 -13
- package/bin/orchestration/plugin/hooks/nexus/init-session.sh +0 -23
- package/bin/orchestration/plugin/hooks/nexus/log-decision.sh +0 -10
- package/bin/orchestration/plugin/hooks/sentinel/post_write_validate.sh +0 -59
- package/bin/orchestration/plugin/hooks/sentinel/pre_bash_readonly_guard.sh +0 -107
- package/bin/orchestration/plugin/hooks/sentinel/session_start.sh +0 -74
- package/bin/orchestration/plugin/hooks/sentinel/stop_require_eval.sh +0 -57
- package/bin/orchestration/plugin/hooks/vessel/log-merge-status.sh +0 -7
- package/bin/orchestration/plugin/hooks/vessel/session-start.sh +0 -14
- package/bin/orchestration/plugin/mcp/mcp.json.template +0 -26
- package/bin/orchestration/plugin/plugin.json +0 -66
- package/bin/orchestration/plugin/skills/forge-algorithmic-art.md +0 -24
- package/bin/orchestration/plugin/skills/forge-canvas-design.md +0 -25
- package/bin/orchestration/plugin/skills/forge-coding.md +0 -161
- package/bin/orchestration/plugin/skills/forge-frontend-design.md +0 -30
- package/bin/orchestration/plugin/skills/forge-mcp-builder.md +0 -37
- package/bin/orchestration/plugin/skills/forge-planning.md +0 -102
- package/bin/orchestration/plugin/skills/forge-skill-creator.md +0 -25
- package/bin/orchestration/plugin/skills/forge-web-artifacts-builder.md +0 -29
- package/bin/orchestration/plugin/skills/lore-brand-guidelines.md +0 -33
- package/bin/orchestration/plugin/skills/lore-changelog.md +0 -69
- package/bin/orchestration/plugin/skills/lore-doc-coauthoring.md +0 -33
- package/bin/orchestration/plugin/skills/lore-documentation.md +0 -57
- package/bin/orchestration/plugin/skills/lore-docx.md +0 -20
- package/bin/orchestration/plugin/skills/lore-pdf.md +0 -20
- package/bin/orchestration/plugin/skills/lore-pptx.md +0 -23
- package/bin/orchestration/plugin/skills/lore-theme-factory.md +0 -20
- package/bin/orchestration/plugin/skills/lore-xlsx.md +0 -20
- package/bin/orchestration/plugin/skills/nexus-doc-coauthoring.md +0 -21
- package/bin/orchestration/plugin/skills/nexus-internal-comms.md +0 -28
- package/bin/orchestration/plugin/skills/nexus-orchestration.md +0 -63
- package/bin/orchestration/plugin/skills/nexus-skill-creator.md +0 -15
- package/bin/orchestration/plugin/skills/nexus-slack-gif-creator.md +0 -21
- package/bin/orchestration/plugin/skills/nexus-triage.md +0 -56
- package/bin/orchestration/plugin/skills/nexus-xlsx.md +0 -20
- package/bin/orchestration/plugin/skills/sentinel-algorithmic-art.md +0 -20
- package/bin/orchestration/plugin/skills/sentinel-criteria.md +0 -115
- package/bin/orchestration/plugin/skills/sentinel-frontend-design.md +0 -20
- package/bin/orchestration/plugin/skills/sentinel-review.md +0 -124
- package/bin/orchestration/plugin/skills/sentinel-web-artifacts-builder.md +0 -20
- package/bin/orchestration/plugin/skills/sentinel-webapp-testing.md +0 -34
- package/bin/orchestration/plugin/skills/shared-claude-api.md +0 -25
- package/bin/orchestration/plugin/skills/vessel-ci-gate.md +0 -68
- package/bin/orchestration/plugin/skills/vessel-internal-comms.md +0 -20
- package/bin/orchestration/plugin/skills/vessel-mcp-builder.md +0 -21
- package/bin/orchestration/plugin/skills/vessel-merge-protocol.md +0 -113
- package/bin/orchestration/plugin/skills/vessel-pdf.md +0 -20
- package/bin/orchestration/plugin/skills/vessel-webapp-testing.md +0 -34
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const { spawn } = require('child_process');
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const binaryPath = path.join(__dirname, '..', 'bin', '
|
|
4
|
+
const binaryPath = path.join(__dirname, '..', 'bin', 'openflows-dashboard-bin');
|
|
5
5
|
const proc = spawn(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
6
6
|
proc.on('exit', (code) => process.exit(code));
|
package/bin/openflows-setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const { spawn } = require('child_process');
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const binaryPath = path.join(__dirname, '..', 'bin', '
|
|
4
|
+
const binaryPath = path.join(__dirname, '..', 'bin', 'openflows-setup-bin');
|
|
5
5
|
const proc = spawn(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
6
6
|
proc.on('exit', (code) => process.exit(code));
|
package/bin/openflows.js
CHANGED
|
@@ -1,288 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* OpenFlows - Autonomous AI Development Team
|
|
4
|
-
*
|
|
5
|
-
* This wrapper handles:
|
|
6
|
-
* 1. Automatic proxy management (for LLM API translation if needed)
|
|
7
|
-
* 2. Environment configuration
|
|
8
|
-
* 3. Graceful startup and shutdown
|
|
9
|
-
*
|
|
10
|
-
* Users don't need to know about proxies - everything is handled automatically.
|
|
11
|
-
*/
|
|
12
|
-
const { spawn, execSync, fork } = require('child_process');
|
|
2
|
+
const { spawn } = require('child_process');
|
|
13
3
|
const path = require('path');
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const binaryPath = path.join(__dirname, '..', 'bin', 'agentflow-bin');
|
|
19
|
-
const PROXY_PORT = process.env.PROXY_PORT || 8765;
|
|
20
|
-
const PROXY_STARTUP_TIMEOUT = 5000;
|
|
21
|
-
|
|
22
|
-
// Check if a port is in use
|
|
23
|
-
function isPortInUse(port) {
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
const req = http.request({
|
|
26
|
-
method: 'GET',
|
|
27
|
-
hostname: 'localhost',
|
|
28
|
-
port: port,
|
|
29
|
-
path: '/health',
|
|
30
|
-
timeout: 500
|
|
31
|
-
}, (res) => {
|
|
32
|
-
resolve(res.statusCode === 200);
|
|
33
|
-
});
|
|
34
|
-
req.on('error', () => resolve(false));
|
|
35
|
-
req.on('timeout', () => {
|
|
36
|
-
req.destroy();
|
|
37
|
-
resolve(false);
|
|
38
|
-
});
|
|
39
|
-
req.end();
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Check if user needs proxy (no direct API keys, but has gateway config)
|
|
44
|
-
function needsProxy() {
|
|
45
|
-
// If user explicitly set PROXY_URL, respect it
|
|
46
|
-
if (process.env.PROXY_URL) {
|
|
47
|
-
return { needed: false, reason: 'PROXY_URL already set' };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// If user has Fireworks API key, they can use it directly
|
|
51
|
-
if (process.env.FIREWORKS_API_KEY) {
|
|
52
|
-
return { needed: false, reason: 'Fireworks direct mode' };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// If user has Anthropic API key, they can use it directly
|
|
56
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
57
|
-
return { needed: false, reason: 'Anthropic direct mode' };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// If user has Gateway config but no direct keys, they need proxy
|
|
61
|
-
if (process.env.GATEWAY_URL || process.env.GATEWAY_API_KEY) {
|
|
62
|
-
return { needed: true, reason: 'Gateway configured, no direct keys' };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// No API config at all - let the binary handle the error
|
|
66
|
-
return { needed: false, reason: 'No API config - will error in binary' };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Start the built-in proxy (anthropic-proxy binary)
|
|
70
|
-
async function startProxy() {
|
|
71
|
-
console.log('[openflows] Starting built-in API proxy...');
|
|
72
|
-
|
|
73
|
-
const proxyBinary = path.join(__dirname, '..', 'bin', 'anthropic-proxy-bin');
|
|
74
|
-
|
|
75
|
-
// Check if proxy binary exists
|
|
76
|
-
if (!fs.existsSync(proxyBinary)) {
|
|
77
|
-
// Try alternative location
|
|
78
|
-
const altProxy = path.join(__dirname, '..', 'bin', 'anthropic-proxy');
|
|
79
|
-
if (!fs.existsSync(altProxy)) {
|
|
80
|
-
console.log('[openflows] No built-in proxy found, skipping proxy startup');
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const proxy = spawn(proxyBinary, [], {
|
|
86
|
-
env: {
|
|
87
|
-
...process.env,
|
|
88
|
-
PORT: PROXY_PORT.toString(),
|
|
89
|
-
RUST_LOG: process.env.RUST_LOG || 'info'
|
|
90
|
-
},
|
|
91
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
let proxyReady = false;
|
|
95
|
-
|
|
96
|
-
return new Promise((resolve, reject) => {
|
|
97
|
-
const timeout = setTimeout(() => {
|
|
98
|
-
if (!proxyReady) {
|
|
99
|
-
console.warn('[openflows] Proxy startup timeout, continuing without proxy');
|
|
100
|
-
resolve(null);
|
|
101
|
-
}
|
|
102
|
-
}, PROXY_STARTUP_TIMEOUT);
|
|
103
|
-
|
|
104
|
-
proxy.stdout.on('data', (data) => {
|
|
105
|
-
const line = data.toString();
|
|
106
|
-
if (line.includes('listening') || line.includes('Proxy') || line.includes('started')) {
|
|
107
|
-
proxyReady = true;
|
|
108
|
-
clearTimeout(timeout);
|
|
109
|
-
console.log(`[openflows] ✓ Proxy started on port ${PROXY_PORT}`);
|
|
110
|
-
resolve(proxy);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
proxy.stderr.on('data', (data) => {
|
|
115
|
-
const line = data.toString();
|
|
116
|
-
// Log proxy errors but don't fail
|
|
117
|
-
if (line.includes('ERROR') || line.includes('error')) {
|
|
118
|
-
console.error('[openflows proxy]', line.trim());
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
proxy.on('error', (err) => {
|
|
123
|
-
clearTimeout(timeout);
|
|
124
|
-
console.warn(`[openflows] Proxy failed to start: ${err.message}`);
|
|
125
|
-
resolve(null);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
proxy.on('exit', (code) => {
|
|
129
|
-
if (!proxyReady) {
|
|
130
|
-
clearTimeout(timeout);
|
|
131
|
-
resolve(null);
|
|
132
|
-
} else {
|
|
133
|
-
console.log(`[openflows] Proxy exited with code ${code}`);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Clean up function
|
|
140
|
-
let cleanupCalled = false;
|
|
141
|
-
function cleanup(proxy, signal = 'SIGTERM') {
|
|
142
|
-
if (cleanupCalled) return;
|
|
143
|
-
cleanupCalled = true;
|
|
144
|
-
|
|
145
|
-
if (proxy) {
|
|
146
|
-
console.log('[openflows] Stopping proxy...');
|
|
147
|
-
try {
|
|
148
|
-
proxy.kill(signal);
|
|
149
|
-
} catch (err) {
|
|
150
|
-
// Ignore cleanup errors
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Main entry point
|
|
156
|
-
async function main() {
|
|
157
|
-
const args = process.argv.slice(2);
|
|
158
|
-
|
|
159
|
-
// Handle special commands
|
|
160
|
-
if (args[0] === '--help' || args[0] === '-h') {
|
|
161
|
-
console.log(`
|
|
162
|
-
OpenFlows - Autonomous AI Development Team
|
|
163
|
-
|
|
164
|
-
Usage:
|
|
165
|
-
openflows [options]
|
|
166
|
-
|
|
167
|
-
Options:
|
|
168
|
-
--help, -h Show this help
|
|
169
|
-
--version, -v Show version
|
|
170
|
-
--no-proxy Disable automatic proxy startup
|
|
171
|
-
--proxy-only Start only the proxy (for testing)
|
|
172
|
-
|
|
173
|
-
Commands:
|
|
174
|
-
openflows-setup Guided setup wizard
|
|
175
|
-
openflows-dashboard Live monitoring TUI
|
|
176
|
-
openflows-doctor Diagnostic checks
|
|
177
|
-
|
|
178
|
-
Environment Variables:
|
|
179
|
-
FIREWORKS_API_KEY Use Fireworks AI directly (recommended)
|
|
180
|
-
ANTHROPIC_API_KEY Use Anthropic directly
|
|
181
|
-
GATEWAY_URL Custom gateway URL (requires proxy)
|
|
182
|
-
GATEWAY_API_KEY Custom gateway API key
|
|
183
|
-
PROXY_PORT Port for built-in proxy (default: 8765)
|
|
184
|
-
|
|
185
|
-
Examples:
|
|
186
|
-
# Quick start with Fireworks (no proxy needed)
|
|
187
|
-
FIREWORKS_API_KEY=your-key openflows
|
|
188
|
-
|
|
189
|
-
# Use custom gateway (proxy auto-starts)
|
|
190
|
-
GATEWAY_URL=https://your-gateway.com/v1 \\
|
|
191
|
-
GATEWAY_API_KEY=your-key openflows
|
|
192
|
-
|
|
193
|
-
Documentation: https://openflows.dev
|
|
194
|
-
`);
|
|
195
|
-
process.exit(0);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (args[0] === '--version' || args[0] === '-v') {
|
|
199
|
-
try {
|
|
200
|
-
const pkg = require('../package.json');
|
|
201
|
-
console.log(`openflows v${pkg.version}`);
|
|
202
|
-
} catch {
|
|
203
|
-
console.log('openflows (version unknown)');
|
|
204
|
-
}
|
|
205
|
-
process.exit(0);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Skip proxy if --no-proxy flag
|
|
209
|
-
const skipProxy = args.includes('--no-proxy');
|
|
210
|
-
|
|
211
|
-
// Start proxy only mode
|
|
212
|
-
if (args[0] === '--proxy-only') {
|
|
213
|
-
const proxy = await startProxy();
|
|
214
|
-
if (proxy) {
|
|
215
|
-
console.log(`[openflows] Proxy running on http://localhost:${PROXY_PORT}`);
|
|
216
|
-
console.log('[openflows] Press Ctrl+C to stop');
|
|
217
|
-
|
|
218
|
-
// Keep running until killed
|
|
219
|
-
process.on('SIGINT', () => cleanup(proxy, 'SIGINT'));
|
|
220
|
-
process.on('SIGTERM', () => cleanup(proxy, 'SIGTERM'));
|
|
221
|
-
} else {
|
|
222
|
-
console.error('[openflows] Failed to start proxy');
|
|
223
|
-
process.exit(1);
|
|
224
|
-
}
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Check if we need to start proxy
|
|
229
|
-
let proxy = null;
|
|
230
|
-
let env = { ...process.env };
|
|
231
|
-
|
|
232
|
-
if (!skipProxy) {
|
|
233
|
-
const { needed, reason } = needsProxy();
|
|
234
|
-
|
|
235
|
-
if (needed) {
|
|
236
|
-
console.log(`[openflows] ${reason} - starting proxy...`);
|
|
237
|
-
|
|
238
|
-
// Check if proxy is already running
|
|
239
|
-
const proxyRunning = await isPortInUse(PROXY_PORT);
|
|
240
|
-
|
|
241
|
-
if (proxyRunning) {
|
|
242
|
-
console.log(`[openflows] ✓ Proxy already running on port ${PROXY_PORT}`);
|
|
243
|
-
} else {
|
|
244
|
-
proxy = await startProxy();
|
|
245
|
-
if (proxy) {
|
|
246
|
-
// Set PROXY_URL for the main binary
|
|
247
|
-
env.PROXY_URL = `http://localhost:${PROXY_PORT}/v1`;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
} else {
|
|
251
|
-
console.log(`[openflows] Mode: ${reason}`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Spawn the main binary
|
|
256
|
-
const proc = spawn(binaryPath, args, {
|
|
257
|
-
env,
|
|
258
|
-
stdio: 'inherit'
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// Handle signals
|
|
262
|
-
process.on('SIGINT', () => {
|
|
263
|
-
cleanup(proxy, 'SIGINT');
|
|
264
|
-
proc.kill('SIGINT');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
process.on('SIGTERM', () => {
|
|
268
|
-
cleanup(proxy, 'SIGTERM');
|
|
269
|
-
proc.kill('SIGTERM');
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// Handle exit
|
|
273
|
-
proc.on('exit', (code) => {
|
|
274
|
-
cleanup(proxy);
|
|
275
|
-
process.exit(code || 0);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
proc.on('error', (err) => {
|
|
279
|
-
console.error('[openflows] Failed to start:', err.message);
|
|
280
|
-
cleanup(proxy);
|
|
281
|
-
process.exit(1);
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
main().catch(err => {
|
|
286
|
-
console.error('[openflows] Error:', err.message);
|
|
287
|
-
process.exit(1);
|
|
288
|
-
});
|
|
4
|
+
const binaryPath = path.join(__dirname, '..', 'bin', 'openflows-bin');
|
|
5
|
+
const proc = spawn(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
6
|
+
proc.on('exit', (code) => process.exit(code));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-agenticflow/openflows",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8-dev.230.5aa03a0",
|
|
4
4
|
"description": "Autonomous AI development team — turns GitHub issues into working PRs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,10 +21,7 @@
|
|
|
21
21
|
"autonomous",
|
|
22
22
|
"development",
|
|
23
23
|
"agents",
|
|
24
|
-
"github"
|
|
25
|
-
"claude",
|
|
26
|
-
"fireworks",
|
|
27
|
-
"anthropic"
|
|
24
|
+
"github"
|
|
28
25
|
],
|
|
29
26
|
"author": "The AgenticFlow Team",
|
|
30
27
|
"license": "MIT",
|
|
@@ -32,12 +29,6 @@
|
|
|
32
29
|
"url": "https://github.com/The-AgenticFlow/AgentFlow/issues"
|
|
33
30
|
},
|
|
34
31
|
"homepage": "https://openflows.dev",
|
|
35
|
-
"files": [
|
|
36
|
-
"bin/",
|
|
37
|
-
"scripts/",
|
|
38
|
-
"README.md",
|
|
39
|
-
".env.example"
|
|
40
|
-
],
|
|
41
32
|
"engines": {
|
|
42
33
|
"node": ">=18.0.0"
|
|
43
34
|
},
|
|
@@ -49,7 +40,6 @@
|
|
|
49
40
|
"x64",
|
|
50
41
|
"arm64"
|
|
51
42
|
],
|
|
52
|
-
"dependencies": {},
|
|
53
43
|
"optionalDependencies": {
|
|
54
44
|
"@openflows/linux-x64-gnu": "0.1.0",
|
|
55
45
|
"@openflows/linux-x64-musl": "0.1.0",
|
package/scripts/install.js
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Post-install script for
|
|
4
|
-
*
|
|
5
|
-
* This script:
|
|
6
|
-
* 1. Downloads the correct pre-built binary for the current platform
|
|
7
|
-
* 2. Installs mcp-proxy (required for GitHub MCP connectivity)
|
|
8
|
-
* 3. Verifies all dependencies are ready
|
|
3
|
+
* Post-install script: downloads the correct pre-built binary for the current platform.
|
|
9
4
|
*/
|
|
10
5
|
const https = require('https');
|
|
11
6
|
const http = require('http');
|
|
12
7
|
const fs = require('fs');
|
|
13
8
|
const path = require('path');
|
|
14
9
|
const os = require('os');
|
|
15
|
-
const { execSync
|
|
10
|
+
const { execSync } = require('child_process');
|
|
16
11
|
|
|
17
12
|
const REPO = 'The-AgenticFlow/AgentFlow';
|
|
18
13
|
const BIN_DIR = path.join(__dirname, '..', 'bin');
|
|
19
|
-
const POSTINSTALL_LOG = path.join(__dirname, '..', '.postinstall-done');
|
|
20
14
|
|
|
21
15
|
function detectPlatform() {
|
|
22
16
|
const platform = os.platform();
|
|
@@ -98,182 +92,65 @@ function extractTarGz(tarPath, destDir) {
|
|
|
98
92
|
});
|
|
99
93
|
}
|
|
100
94
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
* It bridges stdio to HTTP MCP servers like GitHub Copilot's MCP endpoint.
|
|
106
|
-
*
|
|
107
|
-
* Strategy:
|
|
108
|
-
* 1. Check if mcp-proxy is already available
|
|
109
|
-
* 2. Install via uv (fast) or pipx (alternative)
|
|
110
|
-
* 3. Fall back to Docker mode instructions if Python tools unavailable
|
|
111
|
-
*/
|
|
112
|
-
async function ensureMcpProxy() {
|
|
113
|
-
console.log(`[openflows] Checking mcp-proxy installation...`);
|
|
114
|
-
|
|
115
|
-
// Check if already installed
|
|
116
|
-
try {
|
|
117
|
-
execSync('which mcp-proxy', { stdio: 'pipe' });
|
|
118
|
-
console.log(`[openflows] ✓ mcp-proxy already installed`);
|
|
119
|
-
return true;
|
|
120
|
-
} catch {
|
|
121
|
-
// Not installed, proceed with installation
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
console.log(`[openflows] Installing mcp-proxy (required for GitHub MCP)...`);
|
|
125
|
-
|
|
126
|
-
// Try uv first (fastest)
|
|
127
|
-
try {
|
|
128
|
-
execSync('which uv', { stdio: 'pipe' });
|
|
129
|
-
console.log(`[openflows] Installing via uv...`);
|
|
130
|
-
execSync('uv tool install mcp-proxy', {
|
|
131
|
-
stdio: 'inherit',
|
|
132
|
-
timeout: 120000
|
|
133
|
-
});
|
|
134
|
-
console.log(`[openflows] ✓ mcp-proxy installed via uv`);
|
|
135
|
-
return true;
|
|
136
|
-
} catch (err) {
|
|
137
|
-
// uv failed or not available
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Try pipx as alternative
|
|
141
|
-
try {
|
|
142
|
-
execSync('which pipx', { stdio: 'pipe' });
|
|
143
|
-
console.log(`[openflows] Installing via pipx...`);
|
|
144
|
-
execSync('pipx install mcp-proxy', {
|
|
145
|
-
stdio: 'inherit',
|
|
146
|
-
timeout: 120000
|
|
147
|
-
});
|
|
148
|
-
console.log(`[openflows] ✓ mcp-proxy installed via pipx`);
|
|
149
|
-
return true;
|
|
150
|
-
} catch (err) {
|
|
151
|
-
// pipx failed or not available
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Try pip3 as last resort
|
|
155
|
-
try {
|
|
156
|
-
execSync('which pip3', { stdio: 'pipe' });
|
|
157
|
-
console.log(`[openflows] Installing via pip3...`);
|
|
158
|
-
execSync('pip3 install --user mcp-proxy', {
|
|
159
|
-
stdio: 'inherit',
|
|
160
|
-
timeout: 120000
|
|
161
|
-
});
|
|
162
|
-
console.log(`[openflows] ✓ mcp-proxy installed via pip3`);
|
|
163
|
-
return true;
|
|
164
|
-
} catch (err) {
|
|
165
|
-
// pip3 failed or not available
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
console.warn(`[openflows] ⚠ Could not install mcp-proxy automatically.`);
|
|
169
|
-
console.warn(`[openflows] Please install manually:`);
|
|
170
|
-
console.warn(`[openflows] uv tool install mcp-proxy`);
|
|
171
|
-
console.warn(`[openflows] Or use Docker mode:`);
|
|
172
|
-
console.warn(`[openflows] export GITHUB_MCP_TYPE=docker`);
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
95
|
+
async function fetchLatestTag(includePrerelease = false) {
|
|
96
|
+
const url = includePrerelease
|
|
97
|
+
? `https://api.github.com/repos/${REPO}/releases?per_page=10`
|
|
98
|
+
: `https://api.github.com/repos/${REPO}/releases/latest`;
|
|
175
99
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return allPassed;
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
https.get(url, {
|
|
102
|
+
headers: { 'User-Agent': 'openflows-npm-installer' }
|
|
103
|
+
}, (res) => {
|
|
104
|
+
let data = '';
|
|
105
|
+
res.on('data', (chunk) => data += chunk);
|
|
106
|
+
res.on('end', () => {
|
|
107
|
+
try {
|
|
108
|
+
const json = JSON.parse(data);
|
|
109
|
+
if (includePrerelease) {
|
|
110
|
+
const pre = json.find(r => r.prerelease);
|
|
111
|
+
resolve(pre ? pre.tag_name : null);
|
|
112
|
+
} else {
|
|
113
|
+
resolve(json.tag_name);
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
reject(new Error('Failed to parse release info'));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}).on('error', reject);
|
|
120
|
+
});
|
|
199
121
|
}
|
|
200
122
|
|
|
201
123
|
async function main() {
|
|
202
|
-
// Skip postinstall if already done (e.g., during npm link)
|
|
203
|
-
if (fs.existsSync(POSTINSTALL_LOG)) {
|
|
204
|
-
const age = Date.now() - fs.statSync(POSTINSTALL_LOG).mtimeMs;
|
|
205
|
-
if (age < 60000) { // Less than 1 minute old
|
|
206
|
-
console.log(`[openflows] Postinstall already completed, skipping...`);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
124
|
const platform = detectPlatform();
|
|
212
|
-
|
|
213
|
-
console.log(
|
|
214
|
-
console.log(`║ OpenFlows Installation ║`);
|
|
215
|
-
console.log(`║ Autonomous AI Development Team ║`);
|
|
216
|
-
console.log(`╚══════════════════════════════════════════════╝`);
|
|
217
|
-
console.log(``);
|
|
218
|
-
console.log(`[openflows] Platform: ${platform}`);
|
|
125
|
+
const channel = process.env.AGENTFLOW_CHANNEL || (process.env.npm_package_version?.includes('-dev.') ? 'edge' : 'stable');
|
|
126
|
+
console.log(`[@the-agenticflow/openflows] Downloading binary for ${platform} (${channel})...`);
|
|
219
127
|
|
|
220
128
|
// Ensure bin directory exists
|
|
221
129
|
if (!fs.existsSync(BIN_DIR)) {
|
|
222
130
|
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
223
131
|
}
|
|
224
132
|
|
|
225
|
-
// Get
|
|
133
|
+
// Get release tag based on channel
|
|
226
134
|
let tag;
|
|
227
135
|
try {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
let data = '';
|
|
240
|
-
res.on('data', (chunk) => data += chunk);
|
|
241
|
-
res.on('end', () => {
|
|
242
|
-
try {
|
|
243
|
-
const json = JSON.parse(data);
|
|
244
|
-
if (!json.tag_name) {
|
|
245
|
-
reject(new Error('No tag_name in release response'));
|
|
246
|
-
} else {
|
|
247
|
-
resolve(json.tag_name);
|
|
248
|
-
}
|
|
249
|
-
} catch (parseErr) {
|
|
250
|
-
reject(new Error(`Failed to parse release info: ${parseErr.message}`));
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
req.on('error', reject);
|
|
255
|
-
req.setTimeout(30000, () => {
|
|
256
|
-
req.destroy();
|
|
257
|
-
reject(new Error('GitHub API request timeout'));
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
} catch (apiErr) {
|
|
261
|
-
console.error(`[openflows] GitHub API error: ${apiErr.message}`);
|
|
262
|
-
console.error('[openflows] Falling back to latest known version: v0.1.3');
|
|
263
|
-
tag = 'v0.1.3';
|
|
136
|
+
if (channel === 'edge') {
|
|
137
|
+
tag = await fetchLatestTag(true);
|
|
138
|
+
if (!tag) {
|
|
139
|
+
console.warn('[@the-agenticflow/openflows] No edge release found, falling back to latest stable');
|
|
140
|
+
tag = await fetchLatestTag(false);
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
tag = await fetchLatestTag(false);
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
tag = await fetchLatestTag(false);
|
|
264
147
|
}
|
|
265
148
|
|
|
266
149
|
const archiveName = `openflows-${tag}-${platform}.tar.gz`;
|
|
267
150
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${archiveName}`;
|
|
268
|
-
|
|
269
|
-
const tmpDir = path.join(__dirname, '..', '.tmp');
|
|
270
|
-
if (!fs.existsSync(tmpDir)) {
|
|
271
|
-
fs.mkdirSync(tmpDir, { recursive: true });
|
|
272
|
-
}
|
|
273
|
-
const tmpFile = path.join(tmpDir, archiveName);
|
|
151
|
+
const tmpFile = path.join(os.tmpdir(), archiveName);
|
|
274
152
|
|
|
275
153
|
try {
|
|
276
|
-
console.log(`[openflows] Downloading binary for ${platform}...`);
|
|
277
154
|
await download(downloadUrl, tmpFile);
|
|
278
155
|
await extractTarGz(tmpFile, BIN_DIR);
|
|
279
156
|
} catch (err) {
|
|
@@ -281,8 +158,8 @@ async function main() {
|
|
|
281
158
|
if (platform === 'x86_64-unknown-linux-gnu') {
|
|
282
159
|
const muslArchiveName = `openflows-${tag}-x86_64-unknown-linux-musl.tar.gz`;
|
|
283
160
|
const muslDownloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${muslArchiveName}`;
|
|
284
|
-
const muslTmpFile = path.join(
|
|
285
|
-
console.log(`[openflows] Trying musl fallback...`);
|
|
161
|
+
const muslTmpFile = path.join(os.tmpdir(), muslArchiveName);
|
|
162
|
+
console.log(`[@the-agenticflow/openflows] Trying musl fallback...`);
|
|
286
163
|
await download(muslDownloadUrl, muslTmpFile);
|
|
287
164
|
await extractTarGz(muslTmpFile, BIN_DIR);
|
|
288
165
|
fs.unlinkSync(muslTmpFile);
|
|
@@ -292,7 +169,7 @@ async function main() {
|
|
|
292
169
|
}
|
|
293
170
|
|
|
294
171
|
// Rename binaries to match expected names
|
|
295
|
-
const binaries = ['
|
|
172
|
+
const binaries = ['openflows', 'openflows-setup', 'openflows-dashboard', 'openflows-doctor', 'anthropic-proxy'];
|
|
296
173
|
for (const bin of binaries) {
|
|
297
174
|
const src = path.join(BIN_DIR, bin);
|
|
298
175
|
const dst = path.join(BIN_DIR, `${bin}-bin`);
|
|
@@ -305,46 +182,7 @@ async function main() {
|
|
|
305
182
|
if (fs.existsSync(tmpFile)) {
|
|
306
183
|
fs.unlinkSync(tmpFile);
|
|
307
184
|
}
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
if (fs.existsSync(tmpDir) && fs.readdirSync(tmpDir).length === 0) {
|
|
311
|
-
fs.rmdirSync(tmpDir);
|
|
312
|
-
}
|
|
313
|
-
} catch (cleanupErr) {
|
|
314
|
-
// Ignore cleanup errors
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
console.log(`[openflows] ✓ Binaries installed`);
|
|
318
|
-
|
|
319
|
-
// Install mcp-proxy
|
|
320
|
-
await ensureMcpProxy();
|
|
321
|
-
|
|
322
|
-
// Check prerequisites
|
|
323
|
-
checkPrerequisites();
|
|
324
|
-
|
|
325
|
-
// Mark postinstall as done
|
|
326
|
-
fs.writeFileSync(POSTINSTALL_LOG, new Date().toISOString());
|
|
327
|
-
|
|
328
|
-
console.log(``);
|
|
329
|
-
console.log(`╔══════════════════════════════════════════════╗`);
|
|
330
|
-
console.log(`║ Installation Complete! ║`);
|
|
331
|
-
console.log(`╚══════════════════════════════════════════════╝`);
|
|
332
|
-
console.log(``);
|
|
333
|
-
console.log(` Available commands:`);
|
|
334
|
-
console.log(` openflows - Start orchestration`);
|
|
335
|
-
console.log(` openflows-setup - Guided setup wizard`);
|
|
336
|
-
console.log(` openflows-dashboard - Live monitoring TUI`);
|
|
337
|
-
console.log(` openflows-doctor - Diagnostic checks`);
|
|
338
|
-
console.log(``);
|
|
339
|
-
console.log(` Quick start:`);
|
|
340
|
-
console.log(` 1. openflows-setup # Configure API keys`);
|
|
341
|
-
console.log(` 2. openflows # Start the autonomous team`);
|
|
342
|
-
console.log(``);
|
|
343
|
-
console.log(` Docs: https://openflows.dev`);
|
|
344
|
-
console.log(``);
|
|
185
|
+
console.log(`[openflows] Installation complete!`);
|
|
345
186
|
}
|
|
346
187
|
|
|
347
|
-
main()
|
|
348
|
-
console.error('[openflows] Installation failed:', err.message);
|
|
349
|
-
process.exit(1);
|
|
350
|
-
});
|
|
188
|
+
main();
|