@wenrwa/marketplace-cli 0.3.0 → 0.4.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.
@@ -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
+ }
@@ -125,28 +125,47 @@ exports.workspaceCommand
125
125
  }
126
126
  });
127
127
  exports.workspaceCommand
128
- .command('invite-create')
128
+ .command('invite-agent')
129
129
  .argument('<workspace-id>', 'Workspace ID')
130
- .option('--max-uses <n>', 'Maximum number of uses')
130
+ .argument('<wallet>', 'Wallet address of the agent to invite')
131
+ .option('--role <role>', 'Role to assign: manager, reviewer, or member', 'member')
131
132
  .option('--expires <date>', 'Expiration date (ISO 8601)')
132
- .option('--target <wallet>', 'Target wallet for the invite')
133
+ .description('Invite a specific agent to a workspace by wallet address')
134
+ .action(async (workspaceId, wallet, opts) => {
135
+ try {
136
+ const client = (0, client_1.getClient)();
137
+ const body = { targetWallet: wallet };
138
+ if (opts.role && opts.role !== 'member')
139
+ body.role = opts.role;
140
+ if (opts.expires)
141
+ body.expiresAt = opts.expires;
142
+ await client.post(`/workspaces/${workspaceId}/invites`, body);
143
+ console.log(chalk_1.default.green(`Invite sent to ${(0, format_1.shorten)(wallet)} (role: ${opts.role || 'member'})`));
144
+ }
145
+ catch (err) {
146
+ (0, format_1.error)(err.message);
147
+ }
148
+ });
149
+ exports.workspaceCommand
150
+ .command('invite-link')
151
+ .argument('<workspace-id>', 'Workspace ID')
152
+ .option('--max-uses <n>', 'Maximum number of uses')
133
153
  .option('--role <role>', 'Role to assign: manager, reviewer, or member', 'member')
134
- .description('Create an invite link for a workspace')
154
+ .option('--expires <date>', 'Expiration date (ISO 8601)')
155
+ .description('Generate a shareable invite link for a workspace')
135
156
  .action(async (workspaceId, opts) => {
136
157
  try {
137
158
  const client = (0, client_1.getClient)();
138
159
  const body = {};
139
160
  if (opts.maxUses)
140
161
  body.maxUses = parseInt(opts.maxUses, 10);
141
- if (opts.expires)
142
- body.expiresAt = opts.expires;
143
- if (opts.target)
144
- body.targetWallet = opts.target;
145
162
  if (opts.role && opts.role !== 'member')
146
163
  body.role = opts.role;
164
+ if (opts.expires)
165
+ body.expiresAt = opts.expires;
147
166
  const data = await client.post(`/workspaces/${workspaceId}/invites`, body);
148
167
  const invite = data.invite;
149
- (0, format_1.heading)('Invite Created');
168
+ (0, format_1.heading)('Invite Link Created');
150
169
  console.log(` Token: ${invite.token}`);
151
170
  console.log(` Max Uses: ${invite.maxUses ?? 'unlimited'}`);
152
171
  console.log(` Expires: ${invite.expiresAt ?? 'never'}`);
@@ -170,14 +189,18 @@ exports.workspaceCommand
170
189
  console.log('No invites found.');
171
190
  return;
172
191
  }
173
- console.log((0, format_1.makeTable)(['ID', 'Token', 'Uses', 'Max Uses', 'Expires', 'Created'], invites.map((inv) => [
174
- (0, format_1.shorten)(inv.id),
175
- inv.token.slice(0, 12) + '...',
176
- String(inv.useCount),
177
- inv.maxUses != null ? String(inv.maxUses) : 'unlimited',
178
- inv.expiresAt ? new Date(inv.expiresAt).toLocaleDateString() : 'never',
179
- new Date(inv.createdAt).toLocaleDateString(),
180
- ])));
192
+ console.log((0, format_1.makeTable)(['ID', 'Token', 'Type', 'Target/Max', 'Uses', 'Expires', 'Created'], invites.map((inv) => {
193
+ const isTargeted = !!inv.targetWallet;
194
+ return [
195
+ (0, format_1.shorten)(inv.id),
196
+ inv.token.slice(0, 12) + '...',
197
+ isTargeted ? 'targeted' : 'open',
198
+ isTargeted ? (0, format_1.shorten)(inv.targetWallet) : (inv.maxUses != null ? String(inv.maxUses) : 'unlimited'),
199
+ String(inv.useCount),
200
+ inv.expiresAt ? new Date(inv.expiresAt).toLocaleDateString() : 'never',
201
+ new Date(inv.createdAt).toLocaleDateString(),
202
+ ];
203
+ })));
181
204
  }
182
205
  catch (err) {
183
206
  (0, format_1.error)(err.message);
@@ -294,7 +317,6 @@ exports.workspaceCommand
294
317
  console.log(` ID: ${ws.id}`);
295
318
  console.log(` Mode: ${ws.mode}`);
296
319
  console.log(` Visibility: ${ws.visibility || 'private'}`);
297
- console.log(` Escrow: ${ws.use_escrow || ws.useEscrow ? 'Yes' : 'No'}`);
298
320
  if (ws.description)
299
321
  console.log(` Description: ${ws.description}`);
300
322
  if (ws.tags?.length)
@@ -345,6 +367,119 @@ exports.workspaceCommand
345
367
  process.exit(0);
346
368
  });
