@myvillage/cli 1.3.0 → 1.5.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/README.md +14 -199
- package/package.json +11 -6
- package/src/agent-runtime/context.js +99 -0
- package/src/agent-runtime/daemon-entry.js +66 -0
- package/src/agent-runtime/daemon.js +65 -0
- package/src/agent-runtime/loop.js +281 -0
- package/src/agent-runtime/mcp-client.js +93 -0
- package/src/agent-runtime/scheduler.js +53 -0
- package/src/commands/agent-local.js +624 -0
- package/src/commands/agent.js +274 -42
- package/src/commands/bizreqs.js +965 -0
- package/src/commands/comment.js +5 -4
- package/src/commands/community.js +13 -12
- package/src/commands/create-app.js +253 -0
- package/src/commands/create-game.js +9 -8
- package/src/commands/deploy.js +101 -23
- package/src/commands/feed.js +4 -3
- package/src/commands/login.js +164 -76
- package/src/commands/logout.js +45 -7
- package/src/commands/post.js +14 -13
- package/src/commands/profile.js +4 -3
- package/src/commands/search.js +3 -2
- package/src/commands/soulprint.js +1379 -0
- package/src/commands/status.js +64 -28
- package/src/commands/vote.js +46 -18
- package/src/index.js +244 -1
- package/src/utils/agent-scaffolder.js +165 -0
- package/src/utils/api.js +135 -14
- package/src/utils/app-templates.js +2983 -0
- package/src/utils/brand.js +107 -0
- package/src/utils/config.js +17 -1
- package/src/utils/formatters.js +351 -18
- package/src/utils/local-agent.js +168 -0
- package/src/utils/soulprint-api.js +136 -0
- package/src/utils/soulprint-workspace.js +158 -0
package/src/commands/status.js
CHANGED
|
@@ -2,8 +2,9 @@ import { existsSync, readFileSync } from 'fs';
|
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
|
+
import { villageSpinner, brand } from '../utils/brand.js';
|
|
5
6
|
import { isAuthenticated } from '../utils/auth.js';
|
|
6
|
-
import { getMyGames,
|
|
7
|
+
import { getMyGames, getGameStatus } from '../utils/api.js';
|
|
7
8
|
|
|
8
9
|
function readPackageJson(dir) {
|
|
9
10
|
const pkgPath = join(dir, 'package.json');
|
|
@@ -48,33 +49,49 @@ export async function statusCommand() {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
async function showGameStatus(gameId) {
|
|
51
|
-
const spinner =
|
|
52
|
+
const spinner = villageSpinner('Fetching game status...').start();
|
|
52
53
|
|
|
53
54
|
try {
|
|
54
|
-
const
|
|
55
|
+
const data = await getGameStatus(gameId);
|
|
56
|
+
const game = data.game || data;
|
|
55
57
|
|
|
56
58
|
spinner.stop();
|
|
57
59
|
|
|
58
60
|
console.log();
|
|
59
|
-
console.log(chalk.bold(` ${
|
|
61
|
+
console.log(chalk.bold(` ${game.title || game.name || gameId}`));
|
|
60
62
|
console.log();
|
|
61
|
-
console.log(` Status: ${formatStatus(
|
|
62
|
-
console.log(` Play Count: ${
|
|
63
|
-
console.log(` MVT Earned: ${chalk.yellow(
|
|
64
|
-
console.log(` Last Updated: ${
|
|
63
|
+
console.log(` Status: ${formatStatus(game.status)}`);
|
|
64
|
+
console.log(` Play Count: ${brand.gold(game.playCount ?? 0)}`);
|
|
65
|
+
console.log(` MVT Earned: ${chalk.yellow(game.mvtAwarded ?? 0)} tokens`);
|
|
66
|
+
console.log(` Last Updated: ${brand.teal(formatDate(game.updatedAt || game.lastUpdated))}`);
|
|
65
67
|
|
|
66
|
-
if (
|
|
67
|
-
console.log(`
|
|
68
|
+
if (game.slug) {
|
|
69
|
+
console.log(` Slug: ${brand.teal(game.slug)}`);
|
|
68
70
|
}
|
|
71
|
+
|
|
72
|
+
// Show review history if available
|
|
73
|
+
if (game.reviews?.length > 0) {
|
|
74
|
+
console.log();
|
|
75
|
+
console.log(chalk.bold(' Review History:'));
|
|
76
|
+
for (const review of game.reviews) {
|
|
77
|
+
const action = formatReviewAction(review.action);
|
|
78
|
+
const date = formatDate(review.createdAt);
|
|
79
|
+
console.log(` ${action} - ${brand.teal(date)}`);
|
|
80
|
+
if (review.notes) {
|
|
81
|
+
console.log(` ${brand.teal(review.notes)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
69
86
|
console.log();
|
|
70
87
|
} catch (err) {
|
|
71
|
-
const message = err.response?.data?.message || err.message;
|
|
88
|
+
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
72
89
|
spinner.fail(`Failed to fetch game status: ${message}`);
|
|
73
90
|
}
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
async function showAllGames() {
|
|
77
|
-
const spinner =
|
|
94
|
+
const spinner = villageSpinner('Fetching your games...').start();
|
|
78
95
|
|
|
79
96
|
try {
|
|
80
97
|
const data = await getMyGames();
|
|
@@ -84,8 +101,8 @@ async function showAllGames() {
|
|
|
84
101
|
|
|
85
102
|
if (!games.length) {
|
|
86
103
|
console.log();
|
|
87
|
-
console.log(
|
|
88
|
-
console.log(
|
|
104
|
+
console.log(brand.teal(' No deployed games found.'));
|
|
105
|
+
console.log(brand.teal(' Create a game with "myvillage create-game" and deploy it!'));
|
|
89
106
|
console.log();
|
|
90
107
|
return;
|
|
91
108
|
}
|
|
@@ -95,32 +112,51 @@ async function showAllGames() {
|
|
|
95
112
|
console.log();
|
|
96
113
|
|
|
97
114
|
for (const game of games) {
|
|
98
|
-
console.log(` ${chalk.yellow(game.name || game.
|
|
99
|
-
console.log(` Status: ${formatStatus(game.status)} | Plays: ${
|
|
115
|
+
console.log(` ${chalk.yellow(game.title || game.name || game.id)}`);
|
|
116
|
+
console.log(` Status: ${formatStatus(game.status)} | Plays: ${brand.gold(game.playCount ?? 0)} | MVT: ${chalk.yellow(game.mvtAwarded ?? 0)}`);
|
|
100
117
|
|
|
101
|
-
if (game.
|
|
102
|
-
console.log(` ${
|
|
118
|
+
if (game.slug) {
|
|
119
|
+
console.log(` ${brand.teal(game.slug)}`);
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
console.log();
|
|
106
123
|
}
|
|
107
124
|
} catch (err) {
|
|
108
|
-
const message = err.response?.data?.message || err.message;
|
|
125
|
+
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
109
126
|
spinner.fail(`Failed to fetch games: ${message}`);
|
|
110
127
|
}
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
function formatStatus(status) {
|
|
114
131
|
switch (status) {
|
|
115
|
-
case '
|
|
116
|
-
return
|
|
117
|
-
case '
|
|
118
|
-
return chalk.yellow('
|
|
119
|
-
case '
|
|
120
|
-
return chalk.
|
|
121
|
-
case '
|
|
122
|
-
return chalk.
|
|
132
|
+
case 'DRAFT':
|
|
133
|
+
return brand.teal('Draft');
|
|
134
|
+
case 'SUBMITTED':
|
|
135
|
+
return chalk.yellow('Submitted');
|
|
136
|
+
case 'UNDER_REVIEW':
|
|
137
|
+
return chalk.yellow('Under Review');
|
|
138
|
+
case 'APPROVED':
|
|
139
|
+
return chalk.green('Approved');
|
|
140
|
+
case 'REJECTED':
|
|
141
|
+
return chalk.red('Rejected');
|
|
142
|
+
case 'PUBLISHED':
|
|
143
|
+
return chalk.green('Published');
|
|
144
|
+
case 'ARCHIVED':
|
|
145
|
+
return brand.teal('Archived');
|
|
146
|
+
default:
|
|
147
|
+
return brand.teal(status || 'Unknown');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function formatReviewAction(action) {
|
|
152
|
+
switch (action) {
|
|
153
|
+
case 'APPROVE':
|
|
154
|
+
return chalk.green('Approved');
|
|
155
|
+
case 'REJECT':
|
|
156
|
+
return chalk.red('Rejected');
|
|
157
|
+
case 'REQUEST_CHANGES':
|
|
158
|
+
return chalk.yellow('Changes Requested');
|
|
123
159
|
default:
|
|
124
|
-
return
|
|
160
|
+
return brand.teal(action || 'Unknown');
|
|
125
161
|
}
|
|
126
162
|
}
|
package/src/commands/vote.js
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
|
+
import { villageSpinner, brand } from '../utils/brand.js';
|
|
3
4
|
import { isAuthenticated } from '../utils/auth.js';
|
|
4
|
-
import { castVote,
|
|
5
|
+
import { castVote, listMyAgents } from '../utils/api.js';
|
|
5
6
|
|
|
6
7
|
export async function voteCommand(options) {
|
|
7
8
|
if (!isAuthenticated()) {
|
|
8
|
-
console.log(chalk.red('
|
|
9
|
+
console.log(chalk.red(' \u2717 Authentication required. Run \'myvillage login\' first.'));
|
|
9
10
|
return;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// Resolve agent identity if --as flag provided
|
|
14
|
+
let agentProfileId = null;
|
|
15
|
+
|
|
16
|
+
if (options.as) {
|
|
15
17
|
try {
|
|
16
|
-
await
|
|
17
|
-
|
|
18
|
+
const agentsResult = await listMyAgents();
|
|
19
|
+
const agents = agentsResult.data || agentsResult;
|
|
20
|
+
const agent = Array.isArray(agents) ? agents.find(a => a.handle === options.as) : null;
|
|
21
|
+
|
|
22
|
+
if (!agent) {
|
|
23
|
+
console.log(chalk.red(` \u2717 Agent @${options.as} not found. Run 'myvillage agent' to see your agents.\n`));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
agentProfileId = agent.id;
|
|
27
|
+
console.log(brand.teal(` Voting as agent @${agent.handle}\n`));
|
|
18
28
|
} catch (err) {
|
|
19
29
|
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
20
|
-
|
|
30
|
+
console.log(chalk.red(` \u2717 Failed to resolve agent: ${message}\n`));
|
|
31
|
+
return;
|
|
21
32
|
}
|
|
22
|
-
return;
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
// Determine target
|
|
@@ -27,21 +37,39 @@ export async function voteCommand(options) {
|
|
|
27
37
|
const targetId = options.post || options.comment;
|
|
28
38
|
|
|
29
39
|
if (!targetType || !targetId) {
|
|
30
|
-
console.log(chalk.red('
|
|
31
|
-
console.log(
|
|
32
|
-
console.log(
|
|
40
|
+
console.log(chalk.red(' \u2717 Specify a target: --post <id> or --comment <id>'));
|
|
41
|
+
console.log(brand.teal(' Example: myvillage vote --post abc123'));
|
|
42
|
+
console.log(brand.teal(' Example: myvillage vote --comment xyz789 --down\n'));
|
|
33
43
|
return;
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
const value = options.down ? -1 : 1;
|
|
37
|
-
const action = value === 1 ? 'Upvoting' : 'Downvoting';
|
|
38
|
-
const spinner =
|
|
47
|
+
const action = options.undo ? 'Removing vote from' : (value === 1 ? 'Upvoting' : 'Downvoting');
|
|
48
|
+
const spinner = villageSpinner(`${action} ${targetType.toLowerCase()}...`).start();
|
|
39
49
|
|
|
40
50
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
const data = { targetType, targetId, value };
|
|
52
|
+
if (agentProfileId) {
|
|
53
|
+
data.agentProfileId = agentProfileId;
|
|
54
|
+
}
|
|
55
|
+
const result = await castVote(data);
|
|
56
|
+
const resultAction = result?.data?.action;
|
|
57
|
+
|
|
58
|
+
if (options.undo) {
|
|
59
|
+
if (resultAction === 'removed') {
|
|
60
|
+
spinner.succeed(`Vote removed from ${targetType.toLowerCase()} ${targetId}`);
|
|
61
|
+
} else {
|
|
62
|
+
spinner.warn(`No existing vote to remove (${resultAction || 'created'}). A new vote was cast instead.`);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const emoji = value === 1 ? chalk.green('\u25b2') : chalk.red('\u25bc');
|
|
66
|
+
if (resultAction === 'removed') {
|
|
67
|
+
spinner.succeed(`Vote toggled off for ${targetType.toLowerCase()} ${targetId}`);
|
|
68
|
+
} else {
|
|
69
|
+
const word = value === 1 ? 'Upvoted' : 'Downvoted';
|
|
70
|
+
spinner.succeed(`${word} ${targetType.toLowerCase()} ${targetId} ${emoji}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
45
73
|
} catch (err) {
|
|
46
74
|
const message = err.response?.data?.error || err.response?.data?.message || err.message;
|
|
47
75
|
spinner.fail(`Failed to vote: ${message}`);
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,9 @@ import updateNotifier from 'update-notifier';
|
|
|
4
4
|
import { loginCommand } from './commands/login.js';
|
|
5
5
|
import { logoutCommand } from './commands/logout.js';
|
|
6
6
|
import { createGameCommand } from './commands/create-game.js';
|
|
7
|
+
import { createCommand } from './commands/create-app.js';
|
|
8
|
+
import { deployCommand } from './commands/deploy.js';
|
|
9
|
+
import { statusCommand } from './commands/status.js';
|
|
7
10
|
import { feedCommand } from './commands/feed.js';
|
|
8
11
|
import {
|
|
9
12
|
communityCommand,
|
|
@@ -15,6 +18,7 @@ import {
|
|
|
15
18
|
} from './commands/community.js';
|
|
16
19
|
import {
|
|
17
20
|
postCommand,
|
|
21
|
+
postViewCommand,
|
|
18
22
|
postCreateCommand,
|
|
19
23
|
postListCommand,
|
|
20
24
|
postEditCommand,
|
|
@@ -32,7 +36,35 @@ import {
|
|
|
32
36
|
agentDeleteCommand,
|
|
33
37
|
agentJoinCommand,
|
|
34
38
|
agentLeaveCommand,
|
|
39
|
+
agentRunCommand,
|
|
35
40
|
} from './commands/agent.js';
|
|
41
|
+
import {
|
|
42
|
+
agentStartCommand,
|
|
43
|
+
agentStopCommand,
|
|
44
|
+
agentStatusCommand,
|
|
45
|
+
agentLogsCommand,
|
|
46
|
+
agentAddToolCommand,
|
|
47
|
+
agentRemoveToolCommand,
|
|
48
|
+
} from './commands/agent-local.js';
|
|
49
|
+
import {
|
|
50
|
+
bizreqsNewCommand,
|
|
51
|
+
bizreqsSpecCommand,
|
|
52
|
+
bizreqsListCommand,
|
|
53
|
+
bizreqsStatusCommand,
|
|
54
|
+
bizreqsImportCommand,
|
|
55
|
+
} from './commands/bizreqs.js';
|
|
56
|
+
import {
|
|
57
|
+
soulprintInitCommand,
|
|
58
|
+
soulprintIngestCommand,
|
|
59
|
+
soulprintDatasetListCommand,
|
|
60
|
+
soulprintDatasetPullCommand,
|
|
61
|
+
soulprintTrainCommand,
|
|
62
|
+
soulprintJobsCommand,
|
|
63
|
+
soulprintJobDetailCommand,
|
|
64
|
+
soulprintPushCommand,
|
|
65
|
+
soulprintPublishCommand,
|
|
66
|
+
soulprintModelsCommand,
|
|
67
|
+
} from './commands/soulprint.js';
|
|
36
68
|
|
|
37
69
|
const require = createRequire(import.meta.url);
|
|
38
70
|
const pkg = require('../package.json');
|
|
@@ -53,6 +85,7 @@ export function run() {
|
|
|
53
85
|
program
|
|
54
86
|
.command('login')
|
|
55
87
|
.description('Authenticate with MyVillageOS')
|
|
88
|
+
.option('--no-browser', 'Manual login for headless environments (servers, SSH, etc.)')
|
|
56
89
|
.action(loginCommand);
|
|
57
90
|
|
|
58
91
|
program
|
|
@@ -65,6 +98,21 @@ export function run() {
|
|
|
65
98
|
.description('Create a new game project with interactive wizard')
|
|
66
99
|
.action(createGameCommand);
|
|
67
100
|
|
|
101
|
+
program
|
|
102
|
+
.command('create')
|
|
103
|
+
.description('Create a new project (portal, data labeling app, or game)')
|
|
104
|
+
.action(createCommand);
|
|
105
|
+
|
|
106
|
+
program
|
|
107
|
+
.command('deploy')
|
|
108
|
+
.description('Build and deploy your game to MyVillageOS')
|
|
109
|
+
.action(deployCommand);
|
|
110
|
+
|
|
111
|
+
program
|
|
112
|
+
.command('status')
|
|
113
|
+
.description('Check deployment status of your games')
|
|
114
|
+
.action(statusCommand);
|
|
115
|
+
|
|
68
116
|
// ── Network: Feed ───────────────────────────────────
|
|
69
117
|
|
|
70
118
|
program
|
|
@@ -85,6 +133,11 @@ export function run() {
|
|
|
85
133
|
.description('View a post by ID, or create one interactively')
|
|
86
134
|
.action(postCommand);
|
|
87
135
|
|
|
136
|
+
postCmd
|
|
137
|
+
.command('view <id>')
|
|
138
|
+
.description('View a post by ID')
|
|
139
|
+
.action(postViewCommand);
|
|
140
|
+
|
|
88
141
|
postCmd
|
|
89
142
|
.command('create')
|
|
90
143
|
.description('Create a new post (interactive)')
|
|
@@ -168,7 +221,8 @@ export function run() {
|
|
|
168
221
|
.option('--post <id>', 'Vote on a post')
|
|
169
222
|
.option('--comment <id>', 'Vote on a comment')
|
|
170
223
|
.option('-d, --down', 'Downvote instead of upvote')
|
|
171
|
-
.option('--undo
|
|
224
|
+
.option('--undo', 'Remove your existing vote (re-posts to toggle off)')
|
|
225
|
+
.option('--as <agent-handle>', 'Vote as one of your agents')
|
|
172
226
|
.action(voteCommand);
|
|
173
227
|
|
|
174
228
|
// ── Network: Search ─────────────────────────────────
|
|
@@ -227,5 +281,194 @@ export function run() {
|
|
|
227
281
|
.description('Leave a community as an agent')
|
|
228
282
|
.action(agentLeaveCommand);
|
|
229
283
|
|
|
284
|
+
agentCmd
|
|
285
|
+
.command('run <handle>')
|
|
286
|
+
.description('Run a workflow agent (WORKFLOW or HYBRID only)')
|
|
287
|
+
.option('--input <text>', 'Input data for the agent')
|
|
288
|
+
.action(agentRunCommand);
|
|
289
|
+
|
|
290
|
+
// Local agent lifecycle commands
|
|
291
|
+
agentCmd
|
|
292
|
+
.command('start <name>')
|
|
293
|
+
.description('Start a local agent daemon')
|
|
294
|
+
.action(agentStartCommand);
|
|
295
|
+
|
|
296
|
+
agentCmd
|
|
297
|
+
.command('stop <name>')
|
|
298
|
+
.description('Stop a local agent daemon')
|
|
299
|
+
.action(agentStopCommand);
|
|
300
|
+
|
|
301
|
+
agentCmd
|
|
302
|
+
.command('status [name]')
|
|
303
|
+
.description('Show local agent status')
|
|
304
|
+
.option('--remote', 'Include server-side activity from MAN')
|
|
305
|
+
.action(agentStatusCommand);
|
|
306
|
+
|
|
307
|
+
agentCmd
|
|
308
|
+
.command('logs <name>')
|
|
309
|
+
.description('View agent activity logs')
|
|
310
|
+
.option('--follow', 'Follow log output in real-time')
|
|
311
|
+
.option('--since <time>', 'Show logs since timestamp')
|
|
312
|
+
.action(agentLogsCommand);
|
|
313
|
+
|
|
314
|
+
agentCmd
|
|
315
|
+
.command('add-tool <name> <tool>')
|
|
316
|
+
.description('Add an MCP server tool to a local agent')
|
|
317
|
+
.action(agentAddToolCommand);
|
|
318
|
+
|
|
319
|
+
agentCmd
|
|
320
|
+
.command('remove-tool <name> <tool>')
|
|
321
|
+
.description('Remove an MCP server tool from a local agent')
|
|
322
|
+
.action(agentRemoveToolCommand);
|
|
323
|
+
|
|
324
|
+
// ── BizReqs: Business Requirements Pipeline ───────────
|
|
325
|
+
|
|
326
|
+
const bizreqsCmd = program
|
|
327
|
+
.command('bizreqs')
|
|
328
|
+
.description('Business requirements intake and project pipeline');
|
|
329
|
+
|
|
330
|
+
bizreqsCmd
|
|
331
|
+
.command('new')
|
|
332
|
+
.description('Start a new AI-guided business intake session')
|
|
333
|
+
.option('--org <name>', 'Organization name')
|
|
334
|
+
.option('--contact <name>', 'Contact name')
|
|
335
|
+
.option('--from-file <path>', 'Path to a text file with initial context')
|
|
336
|
+
.option('--from-url <url>', 'URL to the organization\'s website')
|
|
337
|
+
.option('--quick', 'Shortened flow (skip dream state, fewer exchanges)')
|
|
338
|
+
.action(bizreqsNewCommand);
|
|
339
|
+
|
|
340
|
+
bizreqsCmd
|
|
341
|
+
.command('spec <id>')
|
|
342
|
+
.description('Generate full project specification from an intake')
|
|
343
|
+
.option('--detail <level>', 'Detail level: brief, standard, comprehensive', 'standard')
|
|
344
|
+
.option('--output <dir>', 'Output directory for spec file', './specs')
|
|
345
|
+
.action(bizreqsSpecCommand);
|
|
346
|
+
|
|
347
|
+
bizreqsCmd
|
|
348
|
+
.command('list')
|
|
349
|
+
.description('List pipeline submissions')
|
|
350
|
+
.option('--status <status>', 'Filter: new, in-review, spec-ready, assigned, in-progress, delivered')
|
|
351
|
+
.option('--city <city>', 'Filter by city')
|
|
352
|
+
.option('--search <query>', 'Search by org name, solution, or ID')
|
|
353
|
+
.option('--sort <sort>', 'Sort: newest, oldest, priority', 'newest')
|
|
354
|
+
.option('-n, --limit <number>', 'Number of results', '50')
|
|
355
|
+
.option('--offset <number>', 'Pagination offset', '0')
|
|
356
|
+
.option('--json', 'Output raw JSON')
|
|
357
|
+
.action(bizreqsListCommand);
|
|
358
|
+
|
|
359
|
+
bizreqsCmd
|
|
360
|
+
.command('status <id>')
|
|
361
|
+
.description('Check project status')
|
|
362
|
+
.action(bizreqsStatusCommand);
|
|
363
|
+
|
|
364
|
+
bizreqsCmd
|
|
365
|
+
.command('import')
|
|
366
|
+
.description('Import requirements from a file or URL')
|
|
367
|
+
.option('--file <path>', 'Path to .txt or .md file')
|
|
368
|
+
.option('--url <url>', 'URL to fetch content from')
|
|
369
|
+
.option('--org <name>', 'Organization name')
|
|
370
|
+
.option('--contact <name>', 'Contact name')
|
|
371
|
+
.action(bizreqsImportCommand);
|
|
372
|
+
|
|
373
|
+
// ── SoulPrint Studio: Model Training Pipeline ───────────
|
|
374
|
+
|
|
375
|
+
const soulprintCmd = program
|
|
376
|
+
.command('soulprint')
|
|
377
|
+
.description('SoulPrint Studio \u2014 datasets, training, and model publishing');
|
|
378
|
+
|
|
379
|
+
soulprintCmd
|
|
380
|
+
.command('init')
|
|
381
|
+
.description('Initialize local training workspace')
|
|
382
|
+
.option('--skip-python', 'Skip Python venv setup')
|
|
383
|
+
.option('--skip-scripts', 'Skip training script download')
|
|
384
|
+
.action(soulprintInitCommand);
|
|
385
|
+
|
|
386
|
+
soulprintCmd
|
|
387
|
+
.command('ingest <path>')
|
|
388
|
+
.description('Ingest training data into a dataset')
|
|
389
|
+
.requiredOption('--dataset <slug>', 'Target dataset slug')
|
|
390
|
+
.requiredOption('--type <type>', 'Data type: text, image, audio, structured, multimodal')
|
|
391
|
+
.option('--source <source>', 'Ingestion source label', 'CLI')
|
|
392
|
+
.option('--captions <path>', 'Path to captions file (image/multimodal)')
|
|
393
|
+
.option('--transcriptions <path>', 'Path to transcriptions file (audio)')
|
|
394
|
+
.option('--schema <path>', 'Path to schema JSON file (structured)')
|
|
395
|
+
.option('--recursive', 'Recurse into subdirectories')
|
|
396
|
+
.option('--glob <pattern>', 'File glob pattern to filter')
|
|
397
|
+
.option('--split <split>', 'Assign all items to a split: train, validation, test')
|
|
398
|
+
.option('--dry-run', 'Show what would be ingested without uploading')
|
|
399
|
+
.option('--concurrency <n>', 'Parallel upload limit', '5')
|
|
400
|
+
.action(soulprintIngestCommand);
|
|
401
|
+
|
|
402
|
+
const soulprintDatasetCmd = soulprintCmd
|
|
403
|
+
.command('datasets')
|
|
404
|
+
.description('Manage training datasets');
|
|
405
|
+
|
|
406
|
+
soulprintDatasetCmd
|
|
407
|
+
.command('list')
|
|
408
|
+
.description('List available datasets on SoulPrint Studio')
|
|
409
|
+
.option('--type <type>', 'Filter by type: text, image, audio, structured, multimodal')
|
|
410
|
+
.option('--status <status>', 'Filter by status: collecting, ready, training, archived')
|
|
411
|
+
.option('--json', 'Output raw JSON')
|
|
412
|
+
.action(soulprintDatasetListCommand);
|
|
413
|
+
|
|
414
|
+
soulprintDatasetCmd
|
|
415
|
+
.command('pull <slug>')
|
|
416
|
+
.description('Download a dataset to your local machine')
|
|
417
|
+
.option('--version <number>', 'Specific version (default: latest frozen)')
|
|
418
|
+
.option('--split <split>', 'Download only a specific split: train, validation, test')
|
|
419
|
+
.option('--force', 'Re-download even if already present locally')
|
|
420
|
+
.action(soulprintDatasetPullCommand);
|
|
421
|
+
|
|
422
|
+
soulprintCmd
|
|
423
|
+
.command('train')
|
|
424
|
+
.description('Run model training locally')
|
|
425
|
+
.requiredOption('--type <type>', 'Training type: text, image, audio, structured, multimodal')
|
|
426
|
+
.requiredOption('--dataset <slug>', 'Dataset slug to train on')
|
|
427
|
+
.option('--version <number>', 'Dataset version (default: latest)')
|
|
428
|
+
.option('--base <model>', 'Base model identifier')
|
|
429
|
+
.option('--method <method>', 'Training method')
|
|
430
|
+
.option('--config <path>', 'Path to training config YAML file')
|
|
431
|
+
.option('--name <name>', 'Name for the resulting model')
|
|
432
|
+
.option('--dry-run', 'Validate config and dataset without starting training')
|
|
433
|
+
.action(soulprintTrainCommand);
|
|
434
|
+
|
|
435
|
+
soulprintCmd
|
|
436
|
+
.command('jobs [jobId]')
|
|
437
|
+
.description('View training job status')
|
|
438
|
+
.option('--status <status>', 'Filter by status')
|
|
439
|
+
.option('--json', 'Output raw JSON')
|
|
440
|
+
.action((jobId, options) => {
|
|
441
|
+
if (jobId) return soulprintJobDetailCommand(jobId, options);
|
|
442
|
+
return soulprintJobsCommand(options);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
soulprintCmd
|
|
446
|
+
.command('models')
|
|
447
|
+
.description('List models in the registry')
|
|
448
|
+
.option('--status <status>', 'Filter: draft, validated, published, rejected')
|
|
449
|
+
.option('--type <type>', 'Filter: text, image, audio, structured, multimodal')
|
|
450
|
+
.option('--json', 'Output raw JSON')
|
|
451
|
+
.action(soulprintModelsCommand);
|
|
452
|
+
|
|
453
|
+
soulprintCmd
|
|
454
|
+
.command('push <path>')
|
|
455
|
+
.description('Upload locally trained model artifacts to SoulPrint Studio')
|
|
456
|
+
.requiredOption('--name <name>', 'Model name')
|
|
457
|
+
.requiredOption('--type <type>', 'Model type: text, image, audio, structured, multimodal')
|
|
458
|
+
.option('--base <model>', 'Base model it was trained from')
|
|
459
|
+
.option('--method <method>', 'Training method used')
|
|
460
|
+
.option('--job <jobId>', 'Link to an existing training job')
|
|
461
|
+
.option('--description <text>', 'Model description')
|
|
462
|
+
.action(soulprintPushCommand);
|
|
463
|
+
|
|
464
|
+
soulprintCmd
|
|
465
|
+
.command('publish <modelSlug>')
|
|
466
|
+
.description('Publish a validated model to the MyVillage platform')
|
|
467
|
+
.option('--villager <id>', 'Target villager ID to own the model')
|
|
468
|
+
.option('--villages <ids>', 'Comma-separated village IDs to associate')
|
|
469
|
+
.option('--tier <tier>', 'Model tier: FREE, BASIC, PRO, ENTERPRISE', 'FREE')
|
|
470
|
+
.option('--public', 'Make the model publicly available')
|
|
471
|
+
.action(soulprintPublishCommand);
|
|
472
|
+
|
|
230
473
|
program.parse();
|
|
231
474
|
}
|