@openconductor/mcp-sdk 1.3.1 → 1.4.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.
@@ -81,9 +81,197 @@ var SubscriptionRequiredError = class extends MCPError {
81
81
  }
82
82
  };
83
83
 
84
+ // src/config/index.ts
85
+ var globalConfig = {
86
+ apiKey: null,
87
+ demoMode: false,
88
+ serverName: "mcp-server",
89
+ serverVersion: "0.0.0",
90
+ initialized: false
91
+ };
92
+ var DEMO_BANNER = `
93
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
94
+ \u2502 \u2502
95
+ \u2502 \u{1F3AE} DEMO MODE ACTIVE \u2502
96
+ \u2502 \u2502
97
+ \u2502 The SDK is running without an API key. \u2502
98
+ \u2502 \u2022 Payment: Mock billing (always allowed, 9999 credits) \u2502
99
+ \u2502 \u2022 Telemetry: Logging to console only \u2502
100
+ \u2502 \u2022 All features work - no data sent to OpenConductor \u2502
101
+ \u2502 \u2502
102
+ \u2502 To enable production mode: \u2502
103
+ \u2502 1. Get a free API key at https://openconductor.ai \u2502
104
+ \u2502 2. Set OPENCONDUCTOR_API_KEY environment variable \u2502
105
+ \u2502 or pass apiKey to initOpenConductor() \u2502
106
+ \u2502 \u2502
107
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
108
+ `;
109
+ var PRODUCTION_BANNER = `
110
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
111
+ \u2502 \u2705 OpenConductor SDK initialized (production mode) \u2502
112
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
113
+ `;
114
+ function initOpenConductor(config = {}) {
115
+ const apiKey = config.apiKey ?? process.env.OPENCONDUCTOR_API_KEY ?? null;
116
+ const demoMode = config.demoMode === true || !apiKey;
117
+ globalConfig = {
118
+ apiKey: demoMode ? null : apiKey,
119
+ demoMode,
120
+ serverName: config.serverName ?? process.env.OPENCONDUCTOR_SERVER_NAME ?? "mcp-server",
121
+ serverVersion: config.serverVersion ?? process.env.npm_package_version ?? "0.0.0",
122
+ initialized: true
123
+ };
124
+ if (!config.quiet) {
125
+ if (demoMode) {
126
+ console.log(DEMO_BANNER);
127
+ } else {
128
+ console.log(PRODUCTION_BANNER);
129
+ }
130
+ }
131
+ return globalConfig;
132
+ }
133
+ function getConfig() {
134
+ if (!globalConfig.initialized) {
135
+ return initOpenConductor({ quiet: true });
136
+ }
137
+ return globalConfig;
138
+ }
139
+ function isDemoMode() {
140
+ return getConfig().demoMode;
141
+ }
142
+
143
+ // src/demo/index.ts
144
+ var MOCK_BILLING_STATUS = {
145
+ allowed: true,
146
+ credits: 9999,
147
+ tier: "demo",
148
+ reason: void 0,
149
+ actionUrl: "https://openconductor.ai/pricing"
150
+ };
151
+ var MOCK_USER_BILLING = {
152
+ credits: 9999,
153
+ tier: "demo",
154
+ active: true
155
+ };
156
+ var MOCK_CREDIT_PACKS = {
157
+ starter: {
158
+ name: "Starter Pack",
159
+ credits: 100,
160
+ price: 9.99,
161
+ perCredit: 0.0999,
162
+ savings: 0,
163
+ bestFor: "Testing and small projects"
164
+ },
165
+ pro: {
166
+ name: "Pro Pack",
167
+ credits: 500,
168
+ price: 39.99,
169
+ perCredit: 0.0799,
170
+ savings: 20,
171
+ bestFor: "Growing projects",
172
+ popular: true
173
+ },
174
+ business: {
175
+ name: "Business Pack",
176
+ credits: 2e3,
177
+ price: 119.99,
178
+ perCredit: 0.0599,
179
+ savings: 40,
180
+ bestFor: "Production workloads"
181
+ }
182
+ };
183
+ function generateMockTimeline(days) {
184
+ const timeline = [];
185
+ const now = /* @__PURE__ */ new Date();
186
+ for (let i = days - 1; i >= 0; i--) {
187
+ const date = new Date(now);
188
+ date.setDate(date.getDate() - i);
189
+ timeline.push({
190
+ date: date.toISOString().split("T")[0],
191
+ used: Math.floor(Math.random() * 50) + 10,
192
+ purchased: i % 7 === 0 ? 500 : 0
193
+ // Weekly purchases
194
+ });
195
+ }
196
+ return timeline;
197
+ }
198
+ function generateMockTransactions(count) {
199
+ const tools = ["analyze-data", "generate-report", "search-docs", "summarize", "translate"];
200
+ const transactions = [];
201
+ const now = /* @__PURE__ */ new Date();
202
+ for (let i = 0; i < count; i++) {
203
+ const isDebit = Math.random() > 0.2;
204
+ const date = new Date(now);
205
+ date.setHours(date.getHours() - i * 2);
206
+ transactions.push({
207
+ id: `txn_demo_${i}`,
208
+ amount: isDebit ? -(Math.floor(Math.random() * 20) + 1) : 500,
209
+ type: isDebit ? "usage" : "purchase",
210
+ tool: isDebit ? tools[Math.floor(Math.random() * tools.length)] : null,
211
+ createdAt: date.toISOString()
212
+ });
213
+ }
214
+ return transactions;
215
+ }
216
+ function getMockAnalytics(period) {
217
+ const days = period === "24h" ? 1 : period === "7d" ? 7 : period === "30d" ? 30 : 90;
218
+ const timeline = generateMockTimeline(days);
219
+ const totalUsed = timeline.reduce((sum, d) => sum + d.used, 0);
220
+ const totalPurchased = timeline.reduce((sum, d) => sum + d.purchased, 0);
221
+ return {
222
+ period,
223
+ balance: 9999,
224
+ summary: {
225
+ totalUsed,
226
+ totalPurchased,
227
+ netChange: totalPurchased - totalUsed,
228
+ burnRate: totalUsed / days,
229
+ daysRemaining: Math.floor(9999 / (totalUsed / days)),
230
+ toolCount: 5,
231
+ transactionCount: days * 3
232
+ },
233
+ topTools: [
234
+ { tool: "analyze-data", calls: 156, credits: 780 },
235
+ { tool: "generate-report", calls: 89, credits: 445 },
236
+ { tool: "search-docs", calls: 234, credits: 234 },
237
+ { tool: "summarize", calls: 67, credits: 335 },
238
+ { tool: "translate", calls: 45, credits: 90 }
239
+ ],
240
+ usageTimeline: timeline,
241
+ recentTransactions: generateMockTransactions(10)
242
+ };
243
+ }
244
+ var DEMO_PREFIX = "[\u{1F3AE} DEMO]";
245
+ var demoLogger = {
246
+ telemetry: (action, data) => {
247
+ console.log(`${DEMO_PREFIX} Telemetry ${action}:`, JSON.stringify(data, null, 2));
248
+ },
249
+ payment: (action, data) => {
250
+ console.log(`${DEMO_PREFIX} Payment ${action}:`, JSON.stringify(data, null, 2));
251
+ },
252
+ billing: (userId, result) => {
253
+ console.log(`${DEMO_PREFIX} Billing check for ${userId}: ALLOWED (demo mode)`);
254
+ },
255
+ deduct: (userId, credits, tool) => {
256
+ console.log(`${DEMO_PREFIX} Would deduct ${credits} credits from ${userId} for ${tool} (skipped in demo)`);
257
+ }
258
+ };
259
+
84
260
  // src/payment/index.ts
85
261
  var paymentConfig = null;