347
369
  });
370
+ exports.workspaceCommand
371
+ .command('chat')
372
+ .argument('<workspace-id>', 'Workspace ID')
373
+ .option('--limit <n>', 'Max messages to display', '50')
374
+ .option('--before <timestamp>', 'Show messages before this ISO timestamp')
375
+ .description('Display recent chat messages in a workspace')
376
+ .action(async (workspaceId, opts) => {
377
+ try {
378
+ const client = (0, client_1.getClient)();
379
+ const params = new URLSearchParams();
380
+ params.set('limit', opts.limit);
381
+ if (opts.before)
382
+ params.set('before', opts.before);
383
+ const query = params.toString();
384
+ const data = await client.get(`/workspaces/${workspaceId}/chat${query ? `?${query}` : ''}`);
385
+ const messages = data.messages || [];
386
+ if (messages.length === 0) {
387
+ console.log('No messages yet.');
388
+ return;
389
+ }
390
+ for (const msg of messages) {
391
+ const time = new Date(msg.createdAt).toLocaleTimeString();
392
+ const sender = (0, format_1.shorten)(msg.senderWallet);
393
+ const reply = msg.replyTo ? chalk_1.default.dim(` (reply to ${(0, format_1.shorten)(msg.replyTo)})`) : '';
394
+ console.log(`${chalk_1.default.dim(time)} ${chalk_1.default.cyan(sender)}${reply}: ${msg.content}`);
395
+ }
396
+ }
397
+ catch (err) {
398
+ (0, format_1.error)(err.message);
399
+ }
400
+ });
401
+ exports.workspaceCommand
402
+ .command('say')
403
+ .argument('<workspace-id>', 'Workspace ID')
404
+ .argument('<message>', 'Message to send')
405
+ .option('--reply-to <id>', 'Reply to a specific message UUID')
406
+ .description('Send a chat message to a workspace')
407
+ .action(async (workspaceId, message, opts) => {
408
+ try {
409
+ const client = (0, client_1.getClient)();
410
+ const body = { content: message };
411
+ if (opts.replyTo)
412
+ body.replyTo = opts.replyTo;
413
+ await client.post(`/workspaces/${workspaceId}/chat`, body);
414
+ console.log(chalk_1.default.green('Message sent.'));
415
+ }
416
+ catch (err) {
417
+ (0, format_1.error)(err.message);
418
+ }
419
+ });
420
+ exports.workspaceCommand
421
+ .command('context')
422
+ .argument('<workspace-id>', 'Workspace ID')
423
+ .description('List shared context keys in a workspace')
424
+ .action(async (workspaceId) => {
425
+ try {
426
+ const client = (0, client_1.getClient)();
427
+ const data = await client.get(`/workspaces/${workspaceId}/context`);
428
+ const contexts = data.contexts || [];
429
+ if (contexts.length === 0) {
430
+ console.log('No context keys found.');
431
+ return;
432
+ }
433
+ (0, format_1.heading)('Shared Context Keys');
434
+ console.log((0, format_1.makeTable)(['Key', 'Producer', 'Updated'], contexts.map((c) => [
435
+ c.key,
436
+ (0, format_1.shorten)(c.producerWallet || c.producer_wallet || '—'),
437
+ c.updatedAt || c.updated_at ? new Date(c.updatedAt || c.updated_at).toLocaleString() : '—',
438
+ ])));
439
+ }
440
+ catch (err) {
441
+ (0, format_1.error)(err.message);
442
+ }
443
+ });
444
+ exports.workspaceCommand
445
+ .command('context-get')
446
+ .argument('<workspace-id>', 'Workspace ID')
447
+ .argument('<key>', 'Context key')
448
+ .description('Read a shared context value')
449
+ .action(async (workspaceId, key) => {
450
+ try {
451
+ const client = (0, client_1.getClient)();
452
+ const data = await client.get(`/workspaces/${workspaceId}/context/${key}`);
453
+ (0, format_1.heading)(`Context: ${key}`);
454
+ console.log(JSON.stringify(data.context?.content ?? data.context, null, 2));
455
+ }
456
+ catch (err) {
457
+ (0, format_1.error)(err.message);
458
+ }
459
+ });
460
+ exports.workspaceCommand
461
+ .command('context-set')
462
+ .argument('<workspace-id>', 'Workspace ID')
463
+ .requiredOption('--key <key>', 'Context key')
464
+ .requiredOption('--value <value>', 'Context value (JSON string)')
465
+ .description('Set a shared context value')
466
+ .action(async (workspaceId, opts) => {
467
+ try {
468
+ const client = (0, client_1.getClient)();
469
+ let content;
470
+ try {
471
+ content = JSON.parse(opts.value);
472
+ }
473
+ catch {
474
+ content = opts.value;
475
+ }
476
+ await client.put(`/workspaces/${workspaceId}/context`, { key: opts.key, content });
477
+ console.log(chalk_1.default.green(`Context key '${opts.key}' set.`));
478
+ }
479
+ catch (err) {
480
+ (0, format_1.error)(err.message);
481
+ }
482
+ });
348
483
  exports.invitesCommand = new commander_1.Command('invites')
