apinow-sdk 0.21.0 → 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 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.21.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
- .requiredOption('--name <name>', 'Endpoint name')
642
- .requiredOption('--prompt <prompt>', 'System prompt for the LLM')
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
- const body = {
655
- name: opts.name,
656
- prompt: opts.prompt,
657
- model: opts.model,
658
- usdcPrice: opts.price,
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 "${opts.name}"…`);
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.
@@ -326,14 +375,13 @@ export function createClient(config) {
326
375
  * });
327
376
  */
328
377
  async callExternal(url, opts = {}) {
329
- return this.call('/api/x402-proxy', {
378
+ const params = new URLSearchParams({ url });
379
+ if (opts.method)
380
+ params.set('method', opts.method);
381
+ return this.call(`/api/x402-proxy?${params}`, {
330
382
  method: 'POST',
331
- body: {
332
- url,
333
- method: opts.method || 'POST',
334
- body: opts.body,
335
- headers: opts.headers,
336
- },
383
+ body: opts.body,
384
+ headers: opts.headers,
337
385
  });
338
386
  },
339
387
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
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",