@wenrwa/marketplace-cli 0.2.0 → 0.4.0
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 +82 -7
- package/dist/__tests__/bridge-config-mcp.test.d.ts +1 -0
- package/dist/__tests__/bridge-config-mcp.test.js +117 -0
- package/dist/__tests__/bridge-server.test.d.ts +1 -0
- package/dist/__tests__/bridge-server.test.js +137 -0
- package/dist/__tests__/bridge-session-manager.test.d.ts +1 -0
- package/dist/__tests__/bridge-session-manager.test.js +104 -0
- package/dist/__tests__/config.test.js +3 -3
- package/dist/bridge/config.d.ts +11 -0
- package/dist/bridge/config.js +79 -0
- package/dist/bridge/mcpRegister.d.ts +28 -0
- package/dist/bridge/mcpRegister.js +35 -0
- package/dist/bridge/realPty.d.ts +2 -0
- package/dist/bridge/realPty.js +88 -0
- package/dist/bridge/server.d.ts +14 -0
- package/dist/bridge/server.js +182 -0
- package/dist/bridge/sessionManager.d.ts +42 -0
- package/dist/bridge/sessionManager.js +79 -0
- package/dist/commands/agent.js +98 -1
- package/dist/commands/apps.js +79 -0
- package/dist/commands/bounty.js +374 -7
- package/dist/commands/bridge.d.ts +3 -0
- package/dist/commands/bridge.js +122 -0
- package/dist/commands/credits.d.ts +2 -0
- package/dist/commands/credits.js +128 -0
- package/dist/commands/keys.d.ts +2 -0
- package/dist/commands/keys.js +72 -0
- package/dist/commands/prompts.d.ts +2 -0
- package/dist/commands/prompts.js +136 -0
- package/dist/commands/repo.d.ts +2 -0
- package/dist/commands/repo.js +197 -0
- package/dist/commands/workspace.d.ts +1 -0
- package/dist/commands/workspace.js +294 -12
- package/dist/index.js +12 -1
- package/dist/utils/client.d.ts +1 -0
- package/dist/utils/client.js +3 -0
- package/dist/utils/config.js +3 -3
- package/package.json +10 -15
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.keysCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const client_1 = require("../utils/client");
|
|
10
|
+
const format_1 = require("../utils/format");
|
|
11
|
+
exports.keysCommand = new commander_1.Command('keys').description('API key management');
|
|
12
|
+
exports.keysCommand
|
|
13
|
+
.command('generate')
|
|
14
|
+
.option('--name <name>', 'Human-readable name for the key')
|
|
15
|
+
.description('Generate a new API key')
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
try {
|
|
18
|
+
const client = (0, client_1.getClient)();
|
|
19
|
+
const data = await client.post('/keys/generate', { name: opts.name });
|
|
20
|
+
const rec = data.keyRecord;
|
|
21
|
+
(0, format_1.success)('API key generated');
|
|
22
|
+
console.log(` ID: ${rec.id}`);
|
|
23
|
+
console.log(` Name: ${rec.name || chalk_1.default.dim('(none)')}`);
|
|
24
|
+
console.log(` Prefix: ${rec.keyPrefix}`);
|
|
25
|
+
console.log();
|
|
26
|
+
console.log(chalk_1.default.yellow.bold(' Full key (shown once — save it now):'));
|
|
27
|
+
console.log(chalk_1.default.yellow(` ${data.key}`));
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
(0, format_1.error)(err.message);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
exports.keysCommand
|
|
34
|
+
.command('list')
|
|
35
|
+
.description('List your API keys')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
try {
|
|
38
|
+
const client = (0, client_1.getClient)();
|
|
39
|
+
const data = await client.get('/keys');
|
|
40
|
+
const keys = data.keys || [];
|
|
41
|
+
if (keys.length === 0) {
|
|
42
|
+
console.log(chalk_1.default.dim(' No API keys'));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
(0, format_1.heading)('API Keys');
|
|
46
|
+
console.log((0, format_1.makeTable)(['ID', 'Name', 'Prefix', 'Permissions', 'Last Used', 'Active'], keys.map((k) => [
|
|
47
|
+
(0, format_1.shorten)(k.id),
|
|
48
|
+
k.name || chalk_1.default.dim('—'),
|
|
49
|
+
k.keyPrefix,
|
|
50
|
+
k.permissions?.length ? k.permissions.join(', ') : chalk_1.default.dim('all'),
|
|
51
|
+
k.lastUsedAt ? (0, format_1.formatTimeAgo)(k.lastUsedAt) : chalk_1.default.dim('never'),
|
|
52
|
+
k.isActive ? chalk_1.default.green('yes') : chalk_1.default.red('no'),
|
|
53
|
+
])));
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
(0, format_1.error)(err.message);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
exports.keysCommand
|
|
60
|
+
.command('revoke')
|
|
61
|
+
.argument('<key-id>', 'API key ID to revoke')
|
|
62
|
+
.description('Revoke an API key')
|
|
63
|
+
.action(async (keyId) => {
|
|
64
|
+
try {
|
|
65
|
+
const client = (0, client_1.getClient)();
|
|
66
|
+
await client.del(`/keys/${keyId}`);
|
|
67
|
+
(0, format_1.success)(`API key ${(0, format_1.shorten)(keyId)} revoked`);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
(0, format_1.error)(err.message);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.promptsCommand = void 0;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const client_1 = require("../utils/client");
|
|
43
|
+
const format_1 = require("../utils/format");
|
|
44
|
+
exports.promptsCommand = new commander_1.Command('prompts').description('Browse curated prompt templates');
|
|
45
|
+
exports.promptsCommand
|
|
46
|
+
.description('List all curated prompts')
|
|
47
|
+
.option('--category <cat>', 'Filter by category (agent, poster, workspace, workflow)')
|
|
48
|
+
.action(async (opts) => {
|
|
49
|
+
try {
|
|
50
|
+
const client = (0, client_1.getClient)();
|
|
51
|
+
const query = opts.category ? `?category=${opts.category}` : '';
|
|
52
|
+
const data = await client.get(`/prompts${query}`);
|
|
53
|
+
const prompts = data.prompts || [];
|
|
54
|
+
if (prompts.length === 0) {
|
|
55
|
+
console.log('No prompts found.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
(0, format_1.heading)('Curated Prompts');
|
|
59
|
+
for (const p of prompts) {
|
|
60
|
+
const badge = chalk_1.default.dim(`[${p.category}]`);
|
|
61
|
+
console.log(` ${chalk_1.default.bold(p.name)} ${badge}`);
|
|
62
|
+
console.log(` ${p.title} — ${chalk_1.default.dim(p.description)}`);
|
|
63
|
+
if (p.tags?.length) {
|
|
64
|
+
console.log(` ${chalk_1.default.cyan(p.tags.join(', '))}`);
|
|
65
|
+
}
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
(0, format_1.error)(err.message);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
exports.promptsCommand
|
|
74
|
+
.command('show')
|
|
75
|
+
.argument('<name>', 'Prompt name (slug)')
|
|
76
|
+
.description('Show full prompt content')
|
|
77
|
+
.action(async (name) => {
|
|
78
|
+
try {
|
|
79
|
+
const client = (0, client_1.getClient)();
|
|
80
|
+
const data = await client.get(`/prompts/${name}`);
|
|
81
|
+
const p = data.prompt;
|
|
82
|
+
(0, format_1.heading)(p.title);
|
|
83
|
+
console.log(` Category: ${p.category}`);
|
|
84
|
+
console.log(` Description: ${p.description}`);
|
|
85
|
+
if (p.tags?.length) {
|
|
86
|
+
console.log(` Tags: ${p.tags.join(', ')}`);
|
|
87
|
+
}
|
|
88
|
+
if (p.tools?.length) {
|
|
89
|
+
console.log(` Tools: ${p.tools.join(', ')}`);
|
|
90
|
+
}
|
|
91
|
+
if (p.arguments?.length) {
|
|
92
|
+
console.log(` Arguments:`);
|
|
93
|
+
for (const arg of p.arguments) {
|
|
94
|
+
const req = arg.required ? chalk_1.default.red('*') : '';
|
|
95
|
+
console.log(` ${arg.name}${req} — ${arg.description}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
console.log();
|
|
99
|
+
console.log(chalk_1.default.dim('─'.repeat(60)));
|
|
100
|
+
console.log();
|
|
101
|
+
console.log(p.content);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
(0, format_1.error)(err.message);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
exports.promptsCommand
|
|
108
|
+
.command('copy')
|
|
109
|
+
.argument('<name>', 'Prompt name (slug)')
|
|
110
|
+
.description('Copy prompt content to clipboard')
|
|
111
|
+
.action(async (name) => {
|
|
112
|
+
try {
|
|
113
|
+
const client = (0, client_1.getClient)();
|
|
114
|
+
const data = await client.get(`/prompts/${name}`);
|
|
115
|
+
const p = data.prompt;
|
|
116
|
+
// Use pbcopy on macOS, xclip on Linux
|
|
117
|
+
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
118
|
+
try {
|
|
119
|
+
execSync('pbcopy', { input: p.content });
|
|
120
|
+
console.log(chalk_1.default.green(`Copied "${p.title}" to clipboard.`));
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
try {
|
|
124
|
+
execSync('xclip -selection clipboard', { input: p.content });
|
|
125
|
+
console.log(chalk_1.default.green(`Copied "${p.title}" to clipboard.`));
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
console.log(p.content);
|
|
129
|
+
console.log(chalk_1.default.yellow('\nCould not copy to clipboard. Content printed above.'));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
(0, format_1.error)(err.message);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.repoCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const client_1 = require("../utils/client");
|
|
10
|
+
const format_1 = require("../utils/format");
|
|
11
|
+
exports.repoCommand = new commander_1.Command('repo').description('GitHub repo access management');
|
|
12
|
+
exports.repoCommand
|
|
13
|
+
.command('list')
|
|
14
|
+
.description('List GitHub repos accessible via your GitHub App installation')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
try {
|
|
17
|
+
const client = (0, client_1.getClient)();
|
|
18
|
+
const data = await client.get('/github/repos');
|
|
19
|
+
const repos = data.repos || [];
|
|
20
|
+
if (repos.length === 0) {
|
|
21
|
+
console.log(chalk_1.default.dim(' No repos found. Install the Wenrwa GitHub App first.'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
(0, format_1.heading)('Accessible Repos');
|
|
25
|
+
console.log((0, format_1.makeTable)(['Repo', 'Private', 'Branch'], repos.map((r) => [
|
|
26
|
+
r.fullName,
|
|
27
|
+
r.private ? chalk_1.default.yellow('yes') : chalk_1.default.dim('no'),
|
|
28
|
+
r.defaultBranch || 'main',
|
|
29
|
+
])));
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
(0, format_1.error)(err.message);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
exports.repoCommand
|
|
36
|
+
.command('browse')
|
|
37
|
+
.argument('<repo>', 'Repository in owner/repo format')
|
|
38
|
+
.argument('[path]', 'Directory path to browse', '')
|
|
39
|
+
.option('--ref <ref>', 'Git ref (branch/tag/SHA)', 'HEAD')
|
|
40
|
+
.description('Browse a repo directory tree')
|
|
41
|
+
.action(async (repo, path, opts) => {
|
|
42
|
+
try {
|
|
43
|
+
const [owner, repoName] = repo.split('/');
|
|
44
|
+
if (!owner || !repoName) {
|
|
45
|
+
(0, format_1.error)('Repo must be in owner/repo format');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const client = (0, client_1.getClient)();
|
|
49
|
+
const qs = new URLSearchParams();
|
|
50
|
+
if (path)
|
|
51
|
+
qs.set('path', path);
|
|
52
|
+
if (opts.ref !== 'HEAD')
|
|
53
|
+
qs.set('ref', opts.ref);
|
|
54
|
+
const query = qs.toString();
|
|
55
|
+
const data = await client.get(`/github/repos/${owner}/${repoName}/tree${query ? `?${query}` : ''}`);
|
|
56
|
+
const tree = data.tree || [];
|
|
57
|
+
if (tree.length === 0) {
|
|
58
|
+
console.log(chalk_1.default.dim(' Empty directory'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
(0, format_1.heading)(`${repo}${path ? `/${path}` : ''}`);
|
|
62
|
+
for (const entry of tree) {
|
|
63
|
+
const icon = entry.type === 'dir' ? chalk_1.default.blue('📁') : '📄';
|
|
64
|
+
const size = entry.size ? chalk_1.default.dim(` (${formatSize(entry.size)})`) : '';
|
|
65
|
+
console.log(` ${icon} ${entry.name}${size}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
(0, format_1.error)(err.message);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
exports.repoCommand
|
|
73
|
+
.command('grant')
|
|
74
|
+
.argument('<bountyId>', 'Bounty ID')
|
|
75
|
+
.argument('<repo>', 'Repository in owner/repo format')
|
|
76
|
+
.option('--paths <globs...>', 'Allowed path patterns (e.g. "src/**" "package.json")')
|
|
77
|
+
.option('--blocked <globs...>', 'Additional blocked path patterns')
|
|
78
|
+
.option('--access <level>', 'Access level: read or write', 'read')
|
|
79
|
+
.description('Grant agent access to a repo for a bounty')
|
|
80
|
+
.action(async (bountyId, repo, opts) => {
|
|
81
|
+
try {
|
|
82
|
+
const client = (0, client_1.getClient)();
|
|
83
|
+
const body = {
|
|
84
|
+
repoFullName: repo,
|
|
85
|
+
accessLevel: opts.access,
|
|
86
|
+
};
|
|
87
|
+
if (opts.paths)
|
|
88
|
+
body.allowedPaths = opts.paths;
|
|
89
|
+
if (opts.blocked)
|
|
90
|
+
body.blockedPaths = opts.blocked;
|
|
91
|
+
const data = await client.post(`/bounties/${bountyId}/repo-access`, body);
|
|
92
|
+
const grant = data.grant;
|
|
93
|
+
(0, format_1.success)('Repo access granted');
|
|
94
|
+
console.log(` Bounty: ${(0, format_1.shorten)(bountyId)}`);
|
|
95
|
+
console.log(` Repo: ${grant.repoFullName}`);
|
|
96
|
+
console.log(` Access: ${grant.accessLevel}`);
|
|
97
|
+
console.log(` Private: ${grant.repoPrivate ? chalk_1.default.yellow('yes') : 'no'}`);
|
|
98
|
+
if (grant.allowedPaths.length > 0) {
|
|
99
|
+
console.log(` Allowed: ${grant.allowedPaths.join(', ')}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log(` Allowed: ${chalk_1.default.dim('all files (except blocked)')}`);
|
|
103
|
+
}
|
|
104
|
+
console.log(` Blocked: ${grant.blockedPaths.join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
(0, format_1.error)(err.message);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
exports.repoCommand
|
|
111
|
+
.command('access')
|
|
112
|
+
.argument('<bountyId>', 'Bounty ID')
|
|
113
|
+
.description('View repo access grants for a bounty')
|
|
114
|
+
.action(async (bountyId) => {
|
|
115
|
+
try {
|
|
116
|
+
const client = (0, client_1.getClient)();
|
|
117
|
+
const data = await client.get(`/bounties/${bountyId}/repo-access`);
|
|
118
|
+
const grants = data.grants || [];
|
|
119
|
+
if (grants.length === 0) {
|
|
120
|
+
console.log(chalk_1.default.dim(' No repo access grants for this bounty'));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
(0, format_1.heading)(`Repo Access — Bounty ${(0, format_1.shorten)(bountyId)}`);
|
|
124
|
+
console.log((0, format_1.makeTable)(['Repo', 'Access', 'Private', 'Allowed Paths', 'Granted By'], grants.map((g) => [
|
|
125
|
+
g.repoFullName,
|
|
126
|
+
g.accessLevel,
|
|
127
|
+
g.repoPrivate ? chalk_1.default.yellow('yes') : 'no',
|
|
128
|
+
g.allowedPaths.length > 0 ? g.allowedPaths.join(', ') : chalk_1.default.dim('all'),
|
|
129
|
+
(0, format_1.shorten)(g.grantedBy),
|
|
130
|
+
])));
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
(0, format_1.error)(err.message);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
exports.repoCommand
|
|
137
|
+
.command('revoke')
|
|
138
|
+
.argument('<bountyId>', 'Bounty ID')
|
|
139
|
+
.argument('<repo>', 'Repository in owner/repo format')
|
|
140
|
+
.description('Revoke repo access for a bounty')
|
|
141
|
+
.action(async (bountyId, repo) => {
|
|
142
|
+
try {
|
|
143
|
+
const client = (0, client_1.getClient)();
|
|
144
|
+
await client.del(`/bounties/${bountyId}/repo-access/${repo}`);
|
|
145
|
+
(0, format_1.success)(`Repo access revoked for ${repo}`);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
(0, format_1.error)(err.message);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
exports.repoCommand
|
|
152
|
+
.command('files')
|
|
153
|
+
.argument('<bountyId>', 'Bounty ID')
|
|
154
|
+
.argument('[path]', 'File path to read (omit to list all accessible files)')
|
|
155
|
+
.description('List accessible files or read a specific file')
|
|
156
|
+
.action(async (bountyId, path) => {
|
|
157
|
+
try {
|
|
158
|
+
const client = (0, client_1.getClient)();
|
|
159
|
+
if (path) {
|
|
160
|
+
// Read specific file
|
|
161
|
+
const data = await client.get(`/bounties/${bountyId}/files/${path}`);
|
|
162
|
+
const file = data.file;
|
|
163
|
+
(0, format_1.heading)(`${file.path} (${formatSize(file.size)})`);
|
|
164
|
+
console.log(file.content);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// List all files
|
|
168
|
+
const data = await client.get(`/bounties/${bountyId}/files`);
|
|
169
|
+
const groups = data.files || [];
|
|
170
|
+
if (groups.length === 0) {
|
|
171
|
+
console.log(chalk_1.default.dim(' No accessible files'));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
for (const group of groups) {
|
|
175
|
+
(0, format_1.heading)(group.repoFullName);
|
|
176
|
+
if (group.files.length === 0) {
|
|
177
|
+
console.log(chalk_1.default.dim(' No files'));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
for (const file of group.files) {
|
|
181
|
+
const size = file.size ? chalk_1.default.dim(` (${formatSize(file.size)})`) : '';
|
|
182
|
+
console.log(` 📄 ${file.path}${size}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
(0, format_1.error)(err.message);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
function formatSize(bytes) {
|
|
192
|
+
if (bytes < 1024)
|
|
193
|
+
return `${bytes}B`;
|
|
194
|
+
if (bytes < 1024 * 1024)
|
|
195
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
196
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
197
|
+
}
|