349
484
  .description('List pending invites for your wallet')
350
485
  .action(async () => {
@@ -366,6 +501,7 @@ exports.invitesCommand = new commander_1.Command('invites')
366
501
  console.log(` Role: ${chalk_1.default.yellow(inv.role || 'member')} Members: ${ws.memberCount ?? '?'} Visibility: ${ws.visibility}`);
367
502
  console.log(` Token: ${inv.token.slice(0, 12)}...`);
368
503
  console.log(` Accept: ${chalk_1.default.dim('wenrwa workspace join ' + inv.token + ' --invite')}`);
504
+ console.log(` Decline: ${chalk_1.default.dim('wenrwa invites decline ' + inv.id)}`);
369
505
  console.log('');
370
506
  }
371
507
  }
@@ -373,3 +509,17 @@ exports.invitesCommand = new commander_1.Command('invites')
373
509
  (0, format_1.error)(err.message);
374
510
  }
375
511
  });
512
+ exports.invitesCommand
513
+ .command('decline')
514
+ .argument('<invite-id>', 'Invite ID to decline')
515
+ .description('Decline a pending workspace invite')
516
+ .action(async (inviteId) => {
517
+ try {
518
+ const client = (0, client_1.getClient)();
519
+ await client.post('/me/invites/decline', { inviteId });
520
+ console.log(chalk_1.default.green('Invite declined.'));
521
+ }
522
+ catch (err) {
523
+ (0, format_1.error)(err.message);
524
+ }
525
+ });
package/dist/index.js CHANGED
@@ -11,6 +11,10 @@ const dashboard_1 = require("./commands/dashboard");
11
11
  const webhook_1 = require("./commands/webhook");
12
12
  const apps_1 = require("./commands/apps");
13
13
  const keys_1 = require("./commands/keys");
14
+ const repo_1 = require("./commands/repo");
15
+ const prompts_1 = require("./commands/prompts");
16
+ const credits_1 = require("./commands/credits");
17
+ const bridge_1 = require("./commands/bridge");
14
18
  const program = new commander_1.Command();
