apinow-sdk 0.24.0 → 0.27.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 +40 -9
- package/dist/cli.js +189 -38
- package/dist/index.d.ts +72 -1
- package/dist/index.js +142 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,9 +59,18 @@ Returns:
|
|
|
59
59
|
| `discoverPrice(url, method?)` | Discover the x402 price of any URL (free) |
|
|
60
60
|
| `search(query, limit?)` | Semantic search across all endpoints |
|
|
61
61
|
| `info(ns, name)` | Get endpoint details (free) |
|
|
62
|
-
| `listWorkflows(opts?)` | List workflows (
|
|
63
|
-
| `
|
|
62
|
+
| `listWorkflows(opts?)` | List workflows (filter by `creator`, `status`) |
|
|
63
|
+
| `listMyWorkflows(opts?)` | List workflows created by your wallet |
|
|
64
|
+
| `getWorkflow(id)` | Get workflow details (incl. `currentVersion`, `creatorWallet`) |
|
|
65
|
+
| `createWorkflow(config)` | Create a workflow (seeds v1) |
|
|
66
|
+
| `updateWorkflow(id, updates)` | Update a workflow (auto-bumps version on graph/price/splits change) |
|
|
67
|
+
| `deleteWorkflow(id)` | Delete a workflow |
|
|
64
68
|
| `runWorkflow(id, input)` | Run a workflow with automatic x402 payment |
|
|
69
|
+
| `listWorkflowVersions(id)` | List versions (free) |
|
|
70
|
+
| `getWorkflowVersion(id, vid)` | Get a specific version |
|
|
71
|
+
| `createWorkflowVersion(id, updates)` | Creator — new version, defaults to active |
|
|
72
|
+
| `setDefaultWorkflowVersion(id, vid)` | Promote/rollback a version |
|
|
73
|
+
| `deleteWorkflowVersion(id, vid)` | Delete a non-default version |
|
|
65
74
|
| `generateUI(opts)` | Start AI UI generation for an endpoint (async) |
|
|
66
75
|
| `generateUIAndWait(opts)` | Generate UI and poll until complete |
|
|
67
76
|
| `getGeneratedUI(id)` | Get a generated UI by ID |
|
|
@@ -74,22 +83,44 @@ Returns:
|
|
|
74
83
|
|
|
75
84
|
### Workflows
|
|
76
85
|
|
|
77
|
-
Workflows chain multiple x402 endpoints into a single paid DAG pipeline with automatic payment splitting.
|
|
86
|
+
Workflows chain multiple x402 endpoints into a single paid DAG pipeline with automatic payment splitting. Each workflow is owned by a `creatorWallet` and tracks an immutable version history.
|
|
78
87
|
|
|
79
88
|
```typescript
|
|
80
|
-
// list workflows
|
|
81
|
-
const { workflows } = await apinow.listWorkflows({
|
|
89
|
+
// list workflows (optionally filter by creator)
|
|
90
|
+
const { workflows } = await apinow.listWorkflows({ creator: '0x...', status: 'active' });
|
|
82
91
|
|
|
83
|
-
//
|
|
84
|
-
const
|
|
85
|
-
|
|
92
|
+
// your own workflows
|
|
93
|
+
const mine = await apinow.listMyWorkflows();
|
|
94
|
+
|
|
95
|
+
// get workflow details (nodes, splits, pricing, currentVersion, creatorWallet)
|
|
96
|
+
const workflow = await apinow.getWorkflow('f5d40784593aa972');
|
|
86
97
|
|
|
87
98
|
// run a workflow — x402 payment covers all nodes + creator split
|
|
88
|
-
const result = await apinow.runWorkflow('
|
|
99
|
+
const result = await apinow.runWorkflow('f5d40784593aa972', {
|
|
89
100
|
query: 'birthday gift ideas for a friend who loves cooking',
|
|
90
101
|
});
|
|
91
102
|
```
|
|
92
103
|
|
|
104
|
+
#### Versions & metadata cooldown
|
|
105
|
+
|
|
106
|
+
- `PUT /api/workflows/{id}` with changes to `graph`, `totalPrice`, or `splits` auto-creates a new version.
|
|
107
|
+
- `name` and `description` can only change **once every 7 days** per workflow (server returns `429` with `retryAfterMs`).
|
|
108
|
+
- To iterate freely, create a new version — no cooldown.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// snapshot history
|
|
112
|
+
const { versions } = await apinow.listWorkflowVersions('f5d40784593aa972');
|
|
113
|
+
|
|
114
|
+
// bump price without renaming
|
|
115
|
+
await apinow.createWorkflowVersion('f5d40784593aa972', {
|
|
116
|
+
totalPrice: '0.12',
|
|
117
|
+
changelog: 'Raised price after usage spike',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// rollback
|
|
121
|
+
await apinow.setDefaultWorkflowVersion('f5d40784593aa972', 1);
|
|
122
|
+
```
|
|
123
|
+
|
|
93
124
|
### AI UI Generation
|
|
94
125
|
|
|
95
126
|
Generate interactive Arrow JS sandbox UIs for any endpoint — ideal for AI agents that need a visual interface.
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ const program = new Command();
|
|
|
7
7
|
program
|
|
8
8
|
.name('apinow')
|
|
9
9
|
.description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
|
|
10
|
-
.version('0.
|
|
10
|
+
.version('0.27.0');
|
|
11
11
|
// ─── Helpers ───
|
|
12
12
|
function getPrivateKey(opts) {
|
|
13
13
|
const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
|
|
@@ -48,8 +48,14 @@ function getWallet(opts) {
|
|
|
48
48
|
const account = privateKeyToAccount(privateKey);
|
|
49
49
|
return { privateKey, address: account.address };
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Signed headers for mutating calls. The backend verifies the signature
|
|
53
|
+
* recovers to the claimed wallet address before accepting the request.
|
|
54
|
+
*/
|
|
55
|
+
async function walletHeaders(privateKey) {
|
|
56
|
+
const apinow = createClient({ privateKey });
|
|
57
|
+
const auth = await apinow.signAuthHeader();
|
|
58
|
+
return { 'Content-Type': 'application/json', ...auth };
|
|
53
59
|
}
|
|
54
60
|
// ─── search ───
|
|
55
61
|
program
|
|
@@ -207,7 +213,7 @@ program
|
|
|
207
213
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
208
214
|
.action(async (opts) => {
|
|
209
215
|
try {
|
|
210
|
-
const { address } = getWallet(opts);
|
|
216
|
+
const { privateKey, address } = getWallet(opts);
|
|
211
217
|
const body = {
|
|
212
218
|
namespace: opts.namespace,
|
|
213
219
|
endpointName: opts.name,
|
|
@@ -218,7 +224,7 @@ program
|
|
|
218
224
|
};
|
|
219
225
|
const data = await fetchJson(`${API_BASE}/api/endpoints`, {
|
|
220
226
|
method: 'POST',
|
|
221
|
-
headers: walletHeaders(
|
|
227
|
+
headers: await walletHeaders(privateKey),
|
|
222
228
|
body: JSON.stringify(body),
|
|
223
229
|
});
|
|
224
230
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -239,7 +245,7 @@ program
|
|
|
239
245
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
240
246
|
.action(async (id, opts) => {
|
|
241
247
|
try {
|
|
242
|
-
const { address } = getWallet(opts);
|
|
248
|
+
const { privateKey, address } = getWallet(opts);
|
|
243
249
|
const body = {};
|
|
244
250
|
if (opts.description)
|
|
245
251
|
body.description = opts.description;
|
|
@@ -251,7 +257,7 @@ program
|
|
|
251
257
|
body.paymentOptions = [{ usdAmount: opts.price, amount: opts.price }];
|
|
252
258
|
const data = await fetchJson(`${API_BASE}/api/endpoints/${id}`, {
|
|
253
259
|
method: 'PUT',
|
|
254
|
-
headers: walletHeaders(
|
|
260
|
+
headers: await walletHeaders(privateKey),
|
|
255
261
|
body: JSON.stringify(body),
|
|
256
262
|
});
|
|
257
263
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -268,10 +274,10 @@ program
|
|
|
268
274
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
269
275
|
.action(async (id, opts) => {
|
|
270
276
|
try {
|
|
271
|
-
const { address } = getWallet(opts);
|
|
277
|
+
const { privateKey, address } = getWallet(opts);
|
|
272
278
|
const data = await fetchJson(`${API_BASE}/api/endpoints/${id}`, {
|
|
273
279
|
method: 'DELETE',
|
|
274
|
-
headers: walletHeaders(
|
|
280
|
+
headers: await walletHeaders(privateKey),
|
|
275
281
|
});
|
|
276
282
|
console.log(JSON.stringify(data, null, 2));
|
|
277
283
|
}
|
|
@@ -425,6 +431,7 @@ program
|
|
|
425
431
|
console.log(` ${data.description || '(no description)'}\n`);
|
|
426
432
|
console.log(` ID: ${data.workflowId}`);
|
|
427
433
|
console.log(` Status: ${data.status}`);
|
|
434
|
+
console.log(` Version: v${data.currentVersion ?? 1}${data.currentVersionId ? ` (${data.currentVersionId.slice(0, 8)}…)` : ''}`);
|
|
428
435
|
console.log(` Cost: $${data.totalPrice} USDC`);
|
|
429
436
|
console.log(` Chain: ${data.chain || 'base'}`);
|
|
430
437
|
console.log(` Creator: ${data.creatorWallet}`);
|
|
@@ -486,7 +493,7 @@ program
|
|
|
486
493
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
487
494
|
.action(async (opts) => {
|
|
488
495
|
try {
|
|
489
|
-
const { address } = getWallet(opts);
|
|
496
|
+
const { privateKey, address } = getWallet(opts);
|
|
490
497
|
const body = { name: opts.name, totalPrice: opts.price };
|
|
491
498
|
if (opts.description)
|
|
492
499
|
body.description = opts.description;
|
|
@@ -498,7 +505,7 @@ program
|
|
|
498
505
|
body.splits = JSON.parse(opts.splits);
|
|
499
506
|
const data = await fetchJson(`${API_BASE}/api/workflows`, {
|
|
500
507
|
method: 'POST',
|
|
501
|
-
headers: walletHeaders(
|
|
508
|
+
headers: await walletHeaders(privateKey),
|
|
502
509
|
body: JSON.stringify(body),
|
|
503
510
|
});
|
|
504
511
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -519,7 +526,7 @@ program
|
|
|
519
526
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
520
527
|
.action(async (id, opts) => {
|
|
521
528
|
try {
|
|
522
|
-
const { address } = getWallet(opts);
|
|
529
|
+
const { privateKey, address } = getWallet(opts);
|
|
523
530
|
const body = {};
|
|
524
531
|
if (opts.name)
|
|
525
532
|
body.name = opts.name;
|
|
@@ -531,7 +538,7 @@ program
|
|
|
531
538
|
body.totalPrice = opts.price;
|
|
532
539
|
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`, {
|
|
533
540
|
method: 'PUT',
|
|
534
|
-
headers: walletHeaders(
|
|
541
|
+
headers: await walletHeaders(privateKey),
|
|
535
542
|
body: JSON.stringify(body),
|
|
536
543
|
});
|
|
537
544
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -548,10 +555,154 @@ program
|
|
|
548
555
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
549
556
|
.action(async (id, opts) => {
|
|
550
557
|
try {
|
|
551
|
-
const { address } = getWallet(opts);
|
|
558
|
+
const { privateKey, address } = getWallet(opts);
|
|
552
559
|
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`, {
|
|
553
560
|
method: 'DELETE',
|
|
554
|
-
headers: walletHeaders(
|
|
561
|
+
headers: await walletHeaders(privateKey),
|
|
562
|
+
});
|
|
563
|
+
console.log(JSON.stringify(data, null, 2));
|
|
564
|
+
}
|
|
565
|
+
catch (err) {
|
|
566
|
+
console.error(`Error: ${err.message}`);
|
|
567
|
+
process.exit(1);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
// ─── my-workflows (creator endpoint view) ───
|
|
571
|
+
program
|
|
572
|
+
.command('my-workflows')
|
|
573
|
+
.description('List workflows you created (uses your wallet)')
|
|
574
|
+
.option('-l, --limit <n>', 'Max results', '50')
|
|
575
|
+
.option('-s, --status <status>', 'Filter: active | draft | paused | all', 'all')
|
|
576
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
577
|
+
.action(async (opts) => {
|
|
578
|
+
try {
|
|
579
|
+
const { privateKey, address } = getWallet(opts);
|
|
580
|
+
const params = new URLSearchParams({
|
|
581
|
+
limit: opts.limit,
|
|
582
|
+
status: opts.status,
|
|
583
|
+
creator: address,
|
|
584
|
+
});
|
|
585
|
+
const data = await fetchJson(`${API_BASE}/api/workflows?${params}`);
|
|
586
|
+
const workflows = data.workflows || [];
|
|
587
|
+
if (!workflows.length) {
|
|
588
|
+
console.log('No workflows found for this wallet.');
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
const rows = [['ID', 'NAME', 'STATUS', 'VER', 'NODES', 'COST']];
|
|
592
|
+
for (const w of workflows) {
|
|
593
|
+
rows.push([
|
|
594
|
+
w.workflowId,
|
|
595
|
+
truncate(w.name || '', 24),
|
|
596
|
+
w.status,
|
|
597
|
+
`v${w.currentVersion ?? 1}`,
|
|
598
|
+
String(w.graph?.nodes?.length || 0),
|
|
599
|
+
`$${w.totalPrice}`,
|
|
600
|
+
]);
|
|
601
|
+
}
|
|
602
|
+
printTable(rows);
|
|
603
|
+
}
|
|
604
|
+
catch (err) {
|
|
605
|
+
console.error(`Error: ${err.message}`);
|
|
606
|
+
process.exit(1);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
// ─── workflow-versions ───
|
|
610
|
+
program
|
|
611
|
+
.command('workflow-versions <id>')
|
|
612
|
+
.description('List all versions of a workflow')
|
|
613
|
+
.action(async (id) => {
|
|
614
|
+
try {
|
|
615
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}/versions`);
|
|
616
|
+
const versions = data.versions || [];
|
|
617
|
+
if (!versions.length) {
|
|
618
|
+
console.log('No versions found.');
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
const rows = [['VER', 'DEFAULT', 'VERSION_ID', 'PRICE', 'CREATED', 'CHANGELOG']];
|
|
622
|
+
for (const v of versions) {
|
|
623
|
+
rows.push([
|
|
624
|
+
`v${v.version}`,
|
|
625
|
+
v.isDefault ? '★' : '',
|
|
626
|
+
v.versionId,
|
|
627
|
+
`$${v.totalPrice}`,
|
|
628
|
+
new Date(v.createdAt).toLocaleDateString(),
|
|
629
|
+
truncate(v.changelog || '', 40),
|
|
630
|
+
]);
|
|
631
|
+
}
|
|
632
|
+
printTable(rows);
|
|
633
|
+
}
|
|
634
|
+
catch (err) {
|
|
635
|
+
console.error(`Error: ${err.message}`);
|
|
636
|
+
process.exit(1);
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
// ─── workflow-version-create ───
|
|
640
|
+
program
|
|
641
|
+
.command('workflow-version-create <id>')
|
|
642
|
+
.description('Create a new version of a workflow (graph/price/splits)')
|
|
643
|
+
.option('--graph <json>', 'Graph JSON (inherits current if omitted)')
|
|
644
|
+
.option('--price <usdc>', 'Total price')
|
|
645
|
+
.option('--splits <json>', 'Splits JSON array')
|
|
646
|
+
.option('--changelog <msg>', 'Changelog message')
|
|
647
|
+
.option('--no-default', 'Create as non-default (keeps current version active)')
|
|
648
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
649
|
+
.action(async (id, opts) => {
|
|
650
|
+
try {
|
|
651
|
+
const { privateKey, address } = getWallet(opts);
|
|
652
|
+
const body = {};
|
|
653
|
+
if (opts.graph)
|
|
654
|
+
body.graph = JSON.parse(opts.graph);
|
|
655
|
+
if (opts.price)
|
|
656
|
+
body.totalPrice = opts.price;
|
|
657
|
+
if (opts.splits)
|
|
658
|
+
body.splits = JSON.parse(opts.splits);
|
|
659
|
+
if (opts.changelog)
|
|
660
|
+
body.changelog = opts.changelog;
|
|
661
|
+
if (opts.default === false)
|
|
662
|
+
body.setDefault = false;
|
|
663
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}/versions`, {
|
|
664
|
+
method: 'POST',
|
|
665
|
+
headers: await walletHeaders(privateKey),
|
|
666
|
+
body: JSON.stringify(body),
|
|
667
|
+
});
|
|
668
|
+
console.log(JSON.stringify(data, null, 2));
|
|
669
|
+
}
|
|
670
|
+
catch (err) {
|
|
671
|
+
console.error(`Error: ${err.message}`);
|
|
672
|
+
process.exit(1);
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
// ─── workflow-version-set-default ───
|
|
676
|
+
program
|
|
677
|
+
.command('workflow-version-set-default <id> <versionIdOrNumber>')
|
|
678
|
+
.description('Set a version as the active/default for a workflow (rollback/promote)')
|
|
679
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
680
|
+
.action(async (id, vid, opts) => {
|
|
681
|
+
try {
|
|
682
|
+
const { privateKey, address } = getWallet(opts);
|
|
683
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}/versions/${vid}`, {
|
|
684
|
+
method: 'PUT',
|
|
685
|
+
headers: await walletHeaders(privateKey),
|
|
686
|
+
body: JSON.stringify({ setDefault: true }),
|
|
687
|
+
});
|
|
688
|
+
console.log(JSON.stringify(data, null, 2));
|
|
689
|
+
}
|
|
690
|
+
catch (err) {
|
|
691
|
+
console.error(`Error: ${err.message}`);
|
|
692
|
+
process.exit(1);
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
// ─── workflow-version-delete ───
|
|
696
|
+
program
|
|
697
|
+
.command('workflow-version-delete <id> <versionIdOrNumber>')
|
|
698
|
+
.description('Delete a non-default workflow version')
|
|
699
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
700
|
+
.action(async (id, vid, opts) => {
|
|
701
|
+
try {
|
|
702
|
+
const { privateKey, address } = getWallet(opts);
|
|
703
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}/versions/${vid}`, {
|
|
704
|
+
method: 'DELETE',
|
|
705
|
+
headers: await walletHeaders(privateKey),
|
|
555
706
|
});
|
|
556
707
|
console.log(JSON.stringify(data, null, 2));
|
|
557
708
|
}
|
|
@@ -573,7 +724,7 @@ program
|
|
|
573
724
|
if (!endpoint.includes('/'))
|
|
574
725
|
throw new Error('Format: namespace/endpoint-name');
|
|
575
726
|
const [ns, ep] = endpoint.split('/');
|
|
576
|
-
const { address } = getWallet(opts);
|
|
727
|
+
const { privateKey, address } = getWallet(opts);
|
|
577
728
|
const details = await fetchJson(`${API_BASE}/api/endpoints/${ns}/${ep}/details`);
|
|
578
729
|
const body = {
|
|
579
730
|
endpointName: ep,
|
|
@@ -693,7 +844,7 @@ program
|
|
|
693
844
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
694
845
|
.action(async (id, opts) => {
|
|
695
846
|
try {
|
|
696
|
-
const { address } = getWallet(opts);
|
|
847
|
+
const { privateKey, address } = getWallet(opts);
|
|
697
848
|
const data = await fetchJson(`${API_BASE}/api/ai/generate-ui`, {
|
|
698
849
|
method: 'DELETE',
|
|
699
850
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -713,7 +864,7 @@ program
|
|
|
713
864
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
714
865
|
.action(async (id, opts) => {
|
|
715
866
|
try {
|
|
716
|
-
const { address } = getWallet(opts);
|
|
867
|
+
const { privateKey, address } = getWallet(opts);
|
|
717
868
|
const data = await fetchJson(`${API_BASE}/api/ai/generate-ui`, {
|
|
718
869
|
method: 'PATCH',
|
|
719
870
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -732,7 +883,7 @@ program
|
|
|
732
883
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
733
884
|
.action(async (id, opts) => {
|
|
734
885
|
try {
|
|
735
|
-
const { address } = getWallet(opts);
|
|
886
|
+
const { privateKey, address } = getWallet(opts);
|
|
736
887
|
const data = await fetchJson(`${API_BASE}/api/ai/generate-ui`, {
|
|
737
888
|
method: 'PATCH',
|
|
738
889
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -753,7 +904,7 @@ program
|
|
|
753
904
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
754
905
|
.action(async (id, opts) => {
|
|
755
906
|
try {
|
|
756
|
-
const { address } = getWallet(opts);
|
|
907
|
+
const { privateKey, address } = getWallet(opts);
|
|
757
908
|
const data = await fetchJson(`${API_BASE}/api/ai/generate-ui`, {
|
|
758
909
|
method: 'PATCH',
|
|
759
910
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -773,7 +924,7 @@ program
|
|
|
773
924
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
774
925
|
.action(async (opts) => {
|
|
775
926
|
try {
|
|
776
|
-
const { address } = getWallet(opts);
|
|
927
|
+
const { privateKey, address } = getWallet(opts);
|
|
777
928
|
const params = new URLSearchParams({ checkFree: '1', wallet: address });
|
|
778
929
|
const data = await fetchJson(`${API_BASE}/api/ai/generate-ui?${params}`);
|
|
779
930
|
console.log(`\n Wallet: ${address}`);
|
|
@@ -792,9 +943,9 @@ program
|
|
|
792
943
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
793
944
|
.action(async (opts) => {
|
|
794
945
|
try {
|
|
795
|
-
const { address } = getWallet(opts);
|
|
946
|
+
const { privateKey, address } = getWallet(opts);
|
|
796
947
|
const data = await fetchJson(`${API_BASE}/api/user-factory/check-balance`, {
|
|
797
|
-
headers: walletHeaders(
|
|
948
|
+
headers: await walletHeaders(privateKey),
|
|
798
949
|
});
|
|
799
950
|
console.log(`\n Wallet: ${address}`);
|
|
800
951
|
console.log(` Balance: ${data.balance} $APINOW`);
|
|
@@ -813,9 +964,9 @@ program
|
|
|
813
964
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
814
965
|
.action(async (opts) => {
|
|
815
966
|
try {
|
|
816
|
-
const { address } = getWallet(opts);
|
|
967
|
+
const { privateKey, address } = getWallet(opts);
|
|
817
968
|
const data = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
818
|
-
headers: walletHeaders(
|
|
969
|
+
headers: await walletHeaders(privateKey),
|
|
819
970
|
});
|
|
820
971
|
const endpoints = data.endpoints || [];
|
|
821
972
|
if (!endpoints.length) {
|
|
@@ -845,11 +996,11 @@ program
|
|
|
845
996
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
846
997
|
.action(async (idea, opts) => {
|
|
847
998
|
try {
|
|
848
|
-
const { address } = getWallet(opts);
|
|
999
|
+
const { privateKey, address } = getWallet(opts);
|
|
849
1000
|
console.error('Generating endpoint config…');
|
|
850
1001
|
const data = await fetchJson(`${API_BASE}/api/user-factory/generate`, {
|
|
851
1002
|
method: 'POST',
|
|
852
|
-
headers: walletHeaders(
|
|
1003
|
+
headers: await walletHeaders(privateKey),
|
|
853
1004
|
body: JSON.stringify({ idea }),
|
|
854
1005
|
});
|
|
855
1006
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -876,7 +1027,7 @@ program
|
|
|
876
1027
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
877
1028
|
.action(async (opts) => {
|
|
878
1029
|
try {
|
|
879
|
-
const { address } = getWallet(opts);
|
|
1030
|
+
const { privateKey, address } = getWallet(opts);
|
|
880
1031
|
let body;
|
|
881
1032
|
if (opts.fromJson) {
|
|
882
1033
|
const { readFileSync } = await import('fs');
|
|
@@ -933,7 +1084,7 @@ program
|
|
|
933
1084
|
console.error(`Creating endpoint "${body.name}"…`);
|
|
934
1085
|
const data = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
935
1086
|
method: 'POST',
|
|
936
|
-
headers: walletHeaders(
|
|
1087
|
+
headers: await walletHeaders(privateKey),
|
|
937
1088
|
body: JSON.stringify(body),
|
|
938
1089
|
});
|
|
939
1090
|
const ep = data.endpoint;
|
|
@@ -961,7 +1112,7 @@ program
|
|
|
961
1112
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
962
1113
|
.action(async (endpointId, opts) => {
|
|
963
1114
|
try {
|
|
964
|
-
const { address } = getWallet(opts);
|
|
1115
|
+
const { privateKey, address } = getWallet(opts);
|
|
965
1116
|
const body = { endpointId, markupPercent: Number(opts.markup) };
|
|
966
1117
|
if (opts.name)
|
|
967
1118
|
body.workflowName = opts.name;
|
|
@@ -977,7 +1128,7 @@ program
|
|
|
977
1128
|
console.error(`Creating markup workflow (${opts.markup}%${tbLabel})…`);
|
|
978
1129
|
const data = await fetchJson(`${API_BASE}/api/user-factory/markup`, {
|
|
979
1130
|
method: 'POST',
|
|
980
|
-
headers: walletHeaders(
|
|
1131
|
+
headers: await walletHeaders(privateKey),
|
|
981
1132
|
body: JSON.stringify(body),
|
|
982
1133
|
});
|
|
983
1134
|
const w = data.workflow;
|
|
@@ -1006,7 +1157,7 @@ program
|
|
|
1006
1157
|
try {
|
|
1007
1158
|
if (!endpoint.includes('/'))
|
|
1008
1159
|
throw new Error('Format: namespace/endpoint-name');
|
|
1009
|
-
const { address } = getWallet(opts);
|
|
1160
|
+
const { privateKey, address } = getWallet(opts);
|
|
1010
1161
|
const [namespace, endpointName] = endpoint.split('/');
|
|
1011
1162
|
const body = { namespace, endpointName };
|
|
1012
1163
|
if (opts.data)
|
|
@@ -1016,7 +1167,7 @@ program
|
|
|
1016
1167
|
console.error(`Testing ${endpoint}…`);
|
|
1017
1168
|
const data = await fetchJson(`${API_BASE}/api/user-factory/test-call`, {
|
|
1018
1169
|
method: 'POST',
|
|
1019
|
-
headers: walletHeaders(
|
|
1170
|
+
headers: await walletHeaders(privateKey),
|
|
1020
1171
|
body: JSON.stringify(body),
|
|
1021
1172
|
});
|
|
1022
1173
|
console.log(JSON.stringify(data.output, null, 2));
|
|
@@ -1044,12 +1195,12 @@ program
|
|
|
1044
1195
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
1045
1196
|
.action(async (idea, opts) => {
|
|
1046
1197
|
try {
|
|
1047
|
-
const { address } = getWallet(opts);
|
|
1198
|
+
const { privateKey, address } = getWallet(opts);
|
|
1048
1199
|
// Step 1: Generate
|
|
1049
1200
|
console.error('Step 1/4: Generating endpoint config from idea…');
|
|
1050
1201
|
const draft = await fetchJson(`${API_BASE}/api/user-factory/generate`, {
|
|
1051
1202
|
method: 'POST',
|
|
1052
|
-
headers: walletHeaders(
|
|
1203
|
+
headers: await walletHeaders(privateKey),
|
|
1053
1204
|
body: JSON.stringify({ idea }),
|
|
1054
1205
|
});
|
|
1055
1206
|
console.error(` → ${draft.name}: ${draft.description}`);
|
|
@@ -1075,7 +1226,7 @@ program
|
|
|
1075
1226
|
createBody.recipientWallet = opts.recipient;
|
|
1076
1227
|
const createData = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
1077
1228
|
method: 'POST',
|
|
1078
|
-
headers: walletHeaders(
|
|
1229
|
+
headers: await walletHeaders(privateKey),
|
|
1079
1230
|
body: JSON.stringify(createBody),
|
|
1080
1231
|
});
|
|
1081
1232
|
const ep = createData.endpoint;
|
|
@@ -1085,7 +1236,7 @@ program
|
|
|
1085
1236
|
const testInput = draft.exampleInput || { prompt: 'test' };
|
|
1086
1237
|
const testData = await fetchJson(`${API_BASE}/api/user-factory/test-call`, {
|
|
1087
1238
|
method: 'POST',
|
|
1088
|
-
headers: walletHeaders(
|
|
1239
|
+
headers: await walletHeaders(privateKey),
|
|
1089
1240
|
body: JSON.stringify({
|
|
1090
1241
|
namespace: ep.namespace,
|
|
1091
1242
|
endpointName: ep.endpointName,
|
|
@@ -1112,7 +1263,7 @@ program
|
|
|
1112
1263
|
markupBody.tokenBuyCA = opts.tokenBuyCa;
|
|
1113
1264
|
const markupData = await fetchJson(`${API_BASE}/api/user-factory/markup`, {
|
|
1114
1265
|
method: 'POST',
|
|
1115
|
-
headers: walletHeaders(
|
|
1266
|
+
headers: await walletHeaders(privateKey),
|
|
1116
1267
|
body: JSON.stringify(markupBody),
|
|
1117
1268
|
});
|
|
1118
1269
|
workflow = markupData.workflow;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,11 +18,31 @@ export interface PriceDiscovery {
|
|
|
18
18
|
network: string;
|
|
19
19
|
upstreamAccepts: any[];
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Agent/server path — signs everything with a raw private key. Enables
|
|
23
|
+
* both x402 paid calls and signed-auth write calls.
|
|
24
|
+
*/
|
|
25
|
+
export interface ApinowServerConfig {
|
|
22
26
|
privateKey: `0x${string}`;
|
|
23
27
|
baseUrl?: string;
|
|
24
28
|
fetch?: typeof globalThis.fetch;
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Browser/wallet path — you provide a `signer` (any EIP-191 `personal_sign`
|
|
32
|
+
* function, e.g. from wagmi's `walletClient.signMessage`) and the connected
|
|
33
|
+
* `address`. Enables signed-auth writes. Paid x402 calls are NOT provided by
|
|
34
|
+
* this path — construct the x402 fetch yourself (see useX402Fetch pattern in
|
|
35
|
+
* the skill docs) and pass it to `paidFetch` if you need unified behaviour.
|
|
36
|
+
*/
|
|
37
|
+
export interface ApinowBrowserConfig {
|
|
38
|
+
signer: (message: string) => Promise<`0x${string}` | string>;
|
|
39
|
+
address: `0x${string}`;
|
|
40
|
+
baseUrl?: string;
|
|
41
|
+
fetch?: typeof globalThis.fetch;
|
|
42
|
+
/** Optional externally-prepared x402 fetch for paid calls. */
|
|
43
|
+
paidFetch?: typeof globalThis.fetch;
|
|
44
|
+
}
|
|
45
|
+
export type ApinowConfig = ApinowServerConfig | ApinowBrowserConfig;
|
|
26
46
|
export interface GenerateUIOptions {
|
|
27
47
|
endpointName: string;
|
|
28
48
|
namespace: string;
|
|
@@ -55,6 +75,11 @@ export interface GeneratedUI {
|
|
|
55
75
|
}
|
|
56
76
|
export declare function createClient(config: ApinowConfig): {
|
|
57
77
|
wallet: `0x${string}`;
|
|
78
|
+
/**
|
|
79
|
+
* Produce a signed `Authorization` header for custom write calls.
|
|
80
|
+
* Pairs with `x-wallet-address`. Backend accepts msg within ~10 min.
|
|
81
|
+
*/
|
|
82
|
+
signAuthHeader: () => Promise<Record<string, string>>;
|
|
58
83
|
/**
|
|
59
84
|
* Call any APINow endpoint. Handles x402 payment automatically.
|
|
60
85
|
*
|
|
@@ -138,6 +163,52 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
138
163
|
}): Promise<any>;
|
|
139
164
|
updateWorkflow(workflowId: string, updates: Record<string, any>): Promise<any>;
|
|
140
165
|
deleteWorkflow(workflowId: string): Promise<any>;
|
|
166
|
+
/**
|
|
167
|
+
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
168
|
+
*/
|
|
169
|
+
listMyWorkflows(opts?: {
|
|
170
|
+
status?: string;
|
|
171
|
+
limit?: number;
|
|
172
|
+
}): Promise<any>;
|
|
173
|
+
/**
|
|
174
|
+
* List all versions of a workflow (public, free).
|
|
175
|
+
*/
|
|
176
|
+
listWorkflowVersions(workflowId: string): Promise<{
|
|
177
|
+
versions: any[];
|
|
178
|
+
}>;
|
|
179
|
+
/**
|
|
180
|
+
* Get a specific workflow version by versionId or numeric version.
|
|
181
|
+
*/
|
|
182
|
+
getWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
183
|
+
/**
|
|
184
|
+
* Create a new workflow version (creator only). Defaults to setting it as default.
|
|
185
|
+
* Omit fields to inherit from current workflow.
|
|
186
|
+
*/
|
|
187
|
+
createWorkflowVersion(workflowId: string, updates?: {
|
|
188
|
+
graph?: {
|
|
189
|
+
nodes: any[];
|
|
190
|
+
outputNode: string;
|
|
191
|
+
outputMapping?: any;
|
|
192
|
+
};
|
|
193
|
+
totalPrice?: string;
|
|
194
|
+
splits?: Array<{
|
|
195
|
+
address: string;
|
|
196
|
+
basisPoints: number;
|
|
197
|
+
label?: string;
|
|
198
|
+
tokenAddress?: string;
|
|
199
|
+
}>;
|
|
200
|
+
mermaidDiagram?: string;
|
|
201
|
+
executionMode?: "balanced" | "optimistic" | "settle_first";
|
|
202
|
+
changelog?: string;
|
|
203
|
+
setDefault?: boolean;
|
|
204
|
+
forkedFrom?: string;
|
|
205
|
+
}): Promise<any>;
|
|
206
|
+
/**
|
|
207
|
+
* Set a version as the default (active) for a workflow. Also rolls the
|
|
208
|
+
* workflow's graph/price/splits back to that version's snapshot.
|
|
209
|
+
*/
|
|
210
|
+
setDefaultWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
211
|
+
deleteWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
141
212
|
/**
|
|
142
213
|
* Run a workflow. Handles x402 payment automatically.
|
|
143
214
|
*
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@ import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
|
|
|
2
2
|
import { registerExactEvmScheme } from '@x402/evm/exact/client';
|
|
3
3
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
4
|
const APINOW_BASE = 'https://apinow.fun';
|
|
5
|
+
function isServerConfig(c) {
|
|
6
|
+
return 'privateKey' in c && typeof c.privateKey === 'string';
|
|
7
|
+
}
|
|
5
8
|
// ─── SDK ───
|
|
6
9
|
// Prevent undici (Node 20+ / Vercel) from crashing when @x402/fetch retries
|
|
7
10
|
// a POST with a cloned Request body stream and the server returns a 3xx redirect.
|
|
@@ -23,18 +26,83 @@ async function followRedirects(res) {
|
|
|
23
26
|
return res;
|
|
24
27
|
}
|
|
25
28
|
export function createClient(config) {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const server = isServerConfig(config);
|
|
30
|
+
const baseUrl = config.baseUrl ?? APINOW_BASE;
|
|
31
|
+
const customFetch = config.fetch;
|
|
32
|
+
// Resolve address + signer from whichever config shape the caller passed.
|
|
33
|
+
const account = server ? privateKeyToAccount(config.privateKey) : null;
|
|
34
|
+
const address = server
|
|
35
|
+
? account.address
|
|
36
|
+
: config.address.toLowerCase();
|
|
37
|
+
const signMessage = server
|
|
38
|
+
? (msg) => account.signMessage({ message: msg })
|
|
39
|
+
: (msg) => Promise.resolve(config.signer(msg)).then((s) => String(s));
|
|
40
|
+
// x402 paid fetch — only available when a private key is provided. Browsers
|
|
41
|
+
// should build their own x402 fetch (see skill.md useX402Fetch) and pass it
|
|
42
|
+
// as `paidFetch` to fall back through here.
|
|
43
|
+
const paidFetchExternal = !server ? config.paidFetch : undefined;
|
|
44
|
+
const fetchWithPayment = server
|
|
45
|
+
? (() => {
|
|
46
|
+
const client = new x402Client();
|
|
47
|
+
registerExactEvmScheme(client, { signer: account });
|
|
48
|
+
const safeFetch = makeSafeFetch(customFetch ?? fetch);
|
|
49
|
+
const rawFetchWithPayment = wrapFetchWithPayment(safeFetch, client);
|
|
50
|
+
return (async (input, init) => {
|
|
51
|
+
const res = await rawFetchWithPayment(input, init);
|
|
52
|
+
return followRedirects(res);
|
|
53
|
+
});
|
|
54
|
+
})()
|
|
55
|
+
: (paidFetchExternal ??
|
|
56
|
+
(() => {
|
|
57
|
+
throw new Error('createClient: paid calls require a `privateKey` config or an explicit `paidFetch`. Pass an x402-wrapped fetch to make paid calls from the browser.');
|
|
58
|
+
}));
|
|
59
|
+
/**
|
|
60
|
+
* Produce an `Authorization: Bearer <msg>||<sig>||<addr>` header signed by
|
|
61
|
+
* the wallet. Backend verifies with ethers.recoverAddress and rejects
|
|
62
|
+
* messages older than ~10 min. Works for both server (privateKey) and
|
|
63
|
+
* browser (walletClient.signMessage) configs.
|
|
64
|
+
*/
|
|
65
|
+
async function signAuthHeader() {
|
|
66
|
+
const issuedAt = new Date().toISOString();
|
|
67
|
+
const nonce = Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
68
|
+
const message = `APINow auth\naddress: ${address}\nissuedAt: ${issuedAt}\nnonce: ${nonce}`;
|
|
69
|
+
const signature = await signMessage(message);
|
|
70
|
+
return {
|
|
71
|
+
Authorization: `Bearer ${message}||${signature}||${address}`,
|
|
72
|
+
'x-wallet-address': address,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fetch wrapper that signs write requests with the wallet private key.
|
|
77
|
+
* Use for any non-paid mutating API (endpoint/workflow/version CRUD).
|
|
78
|
+
*/
|
|
79
|
+
async function authedFetch(url, init = {}) {
|
|
80
|
+
const authHeaders = await signAuthHeader();
|
|
81
|
+
const res = await fetch(url, {
|
|
82
|
+
...init,
|
|
83
|
+
headers: {
|
|
84
|
+
...(init.body ? { 'Content-Type': 'application/json' } : {}),
|
|
85
|
+
...authHeaders,
|
|
86
|
+
...init.headers,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
return res;
|
|
90
|
+
}
|
|
91
|
+
async function authedJson(url, init = {}) {
|
|
92
|
+
const res = await authedFetch(url, init);
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
const text = await res.text();
|
|
95
|
+
throw new Error(`APINow ${res.status}: ${text}`);
|
|
96
|
+
}
|
|
97
|
+
return res.json();
|
|
98
|
+
}
|
|
36
99
|
return {
|
|
37
|
-
wallet:
|
|
100
|
+
wallet: address,
|
|
101
|
+
/**
|
|
102
|
+
* Produce a signed `Authorization` header for custom write calls.
|
|
103
|
+
* Pairs with `x-wallet-address`. Backend accepts msg within ~10 min.
|
|
104
|
+
*/
|
|
105
|
+
signAuthHeader,
|
|
38
106
|
/**
|
|
39
107
|
* Call any APINow endpoint. Handles x402 payment automatically.
|
|
40
108
|
*
|
|
@@ -84,16 +152,10 @@ export function createClient(config) {
|
|
|
84
152
|
},
|
|
85
153
|
// ─── Endpoint CRUD ───
|
|
86
154
|
async createEndpoint(config) {
|
|
87
|
-
|
|
155
|
+
return authedJson(`${baseUrl}/api/endpoints`, {
|
|
88
156
|
method: 'POST',
|
|
89
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
90
157
|
body: JSON.stringify(config),
|
|
91
158
|
});
|
|
92
|
-
if (!res.ok) {
|
|
93
|
-
const text = await res.text();
|
|
94
|
-
throw new Error(`Failed to create endpoint: ${res.status} ${text}`);
|
|
95
|
-
}
|
|
96
|
-
return res.json();
|
|
97
159
|
},
|
|
98
160
|
async getEndpoint(id) {
|
|
99
161
|
const res = await fetch(`${baseUrl}/api/endpoints/${id}`);
|
|
@@ -102,27 +164,13 @@ export function createClient(config) {
|
|
|
102
164
|
return res.json();
|
|
103
165
|
},
|
|
104
166
|
async updateEndpoint(id, updates) {
|
|
105
|
-
|
|
167
|
+
return authedJson(`${baseUrl}/api/endpoints/${id}`, {
|
|
106
168
|
method: 'PUT',
|
|
107
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
108
169
|
body: JSON.stringify(updates),
|
|
109
170
|
});
|
|
110
|
-
if (!res.ok) {
|
|
111
|
-
const text = await res.text();
|
|
112
|
-
throw new Error(`Failed to update endpoint: ${res.status} ${text}`);
|
|
113
|
-
}
|
|
114
|
-
return res.json();
|
|
115
171
|
},
|
|
116
172
|
async deleteEndpoint(id) {
|
|
117
|
-
|
|
118
|
-
method: 'DELETE',
|
|
119
|
-
headers: { 'x-wallet-address': account.address },
|
|
120
|
-
});
|
|
121
|
-
if (!res.ok) {
|
|
122
|
-
const text = await res.text();
|
|
123
|
-
throw new Error(`Failed to delete endpoint: ${res.status} ${text}`);
|
|
124
|
-
}
|
|
125
|
-
return res.json();
|
|
173
|
+
return authedJson(`${baseUrl}/api/endpoints/${id}`, { method: 'DELETE' });
|
|
126
174
|
},
|
|
127
175
|
async listEndpoints(opts = {}) {
|
|
128
176
|
const params = new URLSearchParams();
|
|
@@ -166,40 +214,68 @@ export function createClient(config) {
|
|
|
166
214
|
return res.json();
|
|
167
215
|
},
|
|
168
216
|
async createWorkflow(config) {
|
|
169
|
-
|
|
217
|
+
return authedJson(`${baseUrl}/api/workflows`, {
|
|
170
218
|
method: 'POST',
|
|
171
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
172
219
|
body: JSON.stringify(config),
|
|
173
220
|
});
|
|
174
|
-
if (!res.ok) {
|
|
175
|
-
const text = await res.text();
|
|
176
|
-
throw new Error(`Failed to create workflow: ${res.status} ${text}`);
|
|
177
|
-
}
|
|
178
|
-
return res.json();
|
|
179
221
|
},
|
|
180
222
|
async updateWorkflow(workflowId, updates) {
|
|
181
|
-
|
|
223
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}`, {
|
|
182
224
|
method: 'PUT',
|
|
183
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
184
225
|
body: JSON.stringify(updates),
|
|
185
226
|
});
|
|
186
|
-
if (!res.ok) {
|
|
187
|
-
const text = await res.text();
|
|
188
|
-
throw new Error(`Failed to update workflow: ${res.status} ${text}`);
|
|
189
|
-
}
|
|
190
|
-
return res.json();
|
|
191
227
|
},
|
|
192
228
|
async deleteWorkflow(workflowId) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
229
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}`, { method: 'DELETE' });
|
|
230
|
+
},
|
|
231
|
+
/**
|
|
232
|
+
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
233
|
+
*/
|
|
234
|
+
async listMyWorkflows(opts = {}) {
|
|
235
|
+
return this.listWorkflows({ ...opts, creator: address });
|
|
236
|
+
},
|
|
237
|
+
// ─── Workflow Versions ───
|
|
238
|
+
/**
|
|
239
|
+
* List all versions of a workflow (public, free).
|
|
240
|
+
*/
|
|
241
|
+
async listWorkflowVersions(workflowId) {
|
|
242
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}/versions`);
|
|
243
|
+
if (!res.ok)
|
|
244
|
+
throw new Error(`Failed to list versions: ${res.status}`);
|
|
245
|
+
return res.json();
|
|
246
|
+
},
|
|
247
|
+
/**
|
|
248
|
+
* Get a specific workflow version by versionId or numeric version.
|
|
249
|
+
*/
|
|
250
|
+
async getWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
251
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`);
|
|
252
|
+
if (!res.ok)
|
|
253
|
+
throw new Error(`Failed to get version: ${res.status}`);
|
|
201
254
|
return res.json();
|
|
202
255
|
},
|
|
256
|
+
/**
|
|
257
|
+
* Create a new workflow version (creator only). Defaults to setting it as default.
|
|
258
|
+
* Omit fields to inherit from current workflow.
|
|
259
|
+
*/
|
|
260
|
+
async createWorkflowVersion(workflowId, updates = {}) {
|
|
261
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions`, {
|
|
262
|
+
method: 'POST',
|
|
263
|
+
body: JSON.stringify(updates),
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
/**
|
|
267
|
+
* Set a version as the default (active) for a workflow. Also rolls the
|
|
268
|
+
* workflow's graph/price/splits back to that version's snapshot.
|
|
269
|
+
*/
|
|
270
|
+
async setDefaultWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
271
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`, {
|
|
272
|
+
method: 'PUT',
|
|
273
|
+
body: JSON.stringify({ setDefault: true }),
|
|
274
|
+
});
|
|
275
|
+
},
|
|
276
|
+
async deleteWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
277
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`, { method: 'DELETE' });
|
|
278
|
+
},
|
|
203
279
|
/**
|
|
204
280
|
* Run a workflow. Handles x402 payment automatically.
|
|
205
281
|
*
|
|
@@ -217,82 +293,50 @@ export function createClient(config) {
|
|
|
217
293
|
* Check $APINOW token balance and factory access.
|
|
218
294
|
*/
|
|
219
295
|
async factoryBalance() {
|
|
220
|
-
|
|
221
|
-
headers: { 'x-wallet-address': account.address },
|
|
222
|
-
});
|
|
223
|
-
if (!res.ok)
|
|
224
|
-
throw new Error(`Failed to check balance: ${res.status}`);
|
|
225
|
-
return res.json();
|
|
296
|
+
return authedJson(`${baseUrl}/api/user-factory/check-balance`);
|
|
226
297
|
},
|
|
227
298
|
/**
|
|
228
299
|
* List your user-factory endpoints.
|
|
229
300
|
*/
|
|
230
301
|
async factoryList() {
|
|
231
|
-
|
|
232
|
-
headers: { 'x-wallet-address': account.address },
|
|
233
|
-
});
|
|
234
|
-
if (!res.ok)
|
|
235
|
-
throw new Error(`Failed to list factory endpoints: ${res.status}`);
|
|
236
|
-
return res.json();
|
|
302
|
+
return authedJson(`${baseUrl}/api/user-factory`);
|
|
237
303
|
},
|
|
238
304
|
/**
|
|
239
305
|
* Generate endpoint config from a natural-language idea.
|
|
240
306
|
*/
|
|
241
307
|
async factoryGenerate(idea) {
|
|
242
|
-
|
|
308
|
+
return authedJson(`${baseUrl}/api/user-factory/generate`, {
|
|
243
309
|
method: 'POST',
|
|
244
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
245
310
|
body: JSON.stringify({ idea }),
|
|
246
311
|
});
|
|
247
|
-
if (!res.ok)
|
|
248
|
-
throw new Error(`Failed to generate: ${res.status}`);
|
|
249
|
-
return res.json();
|
|
250
312
|
},
|
|
251
313
|
/**
|
|
252
314
|
* Create an LLM endpoint via user-factory.
|
|
253
315
|
*/
|
|
254
316
|
async factoryCreate(config) {
|
|
255
|
-
|
|
317
|
+
return authedJson(`${baseUrl}/api/user-factory`, {
|
|
256
318
|
method: 'POST',
|
|
257
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
258
319
|
body: JSON.stringify(config),
|
|
259
320
|
});
|
|
260
|
-
if (!res.ok) {
|
|
261
|
-
const text = await res.text();
|
|
262
|
-
throw new Error(`Failed to create endpoint: ${res.status} ${text}`);
|
|
263
|
-
}
|
|
264
|
-
return res.json();
|
|
265
321
|
},
|
|
266
322
|
/**
|
|
267
323
|
* Create a markup workflow wrapping an existing endpoint.
|
|
268
324
|
* Optionally allocate a portion of the markup to a token buy split.
|
|
269
325
|
*/
|
|
270
326
|
async factoryMarkup(opts) {
|
|
271
|
-
|
|
327
|
+
return authedJson(`${baseUrl}/api/user-factory/markup`, {
|
|
272
328
|
method: 'POST',
|
|
273
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
274
329
|
body: JSON.stringify(opts),
|
|
275
330
|
});
|
|
276
|
-
if (!res.ok) {
|
|
277
|
-
const text = await res.text();
|
|
278
|
-
throw new Error(`Failed to create markup: ${res.status} ${text}`);
|
|
279
|
-
}
|
|
280
|
-
return res.json();
|
|
281
331
|
},
|
|
282
332
|
/**
|
|
283
333
|
* Test-call an endpoint without payment (free, server-side LLM call).
|
|
284
334
|
*/
|
|
285
335
|
async factoryTestCall(opts) {
|
|
286
|
-
|
|
336
|
+
return authedJson(`${baseUrl}/api/user-factory/test-call`, {
|
|
287
337
|
method: 'POST',
|
|
288
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
289
338
|
body: JSON.stringify(opts),
|
|
290
339
|
});
|
|
291
|
-
if (!res.ok) {
|
|
292
|
-
const text = await res.text();
|
|
293
|
-
throw new Error(`Failed to test call: ${res.status} ${text}`);
|
|
294
|
-
}
|
|
295
|
-
return res.json();
|
|
296
340
|
},
|
|
297
341
|
// ─── Factory Pipeline ───
|
|
298
342
|
/**
|
|
@@ -352,7 +396,7 @@ export function createClient(config) {
|
|
|
352
396
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
353
397
|
method: 'POST',
|
|
354
398
|
headers: { 'Content-Type': 'application/json' },
|
|
355
|
-
body: JSON.stringify({ ...opts, walletAddress:
|
|
399
|
+
body: JSON.stringify({ ...opts, walletAddress: address }),
|
|
356
400
|
});
|
|
357
401
|
if (!res.ok) {
|
|
358
402
|
const text = await res.text();
|
|
@@ -387,7 +431,7 @@ export function createClient(config) {
|
|
|
387
431
|
* Check free-tier UI generation eligibility for a wallet.
|
|
388
432
|
*/
|
|
389
433
|
async checkFreeUI() {
|
|
390
|
-
const params = new URLSearchParams({ checkFree: '1', wallet:
|
|
434
|
+
const params = new URLSearchParams({ checkFree: '1', wallet: address });
|
|
391
435
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui?${params}`);
|
|
392
436
|
if (!res.ok)
|
|
393
437
|
throw new Error(`Failed to check free tier: ${res.status}`);
|
|
@@ -397,7 +441,7 @@ export function createClient(config) {
|
|
|
397
441
|
* Like, dislike, or comment on a generated UI.
|
|
398
442
|
*/
|
|
399
443
|
async reactToUI(id, action, comment) {
|
|
400
|
-
const body = { id, action, wallet:
|
|
444
|
+
const body = { id, action, wallet: address };
|
|
401
445
|
if (comment)
|
|
402
446
|
body.comment = comment;
|
|
403
447
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
@@ -418,7 +462,7 @@ export function createClient(config) {
|
|
|
418
462
|
const res = await fetch(`${baseUrl}/api/ai/generate-ui`, {
|
|
419
463
|
method: 'DELETE',
|
|
420
464
|
headers: { 'Content-Type': 'application/json' },
|
|
421
|
-
body: JSON.stringify({ id, wallet:
|
|
465
|
+
body: JSON.stringify({ id, wallet: address }),
|
|
422
466
|
});
|
|
423
467
|
if (!res.ok) {
|
|
424
468
|
const text = await res.text();
|
package/package.json
CHANGED