apinow-sdk 0.24.0 → 0.26.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 +51 -0
- package/dist/index.js +105 -83
- 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.26.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
|
@@ -55,6 +55,11 @@ export interface GeneratedUI {
|
|
|
55
55
|
}
|
|
56
56
|
export declare function createClient(config: ApinowConfig): {
|
|
57
57
|
wallet: `0x${string}`;
|
|
58
|
+
/**
|
|
59
|
+
* Produce a signed `Authorization` header for custom write calls.
|
|
60
|
+
* Pairs with `x-wallet-address`. Backend accepts msg within ~10 min.
|
|
61
|
+
*/
|
|
62
|
+
signAuthHeader: () => Promise<Record<string, string>>;
|
|
58
63
|
/**
|
|
59
64
|
* Call any APINow endpoint. Handles x402 payment automatically.
|
|
60
65
|
*
|
|
@@ -138,6 +143,52 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
138
143
|
}): Promise<any>;
|
|
139
144
|
updateWorkflow(workflowId: string, updates: Record<string, any>): Promise<any>;
|
|
140
145
|
deleteWorkflow(workflowId: string): Promise<any>;
|
|
146
|
+
/**
|
|
147
|
+
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
148
|
+
*/
|
|
149
|
+
listMyWorkflows(opts?: {
|
|
150
|
+
status?: string;
|
|
151
|
+
limit?: number;
|
|
152
|
+
}): Promise<any>;
|
|
153
|
+
/**
|
|
154
|
+
* List all versions of a workflow (public, free).
|
|
155
|
+
*/
|
|
156
|
+
listWorkflowVersions(workflowId: string): Promise<{
|
|
157
|
+
versions: any[];
|
|
158
|
+
}>;
|
|
159
|
+
/**
|
|
160
|
+
* Get a specific workflow version by versionId or numeric version.
|
|
161
|
+
*/
|
|
162
|
+
getWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
163
|
+
/**
|
|
164
|
+
* Create a new workflow version (creator only). Defaults to setting it as default.
|
|
165
|
+
* Omit fields to inherit from current workflow.
|
|
166
|
+
*/
|
|
167
|
+
createWorkflowVersion(workflowId: string, updates?: {
|
|
168
|
+
graph?: {
|
|
169
|
+
nodes: any[];
|
|
170
|
+
outputNode: string;
|
|
171
|
+
outputMapping?: any;
|
|
172
|
+
};
|
|
173
|
+
totalPrice?: string;
|
|
174
|
+
splits?: Array<{
|
|
175
|
+
address: string;
|
|
176
|
+
basisPoints: number;
|
|
177
|
+
label?: string;
|
|
178
|
+
tokenAddress?: string;
|
|
179
|
+
}>;
|
|
180
|
+
mermaidDiagram?: string;
|
|
181
|
+
executionMode?: "balanced" | "optimistic" | "settle_first";
|
|
182
|
+
changelog?: string;
|
|
183
|
+
setDefault?: boolean;
|
|
184
|
+
forkedFrom?: string;
|
|
185
|
+
}): Promise<any>;
|
|
186
|
+
/**
|
|
187
|
+
* Set a version as the default (active) for a workflow. Also rolls the
|
|
188
|
+
* workflow's graph/price/splits back to that version's snapshot.
|
|
189
|
+
*/
|
|
190
|
+
setDefaultWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
191
|
+
deleteWorkflowVersion(workflowId: string, versionIdOrNumber: string | number): Promise<any>;
|
|
141
192
|
/**
|
|
142
193
|
* Run a workflow. Handles x402 payment automatically.
|
|
143
194
|
*
|
package/dist/index.js
CHANGED
|
@@ -33,8 +33,54 @@ export function createClient(config) {
|
|
|
33
33
|
const res = await rawFetchWithPayment(input, init);
|
|
34
34
|
return followRedirects(res);
|
|
35
35
|
});
|
|
36
|
+
/**
|
|
37
|
+
* Produce an `Authorization: Bearer <msg>||<sig>||<addr>` header signed by
|
|
38
|
+
* the wallet's private key. Backend verifies with ethers.recoverAddress and
|
|
39
|
+
* rejects messages older than ~10 min.
|
|
40
|
+
*
|
|
41
|
+
* Exposed as a public helper so agents can sign custom write calls too.
|
|
42
|
+
*/
|
|
43
|
+
async function signAuthHeader() {
|
|
44
|
+
const issuedAt = new Date().toISOString();
|
|
45
|
+
const nonce = Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
46
|
+
const message = `APINow auth\naddress: ${account.address}\nissuedAt: ${issuedAt}\nnonce: ${nonce}`;
|
|
47
|
+
const signature = await account.signMessage({ message });
|
|
48
|
+
return {
|
|
49
|
+
Authorization: `Bearer ${message}||${signature}||${account.address}`,
|
|
50
|
+
'x-wallet-address': account.address,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Fetch wrapper that signs write requests with the wallet private key.
|
|
55
|
+
* Use for any non-paid mutating API (endpoint/workflow/version CRUD).
|
|
56
|
+
*/
|
|
57
|
+
async function authedFetch(url, init = {}) {
|
|
58
|
+
const authHeaders = await signAuthHeader();
|
|
59
|
+
const res = await fetch(url, {
|
|
60
|
+
...init,
|
|
61
|
+
headers: {
|
|
62
|
+
...(init.body ? { 'Content-Type': 'application/json' } : {}),
|
|
63
|
+
...authHeaders,
|
|
64
|
+
...init.headers,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
return res;
|
|
68
|
+
}
|
|
69
|
+
async function authedJson(url, init = {}) {
|
|
70
|
+
const res = await authedFetch(url, init);
|
|
71
|
+
if (!res.ok) {
|
|
72
|
+
const text = await res.text();
|
|
73
|
+
throw new Error(`APINow ${res.status}: ${text}`);
|
|
74
|
+
}
|
|
75
|
+
return res.json();
|
|
76
|
+
}
|
|
36
77
|
return {
|
|
37
78
|
wallet: account.address,
|
|
79
|
+
/**
|
|
80
|
+
* Produce a signed `Authorization` header for custom write calls.
|
|
81
|
+
* Pairs with `x-wallet-address`. Backend accepts msg within ~10 min.
|
|
82
|
+
*/
|
|
83
|
+
signAuthHeader,
|
|
38
84
|
/**
|
|
39
85
|
* Call any APINow endpoint. Handles x402 payment automatically.
|
|
40
86
|
*
|
|
@@ -84,16 +130,10 @@ export function createClient(config) {
|
|
|
84
130
|
},
|
|
85
131
|
// ─── Endpoint CRUD ───
|
|
86
132
|
async createEndpoint(config) {
|
|
87
|
-
|
|
133
|
+
return authedJson(`${baseUrl}/api/endpoints`, {
|
|
88
134
|
method: 'POST',
|
|
89
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
90
135
|
body: JSON.stringify(config),
|
|
91
136
|
});
|
|
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
137
|
},
|
|
98
138
|
async getEndpoint(id) {
|
|
99
139
|
const res = await fetch(`${baseUrl}/api/endpoints/${id}`);
|
|
@@ -102,27 +142,13 @@ export function createClient(config) {
|
|
|
102
142
|
return res.json();
|
|
103
143
|
},
|
|
104
144
|
async updateEndpoint(id, updates) {
|
|
105
|
-
|
|
145
|
+
return authedJson(`${baseUrl}/api/endpoints/${id}`, {
|
|
106
146
|
method: 'PUT',
|
|
107
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
108
147
|
body: JSON.stringify(updates),
|
|
109
148
|
});
|
|
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
149
|
},
|
|
116
150
|
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();
|
|
151
|
+
return authedJson(`${baseUrl}/api/endpoints/${id}`, { method: 'DELETE' });
|
|
126
152
|
},
|
|
127
153
|
async listEndpoints(opts = {}) {
|
|
128
154
|
const params = new URLSearchParams();
|
|
@@ -166,40 +192,68 @@ export function createClient(config) {
|
|
|
166
192
|
return res.json();
|
|
167
193
|
},
|
|
168
194
|
async createWorkflow(config) {
|
|
169
|
-
|
|
195
|
+
return authedJson(`${baseUrl}/api/workflows`, {
|
|
170
196
|
method: 'POST',
|
|
171
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
172
197
|
body: JSON.stringify(config),
|
|
173
198
|
});
|
|
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
199
|
},
|
|
180
200
|
async updateWorkflow(workflowId, updates) {
|
|
181
|
-
|
|
201
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}`, {
|
|
182
202
|
method: 'PUT',
|
|
183
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
184
203
|
body: JSON.stringify(updates),
|
|
185
204
|
});
|
|
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
205
|
},
|
|
192
206
|
async deleteWorkflow(workflowId) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}`, { method: 'DELETE' });
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* List workflows you created (convenience for `listWorkflows({ creator: yourWallet })`).
|
|
211
|
+
*/
|
|
212
|
+
async listMyWorkflows(opts = {}) {
|
|
213
|
+
return this.listWorkflows({ ...opts, creator: account.address });
|
|
214
|
+
},
|
|
215
|
+
// ─── Workflow Versions ───
|
|
216
|
+
/**
|
|
217
|
+
* List all versions of a workflow (public, free).
|
|
218
|
+
*/
|
|
219
|
+
async listWorkflowVersions(workflowId) {
|
|
220
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}/versions`);
|
|
221
|
+
if (!res.ok)
|
|
222
|
+
throw new Error(`Failed to list versions: ${res.status}`);
|
|
223
|
+
return res.json();
|
|
224
|
+
},
|
|
225
|
+
/**
|
|
226
|
+
* Get a specific workflow version by versionId or numeric version.
|
|
227
|
+
*/
|
|
228
|
+
async getWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
229
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`);
|
|
230
|
+
if (!res.ok)
|
|
231
|
+
throw new Error(`Failed to get version: ${res.status}`);
|
|
201
232
|
return res.json();
|
|
202
233
|
},
|
|
234
|
+
/**
|
|
235
|
+
* Create a new workflow version (creator only). Defaults to setting it as default.
|
|
236
|
+
* Omit fields to inherit from current workflow.
|
|
237
|
+
*/
|
|
238
|
+
async createWorkflowVersion(workflowId, updates = {}) {
|
|
239
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions`, {
|
|
240
|
+
method: 'POST',
|
|
241
|
+
body: JSON.stringify(updates),
|
|
242
|
+
});
|
|
243
|
+
},
|
|
244
|
+
/**
|
|
245
|
+
* Set a version as the default (active) for a workflow. Also rolls the
|
|
246
|
+
* workflow's graph/price/splits back to that version's snapshot.
|
|
247
|
+
*/
|
|
248
|
+
async setDefaultWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
249
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`, {
|
|
250
|
+
method: 'PUT',
|
|
251
|
+
body: JSON.stringify({ setDefault: true }),
|
|
252
|
+
});
|
|
253
|
+
},
|
|
254
|
+
async deleteWorkflowVersion(workflowId, versionIdOrNumber) {
|
|
255
|
+
return authedJson(`${baseUrl}/api/workflows/${workflowId}/versions/${versionIdOrNumber}`, { method: 'DELETE' });
|
|
256
|
+
},
|
|
203
257
|
/**
|
|
204
258
|
* Run a workflow. Handles x402 payment automatically.
|
|
205
259
|
*
|
|
@@ -217,82 +271,50 @@ export function createClient(config) {
|
|
|
217
271
|
* Check $APINOW token balance and factory access.
|
|
218
272
|
*/
|
|
219
273
|
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();
|
|
274
|
+
return authedJson(`${baseUrl}/api/user-factory/check-balance`);
|
|
226
275
|
},
|
|
227
276
|
/**
|
|
228
277
|
* List your user-factory endpoints.
|
|
229
278
|
*/
|
|
230
279
|
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();
|
|
280
|
+
return authedJson(`${baseUrl}/api/user-factory`);
|
|
237
281
|
},
|
|
238
282
|
/**
|
|
239
283
|
* Generate endpoint config from a natural-language idea.
|
|
240
284
|
*/
|
|
241
285
|
async factoryGenerate(idea) {
|
|
242
|
-
|
|
286
|
+
return authedJson(`${baseUrl}/api/user-factory/generate`, {
|
|
243
287
|
method: 'POST',
|
|
244
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
245
288
|
body: JSON.stringify({ idea }),
|
|
246
289
|
});
|
|
247
|
-
if (!res.ok)
|
|
248
|
-
throw new Error(`Failed to generate: ${res.status}`);
|
|
249
|
-
return res.json();
|
|
250
290
|
},
|
|
251
291
|
/**
|
|
252
292
|
* Create an LLM endpoint via user-factory.
|
|
253
293
|
*/
|
|
254
294
|
async factoryCreate(config) {
|
|
255
|
-
|
|
295
|
+
return authedJson(`${baseUrl}/api/user-factory`, {
|
|
256
296
|
method: 'POST',
|
|
257
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
258
297
|
body: JSON.stringify(config),
|
|
259
298
|
});
|
|
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
299
|
},
|
|
266
300
|
/**
|
|
267
301
|
* Create a markup workflow wrapping an existing endpoint.
|
|
268
302
|
* Optionally allocate a portion of the markup to a token buy split.
|
|
269
303
|
*/
|
|
270
304
|
async factoryMarkup(opts) {
|
|
271
|
-
|
|
305
|
+
return authedJson(`${baseUrl}/api/user-factory/markup`, {
|
|
272
306
|
method: 'POST',
|
|
273
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
274
307
|
body: JSON.stringify(opts),
|
|
275
308
|
});
|
|
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
309
|
},
|
|
282
310
|
/**
|
|
283
311
|
* Test-call an endpoint without payment (free, server-side LLM call).
|
|
284
312
|
*/
|
|
285
313
|
async factoryTestCall(opts) {
|
|
286
|
-
|
|
314
|
+
return authedJson(`${baseUrl}/api/user-factory/test-call`, {
|
|
287
315
|
method: 'POST',
|
|
288
|
-
headers: { 'Content-Type': 'application/json', 'x-wallet-address': account.address },
|
|
289
316
|
body: JSON.stringify(opts),
|
|
290
317
|
});
|
|
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
318
|
},
|
|
297
319
|
// ─── Factory Pipeline ───
|
|
298
320
|
/**
|
package/package.json
CHANGED