@mixrpay/agent-sdk 0.8.4 → 0.8.6

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/index.cjs CHANGED
@@ -100,7 +100,7 @@ var InsufficientBalanceError = class extends MixrPayError {
100
100
  this.name = "InsufficientBalanceError";
101
101
  this.required = required;
102
102
  this.available = available;
103
- this.topUpUrl = "/wallet";
103
+ this.topUpUrl = "https://mixrpay.com/manage/wallet";
104
104
  }
105
105
  };
106
106
  var SessionKeyExpiredError = class extends MixrPayError {
@@ -108,7 +108,7 @@ var SessionKeyExpiredError = class extends MixrPayError {
108
108
  expiredAt;
109
109
  constructor(expiredAt) {
110
110
  super(
111
- `Session key expired at ${expiredAt}. Request a new session key from the wallet owner or create one at your MixrPay server /wallet/sessions`,
111
+ `Session key expired at ${expiredAt}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,
112
112
  "SESSION_KEY_EXPIRED"
113
113
  );
114
114
  this.name = "SessionKeyExpiredError";
@@ -177,7 +177,7 @@ var InvalidSessionKeyError = class extends MixrPayError {
177
177
  reason;
178
178
  constructor(reason = "Invalid session key format") {
179
179
  super(
180
- `${reason}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from your MixrPay server /wallet/sessions`,
180
+ `${reason}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,
181
181
  "INVALID_SESSION_KEY"
182
182
  );
183
183
  this.name = "InvalidSessionKeyError";
@@ -532,7 +532,7 @@ function getAmountUsd(requirements) {
532
532
  }
533
533
 
534
534
  // src/agent-wallet.ts
535
- var SDK_VERSION = "0.8.3";
535
+ var SDK_VERSION = "0.8.5";
536
536
  var DEFAULT_BASE_URL = process.env.MIXRPAY_BASE_URL || "https://www.mixrpay.com";
537
537
  var DEFAULT_TIMEOUT = 3e4;
538
538
  var NETWORKS = {
@@ -648,7 +648,7 @@ var AgentWallet = class {
648
648
  validateConfig(config) {
649
649
  if (!config.sessionKey) {
650
650
  throw new InvalidSessionKeyError(
651
- "Session key is required. Get one from the wallet owner or create one at your MixrPay server /wallet/sessions"
651
+ "Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites"
652
652
  );
653
653
  }
654
654
  const key = config.sessionKey.trim();
@@ -1161,7 +1161,7 @@ var AgentWallet = class {
1161
1161
  *
1162
1162
  * @example
1163
1163
  * ```typescript
1164
- * // Human creates invite at their dashboard, shares code "mixr-abc123"
1164
+ * // Human creates invite at https://mixrpay.com/manage/invites, shares code "mixr-abc123"
1165
1165
  *
1166
1166
  * const result = await AgentWallet.claimInvite({
1167
1167
  * inviteCode: 'mixr-abc123',
@@ -1387,6 +1387,16 @@ var AgentWallet = class {
1387
1387
  const data = await response.json();
1388
1388
  return data.children || [];
1389
1389
  }
1390
+ /**
1391
+ * List child sessions spawned by this agent.
1392
+ *
1393
+ * Alias for `getChildSessions()` for naming consistency.
1394
+ *
1395
+ * @returns Array of child session info
1396
+ */
1397
+ async listChildSessions() {
1398
+ return this.getChildSessions();
1399
+ }
1390
1400
  // ===========================================================================
1391
1401
  // Core Methods
1392
1402
  // ===========================================================================
@@ -1840,7 +1850,7 @@ var AgentWallet = class {
1840
1850
  checks.sessionKeyValid = info.isValid;
1841
1851
  if (!info.isValid) {
1842
1852
  issues.push("Session key is invalid or has been revoked.");
1843
- recommendations.push("Request a new session key from the wallet owner or create one at /wallet/sessions.");
1853
+ recommendations.push("Request a new session key from the wallet owner at https://mixrpay.com/manage/invites");
1844
1854
  }
1845
1855
  const now = /* @__PURE__ */ new Date();
1846
1856
  let expiresInHours = null;
@@ -1880,7 +1890,7 @@ var AgentWallet = class {
1880
1890
  balance = await this.getBalance();
1881
1891
  checks.hasBalance = balance > 0;
1882
1892
  if (balance <= 0) {
1883
- issues.push("Wallet has no USDC balance. Top up at your MixrPay server /wallet");
1893
+ issues.push("Wallet has no USDC balance. Top up at https://mixrpay.com/manage/wallet");
1884
1894
  recommendations.push("Deposit USDC to your wallet address to enable payments.");
1885
1895
  } else if (balance < 1) {
1886
1896
  issues.push(`Low balance: $${balance.toFixed(2)}. Consider topping up.`);
@@ -2532,6 +2542,341 @@ Timestamp: ${timestamp}`;
2532
2542
  };
2533
2543
  }
2534
2544
  // ===========================================================================
2545
+ // JIT MCP Server Methods
2546
+ // ===========================================================================
2547
+ /**
2548
+ * Deploy a JIT MCP server from the Glama directory.
2549
+ *
2550
+ * Deploys any remote-capable MCP server to Cloudflare Workers.
2551
+ * Charges $1 from your session budget.
2552
+ *
2553
+ * @param options - Deployment options including Glama server details and env vars
2554
+ * @returns Deployed instance with private endpoint URL
2555
+ *
2556
+ * @example
2557
+ * ```typescript
2558
+ * const result = await wallet.deployJitMcp({
2559
+ * glamaId: 'notion-mcp',
2560
+ * glamaNamespace: 'notion',
2561
+ * glamaSlug: 'notion-mcp',
2562
+ * toolName: 'My Notion Server',
2563
+ * envVars: { NOTION_API_KEY: 'secret_...' },
2564
+ * ttlHours: 24,
2565
+ * });
2566
+ *
2567
+ * console.log('Endpoint:', result.instance.endpointUrl);
2568
+ * console.log('Expires:', result.instance.expiresAt);
2569
+ * ```
2570
+ */
2571
+ async deployJitMcp(options) {
2572
+ this.logger.debug("deployJitMcp", { glamaId: options.glamaId, toolName: options.toolName });
2573
+ const authHeaders = await this.getSessionAuthHeaders();
2574
+ const response = await fetch(`${this.baseUrl}/api/v2/jit/deploy`, {
2575
+ method: "POST",
2576
+ headers: {
2577
+ "Content-Type": "application/json",
2578
+ ...authHeaders
2579
+ },
2580
+ body: JSON.stringify({
2581
+ glama_id: options.glamaId,
2582
+ glama_namespace: options.glamaNamespace,
2583
+ glama_slug: options.glamaSlug,
2584
+ tool_name: options.toolName,
2585
+ tool_description: options.toolDescription,
2586
+ env_vars: options.envVars,
2587
+ ttl_hours: options.ttlHours || 24
2588
+ // session_id not needed - derived from X-Session-Auth
2589
+ })
2590
+ });
2591
+ if (!response.ok) {
2592
+ const error = await response.json().catch(() => ({}));
2593
+ throw new MixrPayError(error.error || `JIT deploy failed: ${response.status}`);
2594
+ }
2595
+ const data = await response.json();
2596
+ if (data.payment?.amount_usd > 0) {
2597
+ const payment = {
2598
+ amountUsd: data.payment.amount_usd,
2599
+ recipient: "mixrpay-jit-deploy",
2600
+ txHash: data.payment.tx_hash,
2601
+ timestamp: /* @__PURE__ */ new Date(),
2602
+ description: `JIT Deploy: ${options.toolName}`,
2603
+ url: `${this.baseUrl}/api/v2/jit/deploy`,
2604
+ requestId: data.request_id || crypto.randomUUID()
2605
+ };
2606
+ this.payments.push(payment);
2607
+ this.totalSpentUsd += data.payment.amount_usd;
2608
+ this.logger.payment(data.payment.amount_usd, "jit-deploy", options.toolName);
2609
+ if (this.onPayment) {
2610
+ this.onPayment(payment);
2611
+ }
2612
+ }
2613
+ return {
2614
+ instance: this.parseJitInstance(data.instance),
2615
+ payment: {
2616
+ method: data.payment.method,
2617
+ amountUsd: data.payment.amount_usd,
2618
+ txHash: data.payment.tx_hash
2619
+ }
2620
+ };
2621
+ }
2622
+ /**
2623
+ * List your deployed JIT MCP server instances.
2624
+ *
2625
+ * @param options - Optional filters
2626
+ * @returns Array of JIT instances
2627
+ *
2628
+ * @example
2629
+ * ```typescript
2630
+ * const instances = await wallet.listJitInstances({ status: 'active' });
2631
+ * for (const inst of instances) {
2632
+ * console.log(`${inst.toolName}: ${inst.endpointUrl}`);
2633
+ * }
2634
+ * ```
2635
+ */
2636
+ async listJitInstances(options) {
2637
+ this.logger.debug("listJitInstances", options);
2638
+ const authHeaders = await this.getSessionAuthHeaders();
2639
+ const params = new URLSearchParams();
2640
+ if (options?.status) params.set("status", options.status);
2641
+ const response = await fetch(
2642
+ `${this.baseUrl}/api/v2/jit/instances?${params}`,
2643
+ { headers: authHeaders }
2644
+ );
2645
+ if (!response.ok) {
2646
+ const error = await response.json().catch(() => ({}));
2647
+ throw new MixrPayError(error.error || `Failed to list JIT instances: ${response.status}`);
2648
+ }
2649
+ const data = await response.json();
2650
+ return (data.instances || []).map((i) => this.parseJitInstance(i));
2651
+ }
2652
+ /**
2653
+ * Stop a running JIT MCP server instance.
2654
+ *
2655
+ * Instance will be marked as stopped and Worker cleaned up.
2656
+ * No refund is given - instances are billed at deploy time.
2657
+ *
2658
+ * @param instanceId - The instance ID to stop
2659
+ *
2660
+ * @example
2661
+ * ```typescript
2662
+ * await wallet.stopJitInstance('inst_abc123');
2663
+ * console.log('Instance stopped');
2664
+ * ```
2665
+ */
2666
+ async stopJitInstance(instanceId) {
2667
+ this.logger.debug("stopJitInstance", { instanceId });
2668
+ const authHeaders = await this.getSessionAuthHeaders();
2669
+ const response = await fetch(
2670
+ `${this.baseUrl}/api/v2/jit/instances/${instanceId}`,
2671
+ { method: "DELETE", headers: authHeaders }
2672
+ );
2673
+ if (!response.ok) {
2674
+ const error = await response.json().catch(() => ({}));
2675
+ throw new MixrPayError(error.error || `Failed to stop JIT instance: ${response.status}`);
2676
+ }
2677
+ }
2678
+ /**
2679
+ * Parse JIT instance response data.
2680
+ */
2681
+ parseJitInstance(data) {
2682
+ return {
2683
+ id: data.id,
2684
+ endpointUrl: data.endpoint_url,
2685
+ toolName: data.tool_name,
2686
+ glamaId: data.glama_id,
2687
+ glamaNamespace: data.glama_namespace,
2688
+ glamaSlug: data.glama_slug,
2689
+ status: data.status,
2690
+ mode: data.mode,
2691
+ ttlHours: data.ttl_hours,
2692
+ expiresAt: new Date(data.expires_at),
2693
+ createdAt: new Date(data.created_at)
2694
+ };
2695
+ }
2696
+ /**
2697
+ * Get details of a specific JIT MCP server instance.
2698
+ *
2699
+ * @param instanceId - The instance ID to retrieve
2700
+ * @returns Full instance details including endpoint URL
2701
+ *
2702
+ * @example
2703
+ * ```typescript
2704
+ * const instance = await wallet.getJitInstance('inst_abc123');
2705
+ * console.log('Endpoint:', instance.endpointUrl);
2706
+ * console.log('Expires:', instance.expiresAt);
2707
+ * ```
2708
+ */
2709
+ async getJitInstance(instanceId) {
2710
+ this.logger.debug("getJitInstance", { instanceId });
2711
+ const authHeaders = await this.getSessionAuthHeaders();
2712
+ const response = await fetch(
2713
+ `${this.baseUrl}/api/v2/jit/instances/${instanceId}`,
2714
+ { headers: authHeaders }
2715
+ );
2716
+ if (!response.ok) {
2717
+ const error = await response.json().catch(() => ({}));
2718
+ throw new MixrPayError(error.error || `Failed to get JIT instance: ${response.status}`);
2719
+ }
2720
+ const data = await response.json();
2721
+ return this.parseJitInstance(data.instance);
2722
+ }
2723
+ // ===========================================================================
2724
+ // Glama MCP Directory Methods
2725
+ // ===========================================================================
2726
+ /**
2727
+ * Search the Glama MCP server directory.
2728
+ *
2729
+ * Glama indexes 15,000+ MCP servers. Use this to discover tools
2730
+ * that can be deployed as JIT servers.
2731
+ *
2732
+ * Note: This is a public API and does not require authentication.
2733
+ *
2734
+ * @param query - Search query (e.g., "notion", "github", "database")
2735
+ * @returns Array of matching servers with hosting info
2736
+ *
2737
+ * @example
2738
+ * ```typescript
2739
+ * const results = await wallet.searchGlamaDirectory('notion');
2740
+ *
2741
+ * // Filter to only hostable servers
2742
+ * const hostable = results.servers.filter(s => s.canHost);
2743
+ * console.log(`Found ${hostable.length} deployable servers`);
2744
+ *
2745
+ * // Deploy one
2746
+ * if (hostable.length > 0) {
2747
+ * const server = hostable[0];
2748
+ * await wallet.deployJitMcp({
2749
+ * glamaId: server.id,
2750
+ * glamaNamespace: server.namespace,
2751
+ * glamaSlug: server.slug,
2752
+ * toolName: server.name,
2753
+ * envVars: { API_KEY: '...' },
2754
+ * });
2755
+ * }
2756
+ * ```
2757
+ */
2758
+ async searchGlamaDirectory(query) {
2759
+ this.logger.debug("searchGlamaDirectory", { query });
2760
+ const params = new URLSearchParams({ q: query });
2761
+ const response = await fetch(`${this.baseUrl}/api/mcp/glama?${params}`);
2762
+ if (!response.ok) {
2763
+ const error = await response.json().catch(() => ({}));
2764
+ throw new MixrPayError(error.error || `Glama search failed: ${response.status}`);
2765
+ }
2766
+ const data = await response.json();
2767
+ return {
2768
+ servers: (data.servers || []).map((s) => this.parseGlamaServer(s)),
2769
+ pageInfo: data.pageInfo,
2770
+ query: data.query
2771
+ };
2772
+ }
2773
+ /**
2774
+ * Get featured/popular MCP servers from the Glama directory.
2775
+ *
2776
+ * Returns curated list of popular servers when you don't have
2777
+ * a specific search query.
2778
+ *
2779
+ * Note: This is a public API and does not require authentication.
2780
+ *
2781
+ * @returns Array of featured servers with hosting info
2782
+ *
2783
+ * @example
2784
+ * ```typescript
2785
+ * const { servers } = await wallet.getFeaturedGlamaServers();
2786
+ * console.log('Featured servers:', servers.map(s => s.name));
2787
+ * ```
2788
+ */
2789
+ async getFeaturedGlamaServers() {
2790
+ this.logger.debug("getFeaturedGlamaServers");
2791
+ const response = await fetch(`${this.baseUrl}/api/mcp/glama`);
2792
+ if (!response.ok) {
2793
+ const error = await response.json().catch(() => ({}));
2794
+ throw new MixrPayError(error.error || `Failed to get featured servers: ${response.status}`);
2795
+ }
2796
+ const data = await response.json();
2797
+ return {
2798
+ servers: (data.servers || []).map((s) => this.parseGlamaServer(s)),
2799
+ featured: data.featured
2800
+ };
2801
+ }
2802
+ /**
2803
+ * Parse Glama server response data.
2804
+ */
2805
+ parseGlamaServer(data) {
2806
+ const importData = data.importData;
2807
+ return {
2808
+ id: data.id,
2809
+ name: data.name,
2810
+ namespace: data.namespace,
2811
+ slug: data.slug,
2812
+ description: data.description,
2813
+ url: data.url,
2814
+ attributes: data.attributes,
2815
+ canHost: data.canHost,
2816
+ tools: data.tools || [],
2817
+ repository: data.repository,
2818
+ license: data.spdxLicense?.name,
2819
+ importData: importData ? {
2820
+ glamaId: importData.glamaId,
2821
+ glamaNamespace: importData.glamaNamespace,
2822
+ glamaSlug: importData.glamaSlug,
2823
+ suggestedName: importData.suggestedName,
2824
+ suggestedDescription: importData.suggestedDescription,
2825
+ hostingType: importData.hostingType,
2826
+ requiredEnvVars: importData.requiredEnvVars,
2827
+ optionalEnvVars: importData.optionalEnvVars
2828
+ } : void 0
2829
+ };
2830
+ }
2831
+ // ===========================================================================
2832
+ // LLM Completion Methods
2833
+ // ===========================================================================
2834
+ /**
2835
+ * Simple LLM completion - single-turn, no tools.
2836
+ *
2837
+ * This is a convenience method for agents that just need to call an LLM
2838
+ * without the full agentic loop. Useful when Clawdbot spawns agents
2839
+ * that need to make their own LLM calls through MixrPay.
2840
+ *
2841
+ * @param prompt - The user prompt to send
2842
+ * @param options - Optional configuration
2843
+ * @returns The LLM response text and cost
2844
+ *
2845
+ * @example Basic usage
2846
+ * ```typescript
2847
+ * const result = await wallet.complete('Summarize this text: ...');
2848
+ * console.log(result.text);
2849
+ * console.log(`Cost: $${result.costUsd.toFixed(4)}`);
2850
+ * ```
2851
+ *
2852
+ * @example With custom model
2853
+ * ```typescript
2854
+ * const result = await wallet.complete(
2855
+ * 'Write a haiku about coding',
2856
+ * { model: 'gpt-4o', systemPrompt: 'You are a poet.' }
2857
+ * );
2858
+ * ```
2859
+ */
2860
+ async complete(prompt, options) {
2861
+ this.logger.debug("complete", { promptLength: prompt.length, model: options?.model });
2862
+ const result = await this.runAgent({
2863
+ messages: [{ role: "user", content: prompt }],
2864
+ config: {
2865
+ model: options?.model || "gpt-4o-mini",
2866
+ maxIterations: 1,
2867
+ tools: [],
2868
+ // No tools - pure LLM completion
2869
+ systemPrompt: options?.systemPrompt
2870
+ }
2871
+ });
2872
+ return {
2873
+ text: result.response,
2874
+ costUsd: result.cost.totalUsd,
2875
+ tokens: result.tokens,
2876
+ model: options?.model || "gpt-4o-mini"
2877
+ };
2878
+ }
2879
+ // ===========================================================================
2535
2880
  // Agent Runtime API
2536
2881
  // ===========================================================================
2537
2882
  /**