@girardmedia/bootspring 2.1.3 → 2.2.1
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/bootspring.js +157 -83
- package/claude-commands/agent.md +34 -0
- package/claude-commands/bs.md +31 -0
- package/claude-commands/build.md +25 -0
- package/claude-commands/skill.md +31 -0
- package/claude-commands/todo.md +25 -0
- package/dist/core/index.d.ts +5814 -0
- package/dist/core.js +5779 -0
- package/dist/index.js +93883 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp-server.js +2298 -0
- package/generators/api-docs.js +3 -3
- package/generators/decisions.js +14 -14
- package/generators/health.js +6 -6
- package/generators/sprint.js +4 -4
- package/generators/templates/build-planning.template.js +2 -2
- package/generators/visual-doc-generator.js +1 -1
- package/package.json +22 -68
- package/cli/agent.js +0 -799
- package/cli/auth.js +0 -896
- package/cli/billing.js +0 -320
- package/cli/build.js +0 -1442
- package/cli/dashboard.js +0 -123
- package/cli/init.js +0 -669
- package/cli/mcp.js +0 -240
- package/cli/orchestrator.js +0 -240
- package/cli/project.js +0 -825
- package/cli/quality.js +0 -281
- package/cli/skill.js +0 -503
- package/cli/switch.js +0 -453
- package/cli/todo.js +0 -629
- package/cli/update.js +0 -132
- package/core/api-client.d.ts +0 -69
- package/core/api-client.js +0 -1482
- package/core/auth.d.ts +0 -98
- package/core/auth.js +0 -737
- package/core/build-orchestrator.js +0 -508
- package/core/build-state.js +0 -612
- package/core/config.d.ts +0 -106
- package/core/config.js +0 -1328
- package/core/context-loader.js +0 -580
- package/core/context.d.ts +0 -61
- package/core/context.js +0 -327
- package/core/entitlements.d.ts +0 -70
- package/core/entitlements.js +0 -322
- package/core/index.d.ts +0 -53
- package/core/index.js +0 -62
- package/core/mcp-config.js +0 -115
- package/core/policies.d.ts +0 -43
- package/core/policies.js +0 -113
- package/core/policy-matrix.js +0 -303
- package/core/project-activity.js +0 -175
- package/core/redaction.d.ts +0 -5
- package/core/redaction.js +0 -63
- package/core/self-update.js +0 -259
- package/core/session.js +0 -353
- package/core/task-extractor.js +0 -1098
- package/core/telemetry.d.ts +0 -55
- package/core/telemetry.js +0 -617
- package/core/tier-enforcement.js +0 -928
- package/core/utils.d.ts +0 -90
- package/core/utils.js +0 -455
- package/core/validation.js +0 -572
- package/mcp/server.d.ts +0 -57
- package/mcp/server.js +0 -264
package/cli/mcp.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring MCP Command
|
|
3
|
-
* Manage the hosted MCP proxy configuration.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const config = require('../core/config');
|
|
7
|
-
const utils = require('../core/utils');
|
|
8
|
-
const api = require('../core/api-client');
|
|
9
|
-
const auth = require('../core/auth');
|
|
10
|
-
const { ensureProjectMcpConfig } = require('../core/mcp-config');
|
|
11
|
-
const { redactErrorMessage } = require('../core/redaction');
|
|
12
|
-
|
|
13
|
-
const C = utils.COLORS;
|
|
14
|
-
|
|
15
|
-
async function startServer() {
|
|
16
|
-
const server = require('../mcp/server.js');
|
|
17
|
-
await server.main();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function generateConfig() {
|
|
21
|
-
const cfg = config.load();
|
|
22
|
-
const spinner = utils.createSpinner('Generating .mcp.json').start();
|
|
23
|
-
const result = ensureProjectMcpConfig(cfg._projectRoot, { createIfMissing: true });
|
|
24
|
-
|
|
25
|
-
if (result.status === 'created') {
|
|
26
|
-
spinner.succeed(`Created ${result.path}`);
|
|
27
|
-
} else if (result.status === 'updated' || result.status === 'added') {
|
|
28
|
-
spinner.succeed(`Updated ${result.path}`);
|
|
29
|
-
} else if (result.status === 'unchanged') {
|
|
30
|
-
spinner.succeed(`Already configured ${result.path}`);
|
|
31
|
-
} else {
|
|
32
|
-
spinner.fail(`Failed to configure .mcp.json${result.error ? `: ${result.error.message}` : ''}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function showStatus() {
|
|
37
|
-
const cfg = config.load();
|
|
38
|
-
console.log(`\n${C.cyan}${C.bold}Bootspring MCP Proxy${C.reset}\n`);
|
|
39
|
-
console.log(` Project root: ${cfg._projectRoot}`);
|
|
40
|
-
console.log(` Config file: ${cfg._configPath || 'not found'}`);
|
|
41
|
-
console.log(` Authenticated: ${auth.isAuthenticated() ? 'yes' : 'no'}`);
|
|
42
|
-
|
|
43
|
-
if (!auth.isAuthenticated()) {
|
|
44
|
-
console.log(`\n${C.dim}Run 'bootspring auth login' to view hosted tools and resources.${C.reset}\n`);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const [toolsResponse, resourcesResponse] = await Promise.all([
|
|
50
|
-
api.listMcpTools(),
|
|
51
|
-
api.listMcpResources()
|
|
52
|
-
]);
|
|
53
|
-
|
|
54
|
-
const tools = toolsResponse.tools || [];
|
|
55
|
-
const resources = resourcesResponse.resources || [];
|
|
56
|
-
|
|
57
|
-
console.log(`\n${C.bold}Hosted Tools${C.reset}`);
|
|
58
|
-
tools.forEach((tool) => console.log(` ${C.cyan}${tool.name}${C.reset} ${C.dim}${tool.description}${C.reset}`));
|
|
59
|
-
|
|
60
|
-
console.log(`\n${C.bold}Hosted Resources${C.reset}`);
|
|
61
|
-
resources.forEach((resource) => console.log(` ${C.cyan}${resource.uri}${C.reset} ${C.dim}${resource.description}${C.reset}`));
|
|
62
|
-
console.log();
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.log(`\n${C.red}Failed to load hosted MCP metadata: ${redactErrorMessage(error)}${C.reset}\n`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function testMcp() {
|
|
69
|
-
console.log(`\n${C.cyan}${C.bold}Bootspring MCP Test${C.reset}\n`);
|
|
70
|
-
|
|
71
|
-
if (!auth.isAuthenticated()) {
|
|
72
|
-
console.log(`${C.yellow}Authentication required${C.reset}`);
|
|
73
|
-
console.log(`${C.dim}Run 'bootspring auth login' first${C.reset}\n`);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const toolSpinner = utils.createSpinner('Checking hosted tools').start();
|
|
78
|
-
try {
|
|
79
|
-
const toolsResponse = await api.listMcpTools();
|
|
80
|
-
const count = (toolsResponse.tools || []).length;
|
|
81
|
-
toolSpinner.succeed(`Loaded ${count} hosted tool${count === 1 ? '' : 's'}`);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
toolSpinner.fail(redactErrorMessage(error));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const resourceSpinner = utils.createSpinner('Checking hosted resources').start();
|
|
88
|
-
try {
|
|
89
|
-
const resourcesResponse = await api.listMcpResources();
|
|
90
|
-
const count = (resourcesResponse.resources || []).length;
|
|
91
|
-
resourceSpinner.succeed(`Loaded ${count} hosted resource${count === 1 ? '' : 's'}`);
|
|
92
|
-
} catch (error) {
|
|
93
|
-
resourceSpinner.fail(redactErrorMessage(error));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const connectorSpinner = utils.createSpinner('Checking managed connectors').start();
|
|
98
|
-
try {
|
|
99
|
-
const connectorsResponse = await api.listMcpConnectors();
|
|
100
|
-
const count = (connectorsResponse.connectors || []).length;
|
|
101
|
-
connectorSpinner.succeed(`Loaded ${count} managed connector${count === 1 ? '' : 's'}`);
|
|
102
|
-
} catch (error) {
|
|
103
|
-
connectorSpinner.fail(redactErrorMessage(error));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
console.log();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async function listConnectors() {
|
|
110
|
-
console.log(`\n${C.cyan}${C.bold}Managed Connectors${C.reset}\n`);
|
|
111
|
-
|
|
112
|
-
if (!auth.isAuthenticated()) {
|
|
113
|
-
console.log(`${C.yellow}Authentication required${C.reset}`);
|
|
114
|
-
console.log(`${C.dim}Run 'bootspring auth login' first${C.reset}\n`);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const spinner = utils.createSpinner('Fetching connectors').start();
|
|
119
|
-
try {
|
|
120
|
-
const response = await api.listMcpConnectors();
|
|
121
|
-
const connectors = response.connectors || [];
|
|
122
|
-
spinner.stop();
|
|
123
|
-
|
|
124
|
-
if (connectors.length === 0) {
|
|
125
|
-
console.log(`${C.dim}No managed connectors available.${C.reset}\n`);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
connectors.forEach((connector) => {
|
|
130
|
-
const status = connector.active
|
|
131
|
-
? `${C.green}active${C.reset}`
|
|
132
|
-
: connector.accessible
|
|
133
|
-
? `${C.dim}available${C.reset}`
|
|
134
|
-
: `${C.yellow}requires ${connector.requiredTier}${C.reset}`;
|
|
135
|
-
|
|
136
|
-
console.log(` ${C.cyan}${connector.id}${C.reset}`);
|
|
137
|
-
console.log(` ${connector.description}`);
|
|
138
|
-
console.log(` Status: ${status}`);
|
|
139
|
-
console.log();
|
|
140
|
-
});
|
|
141
|
-
} catch (error) {
|
|
142
|
-
spinner.fail(redactErrorMessage(error));
|
|
143
|
-
console.log();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async function toggleConnector(connectorId, enabled) {
|
|
148
|
-
if (!connectorId) {
|
|
149
|
-
console.log(`${C.red}Connector id required${C.reset}`);
|
|
150
|
-
console.log(`${C.dim}Usage: bootspring mcp connectors ${enabled ? 'enable' : 'disable'} <id>${C.reset}\n`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const spinner = utils.createSpinner(`${enabled ? 'Enabling' : 'Disabling'} ${connectorId}`).start();
|
|
155
|
-
try {
|
|
156
|
-
const response = await api.setMcpConnectorEnabled(connectorId, enabled);
|
|
157
|
-
const updated = response.updated;
|
|
158
|
-
spinner.succeed(`${updated?.name || connectorId} ${enabled ? 'enabled' : 'disabled'}`);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
spinner.fail(redactErrorMessage(error));
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
console.log();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function handleConnectors(args) {
|
|
167
|
-
const action = args[0];
|
|
168
|
-
|
|
169
|
-
if (!action || action === 'list') {
|
|
170
|
-
await listConnectors();
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (action === 'enable') {
|
|
175
|
-
await toggleConnector(args[1], true);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (action === 'disable') {
|
|
180
|
-
await toggleConnector(args[1], false);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
console.log(`${C.red}Unknown connector action: ${action}${C.reset}\n`);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function showHelp() {
|
|
188
|
-
console.log(`
|
|
189
|
-
${C.cyan}${C.bold}Bootspring MCP${C.reset}
|
|
190
|
-
|
|
191
|
-
${C.bold}Usage:${C.reset}
|
|
192
|
-
bootspring mcp
|
|
193
|
-
bootspring mcp status
|
|
194
|
-
bootspring mcp test
|
|
195
|
-
bootspring mcp config
|
|
196
|
-
bootspring mcp connectors
|
|
197
|
-
`);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async function run(args) {
|
|
201
|
-
const subcommand = args[0];
|
|
202
|
-
|
|
203
|
-
if (!subcommand) {
|
|
204
|
-
await startServer();
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
switch (subcommand) {
|
|
209
|
-
case 'status':
|
|
210
|
-
await showStatus();
|
|
211
|
-
break;
|
|
212
|
-
case 'test':
|
|
213
|
-
await testMcp();
|
|
214
|
-
break;
|
|
215
|
-
case 'config':
|
|
216
|
-
case 'init':
|
|
217
|
-
case 'setup':
|
|
218
|
-
generateConfig();
|
|
219
|
-
break;
|
|
220
|
-
case 'connectors':
|
|
221
|
-
case 'connector':
|
|
222
|
-
await handleConnectors(args.slice(1));
|
|
223
|
-
break;
|
|
224
|
-
case 'help':
|
|
225
|
-
case '-h':
|
|
226
|
-
case '--help':
|
|
227
|
-
showHelp();
|
|
228
|
-
break;
|
|
229
|
-
default:
|
|
230
|
-
console.log(`${C.red}Unknown subcommand: ${subcommand}${C.reset}\n`);
|
|
231
|
-
showHelp();
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
module.exports = {
|
|
236
|
-
run,
|
|
237
|
-
startServer,
|
|
238
|
-
showStatus,
|
|
239
|
-
testMcp
|
|
240
|
-
};
|
package/cli/orchestrator.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bootspring Orchestrator Command
|
|
3
|
-
* Thin client for hosted workflow orchestration.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const api = require('../core/api-client');
|
|
7
|
-
const auth = require('../core/auth');
|
|
8
|
-
const config = require('../core/config');
|
|
9
|
-
const utils = require('../core/utils');
|
|
10
|
-
|
|
11
|
-
const C = utils.COLORS;
|
|
12
|
-
|
|
13
|
-
function buildProjectContext() {
|
|
14
|
-
const cfg = config.load();
|
|
15
|
-
const techStack = [
|
|
16
|
-
cfg.stack?.framework,
|
|
17
|
-
cfg.stack?.language,
|
|
18
|
-
cfg.stack?.database,
|
|
19
|
-
cfg.stack?.hosting
|
|
20
|
-
].filter(Boolean);
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
name: cfg.project?.name,
|
|
24
|
-
projectType: cfg.stack?.framework || 'unknown',
|
|
25
|
-
techStack,
|
|
26
|
-
cwd: process.cwd()
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function requireAuth() {
|
|
31
|
-
if (auth.isAuthenticated()) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
console.log(`${C.yellow}Not logged in${C.reset}`);
|
|
36
|
-
console.log(`${C.dim}Run 'bootspring auth login' first${C.reset}\n`);
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function listWorkflows() {
|
|
41
|
-
console.log(`\n${C.cyan}${C.bold}Hosted Workflows${C.reset}\n`);
|
|
42
|
-
const response = await api.listWorkflows();
|
|
43
|
-
const workflows = response.workflows || [];
|
|
44
|
-
|
|
45
|
-
if (workflows.length === 0) {
|
|
46
|
-
console.log(`${C.dim}No workflows available for your account.${C.reset}\n`);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
for (const workflow of workflows) {
|
|
51
|
-
const suffix = workflow.accessible ? '' : ` ${C.yellow}(Upgrade Required)${C.reset}`;
|
|
52
|
-
console.log(` ${C.cyan}${workflow.id}${C.reset}${suffix}`);
|
|
53
|
-
console.log(` ${C.dim}${workflow.description}${C.reset}\n`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function showWorkflow(id) {
|
|
58
|
-
if (!id) {
|
|
59
|
-
await listWorkflows();
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const response = await api.getWorkflow(id);
|
|
64
|
-
const workflow = response.workflow || response;
|
|
65
|
-
|
|
66
|
-
console.log(`\n${C.cyan}${C.bold}${workflow.name || workflow.id}${C.reset}\n`);
|
|
67
|
-
console.log(`${workflow.description || 'No description available.'}\n`);
|
|
68
|
-
|
|
69
|
-
if (Array.isArray(workflow.steps) && workflow.steps.length > 0) {
|
|
70
|
-
console.log(`${C.bold}Steps${C.reset}`);
|
|
71
|
-
workflow.steps.forEach((step, index) => {
|
|
72
|
-
const label = step.name || step.title || `Step ${index + 1}`;
|
|
73
|
-
console.log(` ${index + 1}. ${label}`);
|
|
74
|
-
});
|
|
75
|
-
console.log();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (Array.isArray(workflow.agents) && workflow.agents.length > 0) {
|
|
79
|
-
console.log(`${C.bold}Agents${C.reset}`);
|
|
80
|
-
console.log(` ${workflow.agents.join(', ')}`);
|
|
81
|
-
console.log();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async function analyze(task) {
|
|
86
|
-
console.log(`\n${C.cyan}${C.bold}Orchestrator Analysis${C.reset}\n`);
|
|
87
|
-
const response = await api.analyzeContext(buildProjectContext(), task || '', []);
|
|
88
|
-
const recommendations = response.recommendations || {};
|
|
89
|
-
const workflows = recommendations.workflows || [];
|
|
90
|
-
const agents = recommendations.agents || [];
|
|
91
|
-
|
|
92
|
-
if (workflows.length === 0 && agents.length === 0) {
|
|
93
|
-
console.log(`${C.dim}No hosted recommendations were returned.${C.reset}\n`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (workflows.length > 0) {
|
|
98
|
-
console.log(`${C.bold}Recommended Workflows${C.reset}`);
|
|
99
|
-
workflows.forEach((workflow) => {
|
|
100
|
-
console.log(` ${C.cyan}${workflow.id || workflow.name}${C.reset} ${C.dim}(score ${workflow.score || 0})${C.reset}`);
|
|
101
|
-
});
|
|
102
|
-
console.log();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (agents.length > 0) {
|
|
106
|
-
console.log(`${C.bold}Suggested Agents${C.reset}`);
|
|
107
|
-
agents.forEach((agent) => {
|
|
108
|
-
console.log(` ${C.cyan}${agent.id}${C.reset} ${C.dim}${agent.reason}${C.reset}`);
|
|
109
|
-
});
|
|
110
|
-
console.log();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async function suggest(task) {
|
|
115
|
-
console.log(`\n${C.cyan}${C.bold}Hosted Suggestions${C.reset}\n`);
|
|
116
|
-
const response = await api.getSuggestions({ task, cwd: process.cwd() }, 'agent');
|
|
117
|
-
const suggestions = response.suggestions || [];
|
|
118
|
-
|
|
119
|
-
if (suggestions.length === 0) {
|
|
120
|
-
console.log(`${C.dim}No suggestions returned.${C.reset}\n`);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
suggestions.forEach((suggestion) => {
|
|
125
|
-
if (suggestion.agent) {
|
|
126
|
-
console.log(` ${C.cyan}${suggestion.agent}${C.reset} ${C.dim}${suggestion.reason || ''}${C.reset}`);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (suggestion.step?.name) {
|
|
131
|
-
console.log(` ${C.cyan}${suggestion.step.name}${C.reset} ${C.dim}${suggestion.message || ''}${C.reset}`);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
console.log(` ${C.cyan}${suggestion.type || 'suggestion'}${C.reset} ${C.dim}${JSON.stringify(suggestion)}${C.reset}`);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
console.log();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async function startWorkflow(id) {
|
|
142
|
-
if (!id) {
|
|
143
|
-
console.log(`${C.red}Workflow id required${C.reset}`);
|
|
144
|
-
console.log(`${C.dim}Usage: bootspring orchestrator start <workflow-id>${C.reset}\n`);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const response = await api.startWorkflow(id, buildProjectContext(), {});
|
|
149
|
-
const execution = response.execution || {};
|
|
150
|
-
|
|
151
|
-
console.log(`\n${C.cyan}${C.bold}Workflow Started${C.reset}\n`);
|
|
152
|
-
console.log(`${response.message || `Started ${id}`}\n`);
|
|
153
|
-
|
|
154
|
-
if (Array.isArray(execution.steps) && execution.steps.length > 0) {
|
|
155
|
-
console.log(`${C.bold}Steps${C.reset}`);
|
|
156
|
-
execution.steps.forEach((step, index) => {
|
|
157
|
-
console.log(` ${index + 1}. ${step.name || step.title || `Step ${index + 1}`}`);
|
|
158
|
-
});
|
|
159
|
-
console.log();
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async function status() {
|
|
164
|
-
const response = await api.listWorkflows();
|
|
165
|
-
const workflows = response.workflows || [];
|
|
166
|
-
const accessible = workflows.filter((workflow) => workflow.accessible).length;
|
|
167
|
-
|
|
168
|
-
console.log(`\n${C.cyan}${C.bold}Orchestrator Status${C.reset}\n`);
|
|
169
|
-
console.log(` Tier: ${auth.getTier()}`);
|
|
170
|
-
console.log(` Hosted workflows: ${workflows.length}`);
|
|
171
|
-
console.log(` Accessible: ${accessible}\n`);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function showHelp() {
|
|
175
|
-
console.log(`
|
|
176
|
-
${C.cyan}${C.bold}Bootspring Orchestrator${C.reset}
|
|
177
|
-
|
|
178
|
-
${C.bold}Usage:${C.reset}
|
|
179
|
-
bootspring orchestrator <command> [args]
|
|
180
|
-
|
|
181
|
-
${C.bold}Commands:${C.reset}
|
|
182
|
-
${C.cyan}workflows${C.reset} List hosted workflows
|
|
183
|
-
${C.cyan}workflow${C.reset} <id> Show workflow details
|
|
184
|
-
${C.cyan}analyze${C.reset} <task> Analyze project context
|
|
185
|
-
${C.cyan}suggest${C.reset} <task> Get hosted suggestions
|
|
186
|
-
${C.cyan}start${C.reset} <id> Start a hosted workflow
|
|
187
|
-
${C.cyan}status${C.reset} Show orchestrator access
|
|
188
|
-
`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async function run(args) {
|
|
192
|
-
const subcommand = args[0] || 'status';
|
|
193
|
-
const param = args.slice(1).join(' ');
|
|
194
|
-
|
|
195
|
-
if (subcommand === 'help' || subcommand === '-h' || subcommand === '--help') {
|
|
196
|
-
showHelp();
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (!requireAuth()) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
switch (subcommand) {
|
|
206
|
-
case 'workflows':
|
|
207
|
-
case 'list':
|
|
208
|
-
await listWorkflows();
|
|
209
|
-
break;
|
|
210
|
-
case 'workflow':
|
|
211
|
-
await showWorkflow(args[1]);
|
|
212
|
-
break;
|
|
213
|
-
case 'analyze':
|
|
214
|
-
await analyze(param);
|
|
215
|
-
break;
|
|
216
|
-
case 'suggest':
|
|
217
|
-
await suggest(param);
|
|
218
|
-
break;
|
|
219
|
-
case 'start':
|
|
220
|
-
await startWorkflow(args[1]);
|
|
221
|
-
break;
|
|
222
|
-
case 'status':
|
|
223
|
-
await status();
|
|
224
|
-
break;
|
|
225
|
-
default:
|
|
226
|
-
console.log(`${C.red}Unknown subcommand: ${subcommand}${C.reset}\n`);
|
|
227
|
-
showHelp();
|
|
228
|
-
}
|
|
229
|
-
} catch (error) {
|
|
230
|
-
if (error.status === 403) {
|
|
231
|
-
console.log(`${C.yellow}This feature requires a paid Bootspring plan.${C.reset}`);
|
|
232
|
-
console.log(`${C.dim}Upgrade: https://bootspring.com/pricing${C.reset}\n`);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
throw error;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
module.exports = { run };
|