@wenrwa/marketplace-cli 0.1.0 → 0.2.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 +14 -0
- package/dist/__tests__/agent.test.d.ts +1 -0
- package/dist/__tests__/agent.test.js +138 -0
- package/dist/__tests__/apps.test.d.ts +1 -0
- package/dist/__tests__/apps.test.js +160 -0
- package/dist/__tests__/auth.test.d.ts +1 -0
- package/dist/__tests__/auth.test.js +94 -0
- package/dist/__tests__/bounty.test.d.ts +1 -0
- package/dist/__tests__/bounty.test.js +185 -0
- package/dist/__tests__/client.test.d.ts +1 -0
- package/dist/__tests__/client.test.js +106 -0
- package/dist/__tests__/config.test.d.ts +1 -0
- package/dist/__tests__/config.test.js +99 -0
- package/dist/__tests__/dashboard-helpers.test.d.ts +1 -0
- package/dist/__tests__/dashboard-helpers.test.js +123 -0
- package/dist/__tests__/format.test.d.ts +1 -0
- package/dist/__tests__/format.test.js +144 -0
- package/dist/__tests__/helpers.d.ts +7 -0
- package/dist/__tests__/helpers.js +12 -0
- package/dist/__tests__/treasury.test.d.ts +1 -0
- package/dist/__tests__/treasury.test.js +122 -0
- package/dist/__tests__/websocket.test.d.ts +1 -0
- package/dist/__tests__/websocket.test.js +61 -0
- package/dist/__tests__/workspace.test.d.ts +1 -0
- package/dist/__tests__/workspace.test.js +105 -0
- package/dist/commands/agent.d.ts +0 -0
- package/dist/commands/agent.js +0 -0
- package/dist/commands/apps.d.ts +2 -0
- package/dist/commands/apps.js +174 -0
- package/dist/commands/auth.d.ts +0 -0
- package/dist/commands/auth.js +0 -0
- package/dist/commands/bounty.d.ts +0 -0
- package/dist/commands/bounty.js +8 -0
- package/dist/commands/dashboard.d.ts +31 -0
- package/dist/commands/dashboard.js +5 -0
- package/dist/commands/treasury.d.ts +0 -0
- package/dist/commands/treasury.js +2 -2
- package/dist/commands/webhook.d.ts +2 -0
- package/dist/commands/webhook.js +131 -0
- package/dist/commands/workspace.d.ts +0 -0
- package/dist/commands/workspace.js +160 -13
- package/dist/index.d.ts +0 -0
- package/dist/index.js +4 -0
- package/dist/utils/client.d.ts +1 -0
- package/dist/utils/client.js +3 -0
- package/dist/utils/config.d.ts +0 -0
- package/dist/utils/config.js +0 -0
- package/dist/utils/format.d.ts +0 -1
- package/dist/utils/format.js +2 -11
- package/dist/utils/websocket.d.ts +0 -0
- package/dist/utils/websocket.js +0 -0
- package/package.json +5 -2
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const websocket_1 = require("../utils/websocket");
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
chalk_1.default.level = 0;
|
|
10
|
+
});
|
|
11
|
+
function makeEvent(event, data, timestamp) {
|
|
12
|
+
return { event, data, timestamp: timestamp || '2024-06-15T14:30:00.000Z' };
|
|
13
|
+
}
|
|
14
|
+
describe('formatEventPretty()', () => {
|
|
15
|
+
it('formats bounty:created', () => {
|
|
16
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('bounty:created', { title: 'Build API', rewardAmount: '100', rewardSymbol: 'USDC' }));
|
|
17
|
+
expect(result).toContain('[new]');
|
|
18
|
+
expect(result).toContain('Build API');
|
|
19
|
+
});
|
|
20
|
+
it('formats bounty:bid', () => {
|
|
21
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('bounty:bid', { agentWallet: 'abcdefghijklmnop', bidAmount: '50', bountyId: 'bounty123456789' }));
|
|
22
|
+
expect(result).toContain('[bid]');
|
|
23
|
+
});
|
|
24
|
+
it('formats bounty:assigned', () => {
|
|
25
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('bounty:assigned', { bountyId: 'bounty123456789', assigneeWallet: 'wallet12345678' }));
|
|
26
|
+
expect(result).toContain('[assigned]');
|
|
27
|
+
});
|
|
28
|
+
it('formats bounty:progress', () => {
|
|
29
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('bounty:progress', { percentage: 50, bountyId: 'bounty123456789', message: 'Half done' }));
|
|
30
|
+
expect(result).toContain('[progress]');
|
|
31
|
+
expect(result).toContain('50%');
|
|
32
|
+
});
|
|
33
|
+
it('formats bounty:completed', () => {
|
|
34
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('bounty:completed', { bountyId: 'bounty123456789' }));
|
|
35
|
+
expect(result).toContain('[complete]');
|
|
36
|
+
});
|
|
37
|
+
it('formats unknown event as fallback', () => {
|
|
38
|
+
const result = (0, websocket_1.formatEventPretty)(makeEvent('custom:event', { key: 'value' }));
|
|
39
|
+
expect(result).toContain('[custom:event]');
|
|
40
|
+
});
|
|
41
|
+
it('uses current time when timestamp is missing', () => {
|
|
42
|
+
const event = { event: 'bounty:completed', data: { bountyId: 'b1' } };
|
|
43
|
+
const result = (0, websocket_1.formatEventPretty)(event);
|
|
44
|
+
expect(result).toContain('[complete]');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('formatEventJson()', () => {
|
|
48
|
+
it('returns JSON with ts, event, and data', () => {
|
|
49
|
+
const event = makeEvent('bounty:created', { title: 'Test' });
|
|
50
|
+
const result = JSON.parse((0, websocket_1.formatEventJson)(event));
|
|
51
|
+
expect(result.ts).toBe('2024-06-15T14:30:00.000Z');
|
|
52
|
+
expect(result.event).toBe('bounty:created');
|
|
53
|
+
expect(result.data).toEqual({ title: 'Test' });
|
|
54
|
+
});
|
|
55
|
+
it('uses current time when timestamp missing', () => {
|
|
56
|
+
const event = { event: 'test', data: {} };
|
|
57
|
+
const result = JSON.parse((0, websocket_1.formatEventJson)(event));
|
|
58
|
+
expect(result.ts).toBeDefined();
|
|
59
|
+
expect(result.event).toBe('test');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
+
const helpers_1 = require("./helpers");
|
|
8
|
+
const mockClient = (0, helpers_1.createMockClient)();
|
|
9
|
+
jest.mock('../utils/client', () => ({
|
|
10
|
+
getClient: () => mockClient,
|
|
11
|
+
}));
|
|
12
|
+
// Mock websocket to prevent import issues
|
|
13
|
+
jest.mock('../utils/websocket', () => ({
|
|
14
|
+
connectWebSocket: jest.fn(),
|
|
15
|
+
formatEventPretty: jest.fn(),
|
|
16
|
+
formatEventJson: jest.fn(),
|
|
17
|
+
}));
|
|
18
|
+
const workspace_1 = require("../commands/workspace");
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
chalk_1.default.level = 0;
|
|
21
|
+
});
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
async function runCommand(...args) {
|
|
26
|
+
await workspace_1.workspaceCommand.parseAsync(args, { from: 'user' });
|
|
27
|
+
}
|
|
28
|
+
describe('workspace list', () => {
|
|
29
|
+
it('renders a table of workspaces', async () => {
|
|
30
|
+
mockClient.get.mockResolvedValue({
|
|
31
|
+
workspaces: [
|
|
32
|
+
{ id: 'ws-abc-12345678', name: 'Test Workspace', mode: 'open', bounty_count: 5, agent_count: 2, created_at: '2024-01-01' },
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
const spy = jest.spyOn(console, 'log').mockImplementation();
|
|
36
|
+
await runCommand('list');
|
|
37
|
+
expect(mockClient.get).toHaveBeenCalledWith('/workspaces');
|
|
38
|
+
const output = spy.mock.calls.map(c => c[0]).join('\n');
|
|
39
|
+
expect(output).toContain('Test Workspace');
|
|
40
|
+
spy.mockRestore();
|
|
41
|
+
});
|
|
42
|
+
it('handles empty workspace list', async () => {
|
|
43
|
+
mockClient.get.mockResolvedValue({ workspaces: [] });
|
|
44
|
+
const spy = jest.spyOn(console, 'log').mockImplementation();
|
|
45
|
+
await runCommand('list');
|
|
46
|
+
expect(spy).toHaveBeenCalledWith('No workspaces found.');
|
|
47
|
+
spy.mockRestore();
|
|
48
|
+
});
|
|
49
|
+
it('handles API error', async () => {
|
|
50
|
+
mockClient.get.mockRejectedValue(new Error('Network error'));
|
|
51
|
+
const errSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
52
|
+
await runCommand('list');
|
|
53
|
+
expect(errSpy).toHaveBeenCalledWith(expect.stringContaining('Network error'));
|
|
54
|
+
errSpy.mockRestore();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('workspace status', () => {
|
|
58
|
+
it('displays workspace details with bounties and treasury', async () => {
|
|
59
|
+
mockClient.get.mockImplementation((path) => {
|
|
60
|
+
if (path.includes('/treasury')) {
|
|
61
|
+
return Promise.resolve({ balance: '1000', total_funded: '5000', total_paid: '4000' });
|
|
62
|
+
}
|
|
63
|
+
if (path.includes('/bounties')) {
|
|
64
|
+
return Promise.resolve({
|
|
65
|
+
bounties: [{ title: 'Build Feature', status: 'open', assignee_wallet: null, reward_amount: '100', reward_symbol: 'USDC', blocked_by: [] }],
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return Promise.resolve({
|
|
69
|
+
workspace: { id: 'ws1', name: 'Main', mode: 'open', use_escrow: true, created_at: '2024-01-01' },
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const spy = jest.spyOn(console, 'log').mockImplementation();
|
|
73
|
+
await runCommand('status', 'ws1');
|
|
74
|
+
const output = spy.mock.calls.map(c => c[0]).join('\n');
|
|
75
|
+
expect(output).toContain('Main');
|
|
76
|
+
expect(output).toContain('Build Feature');
|
|
77
|
+
expect(output).toContain('Treasury');
|
|
78
|
+
spy.mockRestore();
|
|
79
|
+
});
|
|
80
|
+
it('handles missing treasury gracefully', async () => {
|
|
81
|
+
mockClient.get.mockImplementation((path) => {
|
|
82
|
+
if (path.includes('/treasury'))
|
|
83
|
+
return Promise.reject(new Error('Not found'));
|
|
84
|
+
if (path.includes('/bounties'))
|
|
85
|
+
return Promise.resolve({ bounties: [] });
|
|
86
|
+
return Promise.resolve({
|
|
87
|
+
workspace: { id: 'ws1', name: 'Test WS', mode: 'open', use_escrow: false, created_at: '2024-01-01' },
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
const spy = jest.spyOn(console, 'log').mockImplementation();
|
|
91
|
+
await runCommand('status', 'ws1');
|
|
92
|
+
const output = spy.mock.calls.map(c => c[0]).join('\n');
|
|
93
|
+
expect(output).toContain('Test WS');
|
|
94
|
+
// Treasury heading should NOT appear since the endpoint rejects
|
|
95
|
+
expect(output).not.toContain('Balance:');
|
|
96
|
+
spy.mockRestore();
|
|
97
|
+
});
|
|
98
|
+
it('handles workspace fetch error', async () => {
|
|
99
|
+
mockClient.get.mockRejectedValue(new Error('Workspace not found'));
|
|
100
|
+
const errSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
101
|
+
await runCommand('status', 'ws-bad');
|
|
102
|
+
expect(errSpy).toHaveBeenCalledWith(expect.stringContaining('Workspace not found'));
|
|
103
|
+
errSpy.mockRestore();
|
|
104
|
+
});
|
|
105
|
+
});
|
package/dist/commands/agent.d.ts
CHANGED
|
File without changes
|
package/dist/commands/agent.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,174 @@
|
|
|
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.appsCommand = 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
|
+
const fs_1 = require("fs");
|
|
12
|
+
exports.appsCommand = new commander_1.Command('apps').description('Hosted apps management');
|
|
13
|
+
exports.appsCommand
|
|
14
|
+
.command('list')
|
|
15
|
+
.description('List your hosted apps')
|
|
16
|
+
.option('--status <status>', 'Filter by status (pending, building, deployed, failed)')
|
|
17
|
+
.option('--limit <n>', 'Max results', '20')
|
|
18
|
+
.action(async (opts) => {
|
|
19
|
+
try {
|
|
20
|
+
const client = (0, client_1.getClient)();
|
|
21
|
+
const params = new URLSearchParams();
|
|
22
|
+
params.set('ownerWallet', client.getApiKey());
|
|
23
|
+
if (opts.status)
|
|
24
|
+
params.set('status', opts.status);
|
|
25
|
+
params.set('limit', opts.limit);
|
|
26
|
+
const data = await client.get(`/projects?${params}`);
|
|
27
|
+
const projects = data.projects || [];
|
|
28
|
+
if (projects.length === 0) {
|
|
29
|
+
console.log('No apps found. Create one with: wen-market apps create');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`${chalk_1.default.dim(`Showing ${projects.length} of ${data.total || projects.length} apps`)}\n`);
|
|
33
|
+
console.log((0, format_1.makeTable)(['ID', 'Title', 'Slug', 'Status', 'URL', 'Created'], projects.map((p) => [
|
|
34
|
+
(0, format_1.shorten)(p.id),
|
|
35
|
+
p.title.slice(0, 30),
|
|
36
|
+
`${p.slug}.wenrwa.app`,
|
|
37
|
+
(0, format_1.statusColor)(p.status),
|
|
38
|
+
p.deployed_url || p.preview_url || '—',
|
|
39
|
+
p.created_at ? (0, format_1.formatTimeAgo)(p.created_at) : '—',
|
|
40
|
+
])));
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
(0, format_1.error)(err.message);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
exports.appsCommand
|
|
47
|
+
.command('create')
|
|
48
|
+
.description('Create a new hosted app')
|
|
49
|
+
.requiredOption('--title <title>', 'App title')
|
|
50
|
+
.requiredOption('--reward <amount>', 'Reward amount in USDC')
|
|
51
|
+
.requiredOption('--deadline <date>', 'Deadline (ISO 8601)')
|
|
52
|
+
.option('--description <desc>', 'App description')
|
|
53
|
+
.option('--framework <fw>', 'Framework (react, nextjs, vue, svelte, vanilla)', 'react')
|
|
54
|
+
.option('--visibility <vis>', 'Visibility (public, unlisted)', 'public')
|
|
55
|
+
.action(async (opts) => {
|
|
56
|
+
try {
|
|
57
|
+
const client = (0, client_1.getClient)();
|
|
58
|
+
const amountMicro = String(Math.round(parseFloat(opts.reward) * 1e6));
|
|
59
|
+
const data = await client.post('/projects', {
|
|
60
|
+
title: opts.title,
|
|
61
|
+
description: opts.description || opts.title,
|
|
62
|
+
framework: opts.framework,
|
|
63
|
+
visibility: opts.visibility,
|
|
64
|
+
rewardAmount: amountMicro,
|
|
65
|
+
deadline: new Date(opts.deadline).toISOString(),
|
|
66
|
+
});
|
|
67
|
+
(0, format_1.heading)('App Created');
|
|
68
|
+
console.log(` Project ID: ${data.project.id}`);
|
|
69
|
+
console.log(` Bounty ID: ${data.bountyId}`);
|
|
70
|
+
console.log(` Slug: ${data.project.slug}.wenrwa.app`);
|
|
71
|
+
console.log(` Status: ${(0, format_1.statusColor)(data.project.status)}`);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
(0, format_1.error)(err.message);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
exports.appsCommand
|
|
78
|
+
.command('status')
|
|
79
|
+
.argument('<id>', 'Project ID')
|
|
80
|
+
.description('Show app details')
|
|
81
|
+
.action(async (id) => {
|
|
82
|
+
try {
|
|
83
|
+
const client = (0, client_1.getClient)();
|
|
84
|
+
const data = await client.get(`/projects/${id}`);
|
|
85
|
+
const p = data.project;
|
|
86
|
+
(0, format_1.heading)(`App: ${p.title}`);
|
|
87
|
+
console.log(` ID: ${p.id}`);
|
|
88
|
+
console.log(` Slug: ${p.slug}.wenrwa.app`);
|
|
89
|
+
console.log(` Status: ${(0, format_1.statusColor)(p.status)}`);
|
|
90
|
+
console.log(` Framework: ${p.framework || '—'}`);
|
|
91
|
+
console.log(` Visibility: ${p.visibility}`);
|
|
92
|
+
console.log(` Preview URL: ${p.preview_url || '—'}`);
|
|
93
|
+
console.log(` Deployed URL: ${p.deployed_url || '—'}`);
|
|
94
|
+
console.log(` Created: ${p.created_at}`);
|
|
95
|
+
if (p.deployed_at)
|
|
96
|
+
console.log(` Deployed: ${p.deployed_at}`);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
(0, format_1.error)(err.message);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
exports.appsCommand
|
|
103
|
+
.command('download')
|
|
104
|
+
.argument('<id>', 'Project ID')
|
|
105
|
+
.option('-o, --output <path>', 'Output file path', 'source.zip')
|
|
106
|
+
.description('Download source.zip')
|
|
107
|
+
.action(async (id, opts) => {
|
|
108
|
+
try {
|
|
109
|
+
const client = (0, client_1.getClient)();
|
|
110
|
+
const url = `${client.getApiUrl()}/projects/${id}/source`;
|
|
111
|
+
const res = await fetch(url, {
|
|
112
|
+
headers: { 'X-Wallet-Pubkey': client.getApiKey() },
|
|
113
|
+
});
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
const data = await res.json().catch(() => ({}));
|
|
116
|
+
throw new Error(data?.error?.message || `HTTP ${res.status}`);
|
|
117
|
+
}
|
|
118
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
119
|
+
(0, fs_1.writeFileSync)(opts.output, buffer);
|
|
120
|
+
console.log(chalk_1.default.green(`Downloaded to ${opts.output} (${buffer.length} bytes)`));
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
(0, format_1.error)(err.message);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
exports.appsCommand
|
|
127
|
+
.command('export-github')
|
|
128
|
+
.argument('<id>', 'Project ID')
|
|
129
|
+
.option('--repo <name>', 'GitHub repo name')
|
|
130
|
+
.option('--private', 'Create private repo')
|
|
131
|
+
.description('Export source to GitHub')
|
|
132
|
+
.action(async (id, opts) => {
|
|
133
|
+
try {
|
|
134
|
+
const client = (0, client_1.getClient)();
|
|
135
|
+
const data = await client.post(`/projects/${id}/export-github`, {
|
|
136
|
+
repoName: opts.repo,
|
|
137
|
+
isPrivate: opts.private ?? false,
|
|
138
|
+
});
|
|
139
|
+
console.log(chalk_1.default.green(`Exported to GitHub: ${data.repoUrl}`));
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
if (err.message?.includes('not connected')) {
|
|
143
|
+
console.log(chalk_1.default.yellow('GitHub not connected. Visit the web app to complete OAuth.'));
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
(0, format_1.error)(err.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
exports.appsCommand
|
|
151
|
+
.command('deployments')
|
|
152
|
+
.argument('<id>', 'Project ID')
|
|
153
|
+
.description('List deployment history')
|
|
154
|
+
.action(async (id) => {
|
|
155
|
+
try {
|
|
156
|
+
const client = (0, client_1.getClient)();
|
|
157
|
+
const data = await client.get(`/projects/${id}/deployments`);
|
|
158
|
+
const deployments = data.deployments || [];
|
|
159
|
+
if (deployments.length === 0) {
|
|
160
|
+
console.log('No deployments yet.');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
console.log((0, format_1.makeTable)(['ID', 'Status', 'URL', 'Initiated By', 'Created'], deployments.map((d) => [
|
|
164
|
+
(0, format_1.shorten)(d.id),
|
|
165
|
+
(0, format_1.statusColor)(d.status),
|
|
166
|
+
d.deployed_url || '—',
|
|
167
|
+
(0, format_1.shorten)(d.initiated_by),
|
|
168
|
+
d.created_at ? (0, format_1.formatTimeAgo)(d.created_at) : '—',
|
|
169
|
+
])));
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
(0, format_1.error)(err.message);
|
|
173
|
+
}
|
|
174
|
+
});
|
package/dist/commands/auth.d.ts
CHANGED
|
File without changes
|
package/dist/commands/auth.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/commands/bounty.js
CHANGED
|
@@ -65,6 +65,10 @@ exports.bountyCommand
|
|
|
65
65
|
console.log(` Assignee: ${b.assignee_wallet || '—'}`);
|
|
66
66
|
console.log(` Assignment: ${b.assignment_mode}`);
|
|
67
67
|
console.log(` Verification: ${b.verification_mode}`);
|
|
68
|
+
if (b.expected_deliverable_type && b.expected_deliverable_type !== 'generic') {
|
|
69
|
+
const labels = { pr: 'Pull Request', document: 'Document', report: 'Report' };
|
|
70
|
+
console.log(` Deliverable: ${labels[b.expected_deliverable_type] || b.expected_deliverable_type}`);
|
|
71
|
+
}
|
|
68
72
|
console.log(` Deadline: ${b.deadline || '—'}`);
|
|
69
73
|
console.log(` Max retries: ${b.max_retries ?? 0}`);
|
|
70
74
|
console.log(` Retry count: ${b.retry_count ?? 0}`);
|
|
@@ -75,6 +79,10 @@ exports.bountyCommand
|
|
|
75
79
|
if (b.result_url) {
|
|
76
80
|
console.log(` Result URL: ${b.result_url}`);
|
|
77
81
|
}
|
|
82
|
+
// Show PR URL from latest submission if available
|
|
83
|
+
if (b.pr_url) {
|
|
84
|
+
console.log(` PR URL: ${b.pr_url}`);
|
|
85
|
+
}
|
|
78
86
|
if (b.task_schema) {
|
|
79
87
|
(0, format_1.heading)('Task Schema');
|
|
80
88
|
console.log(JSON.stringify(b.task_schema, null, 2));
|
|
@@ -1,2 +1,33 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import { WsEvent } from '../utils/websocket';
|
|
3
|
+
export interface BountyRow {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: string;
|
|
7
|
+
assignee_wallet?: string;
|
|
8
|
+
percentage?: number;
|
|
9
|
+
last_heartbeat?: string;
|
|
10
|
+
reward_amount: string;
|
|
11
|
+
reward_symbol: string;
|
|
12
|
+
}
|
|
13
|
+
export interface DashboardState {
|
|
14
|
+
workspace: {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
mode: string;
|
|
18
|
+
};
|
|
19
|
+
bounties: BountyRow[];
|
|
20
|
+
treasury: {
|
|
21
|
+
balance: string;
|
|
22
|
+
total_funded: string;
|
|
23
|
+
total_paid: string;
|
|
24
|
+
};
|
|
25
|
+
events: string[];
|
|
26
|
+
startTime: number;
|
|
27
|
+
}
|
|
2
28
|
export declare const dashboardCommand: Command;
|
|
29
|
+
export declare function updateBountyFromEvent(state: DashboardState, event: WsEvent): void;
|
|
30
|
+
export declare function pad(s: string, len: number, right?: boolean): string;
|
|
31
|
+
export declare function colorOverhead(status: string): number;
|
|
32
|
+
export declare function heartbeatColor(hb: string): string;
|
|
33
|
+
export declare function formatUptime(ms: number): string;
|
|
@@ -4,6 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.dashboardCommand = void 0;
|
|
7
|
+
exports.updateBountyFromEvent = updateBountyFromEvent;
|
|
8
|
+
exports.pad = pad;
|
|
9
|
+
exports.colorOverhead = colorOverhead;
|
|
10
|
+
exports.heartbeatColor = heartbeatColor;
|
|
11
|
+
exports.formatUptime = formatUptime;
|
|
7
12
|
const commander_1 = require("commander");
|
|
8
13
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
14
|
const client_1 = require("../utils/client");
|
|
File without changes
|
|
@@ -57,7 +57,7 @@ exports.treasuryCommand
|
|
|
57
57
|
exports.treasuryCommand
|
|
58
58
|
.command('fund')
|
|
59
59
|
.argument('<workspace-id>', 'Workspace ID')
|
|
60
|
-
.requiredOption('--amount <amount>', 'Amount in
|
|
60
|
+
.requiredOption('--amount <amount>', 'Amount in USDC micro-units')
|
|
61
61
|
.option('--tx-signature <sig>', 'On-chain transaction signature')
|
|
62
62
|
.description('Fund workspace treasury')
|
|
63
63
|
.action(async (workspaceId, opts) => {
|
|
@@ -76,7 +76,7 @@ exports.treasuryCommand
|
|
|
76
76
|
exports.treasuryCommand
|
|
77
77
|
.command('distribute')
|
|
78
78
|
.argument('<workspace-id>', 'Workspace ID')
|
|
79
|
-
.requiredOption('--per-agent <amount>', 'Amount per agent in
|
|
79
|
+
.requiredOption('--per-agent <amount>', 'Amount per agent in USDC micro-units')
|
|
80
80
|
.description('Distribute funds to workspace agents')
|
|
81
81
|
.action(async (workspaceId, opts) => {
|
|
82
82
|
try {
|
|
@@ -0,0 +1,131 @@
|
|
|
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.webhookCommand = 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.webhookCommand = new commander_1.Command('webhook').description('Webhook subscription management');
|
|
12
|
+
exports.webhookCommand
|
|
13
|
+
.command('create')
|
|
14
|
+
.requiredOption('--url <url>', 'Webhook callback URL (HTTPS)')
|
|
15
|
+
.requiredOption('--events <types...>', 'Event types to subscribe to (e.g. bounty:created bounty:completed)')
|
|
16
|
+
.option('--workspace <id>', 'Filter to a specific workspace')
|
|
17
|
+
.option('--bounty <id>', 'Filter to a specific bounty')
|
|
18
|
+
.description('Create a new webhook subscription')
|
|
19
|
+
.action(async (opts) => {
|
|
20
|
+
try {
|
|
21
|
+
const client = (0, client_1.getClient)();
|
|
22
|
+
const data = await client.post('/webhooks', {
|
|
23
|
+
url: opts.url,
|
|
24
|
+
eventTypes: opts.events,
|
|
25
|
+
filterWorkspaceId: opts.workspace,
|
|
26
|
+
filterBountyId: opts.bounty,
|
|
27
|
+
});
|
|
28
|
+
const sub = data.subscription;
|
|
29
|
+
(0, format_1.success)('Webhook created');
|
|
30
|
+
console.log(` ID: ${sub.id}`);
|
|
31
|
+
console.log(` URL: ${sub.url}`);
|
|
32
|
+
console.log(` Events: ${sub.eventTypes.join(', ')}`);
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(chalk_1.default.yellow.bold(' Secret (shown once — save it now):'));
|
|
35
|
+
console.log(chalk_1.default.yellow(` ${sub.secret}`));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
(0, format_1.error)(err.message);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
exports.webhookCommand
|
|
42
|
+
.command('list')
|
|
43
|
+
.description('List your webhook subscriptions')
|
|
44
|
+
.action(async () => {
|
|
45
|
+
try {
|
|
46
|
+
const client = (0, client_1.getClient)();
|
|
47
|
+
const data = await client.get('/webhooks');
|
|
48
|
+
const subs = data.subscriptions || [];
|
|
49
|
+
if (subs.length === 0) {
|
|
50
|
+
console.log(chalk_1.default.dim(' No webhook subscriptions'));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
(0, format_1.heading)('Webhook Subscriptions');
|
|
54
|
+
console.log((0, format_1.makeTable)(['ID', 'URL', 'Events', 'Active', 'Failures', 'Last Delivery'], subs.map((s) => [
|
|
55
|
+
(0, format_1.shorten)(s.id),
|
|
56
|
+
s.url.length > 40 ? s.url.slice(0, 37) + '...' : s.url,
|
|
57
|
+
s.eventTypes.length > 2
|
|
58
|
+
? `${s.eventTypes.slice(0, 2).join(', ')} +${s.eventTypes.length - 2}`
|
|
59
|
+
: s.eventTypes.join(', '),
|
|
60
|
+
s.isActive ? chalk_1.default.green('yes') : chalk_1.default.red('no'),
|
|
61
|
+
s.consecutiveFailures > 0 ? chalk_1.default.red(String(s.consecutiveFailures)) : '0',
|
|
62
|
+
s.lastDeliveryAt ? (0, format_1.formatTimeAgo)(s.lastDeliveryAt) : chalk_1.default.dim('never'),
|
|
63
|
+
])));
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
(0, format_1.error)(err.message);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
exports.webhookCommand
|
|
70
|
+
.command('delete')
|
|
71
|
+
.argument('<id>', 'Webhook subscription ID')
|
|
72
|
+
.description('Delete a webhook subscription')
|
|
73
|
+
.action(async (id) => {
|
|
74
|
+
try {
|
|
75
|
+
const client = (0, client_1.getClient)();
|
|
76
|
+
await client.del(`/webhooks/${id}`);
|
|
77
|
+
(0, format_1.success)(`Webhook ${(0, format_1.shorten)(id)} deleted`);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
(0, format_1.error)(err.message);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
exports.webhookCommand
|
|
84
|
+
.command('deliveries')
|
|
85
|
+
.argument('<id>', 'Webhook subscription ID')
|
|
86
|
+
.option('--limit <n>', 'Number of deliveries to show', '10')
|
|
87
|
+
.description('Show recent delivery attempts for a webhook')
|
|
88
|
+
.action(async (id, opts) => {
|
|
89
|
+
try {
|
|
90
|
+
const client = (0, client_1.getClient)();
|
|
91
|
+
const data = await client.get(`/webhooks/${id}/deliveries?limit=${opts.limit}`);
|
|
92
|
+
const deliveries = data.deliveries || [];
|
|
93
|
+
if (deliveries.length === 0) {
|
|
94
|
+
console.log(chalk_1.default.dim(' No deliveries yet'));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
(0, format_1.heading)('Webhook Deliveries');
|
|
98
|
+
console.log((0, format_1.makeTable)(['Event', 'Type', 'Attempt', 'Status', 'HTTP', 'Time'], deliveries.map((d) => [
|
|
99
|
+
(0, format_1.shorten)(d.eventId),
|
|
100
|
+
d.eventType,
|
|
101
|
+
String(d.attempt),
|
|
102
|
+
(0, format_1.statusColor)(d.status),
|
|
103
|
+
d.httpStatus ? String(d.httpStatus) : chalk_1.default.dim('—'),
|
|
104
|
+
d.createdAt ? (0, format_1.formatTimeAgo)(d.createdAt) : '',
|
|
105
|
+
])));
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
(0, format_1.error)(err.message);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
exports.webhookCommand
|
|
112
|
+
.command('test')
|
|
113
|
+
.argument('<id>', 'Webhook subscription ID')
|
|
114
|
+
.description('Send a synthetic test event to a webhook')
|
|
115
|
+
.action(async (id) => {
|
|
116
|
+
try {
|
|
117
|
+
const client = (0, client_1.getClient)();
|
|
118
|
+
console.log(`Sending test event to webhook ${(0, format_1.shorten)(id)}...`);
|
|
119
|
+
const data = await client.post(`/webhooks/${id}/test`, {});
|
|
120
|
+
const delivery = data.delivery;
|
|
121
|
+
if (delivery.status === 'success') {
|
|
122
|
+
(0, format_1.success)(`Test delivered successfully (HTTP ${delivery.httpStatus})`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
(0, format_1.error)(`Test delivery failed: ${delivery.errorMessage || `HTTP ${delivery.httpStatus}`}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
(0, format_1.error)(err.message);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
File without changes
|