15
19
  program
16
20
  .name('wen-market')
@@ -26,4 +30,8 @@ program.addCommand(webhook_1.webhookCommand);
26
30
  program.addCommand(apps_1.appsCommand);
27
31
  program.addCommand(keys_1.keysCommand);
28
32
  program.addCommand(workspace_1.invitesCommand);
33
+ program.addCommand(repo_1.repoCommand);
34
+ program.addCommand(prompts_1.promptsCommand);
35
+ program.addCommand(credits_1.creditsCommand);
36
+ program.addCommand(bridge_1.bridgeCommand);
29
37
  program.parse();
@@ -6,6 +6,7 @@ export declare class ApiClient {
6
6
  get<T>(path: string): Promise<T>;
7
7
  post<T>(path: string, body?: any): Promise<T>;
8
8
  put<T>(path: string, body?: any): Promise<T>;
9
+ patch<T>(path: string, body?: any): Promise<T>;
9
10
  del<T>(path: string): Promise<T>;
10
11
  getApiUrl(): string;
11
12
  getApiKey(): string;
@@ -38,6 +38,9 @@ class ApiClient {
38
38
  put(path, body) {
39
39
  return this.request('PUT', path, body);
40
40
  }
41
+ patch(path, body) {
42
+ return this.request('PATCH', path, body);
43
+ }
41
44
  del(path) {
42
45
  return this.request('DELETE', path);
43
46
  }
@@ -42,7 +42,7 @@ const path = __importStar(require("path"));
42
42
  const os = __importStar(require("os"));
43
43
  const CONFIG_DIR = path.join(os.homedir(), '.wen-market');
44
44
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
45
- const DEFAULT_API_URL = 'http://localhost:3001/api/marketplace';
45
+ const DEFAULT_API_URL = 'http://localhost:3002/api/v1';
46
46
  function loadConfig() {
47
47
  try {
48
48
  const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
@@ -53,8 +53,8 @@ function loadConfig() {
53
53
  }
54
54
  }
55
55
  function saveConfig(config) {
56
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
57
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n');
56
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
57
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
58
58
  }
59
59
  function requireConfig() {
60
60
  const config = loadConfig();
package/package.json CHANGED
@@ -1,18 +1,10 @@
1
1
  {
2
2
  "name": "@wenrwa/marketplace-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "CLI tool for the Wenrwa Agent Marketplace — monitor bounties, agents, workspaces, and treasury from your terminal",
5
5
  "author": "Wenrwa <dev@wenrwa.com>",
6
6
  "license": "MIT",
7
- "homepage": "https://github.com/BunnyDAO/wenrwa-marketplace#readme",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/BunnyDAO/wenrwa-marketplace.git",
11
- "directory": "cli"
12
- },
13
- "bugs": {
14
- "url": "https://github.com/BunnyDAO/wenrwa-marketplace/issues"
15
- },
7
+ "homepage": "https://marketplace.wenrwa.com",
16
8
  "keywords": [
17
9
  "solana",
18
10
  "ai-agent",
@@ -37,17 +29,20 @@
37
29
  "test": "jest"
38
30
  },
39
31
  "dependencies": {
40
- "commander": "^12.0.0",
41
32
  "chalk": "^4.1.2",
42
33
  "cli-table3": "^0.6.0",
43
- "socket.io-client": "^4.7.0"
34
+ "commander": "^12.0.0",
35
+ "node-pty": "^1.1.0",
36
+ "socket.io-client": "^4.7.0",
37
+ "ws": "^8.21.1"
44
38
  },
45
39
  "devDependencies": {
46
- "typescript": "^5.5.0",
47
- "@types/node": "^20.0.0",
48
40
  "@types/jest": "^29.5.0",
41
+ "@types/node": "^20.0.0",
42
+ "@types/ws": "^8.18.1",
49
43
  "jest": "^29.7.0",
50
44
  "ts-jest": "^29.2.0",
51
- "ts-node": "^10.9.0"
45
+ "ts-node": "^10.9.0",
46
+ "typescript": "^5.5.0"
52
47
  }
53
48
  }