apinow-sdk 0.21.1 → 0.22.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/dist/cli.js +171 -11
- package/dist/index.d.ts +31 -0
- package/dist/index.js +49 -0
- package/package.json +1 -1
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.22.0');
|
|
11
11
|
// ─── Helpers ───
|
|
12
12
|
function getPrivateKey(opts) {
|
|
13
13
|
const raw = opts.key || process.env.APINOW_WALLET_PKEY || process.env.PRIVATE_KEY;
|
|
@@ -637,9 +637,9 @@ program
|
|
|
637
637
|
// ─── factory-create ───
|
|
638
638
|
program
|
|
639
639
|
.command('factory-create')
|
|
640
|
-
.description('Create an LLM endpoint via user-factory')
|
|
641
|
-
.
|
|
642
|
-
.
|
|
640
|
+
.description('Create an LLM endpoint via user-factory (flags or --from-json)')
|
|
641
|
+
.option('--name <name>', 'Endpoint name')
|
|
642
|
+
.option('--prompt <prompt>', 'System prompt for the LLM')
|
|
643
643
|
.option('--namespace <ns>', 'Namespace (defaults to u-<wallet>)')
|
|
644
644
|
.option('--description <desc>', 'Endpoint description')
|
|
645
645
|
.option('--model <model>', 'LLM model', 'google/gemini-2.0-flash-001')
|
|
@@ -647,16 +647,54 @@ program
|
|
|
647
647
|
.option('--recipient <wallet>', 'Payment recipient wallet')
|
|
648
648
|
.option('--input-params <json>', 'Input params JSON array')
|
|
649
649
|
.option('--output-params <json>', 'Output params JSON array')
|
|
650
|
+
.option('--from-json <path>', 'JSON file with config (use "-" for stdin). Fields: name, prompt, description, model, suggestedPrice, inputParams, outputParams')
|
|
650
651
|
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
651
652
|
.action(async (opts) => {
|
|
652
653
|
try {
|
|
653
654
|
const { address } = getWallet(opts);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
655
|
+
let body;
|
|
656
|
+
if (opts.fromJson) {
|
|
657
|
+
const { readFileSync } = await import('fs');
|
|
658
|
+
let raw;
|
|
659
|
+
if (opts.fromJson === '-') {
|
|
660
|
+
const chunks = [];
|
|
661
|
+
for await (const chunk of process.stdin)
|
|
662
|
+
chunks.push(chunk);
|
|
663
|
+
raw = Buffer.concat(chunks).toString('utf8');
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
raw = readFileSync(opts.fromJson, 'utf8');
|
|
667
|
+
}
|
|
668
|
+
const json = JSON.parse(raw);
|
|
669
|
+
body = {
|
|
670
|
+
name: json.name,
|
|
671
|
+
prompt: json.prompt,
|
|
672
|
+
model: json.model || opts.model,
|
|
673
|
+
usdcPrice: json.suggestedPrice || json.usdcPrice || opts.price,
|
|
674
|
+
};
|
|
675
|
+
if (json.namespace)
|
|
676
|
+
body.namespace = json.namespace;
|
|
677
|
+
if (json.description)
|
|
678
|
+
body.description = json.description;
|
|
679
|
+
if (json.recipientWallet)
|
|
680
|
+
body.recipientWallet = json.recipientWallet;
|
|
681
|
+
if (json.inputParams)
|
|
682
|
+
body.inputParams = json.inputParams;
|
|
683
|
+
if (json.outputParams)
|
|
684
|
+
body.outputParams = json.outputParams;
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
body = {
|
|
688
|
+
name: opts.name,
|
|
689
|
+
prompt: opts.prompt,
|
|
690
|
+
model: opts.model,
|
|
691
|
+
usdcPrice: opts.price,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
if (!body.name || !body.prompt) {
|
|
695
|
+
console.error('Error: --name and --prompt are required (or provide --from-json)');
|
|
696
|
+
process.exit(1);
|
|
697
|
+
}
|
|
660
698
|
if (opts.namespace)
|
|
661
699
|
body.namespace = opts.namespace;
|
|
662
700
|
if (opts.description)
|
|
@@ -667,7 +705,7 @@ program
|
|
|
667
705
|
body.inputParams = JSON.parse(opts.inputParams);
|
|
668
706
|
if (opts.outputParams)
|
|
669
707
|
body.outputParams = JSON.parse(opts.outputParams);
|
|
670
|
-
console.error(`Creating endpoint "${
|
|
708
|
+
console.error(`Creating endpoint "${body.name}"…`);
|
|
671
709
|
const data = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
672
710
|
method: 'POST',
|
|
673
711
|
headers: walletHeaders(address),
|
|
@@ -765,4 +803,126 @@ program
|
|
|
765
803
|
process.exit(1);
|
|
766
804
|
}
|
|
767
805
|
});
|
|
806
|
+
// ─── factory-pipeline ───
|
|
807
|
+
program
|
|
808
|
+
.command('factory-pipeline <idea>')
|
|
809
|
+
.description('Full pipeline: generate → create → test → optional markup workflow')
|
|
810
|
+
.option('--markup <percent>', 'Markup percent (creates a markup workflow after endpoint creation)')
|
|
811
|
+
.option('--markup-recipient <wallet>', 'Wallet to receive markup USDC')
|
|
812
|
+
.option('--token-buy-percent <percent>', 'Percent of base price for token buy')
|
|
813
|
+
.option('--token-buy-recipient <wallet>', 'Wallet to receive token buy portion')
|
|
814
|
+
.option('--token-buy-ca <address>', 'Token contract address for buy (default: $APINOW)')
|
|
815
|
+
.option('--recipient <wallet>', 'Endpoint payment recipient wallet')
|
|
816
|
+
.option('--price <usdc>', 'Override suggested USDC price')
|
|
817
|
+
.option('--model <model>', 'Override suggested model')
|
|
818
|
+
.option('--dry-run', 'Generate and print config without creating')
|
|
819
|
+
.option('-k, --key <privateKey>', 'Wallet private key')
|
|
820
|
+
.action(async (idea, opts) => {
|
|
821
|
+
try {
|
|
822
|
+
const { address } = getWallet(opts);
|
|
823
|
+
// Step 1: Generate
|
|
824
|
+
console.error('Step 1/4: Generating endpoint config from idea…');
|
|
825
|
+
const draft = await fetchJson(`${API_BASE}/api/user-factory/generate`, {
|
|
826
|
+
method: 'POST',
|
|
827
|
+
headers: walletHeaders(address),
|
|
828
|
+
body: JSON.stringify({ idea }),
|
|
829
|
+
});
|
|
830
|
+
console.error(` → ${draft.name}: ${draft.description}`);
|
|
831
|
+
console.error(` → Model: ${draft.model}, Price: $${draft.suggestedPrice}`);
|
|
832
|
+
console.error(` → Input params: ${(draft.inputParams || []).map((p) => p.name).join(', ') || '(none)'}`);
|
|
833
|
+
console.error(` → Output params: ${(draft.outputParams || []).map((p) => p.name).join(', ') || '(none)'}`);
|
|
834
|
+
if (opts.dryRun) {
|
|
835
|
+
console.log(JSON.stringify(draft, null, 2));
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
// Step 2: Create
|
|
839
|
+
console.error('\nStep 2/4: Creating endpoint…');
|
|
840
|
+
const createBody = {
|
|
841
|
+
name: draft.name,
|
|
842
|
+
prompt: draft.prompt,
|
|
843
|
+
description: draft.description,
|
|
844
|
+
model: opts.model || draft.model || 'google/gemini-2.0-flash-001',
|
|
845
|
+
usdcPrice: opts.price || draft.suggestedPrice || '0.01',
|
|
846
|
+
inputParams: draft.inputParams,
|
|
847
|
+
outputParams: draft.outputParams,
|
|
848
|
+
};
|
|
849
|
+
if (opts.recipient)
|
|
850
|
+
createBody.recipientWallet = opts.recipient;
|
|
851
|
+
const createData = await fetchJson(`${API_BASE}/api/user-factory`, {
|
|
852
|
+
method: 'POST',
|
|
853
|
+
headers: walletHeaders(address),
|
|
854
|
+
body: JSON.stringify(createBody),
|
|
855
|
+
});
|
|
856
|
+
const ep = createData.endpoint;
|
|
857
|
+
console.error(` → Created: ${ep.namespace}/${ep.endpointName}`);
|
|
858
|
+
// Step 3: Test
|
|
859
|
+
console.error('\nStep 3/4: Running test call…');
|
|
860
|
+
const testInput = draft.exampleInput || { prompt: 'test' };
|
|
861
|
+
const testData = await fetchJson(`${API_BASE}/api/user-factory/test-call`, {
|
|
862
|
+
method: 'POST',
|
|
863
|
+
headers: walletHeaders(address),
|
|
864
|
+
body: JSON.stringify({
|
|
865
|
+
namespace: ep.namespace,
|
|
866
|
+
endpointName: ep.endpointName,
|
|
867
|
+
input: testInput,
|
|
868
|
+
saveExample: true,
|
|
869
|
+
}),
|
|
870
|
+
});
|
|
871
|
+
console.error(' → Test passed, example saved');
|
|
872
|
+
// Step 4: Markup (optional)
|
|
873
|
+
let workflow = null;
|
|
874
|
+
if (opts.markup) {
|
|
875
|
+
console.error(`\nStep 4/4: Creating markup workflow (${opts.markup}%)…`);
|
|
876
|
+
const markupBody = {
|
|
877
|
+
endpointId: ep.id,
|
|
878
|
+
markupPercent: Number(opts.markup),
|
|
879
|
+
};
|
|
880
|
+
if (opts.markupRecipient)
|
|
881
|
+
markupBody.markupRecipient = opts.markupRecipient;
|
|
882
|
+
if (opts.tokenBuyPercent)
|
|
883
|
+
markupBody.tokenBuyPercent = Number(opts.tokenBuyPercent);
|
|
884
|
+
if (opts.tokenBuyRecipient)
|
|
885
|
+
markupBody.tokenBuyRecipient = opts.tokenBuyRecipient;
|
|
886
|
+
if (opts.tokenBuyCa)
|
|
887
|
+
markupBody.tokenBuyCA = opts.tokenBuyCa;
|
|
888
|
+
const markupData = await fetchJson(`${API_BASE}/api/user-factory/markup`, {
|
|
889
|
+
method: 'POST',
|
|
890
|
+
headers: walletHeaders(address),
|
|
891
|
+
body: JSON.stringify(markupBody),
|
|
892
|
+
});
|
|
893
|
+
workflow = markupData.workflow;
|
|
894
|
+
console.error(` → Workflow: ${workflow.name} ($${workflow.totalPrice} USDC)`);
|
|
895
|
+
}
|
|
896
|
+
else {
|
|
897
|
+
console.error('\nStep 4/4: Skipped (no --markup flag)');
|
|
898
|
+
}
|
|
899
|
+
// Final output
|
|
900
|
+
const result = {
|
|
901
|
+
endpoint: {
|
|
902
|
+
id: ep.id,
|
|
903
|
+
namespace: ep.namespace,
|
|
904
|
+
name: ep.endpointName,
|
|
905
|
+
model: ep.model,
|
|
906
|
+
price: ep.price,
|
|
907
|
+
tryUrl: `https://apinow.fun${ep.tryUrl}`,
|
|
908
|
+
apiUrl: `https://apinow.fun${ep.apiUrl}`,
|
|
909
|
+
},
|
|
910
|
+
testOutput: testData.output,
|
|
911
|
+
};
|
|
912
|
+
if (workflow) {
|
|
913
|
+
result.workflow = {
|
|
914
|
+
id: workflow.workflowId,
|
|
915
|
+
name: workflow.name,
|
|
916
|
+
totalPrice: workflow.totalPrice,
|
|
917
|
+
markupPercent: workflow.markupPercent,
|
|
918
|
+
viewUrl: `https://apinow.fun${workflow.viewUrl}`,
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
console.log(JSON.stringify(result, null, 2));
|
|
922
|
+
}
|
|
923
|
+
catch (err) {
|
|
924
|
+
console.error(`Error: ${err.message}`);
|
|
925
|
+
process.exit(1);
|
|
926
|
+
}
|
|
927
|
+
});
|
|
768
928
|
program.parse();
|
package/dist/index.d.ts
CHANGED
|
@@ -171,6 +171,37 @@ export declare function createClient(config: ApinowConfig): {
|
|
|
171
171
|
input?: any;
|
|
172
172
|
saveExample?: boolean;
|
|
173
173
|
}): Promise<any>;
|
|
174
|
+
/**
|
|
175
|
+
* Full pipeline: generate config from idea → create endpoint → test → optional markup workflow.
|
|
176
|
+
* Returns { draft, endpoint, testOutput, workflow? }.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* const result = await apinow.factoryPipeline('Score startup pitches on 8 criteria', {
|
|
180
|
+
* recipientWallet: '0x...',
|
|
181
|
+
* markup: { markupPercent: 30, markupRecipient: '0x...' },
|
|
182
|
+
* });
|
|
183
|
+
* console.log(result.endpoint.namespace + '/' + result.endpoint.endpointName);
|
|
184
|
+
* console.log(result.workflow?.viewUrl);
|
|
185
|
+
*/
|
|
186
|
+
factoryPipeline(idea: string, opts?: {
|
|
187
|
+
recipientWallet?: string;
|
|
188
|
+
model?: string;
|
|
189
|
+
usdcPrice?: string;
|
|
190
|
+
markup?: {
|
|
191
|
+
markupPercent?: number;
|
|
192
|
+
markupAmount?: number;
|
|
193
|
+
markupRecipient?: string;
|
|
194
|
+
tokenBuyPercent?: number;
|
|
195
|
+
tokenBuyRecipient?: string;
|
|
196
|
+
tokenBuyCA?: string;
|
|
197
|
+
};
|
|
198
|
+
skipTest?: boolean;
|
|
199
|
+
}): Promise<{
|
|
200
|
+
draft: any;
|
|
201
|
+
endpoint: any;
|
|
202
|
+
testOutput: any;
|
|
203
|
+
workflow: any;
|
|
204
|
+
}>;
|
|
174
205
|
/**
|
|
175
206
|
* Discover the x402 price for any external URL without executing it.
|
|
176
207
|
* Free — no payment required.
|
package/dist/index.js
CHANGED
|
@@ -294,6 +294,55 @@ export function createClient(config) {
|
|
|
294
294
|
}
|
|
295
295
|
return res.json();
|
|
296
296
|
},
|
|
297
|
+
// ─── Factory Pipeline ───
|
|
298
|
+
/**
|
|
299
|
+
* Full pipeline: generate config from idea → create endpoint → test → optional markup workflow.
|
|
300
|
+
* Returns { draft, endpoint, testOutput, workflow? }.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* const result = await apinow.factoryPipeline('Score startup pitches on 8 criteria', {
|
|
304
|
+
* recipientWallet: '0x...',
|
|
305
|
+
* markup: { markupPercent: 30, markupRecipient: '0x...' },
|
|
306
|
+
* });
|
|
307
|
+
* console.log(result.endpoint.namespace + '/' + result.endpoint.endpointName);
|
|
308
|
+
* console.log(result.workflow?.viewUrl);
|
|
309
|
+
*/
|
|
310
|
+
async factoryPipeline(idea, opts = {}) {
|
|
311
|
+
const draft = await this.factoryGenerate(idea);
|
|
312
|
+
const createConfig = {
|
|
313
|
+
name: draft.name,
|
|
314
|
+
prompt: draft.prompt,
|
|
315
|
+
description: draft.description,
|
|
316
|
+
model: opts.model || draft.model || 'google/gemini-2.0-flash-001',
|
|
317
|
+
usdcPrice: opts.usdcPrice || draft.suggestedPrice || '0.01',
|
|
318
|
+
inputParams: draft.inputParams,
|
|
319
|
+
outputParams: draft.outputParams,
|
|
320
|
+
};
|
|
321
|
+
if (opts.recipientWallet)
|
|
322
|
+
createConfig.recipientWallet = opts.recipientWallet;
|
|
323
|
+
const createData = await this.factoryCreate(createConfig);
|
|
324
|
+
const endpoint = createData.endpoint;
|
|
325
|
+
let testOutput = null;
|
|
326
|
+
if (!opts.skipTest) {
|
|
327
|
+
const testInput = draft.exampleInput || { prompt: 'test' };
|
|
328
|
+
const testData = await this.factoryTestCall({
|
|
329
|
+
namespace: endpoint.namespace,
|
|
330
|
+
endpointName: endpoint.endpointName,
|
|
331
|
+
input: testInput,
|
|
332
|
+
saveExample: true,
|
|
333
|
+
});
|
|
334
|
+
testOutput = testData.output;
|
|
335
|
+
}
|
|
336
|
+
let workflow = null;
|
|
337
|
+
if (opts.markup) {
|
|
338
|
+
const markupData = await this.factoryMarkup({
|
|
339
|
+
endpointId: endpoint.id,
|
|
340
|
+
...opts.markup,
|
|
341
|
+
});
|
|
342
|
+
workflow = markupData.workflow;
|
|
343
|
+
}
|
|
344
|
+
return { draft, endpoint, testOutput, workflow };
|
|
345
|
+
},
|
|
297
346
|
// ─── External x402 Proxy ───
|
|
298
347
|
/**
|
|
299
348
|
* Discover the x402 price for any external URL without executing it.
|
package/package.json
CHANGED