@obol/cli 0.3.1 → 0.3.2
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/package.json +1 -1
- package/src/api.js +3 -1
- package/src/setup.js +64 -13
- package/test/setup_helpers.test.mjs +40 -0
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -45,11 +45,13 @@ export async function checkHealth(gatewayUrl) {
|
|
|
45
45
|
return request(`${gatewayUrl}/healthz`);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export async function signup(gatewayUrl, agentId, services, referralCode, setupKey) {
|
|
48
|
+
export async function signup(gatewayUrl, agentId, services, referralCode, setupKey, preferredPaymentMode, walletAddress) {
|
|
49
49
|
const body = { agent_id: agentId };
|
|
50
50
|
if (services && services.length > 0) body.services = services;
|
|
51
51
|
if (referralCode) body.referral_code = referralCode;
|
|
52
52
|
if (setupKey) body.setup_key = setupKey;
|
|
53
|
+
if (preferredPaymentMode) body.preferred_payment_mode = preferredPaymentMode;
|
|
54
|
+
if (walletAddress) body.wallet_address = walletAddress;
|
|
53
55
|
return request(`${gatewayUrl}/v1/signup`, {
|
|
54
56
|
method: 'POST',
|
|
55
57
|
headers: { 'Content-Type': 'application/json' },
|
package/src/setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { resolve } from 'node:path';
|
|
3
|
+
import { basename, resolve } from 'node:path';
|
|
4
4
|
import * as p from '@clack/prompts';
|
|
5
5
|
import pc from 'picocolors';
|
|
6
6
|
import { checkHealth, listConnections, listEndpoints, signup, storeBYOK, validateReferralCode } from './api.js';
|
|
@@ -10,6 +10,30 @@ const cheers = ['Nice!', 'Boom!', "Let's go.", 'Easy.', 'Done.'];
|
|
|
10
10
|
const cheer = () => cheers[Math.floor(Math.random() * cheers.length)];
|
|
11
11
|
const PYTHON_SDK_INSTALL_CMD = 'python3 -m pip install "git+https://github.com/kineticSum/obol-gateway.git#subdirectory=sdk/python"';
|
|
12
12
|
|
|
13
|
+
export function preferredJsPaymentMode(existingEnv = {}) {
|
|
14
|
+
return existingEnv.OBOL_PAYMENT_MODE || 'x402';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function ensureJsProjectManifest(agentId, cwd = process.cwd()) {
|
|
18
|
+
const packageJsonPath = resolve(cwd, 'package.json');
|
|
19
|
+
if (existsSync(packageJsonPath)) return packageJsonPath;
|
|
20
|
+
|
|
21
|
+
const rawName = basename(cwd) || agentId || 'obol-agent';
|
|
22
|
+
const packageName = rawName
|
|
23
|
+
.toLowerCase()
|
|
24
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
25
|
+
.replace(/^-+|-+$/g, '')
|
|
26
|
+
|| 'obol-agent';
|
|
27
|
+
|
|
28
|
+
const manifest = {
|
|
29
|
+
name: packageName,
|
|
30
|
+
private: true,
|
|
31
|
+
type: 'module',
|
|
32
|
+
};
|
|
33
|
+
writeFileSync(packageJsonPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
34
|
+
return packageJsonPath;
|
|
35
|
+
}
|
|
36
|
+
|
|
13
37
|
export async function runSetup() {
|
|
14
38
|
console.log();
|
|
15
39
|
p.intro(pc.bgGreen(pc.black(' Welcome to Obol! ')));
|
|
@@ -138,7 +162,7 @@ export async function runSetup() {
|
|
|
138
162
|
}
|
|
139
163
|
|
|
140
164
|
// --- Payment Mode ---
|
|
141
|
-
let paymentMode = existingEnv
|
|
165
|
+
let paymentMode = preferredJsPaymentMode(existingEnv);
|
|
142
166
|
let x402PrivateKey = existingEnv.OBOL_X402_PRIVATE_KEY || '';
|
|
143
167
|
let walletAddress = existingEnv.OBOL_WALLET_ADDRESS || '';
|
|
144
168
|
|
|
@@ -217,7 +241,15 @@ export async function runSetup() {
|
|
|
217
241
|
let jwt;
|
|
218
242
|
let setupKey = existingEnv.OBOL_AGENT_ID === agentId ? existingEnv.OBOL_SETUP_KEY || '' : '';
|
|
219
243
|
try {
|
|
220
|
-
const result = await signup(
|
|
244
|
+
const result = await signup(
|
|
245
|
+
url,
|
|
246
|
+
agentId,
|
|
247
|
+
services,
|
|
248
|
+
referralCode?.trim() || undefined,
|
|
249
|
+
setupKey,
|
|
250
|
+
paymentMode,
|
|
251
|
+
walletAddress || undefined,
|
|
252
|
+
);
|
|
221
253
|
jwt = result.token;
|
|
222
254
|
setupKey = result.setup_key || setupKey;
|
|
223
255
|
|
|
@@ -299,10 +331,23 @@ export async function runSetup() {
|
|
|
299
331
|
// 4. Detect project type and install SDK
|
|
300
332
|
let sdkInstalled = false;
|
|
301
333
|
let integrationFile = null;
|
|
334
|
+
let projectReady = true;
|
|
302
335
|
|
|
303
|
-
|
|
336
|
+
let hasPackageJson = existsSync(resolve(process.cwd(), 'package.json'));
|
|
304
337
|
|
|
305
338
|
if (lang === 'js') {
|
|
339
|
+
if (!hasPackageJson) {
|
|
340
|
+
s.start('Preparing this folder for JavaScript setup...');
|
|
341
|
+
try {
|
|
342
|
+
const packageJsonPath = ensureJsProjectManifest(agentId);
|
|
343
|
+
hasPackageJson = true;
|
|
344
|
+
s.stop(pc.green(`Created ${packageJsonPath}`));
|
|
345
|
+
} catch (err) {
|
|
346
|
+
projectReady = false;
|
|
347
|
+
s.stop(pc.yellow(`Could not create package.json automatically: ${err.message}`));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
306
351
|
if (hasPackageJson) {
|
|
307
352
|
s.start('Installing @obol/sdk...');
|
|
308
353
|
try {
|
|
@@ -310,19 +355,22 @@ export async function runSetup() {
|
|
|
310
355
|
s.stop(pc.green('SDK installed! ') + cheer());
|
|
311
356
|
sdkInstalled = true;
|
|
312
357
|
} catch {
|
|
358
|
+
projectReady = false;
|
|
313
359
|
s.stop(pc.yellow('Could not auto-install SDK. Run manually: npm install @obol/sdk'));
|
|
314
360
|
}
|
|
315
|
-
} else {
|
|
316
|
-
p.log.info(`Install the SDK when you're ready: ${pc.green('npm install @obol/sdk')}`);
|
|
317
361
|
}
|
|
318
362
|
|
|
319
363
|
// Generate integration file
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
364
|
+
if (hasPackageJson) {
|
|
365
|
+
const obolFile = resolve(process.cwd(), 'obol.js');
|
|
366
|
+
if (!existsSync(obolFile)) {
|
|
367
|
+
s.start('Generating integration file...');
|
|
368
|
+
writeFileSync(obolFile, jsIntegrationFile(agentId, services, paymentMode));
|
|
369
|
+
s.stop(pc.green('Created obol.js'));
|
|
370
|
+
integrationFile = 'obol.js';
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
projectReady = false;
|
|
326
374
|
}
|
|
327
375
|
} else if (lang === 'python') {
|
|
328
376
|
s.start('Installing the Obol Python SDK from GitHub...');
|
|
@@ -366,7 +414,7 @@ export async function runSetup() {
|
|
|
366
414
|
|
|
367
415
|
// --- Summary ---
|
|
368
416
|
console.log();
|
|
369
|
-
p.log.success(pc.bold(
|
|
417
|
+
p.log.success(pc.bold(projectReady ? 'Your agent is connected to Obol!' : 'Your Obol account is ready.'));
|
|
370
418
|
console.log();
|
|
371
419
|
|
|
372
420
|
if (sdkInstalled) {
|
|
@@ -377,6 +425,9 @@ export async function runSetup() {
|
|
|
377
425
|
}
|
|
378
426
|
console.log(` ${pc.dim('Config saved:')} ${pc.green(envPath)}`);
|
|
379
427
|
console.log(` ${pc.dim('Payment mode:')} ${pc.green(paymentMode === 'x402' ? 'Automatic USDC (x402)' : 'Credits via Stripe')}`);
|
|
428
|
+
if (lang === 'js' && !sdkInstalled) {
|
|
429
|
+
console.log(` ${pc.dim('Project status:')} ${pc.yellow('Install @obol/sdk before importing obol.js')}`);
|
|
430
|
+
}
|
|
380
431
|
if (paymentMode === 'x402') {
|
|
381
432
|
if (walletAddress) {
|
|
382
433
|
console.log(` ${pc.dim('Wallet:')} ${pc.green(walletAddress)}`);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { ensureJsProjectManifest, preferredJsPaymentMode } from '../src/setup.js';
|
|
8
|
+
|
|
9
|
+
test('preferredJsPaymentMode defaults to x402 for fresh JS onboarding', () => {
|
|
10
|
+
assert.equal(preferredJsPaymentMode({}), 'x402');
|
|
11
|
+
assert.equal(preferredJsPaymentMode({ OBOL_PAYMENT_MODE: 'credits' }), 'credits');
|
|
12
|
+
assert.equal(preferredJsPaymentMode({ OBOL_PAYMENT_MODE: 'x402' }), 'x402');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('ensureJsProjectManifest creates a runnable package.json when missing', () => {
|
|
16
|
+
const dir = mkdtempSync(join(tmpdir(), 'obol-setup-helper-'));
|
|
17
|
+
try {
|
|
18
|
+
const packageJsonPath = ensureJsProjectManifest('agent-123', dir);
|
|
19
|
+
assert.equal(existsSync(packageJsonPath), true);
|
|
20
|
+
const manifest = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
21
|
+
assert.equal(manifest.private, true);
|
|
22
|
+
assert.equal(manifest.type, 'module');
|
|
23
|
+
assert.ok(manifest.name);
|
|
24
|
+
} finally {
|
|
25
|
+
rmSync(dir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('ensureJsProjectManifest preserves an existing package.json', () => {
|
|
30
|
+
const dir = mkdtempSync(join(tmpdir(), 'obol-setup-helper-existing-'));
|
|
31
|
+
const packageJsonPath = join(dir, 'package.json');
|
|
32
|
+
try {
|
|
33
|
+
writeFileSync(packageJsonPath, '{"name":"already-here","private":true}\n');
|
|
34
|
+
const returnedPath = ensureJsProjectManifest('agent-456', dir);
|
|
35
|
+
assert.equal(returnedPath, packageJsonPath);
|
|
36
|
+
assert.equal(readFileSync(packageJsonPath, 'utf8'), '{"name":"already-here","private":true}\n');
|
|
37
|
+
} finally {
|
|
38
|
+
rmSync(dir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
});
|