86
262
  function initPayment(config) {
263
+ if (isDemoMode()) {
264
+ paymentConfig = {
265
+ apiKey: "demo_key",
266
+ apiUrl: "https://api.openconductor.ai",
267
+ testMode: true,
268
+ upgradeUrl: "https://openconductor.ai/pricing"
269
+ };
270
+ return;
271
+ }
272
+ if (!config?.apiKey) {
273
+ throw new ConfigurationError("payment", "Payment requires apiKey in production mode. Set OPENCONDUCTOR_API_KEY or pass apiKey to initPayment().");
274
+ }
87
275
  paymentConfig = {
88
276
  apiUrl: "https://api.openconductor.ai",
89
277
  testMode: false,
@@ -94,6 +282,10 @@ function getPaymentConfig() {
94
282
  return paymentConfig;
95
283
  }
96
284
  async function checkBilling(params) {
285
+ if (isDemoMode()) {
286
+ demoLogger.billing(params.userId, MOCK_BILLING_STATUS);
287
+ return MOCK_BILLING_STATUS;
288
+ }
97
289
  const config = paymentConfig;
98
290
  if (!config) {
99
291
  throw new ConfigurationError("payment", "Payment not initialized. Call initPayment() first.");
@@ -134,6 +326,10 @@ async function checkBilling(params) {
134
326
  }
135
327
  }
136
328
  async function deductCredits(params) {
329
+ if (isDemoMode()) {
330
+ demoLogger.deduct(params.userId, params.credits, params.toolName);
331
+ return true;
332
+ }
137
333
  const config = paymentConfig;
138
334
  if (!config) return false;
139
335
  if (config.testMode) return true;
@@ -223,6 +419,9 @@ async function canUserAccess(userId, requirement, toolName = "check") {
223
419
  return checkBilling({ userId, requirement, toolName });
224
420
  }
225
421
  async function getUserBillingStatus(userId) {
422
+ if (isDemoMode()) {
423
+ return MOCK_USER_BILLING;
424
+ }
226
425
  const config = paymentConfig;
227
426
  if (!config) return null;
228
427
  if (config.testMode) {
@@ -241,6 +440,9 @@ async function getUserBillingStatus(userId) {
241
440
  }
242
441
  }
243
442
  async function getCreditPacks() {
443
+ if (isDemoMode()) {
444
+ return MOCK_CREDIT_PACKS;
445
+ }
244
446
  const config = paymentConfig;
245
447
  if (!config) return null;
246
448
  try {
@@ -364,7 +566,81 @@ function createUpgradeErrorHandler(handlers) {
364
566
  throw error;
365
567
  };
366
568
  }
569
+ async function getUserAnalytics(userId, period = "30d") {
570
+ if (isDemoMode()) {
571
+ return getMockAnalytics(period);
572
+ }
573
+ const config = paymentConfig;
574
+ if (!config) {
575
+ console.error("[payment] Payment not initialized. Call initPayment() first.");
576
+ return null;
577
+ }
578
+ if (config.testMode) {
579
+ return {
580
+ period,
581
+ balance: 9999,
582
+ summary: {
583
+ totalUsed: 100,
584
+ totalPurchased: 500,
585
+ netChange: 400,
586
+ burnRate: 3.33,
587
+ daysRemaining: 3e3,
588
+ toolCount: 5,
589
+ transactionCount: 30
590
+ },
591
+ topTools: [
592
+ { tool: "test-tool", calls: 10, credits: 50 }
593
+ ],
594
+ usageTimeline: [],
595
+ recentTransactions: []
596
+ };
597
+ }
598
+ try {
599
+ const response = await fetch(
600
+ `${config.apiUrl}/functions/v1/usage-analytics/${userId}?period=${period}`,
601
+ {
602
+ headers: {
603
+ "Authorization": `Bearer ${config.apiKey}`
604
+ }
605
+ }
606
+ );
607
+ if (!response.ok) return null;
608
+ return await response.json();
609
+ } catch (error) {
610
+ console.error("[payment] Analytics fetch error:", error);
611
+ return null;
612
+ }
613
+ }
614
+ async function checkLowBalance(userId, thresholdDays = 7) {
615
+ const analytics = await getUserAnalytics(userId, "7d");
616
+ if (!analytics) return null;
617
+ const { balance, summary } = analytics;
618
+ const { burnRate, daysRemaining } = summary;
619
+ const isLow = daysRemaining !== null && daysRemaining <= thresholdDays;
620
+ let recommendedPack = "starter";
621
+ const weeklyBurn = burnRate * 7;
622
+ if (weeklyBurn > 100) recommendedPack = "pro";
623
+ if (weeklyBurn > 400) recommendedPack = "business";
624
+ let message = "";
625
+ if (isLow) {
626
+ if (daysRemaining === 0) {
627
+ message = `\u26A0\uFE0F Credits depleted! Balance: ${balance}. Buy more to continue.`;
628
+ } else if (daysRemaining <= 1) {
629
+ message = `\u26A0\uFE0F Running low! ~${daysRemaining} day of credits left at current usage.`;
630
+ } else {
631
+ message = `\u{1F4CA} ~${daysRemaining} days of credits remaining at current burn rate (${burnRate.toFixed(1)}/day).`;
632
+ }
633
+ }
634
+ return {
635
+ isLow,
636
+ daysRemaining,
637
+ balance,
638
+ burnRate,
639
+ message,
640
+ recommendedPack
641
+ };
642
+ }
367
643
 
368
- export { canUserAccess, createCreditsCheckout, createPaidTool, createUpgradeErrorHandler, generateUpgradePrompt, getCheckoutUrl, getCreditPacks, getDashboardCheckoutUrl, getPaymentConfig, getUserBillingStatus, initPayment, requirePayment };
644
+ export { canUserAccess, checkLowBalance, createCreditsCheckout, createPaidTool, createUpgradeErrorHandler, generateUpgradePrompt, getCheckoutUrl, getCreditPacks, getDashboardCheckoutUrl, getPaymentConfig, getUserAnalytics, getUserBillingStatus, initPayment, requirePayment };
369
645
  //# sourceMappingURL=index.mjs.map
370
646
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/errors/codes.ts","../../src/errors/index.ts","../../src/payment/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * JSON-RPC 2.0 Standard Error Codes\n * https://www.jsonrpc.org/specification#error_object\n */\nexport const ErrorCodes = {\n // JSON-RPC 2.0 Standard Errors\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n\n // MCP-Specific Errors (-32000 to -32099 reserved for implementation)\n TOOL_NOT_FOUND: -32001,\n TOOL_EXECUTION_ERROR: -32002,\n RESOURCE_NOT_FOUND: -32003,\n AUTHENTICATION_ERROR: -32004,\n AUTHORIZATION_ERROR: -32005,\n RATE_LIMIT_ERROR: -32006,\n TIMEOUT_ERROR: -32007,\n VALIDATION_ERROR: -32008,\n DEPENDENCY_ERROR: -32009,\n CONFIGURATION_ERROR: -32010,\n PAYMENT_REQUIRED: -32011,\n INSUFFICIENT_CREDITS: -32012,\n SUBSCRIPTION_REQUIRED: -32013,\n} as const\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]\n","import { ErrorCodes, type ErrorCode } from './codes'\n\nexport { ErrorCodes, type ErrorCode } from './codes'\n\n/**\n * Base error class for MCP servers\n * Formats errors according to JSON-RPC 2.0 specification\n */\nexport class MCPError extends Error {\n public readonly code: ErrorCode\n public readonly data?: Record<string, unknown>\n\n constructor(\n code: ErrorCode,\n message: string,\n data?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'MCPError'\n this.code = code\n this.data = data\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n }\n\n /**\n * Returns JSON-RPC 2.0 formatted error object\n */\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n ...(this.data && { data: this.data }),\n }\n }\n\n /**\n * Create error response for JSON-RPC\n */\n toResponse(id: string | number | null = null) {\n return {\n jsonrpc: '2.0' as const,\n id,\n error: this.toJSON(),\n }\n }\n}\n\n/**\n * Thrown when tool input validation fails\n */\nexport class ValidationError extends MCPError {\n constructor(field: string, reason: string, value?: unknown) {\n super(ErrorCodes.INVALID_PARAMS, `Validation failed for '${field}': ${reason}`, {\n field,\n reason,\n ...(value !== undefined && { value }),\n })\n this.name = 'ValidationError'\n }\n}\n\n/**\n * Thrown when a requested tool doesn't exist\n */\nexport class ToolNotFoundError extends MCPError {\n constructor(toolName: string) {\n super(ErrorCodes.TOOL_NOT_FOUND, `Tool '${toolName}' not found`, {\n tool: toolName,\n })\n this.name = 'ToolNotFoundError'\n }\n}\n\n/**\n * Thrown when tool execution fails\n */\nexport class ToolExecutionError extends MCPError {\n constructor(toolName: string, reason: string, cause?: Error) {\n super(ErrorCodes.TOOL_EXECUTION_ERROR, `Tool '${toolName}' failed: ${reason}`, {\n tool: toolName,\n reason,\n ...(cause && { cause: cause.message }),\n })\n this.name = 'ToolExecutionError'\n }\n}\n\n/**\n * Thrown when a requested resource doesn't exist\n */\nexport class ResourceNotFoundError extends MCPError {\n constructor(resourceUri: string) {\n super(ErrorCodes.RESOURCE_NOT_FOUND, `Resource '${resourceUri}' not found`, {\n uri: resourceUri,\n })\n this.name = 'ResourceNotFoundError'\n }\n}\n\n/**\n * Thrown when authentication fails\n */\nexport class AuthenticationError extends MCPError {\n constructor(reason: string = 'Authentication required') {\n super(ErrorCodes.AUTHENTICATION_ERROR, reason)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Thrown when authorization fails (authenticated but not permitted)\n */\nexport class AuthorizationError extends MCPError {\n constructor(action: string, resource?: string) {\n const msg = resource\n ? `Not authorized to ${action} on '${resource}'`\n : `Not authorized to ${action}`\n super(ErrorCodes.AUTHORIZATION_ERROR, msg, {\n action,\n ...(resource && { resource }),\n })\n this.name = 'AuthorizationError'\n }\n}\n\n/**\n * Thrown when rate limits are exceeded\n */\nexport class RateLimitError extends MCPError {\n constructor(retryAfterMs?: number) {\n super(ErrorCodes.RATE_LIMIT_ERROR, 'Rate limit exceeded', {\n ...(retryAfterMs && { retryAfterMs }),\n })\n this.name = 'RateLimitError'\n }\n}\n\n/**\n * Thrown when an operation times out\n */\nexport class TimeoutError extends MCPError {\n constructor(operation: string, timeoutMs: number) {\n super(ErrorCodes.TIMEOUT_ERROR, `Operation '${operation}' timed out after ${timeoutMs}ms`, {\n operation,\n timeoutMs,\n })\n this.name = 'TimeoutError'\n }\n}\n\n/**\n * Thrown when a required dependency is unavailable\n */\nexport class DependencyError extends MCPError {\n constructor(dependency: string, reason: string) {\n super(ErrorCodes.DEPENDENCY_ERROR, `Dependency '${dependency}' unavailable: ${reason}`, {\n dependency,\n reason,\n })\n this.name = 'DependencyError'\n }\n}\n\n/**\n * Thrown when server configuration is invalid\n */\nexport class ConfigurationError extends MCPError {\n constructor(setting: string, reason: string) {\n super(ErrorCodes.CONFIGURATION_ERROR, `Invalid configuration '${setting}': ${reason}`, {\n setting,\n reason,\n })\n this.name = 'ConfigurationError'\n }\n}\n\n/**\n * Thrown when payment is required to access a tool\n */\nexport class PaymentRequiredError extends MCPError {\n constructor(toolName: string, options?: { upgradeUrl?: string; priceId?: string }) {\n super(ErrorCodes.PAYMENT_REQUIRED, `Payment required to use '${toolName}'`, {\n tool: toolName,\n ...(options?.upgradeUrl && { upgradeUrl: options.upgradeUrl }),\n ...(options?.priceId && { priceId: options.priceId }),\n })\n this.name = 'PaymentRequiredError'\n }\n}\n\n/**\n * Thrown when user doesn't have enough credits\n */\nexport class InsufficientCreditsError extends MCPError {\n constructor(required: number, available: number, options?: { purchaseUrl?: string }) {\n super(ErrorCodes.INSUFFICIENT_CREDITS, `Insufficient credits: need ${required}, have ${available}`, {\n required,\n available,\n ...(options?.purchaseUrl && { purchaseUrl: options.purchaseUrl }),\n })\n this.name = 'InsufficientCreditsError'\n }\n}\n\n/**\n * Thrown when a subscription tier is required\n */\nexport class SubscriptionRequiredError extends MCPError {\n constructor(requiredTier: string, currentTier?: string, options?: { upgradeUrl?: string }) {\n const msg = currentTier \n ? `Subscription '${requiredTier}' required (current: '${currentTier}')`\n : `Subscription '${requiredTier}' required`\n super(ErrorCodes.SUBSCRIPTION_REQUIRED, msg, {\n requiredTier,\n ...(currentTier && { currentTier }),\n ...(options?.upgradeUrl && { upgradeUrl: options.upgradeUrl }),\n })\n this.name = 'SubscriptionRequiredError'\n }\n}\n","import {\n PaymentRequiredError,\n InsufficientCreditsError,\n SubscriptionRequiredError,\n ConfigurationError,\n} from '../errors'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PaymentConfig {\n /** OpenConductor API key for billing */\n apiKey: string\n /** Base URL for billing API (default: https://api.openconductor.ai) */\n apiUrl?: string\n /** Default upgrade URL to show users */\n upgradeUrl?: string\n /** Enable test mode (skips actual billing) */\n testMode?: boolean\n}\n\nexport interface CreditRequirement {\n /** Number of credits to deduct per call */\n credits: number\n}\n\nexport interface SubscriptionRequirement {\n /** Required subscription tier (e.g., 'pro', 'enterprise') */\n tier: string\n /** Alternative tiers that also grant access */\n allowedTiers?: string[]\n}\n\nexport interface StripeRequirement {\n /** Stripe Price ID for per-call billing */\n priceId: string\n}\n\nexport type PaymentRequirement = \n | CreditRequirement \n | SubscriptionRequirement \n | StripeRequirement\n\nexport interface UserContext {\n /** User ID for billing lookup */\n userId: string\n /** Optional API key override */\n apiKey?: string\n}\n\nexport interface BillingStatus {\n /** Whether the user can proceed */\n allowed: boolean\n /** Current credit balance (if applicable) */\n credits?: number\n /** Current subscription tier (if applicable) */\n tier?: string\n /** Reason for denial (if not allowed) */\n reason?: string\n /** URL for upgrade/purchase */\n actionUrl?: string\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nlet paymentConfig: PaymentConfig | null = null\n\n/**\n * Initialize payment/billing configuration\n * \n * @example\n * ```typescript\n * initPayment({\n * apiKey: process.env.OPENCONDUCTOR_API_KEY!,\n * upgradeUrl: 'https://myapp.com/upgrade'\n * })\n * ```\n */\nexport function initPayment(config: PaymentConfig): void {\n paymentConfig = {\n apiUrl: 'https://api.openconductor.ai',\n testMode: false,\n ...config,\n }\n}\n\n/**\n * Get current payment configuration\n */\nexport function getPaymentConfig(): PaymentConfig | null {\n return paymentConfig\n}\n\n// ============================================================================\n// Billing Client\n// ============================================================================\n\ninterface CheckBillingParams {\n userId: string\n requirement: PaymentRequirement\n toolName: string\n}\n\ninterface DeductCreditsParams {\n userId: string\n credits: number\n toolName: string\n callId?: string\n}\n\nasync function checkBilling(params: CheckBillingParams): Promise<BillingStatus> {\n const config = paymentConfig\n if (!config) {\n throw new ConfigurationError('payment', 'Payment not initialized. Call initPayment() first.')\n }\n\n // Test mode - always allow\n if (config.testMode) {\n return { allowed: true, credits: 9999, tier: 'test' }\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-check`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n userId: params.userId,\n requirement: params.requirement,\n tool: params.toolName,\n }),\n })\n\n if (!response.ok) {\n // Non-2xx response - treat as billing check failed\n const errorBody = await response.text()\n console.error('[payment] Billing check failed:', response.status, errorBody)\n return {\n allowed: false,\n reason: 'Billing service unavailable',\n actionUrl: config.upgradeUrl,\n }\n }\n\n return await response.json() as BillingStatus\n } catch (error) {\n // Network error - fail open or closed based on config\n console.error('[payment] Billing check error:', error)\n return {\n allowed: false,\n reason: 'Unable to verify billing status',\n actionUrl: config.upgradeUrl,\n }\n }\n}\n\nasync function deductCredits(params: DeductCreditsParams): Promise<boolean> {\n const config = paymentConfig\n if (!config) return false\n\n // Test mode - don't actually deduct\n if (config.testMode) return true\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-deduct`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n userId: params.userId,\n credits: params.credits,\n tool: params.toolName,\n callId: params.callId,\n }),\n })\n\n return response.ok\n } catch (error) {\n console.error('[payment] Credit deduction error:', error)\n return false\n }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nfunction isCreditRequirement(req: PaymentRequirement): req is CreditRequirement {\n return 'credits' in req && typeof req.credits === 'number'\n}\n\nfunction isSubscriptionRequirement(req: PaymentRequirement): req is SubscriptionRequirement {\n return 'tier' in req && typeof req.tier === 'string'\n}\n\nfunction isStripeRequirement(req: PaymentRequirement): req is StripeRequirement {\n return 'priceId' in req && typeof req.priceId === 'string'\n}\n\n// ============================================================================\n// Main Middleware\n// ============================================================================\n\nexport interface RequirePaymentOptions {\n /** Tool name for billing records */\n toolName?: string\n /** Function to extract user ID from input */\n getUserId?: (input: unknown) => string | undefined\n /** Custom error handler */\n onPaymentError?: (error: Error) => void\n}\n\n/**\n * One-line payment middleware for MCP tools\n * \n * @example Credits-based billing\n * ```typescript\n * const paidTool = requirePayment({ credits: 10 })(myHandler)\n * ```\n * \n * @example Subscription tier requirement\n * ```typescript\n * const premiumTool = requirePayment({ tier: 'pro' })(myHandler)\n * ```\n * \n * @example With wrapTool\n * ```typescript\n * const safePaidTool = wrapTool(\n * requirePayment({ credits: 5 })(myHandler),\n * { name: 'premium-analysis' }\n * )\n * ```\n */\nexport function requirePayment<TInput extends { userId?: string }, TOutput>(\n requirement: PaymentRequirement,\n options: RequirePaymentOptions = {}\n) {\n return (\n handler: (input: TInput) => TOutput | Promise<TOutput>\n ): ((input: TInput) => Promise<TOutput>) => {\n \n const { toolName = 'unknown', getUserId } = options\n\n return async (input: TInput): Promise<TOutput> => {\n // Extract user ID\n const userId = getUserId?.(input) ?? input.userId\n \n if (!userId) {\n throw new PaymentRequiredError(toolName, {\n upgradeUrl: paymentConfig?.upgradeUrl,\n })\n }\n\n // Check billing status\n const status = await checkBilling({\n userId,\n requirement,\n toolName,\n })\n\n if (!status.allowed) {\n // Throw appropriate error based on requirement type\n if (isCreditRequirement(requirement)) {\n throw new InsufficientCreditsError(\n requirement.credits,\n status.credits ?? 0,\n { purchaseUrl: status.actionUrl }\n )\n }\n\n if (isSubscriptionRequirement(requirement)) {\n throw new SubscriptionRequiredError(\n requirement.tier,\n status.tier,\n { upgradeUrl: status.actionUrl }\n )\n }\n\n // Generic payment required\n throw new PaymentRequiredError(toolName, {\n upgradeUrl: status.actionUrl,\n ...(isStripeRequirement(requirement) && { priceId: requirement.priceId }),\n })\n }\n\n // Execute the handler\n const result = await handler(input)\n\n // Deduct credits after successful execution (if credit-based)\n if (isCreditRequirement(requirement)) {\n await deductCredits({\n userId,\n credits: requirement.credits,\n toolName,\n })\n }\n\n return result\n }\n }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Create a paid tool with built-in payment verification\n * \n * @example\n * ```typescript\n * const analyzeData = createPaidTool({\n * name: 'analyze-data',\n * payment: { credits: 10 },\n * handler: async (input) => {\n * // Your tool logic\n * return result\n * }\n * })\n * ```\n */\nexport function createPaidTool<TInput extends { userId?: string }, TOutput>(config: {\n name: string\n payment: PaymentRequirement\n handler: (input: TInput) => TOutput | Promise<TOutput>\n getUserId?: (input: TInput) => string | undefined\n}): (input: TInput) => Promise<TOutput> {\n return requirePayment<TInput, TOutput>(config.payment, {\n toolName: config.name,\n getUserId: config.getUserId as (input: unknown) => string | undefined,\n })(config.handler)\n}\n\n/**\n * Check if a user can access a paid feature without executing it\n * Useful for UI gating\n * \n * @example\n * ```typescript\n * const canAccess = await canUserAccess('user_123', { credits: 10 }, 'premium-tool')\n * if (!canAccess.allowed) {\n * showUpgradePrompt(canAccess.actionUrl)\n * }\n * ```\n */\nexport async function canUserAccess(\n userId: string,\n requirement: PaymentRequirement,\n toolName: string = 'check'\n): Promise<BillingStatus> {\n return checkBilling({ userId, requirement, toolName })\n}\n\n/**\n * Get user's current billing status\n */\nexport async function getUserBillingStatus(userId: string): Promise<{\n credits: number\n tier: string\n active: boolean\n} | null> {\n const config = paymentConfig\n if (!config) return null\n\n if (config.testMode) {\n return { credits: 9999, tier: 'test', active: true }\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-status/${userId}`, {\n headers: {\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n })\n\n if (!response.ok) return null\n return await response.json()\n } catch {\n return null\n }\n}\n\n// ============================================================================\n// Checkout Helpers\n// ============================================================================\n\nexport type CreditPack = 'starter' | 'pro' | 'business'\n\nexport interface CreditPackInfo {\n name: string\n credits: number\n price: number\n perCredit: number\n savings: number\n bestFor: string\n popular?: boolean\n}\n\nexport interface CheckoutSession {\n sessionId: string\n url: string\n pack: CreditPack\n credits: number\n price: number\n perCredit: number\n}\n\n/**\n * Get available credit packs and pricing\n * \n * @example\n * ```typescript\n * const packs = await getCreditPacks()\n * console.log(packs.pro) // { name: 'Pro Pack', credits: 500, price: 39.99, ... }\n * ```\n */\nexport async function getCreditPacks(): Promise<Record<CreditPack, CreditPackInfo> | null> {\n const config = paymentConfig\n if (!config) return null\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/credit-packs`)\n if (!response.ok) return null\n const data = await response.json()\n return data.packs\n } catch {\n return null\n }\n}\n\n/**\n * Create a Stripe checkout session for purchasing credits\n * Returns a URL to redirect the user to for payment\n * \n * @example\n * ```typescript\n * const checkout = await createCreditsCheckout('pro', {\n * successUrl: 'https://myapp.com/success',\n * cancelUrl: 'https://myapp.com/pricing',\n * })\n * \n * // Redirect user to checkout\n * window.location.href = checkout.url\n * ```\n */\nexport async function createCreditsCheckout(\n pack: CreditPack,\n options: {\n successUrl?: string\n cancelUrl?: string\n } = {}\n): Promise<CheckoutSession | null> {\n const config = paymentConfig\n if (!config) {\n console.error('[payment] Payment not initialized. Call initPayment() first.')\n return null\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/stripe-checkout-credits`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n pack,\n successUrl: options.successUrl,\n cancelUrl: options.cancelUrl,\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n console.error('[payment] Checkout creation failed:', error)\n return null\n }\n\n return await response.json() as CheckoutSession\n } catch (error) {\n console.error('[payment] Checkout error:', error)\n return null\n }\n}\n\n/**\n * Generate a direct checkout URL for embedding in upgrade prompts\n * \n * @example In an error handler:\n * ```typescript\n * catch (error) {\n * if (error instanceof InsufficientCreditsError) {\n * const checkoutUrl = await getCheckoutUrl('pro')\n * return { error: `Insufficient credits. Buy more: ${checkoutUrl}` }\n * }\n * }\n * ```\n */\nexport async function getCheckoutUrl(pack: CreditPack): Promise<string | null> {\n const session = await createCreditsCheckout(pack)\n return session?.url ?? null\n}\n\n// ============================================================================\n// Upgrade Prompts\n// ============================================================================\n\nexport interface UpgradePromptOptions {\n /** Required credits for the blocked action */\n required?: number\n /** Currently available credits */\n available?: number\n /** Tool that was blocked */\n toolName?: string\n /** Include direct checkout links */\n includeLinks?: boolean\n}\n\n/**\n * Generate a user-friendly upgrade prompt message\n * Use this in your error handlers to show helpful messages\n * \n * @example\n * ```typescript\n * catch (error) {\n * if (error instanceof InsufficientCreditsError) {\n * const prompt = await generateUpgradePrompt({\n * required: error.data.required,\n * available: error.data.available,\n * toolName: 'analyze-data'\n * })\n * console.log(prompt.message)\n * // \"You need 10 more credits to use analyze-data. \n * // Buy the Pro Pack (500 credits) for $39.99 → https://...\"\n * }\n * }\n * ```\n */\nexport async function generateUpgradePrompt(\n options: UpgradePromptOptions = {}\n): Promise<{\n message: string\n shortMessage: string\n recommendedPack: CreditPack\n packs: Record<CreditPack, { credits: number; price: number; url: string | null }>\n}> {\n const { required = 0, available = 0, toolName, includeLinks = true } = options\n const needed = Math.max(0, required - available)\n \n // Determine recommended pack based on needed credits\n let recommendedPack: CreditPack = 'starter'\n if (needed > 100) recommendedPack = 'pro'\n if (needed > 500) recommendedPack = 'business'\n \n // Get pack URLs if requested\n const packUrls: Record<CreditPack, string | null> = {\n starter: null,\n pro: null,\n business: null,\n }\n \n if (includeLinks) {\n const [starterUrl, proUrl, businessUrl] = await Promise.all([\n getCheckoutUrl('starter'),\n getCheckoutUrl('pro'),\n getCheckoutUrl('business'),\n ])\n packUrls.starter = starterUrl\n packUrls.pro = proUrl\n packUrls.business = businessUrl\n }\n \n // Build message\n const toolPart = toolName ? ` to use ${toolName}` : ''\n const shortMessage = `Insufficient credits: need ${required}, have ${available}`\n \n let message = `You need ${needed} more credits${toolPart}.\\n\\n`\n message += `💳 Quick top-up options:\\n`\n message += ` • Starter: 100 credits for $9.99${packUrls.starter ? ` → ${packUrls.starter}` : ''}\\n`\n message += ` • Pro: 500 credits for $39.99 (20% off)${packUrls.pro ? ` → ${packUrls.pro}` : ''}\\n`\n message += ` • Business: 2,000 credits for $119.99 (40% off)${packUrls.business ? ` → ${packUrls.business}` : ''}\\n`\n \n if (recommendedPack !== 'starter') {\n message += `\\n✨ Recommended: ${recommendedPack.charAt(0).toUpperCase() + recommendedPack.slice(1)} Pack`\n }\n \n return {\n message,\n shortMessage,\n recommendedPack,\n packs: {\n starter: { credits: 100, price: 9.99, url: packUrls.starter },\n pro: { credits: 500, price: 39.99, url: packUrls.pro },\n business: { credits: 2000, price: 119.99, url: packUrls.business },\n },\n }\n}\n\n/**\n * Get a simple checkout URL for the dashboard\n * Useful when you don't want to create a full Stripe session\n */\nexport function getDashboardCheckoutUrl(options: {\n required?: number\n available?: number\n pack?: CreditPack\n} = {}): string {\n const params = new URLSearchParams()\n params.set('action', 'buy-credits')\n if (options.required) params.set('required', String(options.required))\n if (options.available) params.set('available', String(options.available))\n if (options.pack) params.set('pack', options.pack)\n return `https://dashboard.openconductor.ai?${params.toString()}`\n}\n\n/**\n * Create an error handler that automatically generates upgrade prompts\n * \n * @example\n * ```typescript\n * const handleError = createUpgradeErrorHandler({\n * onInsufficientCredits: (prompt) => {\n * return { error: prompt.shortMessage, upgradeUrl: prompt.packs.pro.url }\n * }\n * })\n * \n * // In your tool:\n * try {\n * return await paidHandler(input)\n * } catch (error) {\n * return handleError(error)\n * }\n * ```\n */\nexport function createUpgradeErrorHandler(handlers: {\n onInsufficientCredits?: (prompt: Awaited<ReturnType<typeof generateUpgradePrompt>>) => unknown\n onSubscriptionRequired?: (error: SubscriptionRequiredError) => unknown\n onPaymentRequired?: (error: PaymentRequiredError) => unknown\n onOtherError?: (error: Error) => unknown\n}) {\n return async (error: Error): Promise<unknown> => {\n if (error instanceof InsufficientCreditsError && handlers.onInsufficientCredits) {\n const prompt = await generateUpgradePrompt({\n required: error.data?.required as number,\n available: error.data?.available as number,\n })\n return handlers.onInsufficientCredits(prompt)\n }\n \n if (error instanceof SubscriptionRequiredError && handlers.onSubscriptionRequired) {\n return handlers.onSubscriptionRequired(error)\n }\n \n if (error instanceof PaymentRequiredError && handlers.onPaymentRequired) {\n return handlers.onPaymentRequired(error)\n }\n \n if (handlers.onOtherError) {\n return handlers.onOtherError(error)\n }\n \n throw error\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/errors/codes.ts","../../src/errors/index.ts","../../src/config/index.ts","../../src/demo/index.ts","../../src/payment/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * JSON-RPC 2.0 Standard Error Codes\n * https://www.jsonrpc.org/specification#error_object\n */\nexport const ErrorCodes = {\n // JSON-RPC 2.0 Standard Errors\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n\n // MCP-Specific Errors (-32000 to -32099 reserved for implementation)\n TOOL_NOT_FOUND: -32001,\n TOOL_EXECUTION_ERROR: -32002,\n RESOURCE_NOT_FOUND: -32003,\n AUTHENTICATION_ERROR: -32004,\n AUTHORIZATION_ERROR: -32005,\n RATE_LIMIT_ERROR: -32006,\n TIMEOUT_ERROR: -32007,\n VALIDATION_ERROR: -32008,\n DEPENDENCY_ERROR: -32009,\n CONFIGURATION_ERROR: -32010,\n PAYMENT_REQUIRED: -32011,\n INSUFFICIENT_CREDITS: -32012,\n SUBSCRIPTION_REQUIRED: -32013,\n} as const\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]\n","import { ErrorCodes, type ErrorCode } from './codes'\n\nexport { ErrorCodes, type ErrorCode } from './codes'\n\n/**\n * Base error class for MCP servers\n * Formats errors according to JSON-RPC 2.0 specification\n */\nexport class MCPError extends Error {\n public readonly code: ErrorCode\n public readonly data?: Record<string, unknown>\n\n constructor(\n code: ErrorCode,\n message: string,\n data?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'MCPError'\n this.code = code\n this.data = data\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n }\n\n /**\n * Returns JSON-RPC 2.0 formatted error object\n */\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n ...(this.data && { data: this.data }),\n }\n }\n\n /**\n * Create error response for JSON-RPC\n */\n toResponse(id: string | number | null = null) {\n return {\n jsonrpc: '2.0' as const,\n id,\n error: this.toJSON(),\n }\n }\n}\n\n/**\n * Thrown when tool input validation fails\n */\nexport class ValidationError extends MCPError {\n constructor(field: string, reason: string, value?: unknown) {\n super(ErrorCodes.INVALID_PARAMS, `Validation failed for '${field}': ${reason}`, {\n field,\n reason,\n ...(value !== undefined && { value }),\n })\n this.name = 'ValidationError'\n }\n}\n\n/**\n * Thrown when a requested tool doesn't exist\n */\nexport class ToolNotFoundError extends MCPError {\n constructor(toolName: string) {\n super(ErrorCodes.TOOL_NOT_FOUND, `Tool '${toolName}' not found`, {\n tool: toolName,\n })\n this.name = 'ToolNotFoundError'\n }\n}\n\n/**\n * Thrown when tool execution fails\n */\nexport class ToolExecutionError extends MCPError {\n constructor(toolName: string, reason: string, cause?: Error) {\n super(ErrorCodes.TOOL_EXECUTION_ERROR, `Tool '${toolName}' failed: ${reason}`, {\n tool: toolName,\n reason,\n ...(cause && { cause: cause.message }),\n })\n this.name = 'ToolExecutionError'\n }\n}\n\n/**\n * Thrown when a requested resource doesn't exist\n */\nexport class ResourceNotFoundError extends MCPError {\n constructor(resourceUri: string) {\n super(ErrorCodes.RESOURCE_NOT_FOUND, `Resource '${resourceUri}' not found`, {\n uri: resourceUri,\n })\n this.name = 'ResourceNotFoundError'\n }\n}\n\n/**\n * Thrown when authentication fails\n */\nexport class AuthenticationError extends MCPError {\n constructor(reason: string = 'Authentication required') {\n super(ErrorCodes.AUTHENTICATION_ERROR, reason)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Thrown when authorization fails (authenticated but not permitted)\n */\nexport class AuthorizationError extends MCPError {\n constructor(action: string, resource?: string) {\n const msg = resource\n ? `Not authorized to ${action} on '${resource}'`\n : `Not authorized to ${action}`\n super(ErrorCodes.AUTHORIZATION_ERROR, msg, {\n action,\n ...(resource && { resource }),\n })\n this.name = 'AuthorizationError'\n }\n}\n\n/**\n * Thrown when rate limits are exceeded\n */\nexport class RateLimitError extends MCPError {\n constructor(retryAfterMs?: number) {\n super(ErrorCodes.RATE_LIMIT_ERROR, 'Rate limit exceeded', {\n ...(retryAfterMs && { retryAfterMs }),\n })\n this.name = 'RateLimitError'\n }\n}\n\n/**\n * Thrown when an operation times out\n */\nexport class TimeoutError extends MCPError {\n constructor(operation: string, timeoutMs: number) {\n super(ErrorCodes.TIMEOUT_ERROR, `Operation '${operation}' timed out after ${timeoutMs}ms`, {\n operation,\n timeoutMs,\n })\n this.name = 'TimeoutError'\n }\n}\n\n/**\n * Thrown when a required dependency is unavailable\n */\nexport class DependencyError extends MCPError {\n constructor(dependency: string, reason: string) {\n super(ErrorCodes.DEPENDENCY_ERROR, `Dependency '${dependency}' unavailable: ${reason}`, {\n dependency,\n reason,\n })\n this.name = 'DependencyError'\n }\n}\n\n/**\n * Thrown when server configuration is invalid\n */\nexport class ConfigurationError extends MCPError {\n constructor(setting: string, reason: string) {\n super(ErrorCodes.CONFIGURATION_ERROR, `Invalid configuration '${setting}': ${reason}`, {\n setting,\n reason,\n })\n this.name = 'ConfigurationError'\n }\n}\n\n/**\n * Thrown when payment is required to access a tool\n */\nexport class PaymentRequiredError extends MCPError {\n constructor(toolName: string, options?: { upgradeUrl?: string; priceId?: string }) {\n super(ErrorCodes.PAYMENT_REQUIRED, `Payment required to use '${toolName}'`, {\n tool: toolName,\n ...(options?.upgradeUrl && { upgradeUrl: options.upgradeUrl }),\n ...(options?.priceId && { priceId: options.priceId }),\n })\n this.name = 'PaymentRequiredError'\n }\n}\n\n/**\n * Thrown when user doesn't have enough credits\n */\nexport class InsufficientCreditsError extends MCPError {\n constructor(required: number, available: number, options?: { purchaseUrl?: string }) {\n super(ErrorCodes.INSUFFICIENT_CREDITS, `Insufficient credits: need ${required}, have ${available}`, {\n required,\n available,\n ...(options?.purchaseUrl && { purchaseUrl: options.purchaseUrl }),\n })\n this.name = 'InsufficientCreditsError'\n }\n}\n\n/**\n * Thrown when a subscription tier is required\n */\nexport class SubscriptionRequiredError extends MCPError {\n constructor(requiredTier: string, currentTier?: string, options?: { upgradeUrl?: string }) {\n const msg = currentTier \n ? `Subscription '${requiredTier}' required (current: '${currentTier}')`\n : `Subscription '${requiredTier}' required`\n super(ErrorCodes.SUBSCRIPTION_REQUIRED, msg, {\n requiredTier,\n ...(currentTier && { currentTier }),\n ...(options?.upgradeUrl && { upgradeUrl: options.upgradeUrl }),\n })\n this.name = 'SubscriptionRequiredError'\n }\n}\n","/**\n * @openconductor/mcp-sdk - Global Configuration\n * \n * Single source of truth for SDK mode (demo vs production)\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface OpenConductorConfig {\n /** OpenConductor API key (optional in demo mode) */\n apiKey?: string\n /** Force demo mode even if API key is provided */\n demoMode?: boolean\n /** Server name for telemetry */\n serverName?: string\n /** Server version */\n serverVersion?: string\n /** Suppress demo mode banner */\n quiet?: boolean\n}\n\nexport interface ResolvedConfig {\n apiKey: string | null\n demoMode: boolean\n serverName: string\n serverVersion: string\n initialized: boolean\n}\n\n// ============================================================================\n// State\n// ============================================================================\n\nlet globalConfig: ResolvedConfig = {\n apiKey: null,\n demoMode: false,\n serverName: 'mcp-server',\n serverVersion: '0.0.0',\n initialized: false,\n}\n\n// ============================================================================\n// Demo Mode Banner\n// ============================================================================\n\nconst DEMO_BANNER = `\n┌─────────────────────────────────────────────────────────────────┐\n│ │\n│ 🎮 DEMO MODE ACTIVE │\n│ │\n│ The SDK is running without an API key. │\n│ • Payment: Mock billing (always allowed, 9999 credits) │\n│ • Telemetry: Logging to console only │\n│ • All features work - no data sent to OpenConductor │\n│ │\n│ To enable production mode: │\n│ 1. Get a free API key at https://openconductor.ai │\n│ 2. Set OPENCONDUCTOR_API_KEY environment variable │\n│ or pass apiKey to initOpenConductor() │\n│ │\n└─────────────────────────────────────────────────────────────────┘\n`\n\nconst PRODUCTION_BANNER = `\n┌─────────────────────────────────────────────────────────────────┐\n│ ✅ OpenConductor SDK initialized (production mode) │\n└─────────────────────────────────────────────────────────────────┘\n`\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the OpenConductor SDK\n * \n * Call this once at startup. If no API key is provided (via config or \n * OPENCONDUCTOR_API_KEY env var), the SDK automatically enables Demo Mode.\n * \n * @example Production mode\n * ```typescript\n * initOpenConductor({\n * apiKey: process.env.OPENCONDUCTOR_API_KEY,\n * serverName: 'my-server',\n * serverVersion: '1.0.0'\n * })\n * ```\n * \n * @example Demo mode (explicit)\n * ```typescript\n * initOpenConductor({ demoMode: true })\n * ```\n * \n * @example Demo mode (auto-detected)\n * ```typescript\n * // No API key? Demo mode activates automatically\n * initOpenConductor({ serverName: 'my-server' })\n * ```\n */\nexport function initOpenConductor(config: OpenConductorConfig = {}): ResolvedConfig {\n // Resolve API key from config or environment\n const apiKey = config.apiKey ?? process.env.OPENCONDUCTOR_API_KEY ?? null\n \n // Determine demo mode\n // Demo if: explicitly set OR no API key provided\n const demoMode = config.demoMode === true || !apiKey\n \n globalConfig = {\n apiKey: demoMode ? null : apiKey,\n demoMode,\n serverName: config.serverName ?? process.env.OPENCONDUCTOR_SERVER_NAME ?? 'mcp-server',\n serverVersion: config.serverVersion ?? process.env.npm_package_version ?? '0.0.0',\n initialized: true,\n }\n \n // Print banner unless quiet\n if (!config.quiet) {\n if (demoMode) {\n console.log(DEMO_BANNER)\n } else {\n console.log(PRODUCTION_BANNER)\n }\n }\n \n return globalConfig\n}\n\n/**\n * Get current SDK configuration\n * Auto-initializes in demo mode if not already initialized\n */\nexport function getConfig(): ResolvedConfig {\n if (!globalConfig.initialized) {\n // Auto-init in demo mode for zero-config experience\n return initOpenConductor({ quiet: true })\n }\n return globalConfig\n}\n\n/**\n * Check if SDK is in demo mode\n */\nexport function isDemoMode(): boolean {\n return getConfig().demoMode\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return globalConfig.initialized\n}\n\n/**\n * Reset configuration (mainly for testing)\n */\nexport function resetConfig(): void {\n globalConfig = {\n apiKey: null,\n demoMode: false,\n serverName: 'mcp-server',\n serverVersion: '0.0.0',\n initialized: false,\n }\n}\n","/**\n * @openconductor/mcp-sdk - Demo Mode Mock Data\n * \n * Realistic sample data for zero-config demo experience\n */\n\nimport type { BillingStatus, UsageAnalytics, CreditPackInfo, CreditPack } from '../payment'\nimport type { ToolMetric } from '../telemetry'\n\n// ============================================================================\n// Mock Billing Data\n// ============================================================================\n\nexport const MOCK_BILLING_STATUS: BillingStatus = {\n allowed: true,\n credits: 9999,\n tier: 'demo',\n reason: undefined,\n actionUrl: 'https://openconductor.ai/pricing',\n}\n\nexport const MOCK_USER_BILLING = {\n credits: 9999,\n tier: 'demo',\n active: true,\n}\n\nexport const MOCK_CREDIT_PACKS: Record<CreditPack, CreditPackInfo> = {\n starter: {\n name: 'Starter Pack',\n credits: 100,\n price: 9.99,\n perCredit: 0.0999,\n savings: 0,\n bestFor: 'Testing and small projects',\n },\n pro: {\n name: 'Pro Pack',\n credits: 500,\n price: 39.99,\n perCredit: 0.0799,\n savings: 20,\n bestFor: 'Growing projects',\n popular: true,\n },\n business: {\n name: 'Business Pack',\n credits: 2000,\n price: 119.99,\n perCredit: 0.0599,\n savings: 40,\n bestFor: 'Production workloads',\n },\n}\n\n// ============================================================================\n// Mock Analytics Data\n// ============================================================================\n\nfunction generateMockTimeline(days: number): Array<{ date: string; used: number; purchased: number }> {\n const timeline: Array<{ date: string; used: number; purchased: number }> = []\n const now = new Date()\n \n for (let i = days - 1; i >= 0; i--) {\n const date = new Date(now)\n date.setDate(date.getDate() - i)\n timeline.push({\n date: date.toISOString().split('T')[0],\n used: Math.floor(Math.random() * 50) + 10,\n purchased: i % 7 === 0 ? 500 : 0, // Weekly purchases\n })\n }\n \n return timeline\n}\n\nfunction generateMockTransactions(count: number): UsageAnalytics['recentTransactions'] {\n const tools = ['analyze-data', 'generate-report', 'search-docs', 'summarize', 'translate']\n const transactions: UsageAnalytics['recentTransactions'] = []\n const now = new Date()\n \n for (let i = 0; i < count; i++) {\n const isDebit = Math.random() > 0.2\n const date = new Date(now)\n date.setHours(date.getHours() - i * 2)\n \n transactions.push({\n id: `txn_demo_${i}`,\n amount: isDebit ? -(Math.floor(Math.random() * 20) + 1) : 500,\n type: isDebit ? 'usage' : 'purchase',\n tool: isDebit ? tools[Math.floor(Math.random() * tools.length)] : null,\n createdAt: date.toISOString(),\n })\n }\n \n return transactions\n}\n\nexport function getMockAnalytics(period: '24h' | '7d' | '30d' | 'all'): UsageAnalytics {\n const days = period === '24h' ? 1 : period === '7d' ? 7 : period === '30d' ? 30 : 90\n const timeline = generateMockTimeline(days)\n const totalUsed = timeline.reduce((sum, d) => sum + d.used, 0)\n const totalPurchased = timeline.reduce((sum, d) => sum + d.purchased, 0)\n \n return {\n period,\n balance: 9999,\n summary: {\n totalUsed,\n totalPurchased,\n netChange: totalPurchased - totalUsed,\n burnRate: totalUsed / days,\n daysRemaining: Math.floor(9999 / (totalUsed / days)),\n toolCount: 5,\n transactionCount: days * 3,\n },\n topTools: [\n { tool: 'analyze-data', calls: 156, credits: 780 },\n { tool: 'generate-report', calls: 89, credits: 445 },\n { tool: 'search-docs', calls: 234, credits: 234 },\n { tool: 'summarize', calls: 67, credits: 335 },\n { tool: 'translate', calls: 45, credits: 90 },\n ],\n usageTimeline: timeline,\n recentTransactions: generateMockTransactions(10),\n }\n}\n\n// ============================================================================\n// Mock Telemetry Data\n// ============================================================================\n\nexport function createMockMetric(tool: string, duration: number, success: boolean): ToolMetric {\n return {\n tool,\n duration,\n success,\n error: success ? undefined : 'Mock error for demo',\n timestamp: new Date().toISOString(),\n }\n}\n\n// ============================================================================\n// Demo Console Logger\n// ============================================================================\n\nconst DEMO_PREFIX = '[🎮 DEMO]'\n\nexport const demoLogger = {\n telemetry: (action: string, data: Record<string, unknown>) => {\n console.log(`${DEMO_PREFIX} Telemetry ${action}:`, JSON.stringify(data, null, 2))\n },\n \n payment: (action: string, data: Record<string, unknown>) => {\n console.log(`${DEMO_PREFIX} Payment ${action}:`, JSON.stringify(data, null, 2))\n },\n \n billing: (userId: string, result: BillingStatus) => {\n console.log(`${DEMO_PREFIX} Billing check for ${userId}: ALLOWED (demo mode)`)\n },\n \n deduct: (userId: string, credits: number, tool: string) => {\n console.log(`${DEMO_PREFIX} Would deduct ${credits} credits from ${userId} for ${tool} (skipped in demo)`)\n },\n}\n","import {\n PaymentRequiredError,\n InsufficientCreditsError,\n SubscriptionRequiredError,\n ConfigurationError,\n} from '../errors'\nimport { getConfig, isDemoMode } from '../config'\nimport {\n MOCK_BILLING_STATUS,\n MOCK_USER_BILLING,\n MOCK_CREDIT_PACKS,\n getMockAnalytics,\n demoLogger,\n} from '../demo'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PaymentConfig {\n /** OpenConductor API key for billing */\n apiKey: string\n /** Base URL for billing API (default: https://api.openconductor.ai) */\n apiUrl?: string\n /** Default upgrade URL to show users */\n upgradeUrl?: string\n /** Enable test mode (skips actual billing) */\n testMode?: boolean\n}\n\nexport interface CreditRequirement {\n /** Number of credits to deduct per call */\n credits: number\n}\n\nexport interface SubscriptionRequirement {\n /** Required subscription tier (e.g., 'pro', 'enterprise') */\n tier: string\n /** Alternative tiers that also grant access */\n allowedTiers?: string[]\n}\n\nexport interface StripeRequirement {\n /** Stripe Price ID for per-call billing */\n priceId: string\n}\n\nexport type PaymentRequirement = \n | CreditRequirement \n | SubscriptionRequirement \n | StripeRequirement\n\nexport interface UserContext {\n /** User ID for billing lookup */\n userId: string\n /** Optional API key override */\n apiKey?: string\n}\n\nexport interface BillingStatus {\n /** Whether the user can proceed */\n allowed: boolean\n /** Current credit balance (if applicable) */\n credits?: number\n /** Current subscription tier (if applicable) */\n tier?: string\n /** Reason for denial (if not allowed) */\n reason?: string\n /** URL for upgrade/purchase */\n actionUrl?: string\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nlet paymentConfig: PaymentConfig | null = null\n\n/**\n * Initialize payment/billing configuration\n * \n * In demo mode, this is optional - mock billing will be used automatically.\n * \n * @example\n * ```typescript\n * initPayment({\n * apiKey: process.env.OPENCONDUCTOR_API_KEY!,\n * upgradeUrl: 'https://myapp.com/upgrade'\n * })\n * ```\n */\nexport function initPayment(config?: PaymentConfig): void {\n // In demo mode, auto-configure with mocks\n if (isDemoMode()) {\n paymentConfig = {\n apiKey: 'demo_key',\n apiUrl: 'https://api.openconductor.ai',\n testMode: true,\n upgradeUrl: 'https://openconductor.ai/pricing',\n }\n return\n }\n \n // Production mode - require config\n if (!config?.apiKey) {\n throw new ConfigurationError('payment', 'Payment requires apiKey in production mode. Set OPENCONDUCTOR_API_KEY or pass apiKey to initPayment().')\n }\n \n paymentConfig = {\n apiUrl: 'https://api.openconductor.ai',\n testMode: false,\n ...config,\n }\n}\n\n/**\n * Get current payment configuration\n */\nexport function getPaymentConfig(): PaymentConfig | null {\n return paymentConfig\n}\n\n// ============================================================================\n// Billing Client\n// ============================================================================\n\ninterface CheckBillingParams {\n userId: string\n requirement: PaymentRequirement\n toolName: string\n}\n\ninterface DeductCreditsParams {\n userId: string\n credits: number\n toolName: string\n callId?: string\n}\n\nasync function checkBilling(params: CheckBillingParams): Promise<BillingStatus> {\n // Demo mode - return mock data\n if (isDemoMode()) {\n demoLogger.billing(params.userId, MOCK_BILLING_STATUS)\n return MOCK_BILLING_STATUS\n }\n\n const config = paymentConfig\n if (!config) {\n throw new ConfigurationError('payment', 'Payment not initialized. Call initPayment() first.')\n }\n\n // Test mode - always allow\n if (config.testMode) {\n return { allowed: true, credits: 9999, tier: 'test' }\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-check`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n userId: params.userId,\n requirement: params.requirement,\n tool: params.toolName,\n }),\n })\n\n if (!response.ok) {\n // Non-2xx response - treat as billing check failed\n const errorBody = await response.text()\n console.error('[payment] Billing check failed:', response.status, errorBody)\n return {\n allowed: false,\n reason: 'Billing service unavailable',\n actionUrl: config.upgradeUrl,\n }\n }\n\n return await response.json() as BillingStatus\n } catch (error) {\n // Network error - fail open or closed based on config\n console.error('[payment] Billing check error:', error)\n return {\n allowed: false,\n reason: 'Unable to verify billing status',\n actionUrl: config.upgradeUrl,\n }\n }\n}\n\nasync function deductCredits(params: DeductCreditsParams): Promise<boolean> {\n // Demo mode - log but don't deduct\n if (isDemoMode()) {\n demoLogger.deduct(params.userId, params.credits, params.toolName)\n return true\n }\n\n const config = paymentConfig\n if (!config) return false\n\n // Test mode - don't actually deduct\n if (config.testMode) return true\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-deduct`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n userId: params.userId,\n credits: params.credits,\n tool: params.toolName,\n callId: params.callId,\n }),\n })\n\n return response.ok\n } catch (error) {\n console.error('[payment] Credit deduction error:', error)\n return false\n }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nfunction isCreditRequirement(req: PaymentRequirement): req is CreditRequirement {\n return 'credits' in req && typeof req.credits === 'number'\n}\n\nfunction isSubscriptionRequirement(req: PaymentRequirement): req is SubscriptionRequirement {\n return 'tier' in req && typeof req.tier === 'string'\n}\n\nfunction isStripeRequirement(req: PaymentRequirement): req is StripeRequirement {\n return 'priceId' in req && typeof req.priceId === 'string'\n}\n\n// ============================================================================\n// Main Middleware\n// ============================================================================\n\nexport interface RequirePaymentOptions {\n /** Tool name for billing records */\n toolName?: string\n /** Function to extract user ID from input */\n getUserId?: (input: unknown) => string | undefined\n /** Custom error handler */\n onPaymentError?: (error: Error) => void\n}\n\n/**\n * One-line payment middleware for MCP tools\n * \n * @example Credits-based billing\n * ```typescript\n * const paidTool = requirePayment({ credits: 10 })(myHandler)\n * ```\n * \n * @example Subscription tier requirement\n * ```typescript\n * const premiumTool = requirePayment({ tier: 'pro' })(myHandler)\n * ```\n * \n * @example With wrapTool\n * ```typescript\n * const safePaidTool = wrapTool(\n * requirePayment({ credits: 5 })(myHandler),\n * { name: 'premium-analysis' }\n * )\n * ```\n */\nexport function requirePayment<TInput extends { userId?: string }, TOutput>(\n requirement: PaymentRequirement,\n options: RequirePaymentOptions = {}\n) {\n return (\n handler: (input: TInput) => TOutput | Promise<TOutput>\n ): ((input: TInput) => Promise<TOutput>) => {\n \n const { toolName = 'unknown', getUserId } = options\n\n return async (input: TInput): Promise<TOutput> => {\n // Extract user ID\n const userId = getUserId?.(input) ?? input.userId\n \n if (!userId) {\n throw new PaymentRequiredError(toolName, {\n upgradeUrl: paymentConfig?.upgradeUrl,\n })\n }\n\n // Check billing status\n const status = await checkBilling({\n userId,\n requirement,\n toolName,\n })\n\n if (!status.allowed) {\n // Throw appropriate error based on requirement type\n if (isCreditRequirement(requirement)) {\n throw new InsufficientCreditsError(\n requirement.credits,\n status.credits ?? 0,\n { purchaseUrl: status.actionUrl }\n )\n }\n\n if (isSubscriptionRequirement(requirement)) {\n throw new SubscriptionRequiredError(\n requirement.tier,\n status.tier,\n { upgradeUrl: status.actionUrl }\n )\n }\n\n // Generic payment required\n throw new PaymentRequiredError(toolName, {\n upgradeUrl: status.actionUrl,\n ...(isStripeRequirement(requirement) && { priceId: requirement.priceId }),\n })\n }\n\n // Execute the handler\n const result = await handler(input)\n\n // Deduct credits after successful execution (if credit-based)\n if (isCreditRequirement(requirement)) {\n await deductCredits({\n userId,\n credits: requirement.credits,\n toolName,\n })\n }\n\n return result\n }\n }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Create a paid tool with built-in payment verification\n * \n * @example\n * ```typescript\n * const analyzeData = createPaidTool({\n * name: 'analyze-data',\n * payment: { credits: 10 },\n * handler: async (input) => {\n * // Your tool logic\n * return result\n * }\n * })\n * ```\n */\nexport function createPaidTool<TInput extends { userId?: string }, TOutput>(config: {\n name: string\n payment: PaymentRequirement\n handler: (input: TInput) => TOutput | Promise<TOutput>\n getUserId?: (input: TInput) => string | undefined\n}): (input: TInput) => Promise<TOutput> {\n return requirePayment<TInput, TOutput>(config.payment, {\n toolName: config.name,\n getUserId: config.getUserId as (input: unknown) => string | undefined,\n })(config.handler)\n}\n\n/**\n * Check if a user can access a paid feature without executing it\n * Useful for UI gating\n * \n * @example\n * ```typescript\n * const canAccess = await canUserAccess('user_123', { credits: 10 }, 'premium-tool')\n * if (!canAccess.allowed) {\n * showUpgradePrompt(canAccess.actionUrl)\n * }\n * ```\n */\nexport async function canUserAccess(\n userId: string,\n requirement: PaymentRequirement,\n toolName: string = 'check'\n): Promise<BillingStatus> {\n return checkBilling({ userId, requirement, toolName })\n}\n\n/**\n * Get user's current billing status\n */\nexport async function getUserBillingStatus(userId: string): Promise<{\n credits: number\n tier: string\n active: boolean\n} | null> {\n // Demo mode - return mock data\n if (isDemoMode()) {\n return MOCK_USER_BILLING\n }\n\n const config = paymentConfig\n if (!config) return null\n\n if (config.testMode) {\n return { credits: 9999, tier: 'test', active: true }\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/billing-status/${userId}`, {\n headers: {\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n })\n\n if (!response.ok) return null\n return await response.json()\n } catch {\n return null\n }\n}\n\n// ============================================================================\n// Checkout Helpers\n// ============================================================================\n\nexport type CreditPack = 'starter' | 'pro' | 'business'\n\nexport interface CreditPackInfo {\n name: string\n credits: number\n price: number\n perCredit: number\n savings: number\n bestFor: string\n popular?: boolean\n}\n\nexport interface CheckoutSession {\n sessionId: string\n url: string\n pack: CreditPack\n credits: number\n price: number\n perCredit: number\n}\n\n/**\n * Get available credit packs and pricing\n * \n * @example\n * ```typescript\n * const packs = await getCreditPacks()\n * console.log(packs.pro) // { name: 'Pro Pack', credits: 500, price: 39.99, ... }\n * ```\n */\nexport async function getCreditPacks(): Promise<Record<CreditPack, CreditPackInfo> | null> {\n // Demo mode - return mock packs\n if (isDemoMode()) {\n return MOCK_CREDIT_PACKS\n }\n\n const config = paymentConfig\n if (!config) return null\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/credit-packs`)\n if (!response.ok) return null\n const data = await response.json()\n return data.packs\n } catch {\n return null\n }\n}\n\n/**\n * Create a Stripe checkout session for purchasing credits\n * Returns a URL to redirect the user to for payment\n * \n * @example\n * ```typescript\n * const checkout = await createCreditsCheckout('pro', {\n * successUrl: 'https://myapp.com/success',\n * cancelUrl: 'https://myapp.com/pricing',\n * })\n * \n * // Redirect user to checkout\n * window.location.href = checkout.url\n * ```\n */\nexport async function createCreditsCheckout(\n pack: CreditPack,\n options: {\n successUrl?: string\n cancelUrl?: string\n } = {}\n): Promise<CheckoutSession | null> {\n const config = paymentConfig\n if (!config) {\n console.error('[payment] Payment not initialized. Call initPayment() first.')\n return null\n }\n\n try {\n const response = await fetch(`${config.apiUrl}/functions/v1/stripe-checkout-credits`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify({\n pack,\n successUrl: options.successUrl,\n cancelUrl: options.cancelUrl,\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n console.error('[payment] Checkout creation failed:', error)\n return null\n }\n\n return await response.json() as CheckoutSession\n } catch (error) {\n console.error('[payment] Checkout error:', error)\n return null\n }\n}\n\n/**\n * Generate a direct checkout URL for embedding in upgrade prompts\n * \n * @example In an error handler:\n * ```typescript\n * catch (error) {\n * if (error instanceof InsufficientCreditsError) {\n * const checkoutUrl = await getCheckoutUrl('pro')\n * return { error: `Insufficient credits. Buy more: ${checkoutUrl}` }\n * }\n * }\n * ```\n */\nexport async function getCheckoutUrl(pack: CreditPack): Promise<string | null> {\n const session = await createCreditsCheckout(pack)\n return session?.url ?? null\n}\n\n// ============================================================================\n// Upgrade Prompts\n// ============================================================================\n\nexport interface UpgradePromptOptions {\n /** Required credits for the blocked action */\n required?: number\n /** Currently available credits */\n available?: number\n /** Tool that was blocked */\n toolName?: string\n /** Include direct checkout links */\n includeLinks?: boolean\n}\n\n/**\n * Generate a user-friendly upgrade prompt message\n * Use this in your error handlers to show helpful messages\n * \n * @example\n * ```typescript\n * catch (error) {\n * if (error instanceof InsufficientCreditsError) {\n * const prompt = await generateUpgradePrompt({\n * required: error.data.required,\n * available: error.data.available,\n * toolName: 'analyze-data'\n * })\n * console.log(prompt.message)\n * // \"You need 10 more credits to use analyze-data. \n * // Buy the Pro Pack (500 credits) for $39.99 → https://...\"\n * }\n * }\n * ```\n */\nexport async function generateUpgradePrompt(\n options: UpgradePromptOptions = {}\n): Promise<{\n message: string\n shortMessage: string\n recommendedPack: CreditPack\n packs: Record<CreditPack, { credits: number; price: number; url: string | null }>\n}> {\n const { required = 0, available = 0, toolName, includeLinks = true } = options\n const needed = Math.max(0, required - available)\n \n // Determine recommended pack based on needed credits\n let recommendedPack: CreditPack = 'starter'\n if (needed > 100) recommendedPack = 'pro'\n if (needed > 500) recommendedPack = 'business'\n \n // Get pack URLs if requested\n const packUrls: Record<CreditPack, string | null> = {\n starter: null,\n pro: null,\n business: null,\n }\n \n if (includeLinks) {\n const [starterUrl, proUrl, businessUrl] = await Promise.all([\n getCheckoutUrl('starter'),\n getCheckoutUrl('pro'),\n getCheckoutUrl('business'),\n ])\n packUrls.starter = starterUrl\n packUrls.pro = proUrl\n packUrls.business = businessUrl\n }\n \n // Build message\n const toolPart = toolName ? ` to use ${toolName}` : ''\n const shortMessage = `Insufficient credits: need ${required}, have ${available}`\n \n let message = `You need ${needed} more credits${toolPart}.\\n\\n`\n message += `💳 Quick top-up options:\\n`\n message += ` • Starter: 100 credits for $9.99${packUrls.starter ? ` → ${packUrls.starter}` : ''}\\n`\n message += ` • Pro: 500 credits for $39.99 (20% off)${packUrls.pro ? ` → ${packUrls.pro}` : ''}\\n`\n message += ` • Business: 2,000 credits for $119.99 (40% off)${packUrls.business ? ` → ${packUrls.business}` : ''}\\n`\n \n if (recommendedPack !== 'starter') {\n message += `\\n✨ Recommended: ${recommendedPack.charAt(0).toUpperCase() + recommendedPack.slice(1)} Pack`\n }\n \n return {\n message,\n shortMessage,\n recommendedPack,\n packs: {\n starter: { credits: 100, price: 9.99, url: packUrls.starter },\n pro: { credits: 500, price: 39.99, url: packUrls.pro },\n business: { credits: 2000, price: 119.99, url: packUrls.business },\n },\n }\n}\n\n/**\n * Get a simple checkout URL for the dashboard\n * Useful when you don't want to create a full Stripe session\n */\nexport function getDashboardCheckoutUrl(options: {\n required?: number\n available?: number\n pack?: CreditPack\n} = {}): string {\n const params = new URLSearchParams()\n params.set('action', 'buy-credits')\n if (options.required) params.set('required', String(options.required))\n if (options.available) params.set('available', String(options.available))\n if (options.pack) params.set('pack', options.pack)\n return `https://dashboard.openconductor.ai?${params.toString()}`\n}\n\n/**\n * Create an error handler that automatically generates upgrade prompts\n * \n * @example\n * ```typescript\n * const handleError = createUpgradeErrorHandler({\n * onInsufficientCredits: (prompt) => {\n * return { error: prompt.shortMessage, upgradeUrl: prompt.packs.pro.url }\n * }\n * })\n * \n * // In your tool:\n * try {\n * return await paidHandler(input)\n * } catch (error) {\n * return handleError(error)\n * }\n * ```\n */\nexport function createUpgradeErrorHandler(handlers: {\n onInsufficientCredits?: (prompt: Awaited<ReturnType<typeof generateUpgradePrompt>>) => unknown\n onSubscriptionRequired?: (error: SubscriptionRequiredError) => unknown\n onPaymentRequired?: (error: PaymentRequiredError) => unknown\n onOtherError?: (error: Error) => unknown\n}) {\n return async (error: Error): Promise<unknown> => {\n if (error instanceof InsufficientCreditsError && handlers.onInsufficientCredits) {\n const prompt = await generateUpgradePrompt({\n required: error.data?.required as number,\n available: error.data?.available as number,\n })\n return handlers.onInsufficientCredits(prompt)\n }\n \n if (error instanceof SubscriptionRequiredError && handlers.onSubscriptionRequired) {\n return handlers.onSubscriptionRequired(error)\n }\n \n if (error instanceof PaymentRequiredError && handlers.onPaymentRequired) {\n return handlers.onPaymentRequired(error)\n }\n \n if (handlers.onOtherError) {\n return handlers.onOtherError(error)\n }\n \n throw error\n }\n}\n\n// ============================================================================\n// Usage Analytics\n// ============================================================================\n\nexport type AnalyticsPeriod = '24h' | '7d' | '30d' | 'all'\n\nexport interface UsageAnalytics {\n period: AnalyticsPeriod\n balance: number\n summary: {\n totalUsed: number\n totalPurchased: number\n netChange: number\n burnRate: number\n daysRemaining: number | null\n toolCount: number\n transactionCount: number\n }\n topTools: Array<{\n tool: string\n calls: number\n credits: number\n }>\n usageTimeline: Array<{\n date: string\n used: number\n purchased: number\n }>\n recentTransactions: Array<{\n id: string\n amount: number\n type: string\n tool: string | null\n createdAt: string\n }>\n}\n\n/**\n * Get usage analytics for a user\n * \n * @example\n * ```typescript\n * const analytics = await getUserAnalytics('user_123', '30d')\n * console.log(`Burn rate: ${analytics.summary.burnRate} credits/day`)\n * console.log(`Days remaining: ${analytics.summary.daysRemaining}`)\n * ```\n */\nexport async function getUserAnalytics(\n userId: string,\n period: AnalyticsPeriod = '30d'\n): Promise<UsageAnalytics | null> {\n // Demo mode - return realistic mock data\n if (isDemoMode()) {\n return getMockAnalytics(period)\n }\n\n const config = paymentConfig\n if (!config) {\n console.error('[payment] Payment not initialized. Call initPayment() first.')\n return null\n }\n\n if (config.testMode) {\n // Return mock data in test mode\n return {\n period,\n balance: 9999,\n summary: {\n totalUsed: 100,\n totalPurchased: 500,\n netChange: 400,\n burnRate: 3.33,\n daysRemaining: 3000,\n toolCount: 5,\n transactionCount: 30,\n },\n topTools: [\n { tool: 'test-tool', calls: 10, credits: 50 },\n ],\n usageTimeline: [],\n recentTransactions: [],\n }\n }\n\n try {\n const response = await fetch(\n `${config.apiUrl}/functions/v1/usage-analytics/${userId}?period=${period}`,\n {\n headers: {\n 'Authorization': `Bearer ${config.apiKey}`,\n },\n }\n )\n\n if (!response.ok) return null\n return await response.json() as UsageAnalytics\n } catch (error) {\n console.error('[payment] Analytics fetch error:', error)\n return null\n }\n}\n\n/**\n * Check if user's credits are running low based on burn rate\n * Returns recommended action if low\n * \n * @example\n * ```typescript\n * const warning = await checkLowBalance('user_123')\n * if (warning) {\n * sendNotification(warning.message)\n * }\n * ```\n */\nexport async function checkLowBalance(\n userId: string,\n thresholdDays: number = 7\n): Promise<{\n isLow: boolean\n daysRemaining: number | null\n balance: number\n burnRate: number\n message: string\n recommendedPack: CreditPack\n} | null> {\n const analytics = await getUserAnalytics(userId, '7d')\n if (!analytics) return null\n\n const { balance, summary } = analytics\n const { burnRate, daysRemaining } = summary\n \n const isLow = daysRemaining !== null && daysRemaining <= thresholdDays\n \n // Recommend pack based on burn rate\n let recommendedPack: CreditPack = 'starter'\n const weeklyBurn = burnRate * 7\n if (weeklyBurn > 100) recommendedPack = 'pro'\n if (weeklyBurn > 400) recommendedPack = 'business'\n \n let message = ''\n if (isLow) {\n if (daysRemaining === 0) {\n message = `⚠️ Credits depleted! Balance: ${balance}. Buy more to continue.`\n } else if (daysRemaining <= 1) {\n message = `⚠️ Running low! ~${daysRemaining} day of credits left at current usage.`\n } else {\n message = `📊 ~${daysRemaining} days of credits remaining at current burn rate (${burnRate.toFixed(1)}/day).`\n }\n }\n \n return {\n isLow,\n daysRemaining,\n balance,\n burnRate,\n message,\n recommendedPack,\n }\n}\n"]}