apinow-sdk 0.15.1 → 0.16.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 +46 -0
- package/dist/cli.js +97 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.js +38 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -42,9 +42,30 @@ Returns:
|
|
|
42
42
|
| `call(endpoint, opts?)` | Call any endpoint with automatic x402 payment |
|
|
43
43
|
| `search(query, limit?)` | Semantic search across all endpoints |
|
|
44
44
|
| `info(ns, name)` | Get endpoint details (free) |
|
|
45
|
+
| `listWorkflows(opts?)` | List workflows (free) |
|
|
46
|
+
| `getWorkflow(id)` | Get workflow details (free) |
|
|
47
|
+
| `runWorkflow(id, input)` | Run a workflow with automatic x402 payment |
|
|
45
48
|
| `wallet` | Your wallet address |
|
|
46
49
|
| `fetch` | Raw x402-wrapped `fetch` for advanced use |
|
|
47
50
|
|
|
51
|
+
### Workflows
|
|
52
|
+
|
|
53
|
+
Workflows chain multiple x402 endpoints into a single paid DAG pipeline with automatic payment splitting.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// list workflows
|
|
57
|
+
const { workflows } = await apinow.listWorkflows({ status: 'active', limit: 10 });
|
|
58
|
+
|
|
59
|
+
// get workflow details (nodes, splits, pricing)
|
|
60
|
+
const workflow = await apinow.getWorkflow('90931d9c8fb94df9');
|
|
61
|
+
console.log(workflow.name, workflow.totalPrice, workflow.graph.nodes);
|
|
62
|
+
|
|
63
|
+
// run a workflow — x402 payment covers all nodes + creator split
|
|
64
|
+
const result = await apinow.runWorkflow('90931d9c8fb94df9', {
|
|
65
|
+
query: 'birthday gift ideas for a friend who loves cooking',
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
48
69
|
## CLI
|
|
49
70
|
|
|
50
71
|
```bash
|
|
@@ -87,6 +108,31 @@ npx apinow call ns/endpoint -m GET -k 0xYOUR_KEY
|
|
|
87
108
|
| `-m, --method <method>` | HTTP method (default: from endpoint) |
|
|
88
109
|
| `-k, --key <privateKey>` | Wallet key (or set `APINOW_WALLET_PKEY`) |
|
|
89
110
|
|
|
111
|
+
### `workflows` — list workflows
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx apinow workflows
|
|
115
|
+
npx apinow workflows --status active --limit 10
|
|
116
|
+
npx apinow workflows --creator 0x32e8...E934
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `workflow` — workflow details
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx apinow workflow 90931d9c8fb94df9
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `run-workflow` — run a workflow (paid)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
APINOW_WALLET_PKEY=0x... npx apinow run-workflow 90931d9c8fb94df9 -d '{"query":"birthday gift ideas"}'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Flag | Description |
|
|
132
|
+
|------|-------------|
|
|
133
|
+
| `-d, --data <json>` | JSON input (default: `{"query":"hello world"}`) |
|
|
134
|
+
| `-k, --key <privateKey>` | Wallet key (or set `APINOW_WALLET_PKEY`) |
|
|
135
|
+
|
|
90
136
|
## Requirements
|
|
91
137
|
|
|
92
138
|
- Node.js v18+
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ const program = new Command();
|
|
|
6
6
|
program
|
|
7
7
|
.name('apinow')
|
|
8
8
|
.description('CLI for APINow.fun — search, inspect, and call pay-per-request APIs')
|
|
9
|
-
.version('0.
|
|
9
|
+
.version('0.16.0');
|
|
10
10
|
// ─── Helpers ───
|
|
11
11
|
function getPrivateKey(opts) {
|
|
12
12
|
const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
|
|
@@ -216,4 +216,100 @@ program
|
|
|
216
216
|
process.exit(1);
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
+
// ─── workflows ───
|
|
220
|
+
program
|
|
221
|
+
.command('workflows')
|
|
222
|
+
.description('List workflows')
|
|
223
|
+
.option('-l, --limit <n>', 'Max results', '20')
|
|
224
|
+
.option('-c, --creator <address>', 'Filter by creator wallet')
|
|
225
|
+
.option('-s, --status <status>', 'Filter by status: active | draft | all', 'all')
|
|
226
|
+
.action(async (opts) => {
|
|
227
|
+
try {
|
|
228
|
+
const params = new URLSearchParams({ limit: opts.limit, status: opts.status });
|
|
229
|
+
if (opts.creator)
|
|
230
|
+
params.set('creator', opts.creator);
|
|
231
|
+
const data = await fetchJson(`${API_BASE}/api/workflows?${params}`);
|
|
232
|
+
const workflows = data.workflows || [];
|
|
233
|
+
if (!workflows.length) {
|
|
234
|
+
console.log('No workflows found.');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const rows = [['ID', 'NAME', 'STATUS', 'NODES', 'COST', 'DESCRIPTION']];
|
|
238
|
+
for (const w of workflows) {
|
|
239
|
+
rows.push([
|
|
240
|
+
w.workflowId,
|
|
241
|
+
truncate(w.name || '', 24),
|
|
242
|
+
w.status,
|
|
243
|
+
String(w.graph?.nodes?.length || 0),
|
|
244
|
+
`$${w.totalPrice}`,
|
|
245
|
+
truncate(w.description || '', 40),
|
|
246
|
+
]);
|
|
247
|
+
}
|
|
248
|
+
printTable(rows);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
console.error(`Error: ${err.message}`);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
// ─── workflow info ───
|
|
256
|
+
program
|
|
257
|
+
.command('workflow <id>')
|
|
258
|
+
.description('Get workflow details')
|
|
259
|
+
.action(async (id) => {
|
|
260
|
+
try {
|
|
261
|
+
const data = await fetchJson(`${API_BASE}/api/workflows/${id}`);
|
|
262
|
+
console.log(`\n ${data.name}`);
|
|
263
|
+
console.log(` ${'─'.repeat(40)}`);
|
|
264
|
+
console.log(` ${data.description || '(no description)'}\n`);
|
|
265
|
+
console.log(` ID: ${data.workflowId}`);
|
|
266
|
+
console.log(` Status: ${data.status}`);
|
|
267
|
+
console.log(` Cost: $${data.totalPrice} USDC`);
|
|
268
|
+
console.log(` Chain: ${data.chain || 'base'}`);
|
|
269
|
+
console.log(` Creator: ${data.creatorWallet}`);
|
|
270
|
+
console.log(` Nodes: ${data.graph?.nodes?.length || 0}`);
|
|
271
|
+
if (data.graph?.nodes?.length) {
|
|
272
|
+
console.log(`\n Pipeline:`);
|
|
273
|
+
for (const node of data.graph.nodes) {
|
|
274
|
+
const deps = node.dependsOn?.length ? ` (depends on: ${node.dependsOn.join(', ')})` : '';
|
|
275
|
+
const isOutput = node.id === data.graph.outputNode ? ' [output]' : '';
|
|
276
|
+
console.log(` → ${node.id}: ${node.endpoint}${deps}${isOutput}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (data.splits?.length) {
|
|
280
|
+
console.log(`\n Payment Split:`);
|
|
281
|
+
for (const s of data.splits) {
|
|
282
|
+
const pct = (s.basisPoints / 100).toFixed(1);
|
|
283
|
+
const usd = (parseFloat(data.totalPrice) * s.basisPoints / 10000).toFixed(4);
|
|
284
|
+
console.log(` ${s.label}: ${pct}% ($${usd})`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
console.log('');
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
console.error(`Error: ${err.message}`);
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
// ─── run workflow ───
|
|
295
|
+
program
|
|
296
|
+
.command('run-workflow <id>')
|
|
297
|
+
.description('Run a workflow (x402 paid)')
|
|
298
|
+
.option('-d, --data <json>', 'JSON input', '{"query":"hello world"}')
|
|
299
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
300
|
+
.action(async (id, opts) => {
|
|
301
|
+
try {
|
|
302
|
+
const privateKey = getPrivateKey(opts);
|
|
303
|
+
const body = JSON.parse(opts.data);
|
|
304
|
+
const details = await fetchJson(`${API_BASE}/api/workflows/${id}`);
|
|
305
|
+
console.error(`Running workflow "${details.name}" — cost: $${details.totalPrice} USDC`);
|
|
306
|
+
const apinow = createClient({ privateKey });
|
|
307
|
+
const result = await apinow.runWorkflow(id, body);
|
|
308
|
+
console.log(JSON.stringify(result, null, 2));
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
console.error(`Error: ${err.message}`);
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
219
315
|
program.parse();
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,25 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
27
27
|
* Get public endpoint info (free, no payment).
|
|
28
28
|
*/
|
|
29
29
|
info(namespace: string, endpointName: string): Promise<any>;
|
|
30
|
+
/**
|
|
31
|
+
* List workflows. Optionally filter by creator or status.
|
|
32
|
+
*/
|
|
33
|
+
listWorkflows(opts?: {
|
|
34
|
+
creator?: string;
|
|
35
|
+
status?: string;
|
|
36
|
+
limit?: number;
|
|
37
|
+
}): Promise<any>;
|
|
38
|
+
/**
|
|
39
|
+
* Get workflow details by ID.
|
|
40
|
+
*/
|
|
41
|
+
getWorkflow(workflowId: string): Promise<any>;
|
|
42
|
+
/**
|
|
43
|
+
* Run a workflow. Handles x402 payment automatically.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
|
|
47
|
+
*/
|
|
48
|
+
runWorkflow(workflowId: string, input: Record<string, any>): Promise<any>;
|
|
30
49
|
/**
|
|
31
50
|
* The underlying x402-wrapped fetch, for advanced use.
|
|
32
51
|
*/
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,44 @@ export function createClient(config) {
|
|
|
58
58
|
throw new Error(`Failed to fetch info: ${res.status}`);
|
|
59
59
|
return res.json();
|
|
60
60
|
},
|
|
61
|
+
// ─── Workflows ───
|
|
62
|
+
/**
|
|
63
|
+
* List workflows. Optionally filter by creator or status.
|
|
64
|
+
*/
|
|
65
|
+
async listWorkflows(opts = {}) {
|
|
66
|
+
const params = new URLSearchParams();
|
|
67
|
+
if (opts.limit)
|
|
68
|
+
params.set('limit', String(opts.limit));
|
|
69
|
+
if (opts.creator)
|
|
70
|
+
params.set('creator', opts.creator);
|
|
71
|
+
if (opts.status)
|
|
72
|
+
params.set('status', opts.status);
|
|
73
|
+
const res = await fetch(`${baseUrl}/api/workflows?${params}`);
|
|
74
|
+
if (!res.ok)
|
|
75
|
+
throw new Error(`Failed to list workflows: ${res.status}`);
|
|
76
|
+
return res.json();
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Get workflow details by ID.
|
|
80
|
+
*/
|
|
81
|
+
async getWorkflow(workflowId) {
|
|
82
|
+
const res = await fetch(`${baseUrl}/api/workflows/${workflowId}`);
|
|
83
|
+
if (!res.ok)
|
|
84
|
+
throw new Error(`Failed to get workflow: ${res.status}`);
|
|
85
|
+
return res.json();
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Run a workflow. Handles x402 payment automatically.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const result = await apinow.runWorkflow('90931d9c8fb94df9', { query: 'hello world' });
|
|
92
|
+
*/
|
|
93
|
+
async runWorkflow(workflowId, input) {
|
|
94
|
+
return this.call(`/api/workflows/${workflowId}/run`, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
body: input,
|
|
97
|
+
});
|
|
98
|
+
},
|
|
61
99
|
/**
|
|
62
100
|
* The underlying x402-wrapped fetch, for advanced use.
|
|
63
101
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apinow-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pay-per-call API SDK & CLI for APINow.fun — wraps x402 so you don't have to",
|
|
3
|
+
"version": "0.16.0",
|
|
4
|
+
"description": "Pay-per-call API SDK & CLI for APINow.fun — endpoints + workflows, wraps x402 so you don't have to",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"web3",
|
|
25
25
|
"ai",
|
|
26
26
|
"llm",
|
|
27
|
-
"cli"
|
|
27
|
+
"cli",
|
|
28
|
+
"workflow",
|
|
29
|
+
"dag"
|
|
28
30
|
],
|
|
29
31
|
"author": "ApiNow.fun",
|
|
30
32
|
"license": "MIT",
|