flowstack-sdk 0.2.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/mock/fixtures.ts","../../src/context/FlowstackProvider.tsx","../../src/wallet/useWalletAuth.ts","../../src/wallet/useInferBalance.ts","../../src/wallet/useAgentBalance.ts","../../src/wallet/useDeposit.ts","../../src/wallet/useBuyInfer.ts","../../src/wallet/useAppAccess.ts","../../src/wallet/WalletProvider.tsx","../../src/wallet/LoginButton.tsx","../../src/wallet/InferBalanceBadge.tsx","../../src/wallet/AgentBalanceBadge.tsx","../../src/wallet/NeedsAgent.tsx","../../src/wallet/PaymentRequired.tsx","../../src/wallet/BuyInferModal.tsx","../../src/wallet/AppPaywall.tsx"],"names":["useState","useEffect","useCallback","POLL_INTERVAL_MS","useRef","useConfig","createContext","jsx","jsxs","badgeStyle"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Mock Fixtures for Development Mode\n *\n * Provides realistic test data for development without a backend.\n */\n\nimport type {\n FlowstackCredentials,\n WorkspaceInfo,\n DatasetInfo,\n VisualizationData,\n ChatMessage,\n DataSource,\n User,\n ManagedUser,\n UserStats,\n UserActivityLog,\n} from '../types';\n\n/**\n * Mock user credentials\n */\nexport const mockCredentials: FlowstackCredentials = {\n apiKey: 'mock_session_token_abc123',\n tenantId: 't_mock_tenant',\n userId: 'user_mock_123',\n email: 'demo@example.com',\n expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),\n};\n\n/**\n * Mock user derived from credentials\n */\nexport const mockUser: User = {\n id: 'user_mock_123',\n email: 'demo@example.com',\n tenantId: 't_mock_tenant',\n expiresAt: mockCredentials.expiresAt,\n};\n\n/**\n * Mock workspaces\n */\nexport const mockWorkspaces: WorkspaceInfo[] = [\n {\n workspaceId: 'ws_demo_1',\n name: 'Demo Workspace',\n description: 'A demo workspace for testing',\n datasetCount: 3,\n visualizationCount: 5,\n modelCount: 1,\n createdAt: '2024-01-15T10:00:00Z',\n lastAccessed: new Date().toISOString(),\n },\n {\n workspaceId: 'ws_analytics',\n name: 'Analytics Project',\n description: 'Customer analytics and insights',\n datasetCount: 7,\n visualizationCount: 12,\n modelCount: 2,\n createdAt: '2024-02-20T14:30:00Z',\n lastAccessed: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n workspaceId: 'ws_ml_project',\n name: 'ML Experiments',\n description: 'Machine learning model experiments',\n datasetCount: 5,\n visualizationCount: 8,\n modelCount: 4,\n createdAt: '2024-03-10T09:15:00Z',\n lastAccessed: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),\n },\n];\n\n/**\n * Mock datasets\n */\nexport const mockDatasets: DatasetInfo[] = [\n {\n id: 'ds_customers',\n name: 'customers',\n rows: 10000,\n columns: 12,\n columnNames: ['id', 'name', 'email', 'created_at', 'country', 'segment', 'revenue', 'orders', 'last_order', 'lifetime_value', 'churn_risk', 'status'],\n schema: {\n id: { type: 'string', nullable: false, unique: true },\n name: { type: 'string', nullable: false },\n email: { type: 'string', nullable: false },\n created_at: { type: 'date', nullable: false },\n country: { type: 'string', nullable: true },\n segment: { type: 'string', nullable: true },\n revenue: { type: 'number', nullable: false },\n orders: { type: 'number', nullable: false },\n last_order: { type: 'date', nullable: true },\n lifetime_value: { type: 'number', nullable: false },\n churn_risk: { type: 'number', nullable: true },\n status: { type: 'string', nullable: false },\n },\n createdAt: '2024-01-15T10:30:00Z',\n updatedAt: '2024-03-15T08:00:00Z',\n },\n {\n id: 'ds_orders',\n name: 'orders',\n rows: 50000,\n columns: 8,\n columnNames: ['order_id', 'customer_id', 'order_date', 'total', 'status', 'items', 'shipping_country', 'payment_method'],\n createdAt: '2024-01-20T11:00:00Z',\n updatedAt: '2024-03-14T16:45:00Z',\n },\n {\n id: 'ds_products',\n name: 'products',\n rows: 500,\n columns: 10,\n columnNames: ['product_id', 'name', 'category', 'price', 'cost', 'stock', 'rating', 'reviews', 'created_at', 'is_active'],\n createdAt: '2024-02-01T09:00:00Z',\n updatedAt: '2024-03-10T14:20:00Z',\n },\n];\n\n/**\n * Mock visualizations\n */\nexport const mockVisualizations: VisualizationData[] = [\n {\n name: 'Revenue by Month',\n type: 'line_chart',\n format: 'png',\n createdAt: '2024-03-15T10:00:00Z',\n metadata: { xAxis: 'month', yAxis: 'revenue' },\n },\n {\n name: 'Customer Segments',\n type: 'pie_chart',\n format: 'png',\n createdAt: '2024-03-14T15:30:00Z',\n metadata: { dimension: 'segment', measure: 'count' },\n },\n {\n name: 'Orders Heatmap',\n type: 'heatmap',\n format: 'png',\n createdAt: '2024-03-13T11:45:00Z',\n metadata: { xAxis: 'day_of_week', yAxis: 'hour' },\n },\n];\n\n/**\n * Mock data sources\n */\nexport const mockDataSources: DataSource[] = [\n {\n source_id: 'src_mongodb_1',\n tenant_id: 't_mock_tenant',\n source_type: 'mongodb',\n name: 'Production MongoDB',\n auth_method: 'connection_string',\n is_tenant_wide: true,\n created_at: Date.now() - 30 * 24 * 60 * 60 * 1000,\n credentials_preview: { host: 'mongodb.example.com', database: 'production' },\n },\n {\n source_id: 'src_postgres_1',\n tenant_id: 't_mock_tenant',\n source_type: 'postgresql',\n name: 'Analytics Database',\n auth_method: 'connection_string',\n is_tenant_wide: false,\n user_id: 'user_mock_123',\n created_at: Date.now() - 14 * 24 * 60 * 60 * 1000,\n credentials_preview: { host: 'pg.example.com', database: 'analytics' },\n },\n];\n\n/**\n * Mock chat messages (for demo)\n */\nexport const mockChatHistory: ChatMessage[] = [\n {\n id: 'msg_1',\n role: 'user',\n content: 'What are my top customers by revenue?',\n timestamp: new Date(Date.now() - 5 * 60 * 1000),\n },\n {\n id: 'msg_2',\n role: 'assistant',\n content: 'I analyzed the customers dataset and found your top 10 customers by revenue. Here are the results:\\n\\n1. Acme Corp - $125,000\\n2. TechStart Inc - $98,500\\n3. Global Retail - $87,200\\n...',\n timestamp: new Date(Date.now() - 4 * 60 * 1000),\n toolCalls: [\n {\n id: 'tool_1',\n name: 'query_dataset',\n args: { dataset: 'customers', query: 'SELECT * FROM customers ORDER BY revenue DESC LIMIT 10' },\n result: { rows: 10 },\n status: 'complete',\n },\n ],\n },\n];\n\n/**\n * Generate a unique ID for mock data\n */\nexport function generateMockId(prefix: string = 'mock'): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Simulate network delay for realistic mock responses\n */\nexport function mockDelay(minMs: number = 100, maxMs: number = 500): Promise<void> {\n const delay = Math.random() * (maxMs - minMs) + minMs;\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\n// =============================================================================\n// User Management Mock Data\n// =============================================================================\n\n/**\n * Mock managed users for admin dashboard\n */\nexport const mockManagedUsers: ManagedUser[] = [\n {\n id: 'user_mock_123',\n email: 'demo@example.com',\n name: 'Demo User',\n role: 'owner',\n status: 'active',\n tenantId: 't_mock_tenant',\n createdAt: '2024-01-01T10:00:00Z',\n lastLoginAt: new Date().toISOString(),\n lastActivityAt: new Date().toISOString(),\n metadata: { plan: 'pro', company: 'Demo Inc' },\n },\n {\n id: 'user_admin_456',\n email: 'admin@example.com',\n name: 'Admin User',\n role: 'admin',\n status: 'active',\n tenantId: 't_mock_tenant',\n createdAt: '2024-01-15T14:30:00Z',\n lastLoginAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n lastActivityAt: new Date(Date.now() - 30 * 60 * 1000).toISOString(),\n },\n {\n id: 'user_member_789',\n email: 'member@example.com',\n name: 'Team Member',\n role: 'member',\n status: 'active',\n tenantId: 't_mock_tenant',\n createdAt: '2024-02-10T09:00:00Z',\n lastLoginAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),\n lastActivityAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),\n },\n {\n id: 'user_suspended_101',\n email: 'suspended@example.com',\n name: 'Suspended User',\n role: 'member',\n status: 'suspended',\n tenantId: 't_mock_tenant',\n createdAt: '2024-02-20T11:00:00Z',\n lastLoginAt: '2024-03-01T08:00:00Z',\n metadata: { suspendReason: 'Policy violation' },\n },\n {\n id: 'user_pending_102',\n email: 'pending@example.com',\n name: 'New User',\n role: 'viewer',\n status: 'pending_verification',\n tenantId: 't_mock_tenant',\n createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),\n },\n];\n\n/**\n * Mock user statistics\n */\nexport const mockUserStats: UserStats = {\n totalUsers: 127,\n activeUsers: 98,\n usersByRole: {\n owner: 1,\n admin: 5,\n member: 85,\n viewer: 36,\n },\n usersByStatus: {\n active: 98,\n suspended: 8,\n pending_verification: 15,\n deactivated: 6,\n },\n newUsersThisMonth: 23,\n dailyActiveUsers: [45, 52, 48, 61, 55, 43, 38, 67, 72, 58, 63, 71, 65, 54],\n};\n\n/**\n * Mock user activity logs\n */\nexport const mockUserActivity: UserActivityLog[] = [\n {\n id: 'act_1',\n userId: 'user_mock_123',\n activityType: 'login',\n description: 'Logged in from Chrome on macOS',\n timestamp: new Date().toISOString(),\n },\n {\n id: 'act_2',\n userId: 'user_mock_123',\n activityType: 'query_execute',\n description: 'Executed query: \"Show top customers\"',\n timestamp: new Date(Date.now() - 30 * 60 * 1000).toISOString(),\n resourceType: 'workspace',\n resourceId: 'ws_demo_1',\n },\n {\n id: 'act_3',\n userId: 'user_mock_123',\n activityType: 'dataset_upload',\n description: 'Uploaded dataset: sales_data.csv',\n timestamp: new Date(Date.now() - 60 * 60 * 1000).toISOString(),\n resourceType: 'dataset',\n resourceId: 'ds_sales',\n },\n {\n id: 'act_4',\n userId: 'user_mock_123',\n activityType: 'workspace_create',\n description: 'Created workspace: Analytics Project',\n timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),\n resourceType: 'workspace',\n resourceId: 'ws_analytics',\n },\n {\n id: 'act_5',\n userId: 'user_mock_123',\n activityType: 'logout',\n description: 'Logged out',\n timestamp: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),\n },\n];\n","'use client';\n\n/**\n * Flowstack SDK Provider\n *\n * Main context provider that manages all SDK state including:\n * - Authentication (credentials, session)\n * - Workspaces (list, selection, creation)\n * - Chat messages with persistence\n * - Datasets, visualizations, reports, models\n * - Query execution state\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n ReactNode,\n} from 'react';\n\nimport type {\n FlowstackConfig,\n FlowstackCredentials,\n FlowstackContextValue,\n ChatMessage,\n WorkspaceInfo,\n DatasetInfo,\n VisualizationData,\n ReportInfo,\n ModelInfo,\n ScriptInfo,\n SessionState,\n} from '../types';\n\nimport {\n listWorkspaces,\n createWorkspace as apiCreateWorkspace,\n listDatasets,\n listVisualizations,\n listReports,\n listModels,\n listScripts,\n} from '../api/client';\n\nimport {\n saveCredentials,\n loadCredentials,\n clearCredentials,\n saveSelectedWorkspace,\n loadSelectedWorkspace,\n clearSelectedWorkspace,\n saveMessages,\n loadMessages,\n clearMessages as clearStoredMessages,\n clearAllFlowstackData,\n} from '../utils/storage';\n\nimport {\n mockCredentials,\n mockWorkspaces,\n mockDatasets,\n mockVisualizations,\n mockDelay,\n generateMockId,\n} from '../mock/fixtures';\n\n// Default configuration\nconst DEFAULT_BASE_URL = 'https://sage-api.flowstack.fun';\n// NOTE: there is intentionally no DEFAULT_TENANT_ID. For authenticated calls the\n// backend derives tenant_id from the JWT/API key and ignores any client-sent\n// X-Tenant-ID, so a default is pointless there. The only case that needs an\n// explicit tenant is anonymous access (usePublicCollection) — and silently\n// defaulting that to a real platform tenant would route a misconfigured app's\n// public data into the wrong pool. So tenant is JWT-derived or explicitly set.\n\n/**\n * Normalize workspace object from backend (snake_case) to SDK (camelCase).\n * The backend returns workspace_id, dataset_count, etc. but the SDK type expects camelCase.\n */\nfunction normalizeWorkspace(ws: any): WorkspaceInfo {\n return {\n workspaceId: ws.workspaceId || ws.workspace_id || ws.id || '',\n name: ws.name || '',\n description: ws.description,\n datasetCount: ws.datasetCount ?? ws.dataset_count ?? 0,\n visualizationCount: ws.visualizationCount ?? ws.visualization_count ?? 0,\n modelCount: ws.modelCount ?? ws.model_count ?? 0,\n createdAt: ws.createdAt || ws.created_at || '',\n lastAccessed: ws.lastAccessed || ws.last_accessed || '',\n };\n}\n\n/** Check if a URL is a valid presigned S3 URL (not raw/unsigned). */\nfunction isPresignedUrl(url?: string): boolean {\n return !!url && url.includes('X-Amz-');\n}\n\n/** Normalize visualization object from backend snake_case to SDK camelCase. */\nfunction normalizeVisualization(v: any): VisualizationData {\n const meta = v.metadata || {};\n // Presigned URLs first — they have auth. Unsigned S3 URLs will AccessDenied.\n const imageUrl =\n v.presigned_url || meta.presigned_url ||\n v.imageUrl || v.image_url ||\n (v.url && !v.url.includes('s3.amazonaws.com') ? v.url : undefined) ||\n (meta.url && !meta.url.includes('s3.amazonaws.com') ? meta.url : undefined) ||\n meta.image_url ||\n undefined;\n return {\n name: v.name || '',\n type: v.type || v.visualization_type || v.chart_type || meta.chart_type,\n imageUrl,\n imageBase64: v.imageBase64 || v.image_base64 || meta.image_base64,\n format: v.format || meta.format,\n createdAt: v.createdAt || v.created_at || meta.created_at,\n metadata: v.metadata,\n };\n}\n\n/** Normalize dataset object from backend to SDK format. */\nfunction normalizeDataset(d: any): DatasetInfo {\n // Backend returns shape: [rows, cols] and columns: [\"col1\", \"col2\", ...]\n const shape = d.shape || [];\n const colArray = Array.isArray(d.columns) ? d.columns : d.column_names || d.columns_list || [];\n const rowCount = d.rows ?? d.row_count ?? d.num_rows ?? d.size ?? (shape[0] || 0);\n const colCount = typeof d.columns === 'number' ? d.columns : (d.column_count ?? d.num_columns ?? shape[1] ?? colArray.length ?? 0);\n return {\n ...d,\n id: d.id || d.dataset_id,\n name: d.name || d.dataset_name || '',\n rows: rowCount,\n columns: colCount,\n columnNames: colArray,\n createdAt: d.createdAt || d.created_at,\n fileSize: d.fileSize || d.file_size || d.size,\n schema: d.schema || d.dtypes,\n };\n}\n\n// Context instance\nconst FlowstackContext = createContext<FlowstackContextValue | null>(null);\n\n/**\n * Extract user ID from JWT or API key\n */\nfunction extractUserId(apiKey: string): string {\n try {\n // JWT token - extract from payload\n if (apiKey.includes('.')) {\n const parts = apiKey.split('.');\n if (parts.length === 3) {\n try {\n const payload = JSON.parse(atob(parts[1]));\n if (payload.user_id) return String(payload.user_id);\n } catch {\n // JWT decode failed\n }\n }\n }\n\n // Legacy API key format\n if (apiKey.startsWith('sage_t_')) {\n return apiKey.substring(7, 23);\n } else if (apiKey.startsWith('sage_')) {\n return apiKey.substring(5, 21);\n }\n\n // Fallback\n return apiKey.substring(0, 16);\n } catch {\n return apiKey.substring(0, 16);\n }\n}\n\n/**\n * Derive tenant_id from a JWT's payload (browser-safe, no jsonwebtoken dep).\n * Returns undefined when it can't be derived — callers fall back to an explicitly\n * configured tenantId, never to a hardcoded platform tenant.\n */\nfunction extractTenantId(apiKey?: string | null): string | undefined {\n if (!apiKey || !apiKey.includes('.')) return undefined;\n try {\n const parts = apiKey.split('.');\n if (parts.length === 3) {\n const payload = JSON.parse(atob(parts[1]));\n if (payload.tenant_id) return String(payload.tenant_id);\n }\n } catch {\n // not a decodable JWT — caller falls back to configured tenantId\n }\n return undefined;\n}\n\n/**\n * Check if credentials are expired\n */\nfunction isExpired(credentials: FlowstackCredentials): boolean {\n if (!credentials.expiresAt) {\n // Try to extract from JWT\n if (credentials.apiKey.includes('.')) {\n try {\n const parts = credentials.apiKey.split('.');\n const payload = JSON.parse(atob(parts[1]));\n if (payload.exp) {\n return Date.now() > payload.exp * 1000;\n }\n } catch {\n return false;\n }\n }\n return false;\n }\n\n const expiresAt = new Date(credentials.expiresAt);\n return expiresAt < new Date();\n}\n\n/**\n * FlowstackProvider Props\n */\ninterface FlowstackProviderProps {\n children: ReactNode;\n config: FlowstackConfig;\n /**\n * P0-72: Optional Privy auth state passed from the parent. When provided,\n * FlowstackProvider cross-validates stored credentials against Privy on\n * mount — if Privy says \"not authenticated\", stale Flowstack creds are\n * cleared instead of blindly hydrated. This eliminates the 4-minute 401\n * request storm on cold load when Privy's session is absent but\n * sessionStorage still has `flowstack_credentials`.\n *\n * When omitted (e.g., SIWE-only mode, tests), the provider falls back\n * to the legacy behavior of trusting sessionStorage.\n */\n privyAuthState?: {\n ready: boolean;\n authenticated: boolean;\n };\n}\n\n/**\n * Flowstack Provider Component\n *\n * Wrap your app with this provider to enable all Flowstack SDK features.\n *\n * @example\n * ```tsx\n * <FlowstackProvider config={{ jwtSecret: process.env.JWT_SECRET! }}>\n * <App />\n * </FlowstackProvider>\n * ```\n */\nexport function FlowstackProvider({\n children,\n config,\n privyAuthState,\n}: FlowstackProviderProps) {\n // Configuration\n const baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n // Empty string (not a real tenant) when unset — authenticated calls ignore the\n // X-Tenant-ID header (backend uses the JWT), and usePublicCollection hard-errors\n // on an empty tenant rather than silently using a platform default.\n const tenantId = config.tenantId || '';\n const isMockMode = config.mode === 'mock';\n\n // Auth state\n const [credentials, setCredentialsState] = useState<FlowstackCredentials | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n\n // Session state\n const [session, setSession] = useState<SessionState>({\n sessionId: null,\n workspaceId: null,\n isConnected: false,\n lastActivity: null,\n });\n\n // Workspaces state\n const [workspaces, setWorkspaces] = useState<WorkspaceInfo[]>([]);\n const [selectedWorkspace, setSelectedWorkspaceState] = useState<WorkspaceInfo | null>(null);\n const [isLoadingWorkspaces, setIsLoadingWorkspaces] = useState(false);\n\n // Chat state\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n\n // Query state\n const [isQueryRunning, setIsQueryRunning] = useState(false);\n const [queryStartTime, setQueryStartTime] = useState<number | null>(null);\n\n // Data state\n const [datasets, setDatasetsState] = useState<DatasetInfo[]>([]);\n const [isLoadingDatasets, setIsLoadingDatasets] = useState(false);\n\n const [visualizations, setVisualizationsState] = useState<VisualizationData[]>([]);\n const [isLoadingVisualizations, setIsLoadingVisualizations] = useState(false);\n\n const [reports, setReportsState] = useState<ReportInfo[]>([]);\n const [isLoadingReports, setIsLoadingReports] = useState(false);\n\n const [models, setModelsState] = useState<ModelInfo[]>([]);\n const [isLoadingModels, setIsLoadingModels] = useState(false);\n\n const [scripts, setScriptsState] = useState<ScriptInfo[]>([]);\n const [isLoadingScripts, setIsLoadingScripts] = useState(false);\n\n // UI state\n const [isSidebarOpen, setSidebarOpen] = useState(true);\n const [activeTab, setActiveTab] = useState<'chat' | 'datasets' | 'visualizations' | 'reports' | 'models'>('chat');\n\n // Build client config for API calls\n const clientConfig = { baseUrl, tenantId };\n\n // =============================================================================\n // Authentication\n // =============================================================================\n\n // Load credentials on mount — with P0-72 Privy cross-validation.\n //\n // Legacy behavior (no privyAuthState prop):\n // Trust sessionStorage. Hydrate whatever's there if not expired.\n //\n // P0-72 behavior (privyAuthState passed):\n // Wait for `ready`, then hydrate only if Privy agrees the user is\n // authenticated. If sessionStorage has creds but Privy says no,\n // clear the stale creds instead of firing authenticated API\n // requests into a 401 storm.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // Gate on Privy being ready when caller opted into cross-validation.\n if (privyAuthState && !privyAuthState.ready) {\n return;\n }\n\n const stored = loadCredentials('session');\n if (!stored) {\n setIsInitialized(true);\n return;\n }\n\n if (isExpired(stored)) {\n clearCredentials('session');\n setIsInitialized(true);\n return;\n }\n\n // app_scope cross-check: if this provider is configured with an appScope\n // (a built app), the stored JWT must carry a matching claim. A JWT issued\n // from the main Casino login (app_scope=null) silently bypasses all\n // collection guards and loads the full platform orchestrator instead of\n // the app's custom agent. Same logic as the broker fix for the Privy path.\n if (config.appScope) {\n try {\n const _parts = stored.apiKey.split('.');\n const _payload = JSON.parse(atob(_parts[1]));\n const _tokenScope: string | null = _payload.app_scope ?? null;\n if (_tokenScope !== config.appScope) {\n clearCredentials('session');\n clearAllFlowstackData('session');\n setIsInitialized(true);\n return;\n }\n } catch {\n // Malformed JWT — clear and force re-auth.\n clearCredentials('session');\n setIsInitialized(true);\n return;\n }\n }\n\n // P0-72 cross-check: Privy is the source of truth for \"is this user\n // authenticated.\" If sessionStorage disagrees, trust Privy and clear\n // the stale Flowstack creds.\n if (privyAuthState && !privyAuthState.authenticated) {\n console.log('[FlowstackProvider] Privy session absent, clearing stale credentials');\n clearCredentials('session');\n clearAllFlowstackData('session');\n setIsInitialized(true);\n return;\n }\n\n // Both storage and (optionally) Privy agree — hydrate.\n setCredentialsState(stored);\n const workspaceId = loadSelectedWorkspace(stored, 'local');\n if (workspaceId) {\n setSession(prev => ({\n ...prev,\n sessionId: workspaceId,\n workspaceId,\n isConnected: true,\n }));\n }\n setIsInitialized(true);\n }, [privyAuthState?.ready, privyAuthState?.authenticated]);\n\n // Set credentials handler\n const setCredentials = useCallback((creds: FlowstackCredentials | null) => {\n setCredentialsState(creds);\n if (creds) {\n // Resolve tenant: explicit on the creds, else derive from the JWT, else the\n // configured tenantId. No hardcoded platform default.\n const credsWithTenant = {\n ...creds,\n tenantId: creds.tenantId || extractTenantId(creds.apiKey) || tenantId,\n };\n saveCredentials(credsWithTenant, 'session');\n } else {\n clearCredentials('session');\n }\n }, [tenantId]);\n\n // Logout handler\n const logout = useCallback(() => {\n if (credentials) {\n // Clear workspace selection\n clearSelectedWorkspace(credentials, 'local');\n\n // Clear messages for current workspace\n if (session.workspaceId) {\n clearStoredMessages(session.workspaceId, credentials, 'session');\n }\n }\n\n // Clear all Flowstack data\n clearAllFlowstackData('local');\n clearAllFlowstackData('session');\n\n // One-shot marker (set AFTER the clears so it survives): tells the next\n // BrokeredLoginButton click to pass force_login=1, so the broker purges its\n // sticky Privy/Casino session and the user can sign in with a DIFFERENT\n // account. Without this, brokered re-login silently returns the same identity.\n try {\n if (typeof window !== 'undefined') {\n window.localStorage.setItem('flowstack:force_relogin', '1');\n }\n } catch { /* storage unavailable — non-fatal */ }\n\n // Reset state\n setCredentialsState(null);\n setWorkspaces([]);\n setSelectedWorkspaceState(null);\n setMessages([]);\n setDatasetsState([]);\n setVisualizationsState([]);\n setReportsState([]);\n setModelsState([]);\n setSession({\n sessionId: null,\n workspaceId: null,\n isConnected: false,\n lastActivity: null,\n });\n }, [credentials, session.workspaceId]);\n\n // =============================================================================\n // Workspace Management\n // =============================================================================\n\n // Refresh workspaces\n const refreshWorkspaces = useCallback(async () => {\n if (!credentials && !isMockMode) return;\n\n setIsLoadingWorkspaces(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setWorkspaces(mockWorkspaces);\n return;\n }\n\n const response = await listWorkspaces(credentials!, 50, clientConfig);\n if (response.ok && response.data) {\n setWorkspaces(response.data.workspaces.map(normalizeWorkspace));\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh workspaces:', error);\n } finally {\n setIsLoadingWorkspaces(false);\n }\n }, [credentials, clientConfig, isMockMode]);\n\n // Create workspace\n const createWorkspace = useCallback(async (name: string, description?: string): Promise<WorkspaceInfo | null> => {\n if (!credentials && !isMockMode) return null;\n\n try {\n if (isMockMode) {\n await mockDelay();\n const newWorkspace: WorkspaceInfo = {\n workspaceId: generateMockId('ws'),\n name,\n description,\n datasetCount: 0,\n visualizationCount: 0,\n modelCount: 0,\n createdAt: new Date().toISOString(),\n lastAccessed: new Date().toISOString(),\n };\n setWorkspaces(prev => [newWorkspace, ...prev]);\n return newWorkspace;\n }\n\n const response = await apiCreateWorkspace(credentials!, name, description, clientConfig);\n if (response.ok && response.data) {\n const newWorkspace = normalizeWorkspace(response.data.workspace);\n setWorkspaces(prev => [newWorkspace, ...prev]);\n return newWorkspace;\n }\n return null;\n } catch (error) {\n console.error('[Flowstack] Failed to create workspace:', error);\n return null;\n }\n }, [credentials, clientConfig, isMockMode]);\n\n // Select workspace\n const setSelectedWorkspace = useCallback((workspace: WorkspaceInfo | null) => {\n setSelectedWorkspaceState(workspace);\n\n if (workspace && credentials) {\n // Update session\n setSession(prev => ({\n ...prev,\n sessionId: workspace.workspaceId,\n workspaceId: workspace.workspaceId,\n isConnected: true,\n lastActivity: new Date(),\n }));\n\n // Persist selection\n saveSelectedWorkspace(workspace.workspaceId, credentials, 'local');\n\n // Load messages for this workspace\n const storedMessages = loadMessages<ChatMessage>(\n workspace.workspaceId,\n credentials,\n 'session'\n );\n\n // Fix any interrupted streaming messages\n const fixedMessages = storedMessages.map(m => ({\n ...m,\n timestamp: new Date(m.timestamp),\n isStreaming: false,\n content: m.isStreaming && !m.content?.trim()\n ? '*(Response interrupted)*'\n : m.content,\n }));\n setMessages(fixedMessages);\n\n // Clear data - will be refreshed\n setDatasetsState([]);\n setVisualizationsState([]);\n setReportsState([]);\n setModelsState([]);\n } else {\n setSession(prev => ({\n ...prev,\n sessionId: null,\n workspaceId: null,\n isConnected: false,\n }));\n setMessages([]);\n }\n }, [credentials]);\n\n // Auto-load workspaces when authenticated (or in mock mode)\n useEffect(() => {\n if ((credentials || isMockMode) && workspaces.length === 0 && isInitialized) {\n refreshWorkspaces();\n }\n }, [credentials, isInitialized, isMockMode]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Auto-select or auto-create workspace when workspaces load\n useEffect(() => {\n if (!credentials && !isMockMode) return;\n if (selectedWorkspace) return;\n\n if (workspaces.length > 0) {\n // If a session workspace exists, select it; otherwise select the first one\n const found = session.workspaceId\n ? workspaces.find(ws => ws.workspaceId === session.workspaceId)\n : null;\n // Use setSelectedWorkspace (not raw state setter) to trigger message restoration\n setSelectedWorkspace(found || workspaces[0]);\n } else if (workspaces.length === 0 && isInitialized && !isLoadingWorkspaces) {\n // No workspaces — auto-create a default one\n createWorkspace('My Workspace', 'Default workspace').then(ws => {\n if (ws) setSelectedWorkspace(ws);\n });\n }\n }, [workspaces, session.workspaceId, selectedWorkspace, credentials, isMockMode, isInitialized, isLoadingWorkspaces]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // =============================================================================\n // Message Management\n // =============================================================================\n\n const addMessage = useCallback((message: ChatMessage) => {\n setMessages(prev => {\n const updated = [...prev, message];\n\n // Persist non-streaming messages\n if (!message.isStreaming && credentials && session.workspaceId) {\n saveMessages(updated, session.workspaceId, credentials, 'session');\n }\n\n return updated;\n });\n }, [credentials, session.workspaceId]);\n\n const updateMessage = useCallback((id: string, updates: Partial<ChatMessage>) => {\n setMessages(prev => {\n const updated = prev.map(msg =>\n msg.id === id ? { ...msg, ...updates } : msg\n );\n\n // Persist when streaming completes\n if (updates.isStreaming === false && credentials && session.workspaceId) {\n saveMessages(updated, session.workspaceId, credentials, 'session');\n }\n\n return updated;\n });\n }, [credentials, session.workspaceId]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n if (credentials && session.workspaceId) {\n clearStoredMessages(session.workspaceId, credentials, 'session');\n }\n }, [credentials, session.workspaceId]);\n\n // =============================================================================\n // Dataset Management\n // =============================================================================\n\n const setDatasets = useCallback((datasets: DatasetInfo[]) => {\n setDatasetsState(datasets);\n }, []);\n\n const refreshDatasets = useCallback(async () => {\n if ((!credentials || !selectedWorkspace) && !isMockMode) return;\n\n setIsLoadingDatasets(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setDatasetsState(mockDatasets);\n return;\n }\n\n const response = await listDatasets(\n credentials!,\n selectedWorkspace!.workspaceId,\n clientConfig\n );\n if (response.ok && response.data) {\n setDatasetsState(response.data.datasets.map(normalizeDataset));\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh datasets:', error);\n } finally {\n setIsLoadingDatasets(false);\n }\n }, [credentials, selectedWorkspace, clientConfig, isMockMode]);\n\n // =============================================================================\n // Visualization Management\n // =============================================================================\n\n const setVisualizations = useCallback((vizs: VisualizationData[]) => {\n setVisualizationsState(vizs);\n }, []);\n\n const addVisualization = useCallback((viz: VisualizationData) => {\n setVisualizationsState(prev => {\n const exists = prev.some(v => v.name === viz.name);\n if (exists) {\n return prev.map(v => v.name === viz.name ? viz : v);\n }\n return [...prev, viz];\n });\n }, []);\n\n const refreshVisualizations = useCallback(async () => {\n if ((!credentials || !selectedWorkspace) && !isMockMode) return;\n\n setIsLoadingVisualizations(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setVisualizationsState(mockVisualizations);\n return;\n }\n\n const response = await listVisualizations(\n credentials!,\n selectedWorkspace!.workspaceId,\n clientConfig\n );\n if (response.ok && response.data) {\n const apiVizs = response.data.visualizations.map(normalizeVisualization);\n // Merge: preserve image data from streaming visualizations (SSE events\n // include imageBase64/imageUrl but the list API does not)\n setVisualizationsState(prev => {\n const streamMap = new Map(prev.filter(v => v.imageUrl || v.imageBase64).map(v => [v.name, v]));\n return apiVizs.map(v => {\n const streamed = streamMap.get(v.name);\n if (streamed && !v.imageUrl && !v.imageBase64) {\n return { ...v, imageUrl: streamed.imageUrl, imageBase64: streamed.imageBase64, format: streamed.format || v.format };\n }\n return v;\n });\n });\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh visualizations:', error);\n } finally {\n setIsLoadingVisualizations(false);\n }\n }, [credentials, selectedWorkspace, clientConfig, isMockMode]);\n\n const clearVisualizations = useCallback(() => {\n setVisualizationsState([]);\n }, []);\n\n // =============================================================================\n // Report Management\n // =============================================================================\n\n const refreshReports = useCallback(async () => {\n if ((!credentials || !selectedWorkspace) && !isMockMode) return;\n\n setIsLoadingReports(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setReportsState([]); // No mock reports by default\n return;\n }\n\n const response = await listReports(\n credentials!,\n selectedWorkspace!.workspaceId,\n clientConfig\n );\n if (response.ok && response.data) {\n setReportsState(response.data.reports);\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh reports:', error);\n } finally {\n setIsLoadingReports(false);\n }\n }, [credentials, selectedWorkspace, clientConfig, isMockMode]);\n\n // =============================================================================\n // Model Management\n // =============================================================================\n\n const refreshModels = useCallback(async () => {\n if ((!credentials || !selectedWorkspace) && !isMockMode) return;\n\n setIsLoadingModels(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setModelsState([]); // No mock models by default\n return;\n }\n\n const response = await listModels(\n credentials!,\n selectedWorkspace!.workspaceId,\n clientConfig\n );\n if (response.ok && response.data) {\n setModelsState(response.data.models);\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh models:', error);\n } finally {\n setIsLoadingModels(false);\n }\n }, [credentials, selectedWorkspace, clientConfig, isMockMode]);\n\n // =============================================================================\n // Script Management\n // =============================================================================\n\n const refreshScripts = useCallback(async () => {\n if ((!credentials || !selectedWorkspace) && !isMockMode) return;\n\n setIsLoadingScripts(true);\n try {\n if (isMockMode) {\n await mockDelay();\n setScriptsState([]);\n return;\n }\n\n const response = await listScripts(\n credentials!,\n selectedWorkspace!.workspaceId,\n clientConfig\n );\n if (response.ok && response.data) {\n setScriptsState(response.data.scripts);\n }\n } catch (error) {\n console.error('[Flowstack] Failed to refresh scripts:', error);\n } finally {\n setIsLoadingScripts(false);\n }\n }, [credentials, selectedWorkspace, clientConfig, isMockMode]);\n\n // =============================================================================\n // Auto-refresh on workspace change\n // =============================================================================\n\n useEffect(() => {\n if ((credentials || isMockMode) && selectedWorkspace) {\n const timer = setTimeout(() => {\n refreshDatasets();\n refreshVisualizations();\n refreshReports();\n refreshModels();\n refreshScripts();\n }, 100);\n return () => clearTimeout(timer);\n }\n }, [selectedWorkspace?.workspaceId, isMockMode]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // =============================================================================\n // Context Value\n // =============================================================================\n\n const value: FlowstackContextValue = {\n // Config\n config,\n\n // Auth\n credentials,\n setCredentials,\n isAuthenticated: !!credentials,\n isInitialized,\n logout,\n\n // Session\n session,\n\n // Workspaces\n workspaces,\n selectedWorkspace,\n setSelectedWorkspace,\n refreshWorkspaces,\n createWorkspace,\n isLoadingWorkspaces,\n\n // Messages\n messages,\n addMessage,\n updateMessage,\n clearMessages,\n\n // Query state\n isQueryRunning,\n setIsQueryRunning,\n queryStartTime,\n setQueryStartTime,\n\n // Datasets\n datasets,\n setDatasets,\n refreshDatasets,\n isLoadingDatasets,\n\n // Visualizations\n visualizations,\n setVisualizations,\n addVisualization,\n refreshVisualizations,\n isLoadingVisualizations,\n clearVisualizations,\n\n // Reports\n reports,\n refreshReports,\n isLoadingReports,\n\n // Models\n models,\n refreshModels,\n isLoadingModels,\n\n // Scripts\n scripts,\n refreshScripts,\n isLoadingScripts,\n\n // UI\n isSidebarOpen,\n setSidebarOpen,\n activeTab,\n setActiveTab,\n };\n\n return (\n <FlowstackContext.Provider value={value}>\n {children}\n </FlowstackContext.Provider>\n );\n}\n\n/**\n * Hook to access Flowstack context\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { isAuthenticated, credentials } = useFlowstack();\n * // ...\n * }\n * ```\n */\nexport function useFlowstack(): FlowstackContextValue {\n const context = useContext(FlowstackContext);\n if (!context) {\n throw new Error('useFlowstack must be used within a FlowstackProvider');\n }\n return context;\n}\n\n/**\n * Optional hook - returns null if not in provider (for conditional usage)\n */\nexport function useFlowstackOptional(): FlowstackContextValue | null {\n return useContext(FlowstackContext);\n}\n","/**\n * useWalletAuth — handles both Privy (embedded) and SIWE (external) auth paths.\n *\n * Both paths produce the same result: a JWT with a wallet_address claim\n * stored via the existing FlowstackProvider credential flow.\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { useConfig } from 'wagmi';\nimport { useFlowstackOptional } from '../context/FlowstackProvider';\nimport type { UseWalletAuthReturn } from './types';\n\nexport function useWalletAuth(): UseWalletAuthReturn {\n const wagmiConfig = useConfig();\n const flowstack = useFlowstackOptional();\n const [isConnected, setIsConnected] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [address, setAddress] = useState<string | null>(null);\n const [isEmbeddedWallet, setIsEmbeddedWallet] = useState(false);\n const [authMethod, setAuthMethod] = useState<'privy' | 'siwe' | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const baseUrl = flowstack?.config?.baseUrl || 'https://sage-api.flowstack.fun';\n\n // Check if existing credentials have a wallet_address\n useEffect(() => {\n if (flowstack?.credentials?.apiKey) {\n try {\n const parts = flowstack.credentials.apiKey.split('.');\n if (parts.length < 2) return;\n const payload = JSON.parse(atob(parts[1]));\n if (payload.wallet_address) {\n setAddress(payload.wallet_address);\n setIsConnected(true);\n // Can't determine method from JWT alone, but it's authenticated\n }\n } catch {\n // Not a JWT or can't decode — ignore\n }\n }\n }, [flowstack?.credentials]);\n\n const loginWithPrivy = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Dynamic import to avoid bundling Privy when not used\n const { usePrivy } = await import('@privy-io/react-auth');\n // Note: this hook must be called from within PrivyProvider context.\n // The actual Privy login is triggered via PrivyProvider's login method.\n // This function is called after Privy auth completes with a token.\n throw new Error(\n 'loginWithPrivy must be called from a component wrapped in WalletProvider. ' +\n 'Use the LoginButton component instead.'\n );\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Privy login failed');\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const loginWithSIWE = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Dynamic import wagmi core actions\n const { getAccount, signMessage } = await import('@wagmi/core');\n\n const account = getAccount(wagmiConfig);\n if (!account.address) {\n throw new Error('No wallet connected. Connect MetaMask first.');\n }\n\n // 1. Get nonce from backend\n const nonceResp = await fetch(`${baseUrl}/auth/wallet/nonce`);\n if (!nonceResp.ok) throw new Error('Failed to get SIWE nonce');\n const { nonce } = await nonceResp.json();\n\n // 2. Construct SIWE message\n const domain = typeof window !== 'undefined' ? window.location.host : 'localhost';\n const origin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n // Use the actual chain the wallet is connected on — never hardcode.\n // Hardcoding 421614 (Arbitrum Sepolia testnet) caused MetaMask to reject\n // signatures from mainnet wallets (chain 42161).\n const chainId = account.chainId ?? wagmiConfig.chains?.[0]?.id ?? 42161;\n const siweMessage = [\n `${domain} wants you to sign in with your Ethereum account:`,\n account.address,\n '',\n 'Sign in to Casino with INFER tokens',\n '',\n `URI: ${origin}`,\n `Version: 1`,\n `Chain ID: ${chainId}`,\n `Nonce: ${nonce}`,\n `Issued At: ${new Date().toISOString()}`,\n ].join('\\n');\n\n // 3. Sign with wallet\n const signature = await signMessage(wagmiConfig, { message: siweMessage });\n\n // 4. Verify with backend\n const verifyResp = await fetch(`${baseUrl}/auth/wallet/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ message: siweMessage, signature }),\n });\n\n if (!verifyResp.ok) {\n const err = await verifyResp.json();\n throw new Error(err.detail || 'SIWE verification failed');\n }\n\n const data = await verifyResp.json();\n\n // 5. Store credentials via FlowstackProvider\n if (flowstack?.setCredentials) {\n flowstack.setCredentials({\n apiKey: data.session_token,\n tenantId: data.tenant_id,\n userId: data.user_id,\n expiresAt: data.expires_at,\n });\n }\n\n setAddress(data.wallet_address);\n setIsConnected(true);\n setIsEmbeddedWallet(false);\n setAuthMethod('siwe');\n\n } catch (e) {\n setError(e instanceof Error ? e.message : 'SIWE login failed');\n } finally {\n setIsLoading(false);\n }\n }, [baseUrl, flowstack]);\n\n const login = useCallback(async (method: 'privy' | 'wallet' = 'privy') => {\n if (method === 'privy') {\n await loginWithPrivy();\n } else {\n await loginWithSIWE();\n }\n }, [loginWithPrivy, loginWithSIWE]);\n\n const logout = useCallback(() => {\n setIsConnected(false);\n setAddress(null);\n setAuthMethod(null);\n setIsEmbeddedWallet(false);\n setError(null);\n flowstack?.logout?.();\n }, [flowstack]);\n\n return {\n isConnected,\n isLoading,\n address,\n isEmbeddedWallet,\n authMethod,\n error,\n login,\n logout,\n };\n}\n","/**\n * useInferBalance — polls the backend for INFER token balance.\n *\n * Uses GET /billing/infer/balance which reads on-chain balance\n * and subtracts active holds.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { useFlowstackOptional } from '../context/FlowstackProvider';\nimport type { InferBalance, UseInferBalanceReturn } from './types';\n\nconst POLL_INTERVAL_MS = 15_000; // 15 seconds\n\nexport function useInferBalance(): UseInferBalanceReturn {\n const flowstack = useFlowstackOptional();\n const [data, setData] = useState<InferBalance | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const baseUrl = flowstack?.config?.baseUrl || 'https://sage-api.flowstack.fun';\n const apiKey = flowstack?.credentials?.apiKey;\n const tenantId = flowstack?.credentials?.tenantId;\n\n const fetchBalance = useCallback(async () => {\n if (!apiKey) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const resp = await fetch(`${baseUrl}/billing/infer/balance`, {\n headers: {\n 'Authorization': `Bearer ${apiKey}`,\n 'X-Tenant-ID': tenantId || '',\n },\n });\n\n if (resp.status === 400) {\n // No wallet connected — not an error, just no balance\n setData(null);\n return;\n }\n\n if (!resp.ok) {\n throw new Error(`Balance check failed: ${resp.status}`);\n }\n\n const json = await resp.json();\n setData({\n balanceWei: json.balance_wei,\n heldWei: json.held_wei,\n availableWei: json.available_wei,\n balance: json.infer_balance,\n available: json.infer_available,\n queryCredits: json.query_credits,\n });\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to fetch balance');\n } finally {\n setIsLoading(false);\n }\n }, [apiKey, baseUrl, tenantId]);\n\n // Initial fetch + polling\n useEffect(() => {\n fetchBalance();\n\n intervalRef.current = setInterval(fetchBalance, POLL_INTERVAL_MS);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [fetchBalance]);\n\n return { data, isLoading, error, refetch: fetchBalance };\n}\n","/**\n * useAgentBalance — polls the backend for AGENT token balance.\n *\n * Uses GET /billing/agent/balance which reads on-chain AGENT balance\n * from the AgentPayment contract and subtracts active holds.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { useFlowstackOptional } from '../context/FlowstackProvider';\nimport type { AgentBalance, UseAgentBalanceReturn } from './types';\n\nconst POLL_INTERVAL_MS = 15_000; // 15 seconds\n\nexport function useAgentBalance(): UseAgentBalanceReturn {\n const flowstack = useFlowstackOptional();\n const [data, setData] = useState<AgentBalance | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const baseUrl = flowstack?.config?.baseUrl || 'https://sage-api.flowstack.fun';\n const apiKey = flowstack?.credentials?.apiKey;\n const tenantId = flowstack?.credentials?.tenantId;\n\n const fetchBalance = useCallback(async () => {\n if (!apiKey) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const resp = await fetch(`${baseUrl}/billing/agent/balance`, {\n headers: {\n 'Authorization': `Bearer ${apiKey}`,\n 'X-Tenant-ID': tenantId || '',\n },\n });\n\n if (resp.status === 400) {\n // No wallet connected — not an error, just no balance\n setData(null);\n return;\n }\n\n if (!resp.ok) {\n throw new Error(`AGENT balance check failed: ${resp.status}`);\n }\n\n const json = await resp.json();\n setData({\n balanceWei: json.balance_wei,\n heldWei: json.held_wei,\n availableWei: json.available_wei,\n balance: json.agent_balance,\n available: json.agent_available,\n buildCredits: json.build_credits,\n });\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to fetch AGENT balance');\n } finally {\n setIsLoading(false);\n }\n }, [apiKey, baseUrl, tenantId]);\n\n // Initial fetch + polling\n useEffect(() => {\n fetchBalance();\n\n intervalRef.current = setInterval(fetchBalance, POLL_INTERVAL_MS);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [fetchBalance]);\n\n return { data, isLoading, error, refetch: fetchBalance };\n}\n","/**\n * useDeposit — approve + deposit INFER tokens into InferencePayment contract.\n *\n * For crypto-native users who already have INFER tokens.\n * Handles the two-step ERC-20 flow: approve → deposit.\n */\n\nimport { useState, useCallback } from 'react';\nimport { useConfig } from 'wagmi';\nimport type { UseDepositReturn } from './types';\n\n// InferencePayment contract addresses by chain\nconst CONTRACTS: Record<string, { payment: string; token: string }> = {\n 'arbitrum-sepolia': {\n payment: '0x879101330bcB251CBB775559419cB6389346ee8c',\n token: '0xD31f5765F92D7D3fF0463eeaa14C157d423aF9E1',\n },\n 'arbitrum': {\n payment: '0x879101330bcB251CBB775559419cB6389346ee8c',\n token: '0xD31f5765F92D7D3fF0463eeaa14C157d423aF9E1',\n },\n};\n\nconst ERC20_APPROVE_ABI = [\n {\n name: 'approve',\n type: 'function',\n inputs: [\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n] as const;\n\nconst DEPOSIT_ABI = [\n {\n name: 'deposit',\n type: 'function',\n inputs: [{ name: 'amount', type: 'uint256' }],\n outputs: [],\n stateMutability: 'nonpayable',\n },\n] as const;\n\nexport function useDeposit(chain: string = 'arbitrum-sepolia'): UseDepositReturn {\n const wagmiConfig = useConfig();\n const [isDepositing, setIsDepositing] = useState(false);\n const [txHash, setTxHash] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const contracts = CONTRACTS[chain] || CONTRACTS['arbitrum-sepolia'];\n\n const deposit = useCallback(async (inferAmount: number): Promise<string | null> => {\n setIsDepositing(true);\n setError(null);\n setTxHash(null);\n\n try {\n // Dynamic import viem + wagmi\n const { writeContract, waitForTransactionReceipt } = await import('@wagmi/core');\n const { parseUnits } = await import('viem');\n\n const amountWei = parseUnits(inferAmount.toString(), 18);\n\n // Step 1: Approve InferencePayment to spend INFER\n const approveTx = await writeContract(wagmiConfig, {\n address: contracts.token as `0x${string}`,\n abi: ERC20_APPROVE_ABI,\n functionName: 'approve',\n args: [contracts.payment as `0x${string}`, amountWei],\n });\n\n await waitForTransactionReceipt(wagmiConfig, { hash: approveTx });\n\n // Step 2: Deposit into InferencePayment\n const depositTx = await writeContract(wagmiConfig, {\n address: contracts.payment as `0x${string}`,\n abi: DEPOSIT_ABI,\n functionName: 'deposit',\n args: [amountWei],\n });\n\n await waitForTransactionReceipt(wagmiConfig, { hash: depositTx });\n\n setTxHash(depositTx);\n return depositTx;\n\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Deposit failed';\n setError(msg);\n return null;\n } finally {\n setIsDepositing(false);\n }\n }, [contracts]);\n\n return { deposit, isDepositing, txHash, error };\n}\n","/**\n * useBuyInfer — opens fiat on-ramp widget (MoonPay/Transak).\n *\n * Handles: credit card → INFER → auto-deposit. User never touches crypto.\n * The on-ramp provider delivers INFER to the user's embedded wallet,\n * then the SDK auto-deposits into InferencePayment.\n */\n\nimport { useState, useCallback } from 'react';\nimport type { UseBuyInferReturn } from './types';\n\ninterface BuyInferOptions {\n /** MoonPay or Transak API key */\n apiKey?: string;\n /** sandbox or production */\n environment?: 'sandbox' | 'production';\n /** Wallet address to receive INFER */\n walletAddress?: string;\n}\n\nexport function useBuyInfer(options: BuyInferOptions = {}): UseBuyInferReturn {\n const [isBuying, setIsBuying] = useState(false);\n const [status, setStatus] = useState<'idle' | 'pending' | 'completed' | 'failed'>('idle');\n const [error, setError] = useState<string | null>(null);\n\n const buy = useCallback((amount?: number) => {\n if (!options.apiKey) {\n setError('On-ramp not configured. Set onRampConfig in FlowstackConfig.');\n return;\n }\n\n if (!options.walletAddress) {\n setError('No wallet address. Sign up first.');\n return;\n }\n\n setIsBuying(true);\n setStatus('pending');\n setError(null);\n\n // MoonPay widget URL\n const baseUrl = options.environment === 'production'\n ? 'https://buy.moonpay.com'\n : 'https://buy-sandbox.moonpay.com';\n\n const params = new URLSearchParams({\n apiKey: options.apiKey,\n currencyCode: 'infer_arbitrum', // MoonPay currency code for INFER on Arbitrum\n walletAddress: options.walletAddress,\n ...(amount ? { baseCurrencyAmount: amount.toString() } : {}),\n colorCode: '#d4a843', // Casino amber\n showWalletAddressForm: 'false',\n });\n\n const widgetUrl = `${baseUrl}?${params.toString()}`;\n\n // Open in popup or redirect\n const popup = window.open(\n widgetUrl,\n 'moonpay',\n 'width=500,height=700,left=200,top=100'\n );\n\n if (!popup) {\n // Fallback: redirect\n window.location.href = widgetUrl;\n return;\n }\n\n // Poll for popup close (MoonPay doesn't have reliable postMessage)\n const pollInterval = setInterval(() => {\n if (popup.closed) {\n clearInterval(pollInterval);\n setIsBuying(false);\n // We can't know if purchase succeeded from popup close alone.\n // Balance polling (useInferBalance) will detect the deposit.\n setStatus('completed');\n }\n }, 1000);\n\n }, [options]);\n\n return { buy, isBuying, status, error };\n}\n","/**\n * useAppAccess — checks whether the authenticated end-user has access to a\n * monetized built app, and provides a checkout function to unlock it.\n *\n * Polls GET /billing/app-access/status every 60 seconds.\n * On `checkout()` call, opens a Stripe Checkout session for one-time purchase.\n *\n * Usage:\n * const { hasAccess, queriesRemaining, checkout } = useAppAccess(config.appScope);\n * if (!hasAccess) return <AppPaywall siteId={config.appScope} ... />;\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { useFlowstackOptional } from '../context/FlowstackProvider';\nimport type { UseAppAccessReturn } from './types';\n\nconst POLL_INTERVAL_MS = 60_000; // 60 seconds\n\nexport function useAppAccess(\n siteId: string,\n opts?: { builderTenantId?: string }\n): UseAppAccessReturn {\n const flowstack = useFlowstackOptional();\n const [hasAccess, setHasAccess] = useState(true); // optimistic until first check\n const [queriesUsed, setQueriesUsed] = useState(0);\n const [queriesRemaining, setQueriesRemaining] = useState<number | null>(null);\n const [paymentMode, setPaymentMode] = useState<'stripe' | 'agent' | 'both' | null>(null);\n const [unlockPriceCents, setUnlockPriceCents] = useState<number | null>(null);\n const [unlockPriceLabel, setUnlockPriceLabel] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const baseUrl = flowstack?.config?.baseUrl || 'https://sage-api.flowstack.fun';\n const apiKey = flowstack?.credentials?.apiKey;\n\n const fetchStatus = useCallback(async () => {\n if (!siteId || !apiKey) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const params = new URLSearchParams({ site_id: siteId });\n if (opts?.builderTenantId) params.set('builder_tenant_id', opts.builderTenantId);\n\n const resp = await fetch(`${baseUrl}/billing/app-access/status?${params}`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n\n if (!resp.ok) {\n // Non-200: fail open rather than blocking the end-user\n setHasAccess(true);\n return;\n }\n\n const data = await resp.json();\n setHasAccess(data.has_access ?? true);\n setQueriesUsed(data.queries_used ?? 0);\n setQueriesRemaining(data.queries_remaining ?? null);\n setPaymentMode(data.payment_mode ?? null);\n setUnlockPriceCents(data.unlock_price_cents ?? null);\n setUnlockPriceLabel(data.unlock_price_label ?? null);\n } catch (err: any) {\n setError(err.message || 'Failed to check access status');\n // Fail open\n setHasAccess(true);\n } finally {\n setIsLoading(false);\n }\n }, [siteId, apiKey, baseUrl, opts?.builderTenantId]);\n\n // Initial fetch + polling\n useEffect(() => {\n if (!siteId || !apiKey) return;\n fetchStatus();\n intervalRef.current = setInterval(fetchStatus, POLL_INTERVAL_MS);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [fetchStatus, siteId, apiKey]);\n\n const checkout = useCallback(\n async (checkoutOpts?: { successUrl?: string; cancelUrl?: string }) => {\n if (!apiKey || !siteId) return;\n\n try {\n const successUrl =\n checkoutOpts?.successUrl ||\n (typeof window !== 'undefined' ? window.location.href : '');\n const cancelUrl =\n checkoutOpts?.cancelUrl ||\n (typeof window !== 'undefined' ? window.location.href : '');\n\n const resp = await fetch(`${baseUrl}/billing/app-access/checkout`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n site_id: siteId,\n success_url: successUrl,\n cancel_url: cancelUrl,\n }),\n });\n\n if (!resp.ok) {\n const body = await resp.json().catch(() => ({}));\n throw new Error(body.detail || `Checkout failed: ${resp.status}`);\n }\n\n const data = await resp.json();\n if (data.url && typeof window !== 'undefined') {\n window.location.href = data.url;\n }\n } catch (err: any) {\n setError(err.message || 'Checkout failed');\n }\n },\n [apiKey, siteId, baseUrl]\n );\n\n return {\n hasAccess,\n queriesUsed,\n queriesRemaining,\n paymentMode,\n unlockPriceCents,\n unlockPriceLabel,\n isLoading,\n error,\n checkout,\n refetch: fetchStatus,\n };\n}\n","/**\n * WalletProvider — wraps Privy + wagmi + react-query in the correct hierarchy.\n *\n * Provider order (per Privy docs):\n * PrivyProvider > QueryClientProvider > WagmiProvider (@privy-io/wagmi)\n *\n * When `privyAppId` is omitted the provider renders children directly\n * (SIWE-only mode). Hooks that depend on Privy will be unavailable.\n */\n\n'use client';\n\nimport React, { createContext, useContext, useMemo, useState } from 'react';\nimport { PrivyProvider } from '@privy-io/react-auth';\nimport { WagmiProvider, createConfig } from '@privy-io/wagmi';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { arbitrum, arbitrumSepolia } from 'viem/chains';\nimport { http, type Transport, injected } from 'wagmi';\nimport type { WalletProviderProps } from './types';\n\ndeclare global {\n interface Window {\n __wagmiConfig?: ReturnType<typeof createConfig>;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Context — lets child hooks know if Privy is available\n// ---------------------------------------------------------------------------\n\ninterface WalletContextValue {\n /** true when PrivyProvider is in the tree */\n privyReady: boolean;\n /** Casino API base URL passed through from props */\n baseUrl: string;\n}\n\nconst WalletCtx = createContext<WalletContextValue>({\n privyReady: false,\n baseUrl: 'https://sage-api.flowstack.fun',\n});\n\nexport const useWalletContext = () => useContext(WalletCtx);\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function WalletProvider({\n children,\n privyAppId,\n chain = 'arbitrum',\n baseUrl = 'https://sage-api.flowstack.fun',\n walletConnectProjectId,\n}: WalletProviderProps) {\n const [queryClient] = useState(() => new QueryClient());\n const selectedChain = chain === 'arbitrum-sepolia' ? arbitrumSepolia : arbitrum;\n\n const wagmiConfig = useMemo(() => {\n const config = createConfig({\n chains: [selectedChain],\n transports: { [selectedChain.id]: http() } as Record<number, Transport>,\n // Explicit connectors so wagmi always has something to work with.\n // Without these, useConnect().connectors is empty → connectAsync({ connector: undefined })\n // → \"undefined is not an object (evaluating 'n.uid')\" crash.\n connectors: [\n injected(), // MetaMask, Rabby, Brave, any browser extension wallet\n ],\n });\n // Expose wagmi config for imperative access (used by WalletLinkButton)\n if (typeof window !== 'undefined') {\n window.__wagmiConfig = config;\n }\n return config;\n }, [selectedChain]);\n\n // No Privy app ID — render without Privy (SIWE-only mode)\n if (!privyAppId) {\n return (\n <WalletCtx.Provider value={{ privyReady: false, baseUrl }}>\n <QueryClientProvider client={queryClient}>\n {children}\n </QueryClientProvider>\n </WalletCtx.Provider>\n );\n }\n\n return (\n <PrivyProvider\n appId={privyAppId}\n config={{\n // Embedded signer — the EOA keypair that controls the smart wallet.\n // Must be created for all users so the smart wallet has a signer.\n // NOTE: @privy-io/react-auth v3 nests createOnLogin per chain\n // (embeddedWallets.ethereum.createOnLogin). The old v2 flat shape\n // (embeddedWallets.createOnLogin) is silently ignored on v3, so NO\n // wallet gets created on login — the user authenticates but has no\n // wallet/address. Use the v3 shape.\n embeddedWallets: {\n ethereum: {\n createOnLogin: 'all-users',\n },\n showWalletUIs: false,\n },\n // EVM smart wallet (ERC-4337) — Kernel/ZeroDev implementation.\n // Must be enabled in the Privy dashboard (Smart wallets → Kernel → Arbitrum).\n // The smart wallet address is what Privy returns as type='smart_wallet'\n // in linked_accounts, and is the canonical address for the token economy.\n // @ts-ignore — 'smart_wallets' may not be in older @privy-io/react-auth types\n smart_wallets: {\n type: 'kernel',\n },\n loginMethods: ['email', 'google', 'apple', 'twitter', 'github', 'linkedin', 'spotify', 'wallet'],\n appearance: { theme: 'dark' },\n defaultChain: selectedChain,\n ...(walletConnectProjectId ? { walletConnectCloudProjectId: walletConnectProjectId } : {}),\n }}\n >\n <QueryClientProvider client={queryClient}>\n <WagmiProvider config={wagmiConfig}>\n <WalletCtx.Provider value={{ privyReady: true, baseUrl }}>\n {children}\n </WalletCtx.Provider>\n </WagmiProvider>\n </QueryClientProvider>\n </PrivyProvider>\n );\n}\n","/**\n * LoginButton — \"Sign up with Google\" / \"Connect Wallet\" toggle.\n *\n * Default: Privy (email/Google) signup. Toggle to external wallet (MetaMask).\n */\n\n'use client';\n\nimport React, { useState, useCallback } from 'react';\n\ninterface LoginButtonProps {\n /** Callback after successful auth */\n onSuccess?: (walletAddress: string) => void;\n /** Callback on auth error */\n onError?: (error: string) => void;\n /** Show wallet connect option */\n showWalletOption?: boolean;\n /** CSS class name */\n className?: string;\n}\n\nexport function LoginButton({\n onSuccess,\n onError,\n showWalletOption = true,\n className,\n}: LoginButtonProps) {\n const [mode, setMode] = useState<'signup' | 'wallet'>('signup');\n const [isLoading, setIsLoading] = useState(false);\n\n const handlePrivyLogin = useCallback(async () => {\n setIsLoading(true);\n try {\n // Privy login is handled by PrivyProvider's login method\n // This component should be used inside WalletProvider which wraps PrivyProvider\n const { usePrivy } = await import('@privy-io/react-auth');\n // Note: hooks can't be dynamically called. This is a placeholder —\n // the actual implementation uses PrivyProvider's context.\n onError?.('Use this component inside WalletProvider');\n } catch (e) {\n onError?.(e instanceof Error ? e.message : 'Login failed');\n } finally {\n setIsLoading(false);\n }\n }, [onSuccess, onError]);\n\n const handleWalletConnect = useCallback(async () => {\n setIsLoading(true);\n try {\n // This triggers wagmi's connect flow\n onError?.('Wallet connect requires WalletProvider context');\n } catch (e) {\n onError?.(e instanceof Error ? e.message : 'Wallet connect failed');\n } finally {\n setIsLoading(false);\n }\n }, [onError]);\n\n return (\n <div className={className}>\n {mode === 'signup' ? (\n <button\n onClick={handlePrivyLogin}\n disabled={isLoading}\n style={{\n padding: '12px 24px',\n borderRadius: '8px',\n border: 'none',\n backgroundColor: '#d4a843',\n color: '#0a0a0a',\n fontWeight: 600,\n cursor: isLoading ? 'not-allowed' : 'pointer',\n opacity: isLoading ? 0.7 : 1,\n width: '100%',\n }}\n >\n {isLoading ? 'Signing in...' : 'Sign up with Google'}\n </button>\n ) : (\n <button\n onClick={handleWalletConnect}\n disabled={isLoading}\n style={{\n padding: '12px 24px',\n borderRadius: '8px',\n border: '1px solid #c4bdb3',\n backgroundColor: 'transparent',\n color: '#c4bdb3',\n fontWeight: 600,\n cursor: isLoading ? 'not-allowed' : 'pointer',\n opacity: isLoading ? 0.7 : 1,\n width: '100%',\n }}\n >\n {isLoading ? 'Connecting...' : 'Connect Wallet'}\n </button>\n )}\n\n {showWalletOption && (\n <button\n onClick={() => setMode(mode === 'signup' ? 'wallet' : 'signup')}\n style={{\n marginTop: '8px',\n padding: '8px',\n background: 'none',\n border: 'none',\n color: '#c4bdb3',\n fontSize: '13px',\n cursor: 'pointer',\n width: '100%',\n textAlign: 'center',\n }}\n >\n {mode === 'signup'\n ? 'Already have INFER? Connect wallet'\n : 'Sign up with email instead'}\n </button>\n )}\n </div>\n );\n}\n","/**\n * InferBalanceBadge — shows INFER balance in a compact badge.\n *\n * Displays query credits remaining. Shows \"Buy More\" when low.\n */\n\n'use client';\n\nimport React from 'react';\nimport { useInferBalance } from './useInferBalance';\n\ninterface InferBalanceBadgeProps {\n /** Threshold to show \"Buy More\" warning */\n lowBalanceThreshold?: number;\n /** Callback when \"Buy More\" is clicked */\n onBuyMore?: () => void;\n /** CSS class name */\n className?: string;\n}\n\nexport function InferBalanceBadge({\n lowBalanceThreshold = 5,\n onBuyMore,\n className,\n}: InferBalanceBadgeProps) {\n const { data, isLoading } = useInferBalance();\n\n if (isLoading && !data) {\n return (\n <span className={className} style={{ ...badgeStyle, opacity: 0.5 }}>\n ...\n </span>\n );\n }\n\n if (!data) return null;\n\n const isLow = data.queryCredits <= lowBalanceThreshold;\n\n return (\n <span\n className={className}\n style={{\n ...badgeStyle,\n backgroundColor: isLow ? '#3a1c1c' : '#1a1a1a',\n borderColor: isLow ? '#d44343' : '#333',\n }}\n >\n <span style={{ color: isLow ? '#d44343' : '#d4a843', fontWeight: 600 }}>\n {data.queryCredits}\n </span>\n <span style={{ color: '#c4bdb3', marginLeft: '4px', fontSize: '12px' }}>\n queries\n </span>\n {isLow && onBuyMore && (\n <button\n onClick={onBuyMore}\n style={{\n marginLeft: '8px',\n padding: '2px 8px',\n borderRadius: '4px',\n border: '1px solid #d4a843',\n backgroundColor: 'transparent',\n color: '#d4a843',\n fontSize: '11px',\n cursor: 'pointer',\n }}\n >\n Buy More\n </button>\n )}\n </span>\n );\n}\n\nconst badgeStyle: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n padding: '4px 12px',\n borderRadius: '20px',\n border: '1px solid #333',\n fontSize: '13px',\n fontFamily: 'var(--font-body, Inter, sans-serif)',\n};\n","/**\n * AgentBalanceBadge — shows AGENT token balance in a compact badge.\n *\n * Displays build credits remaining. Shows \"Buy More\" when low.\n */\n\n'use client';\n\nimport React from 'react';\nimport { useAgentBalance } from './useAgentBalance';\n\ninterface AgentBalanceBadgeProps {\n /** Threshold to show \"Buy More\" warning */\n lowBalanceThreshold?: number;\n /** Callback when \"Buy More\" is clicked */\n onBuyMore?: () => void;\n /** CSS class name */\n className?: string;\n}\n\nexport function AgentBalanceBadge({\n lowBalanceThreshold = 2,\n onBuyMore,\n className,\n}: AgentBalanceBadgeProps) {\n const { data, isLoading } = useAgentBalance();\n\n if (isLoading && !data) {\n return (\n <span className={className} style={{ ...badgeStyle, opacity: 0.5 }}>\n ...\n </span>\n );\n }\n\n if (!data) return null;\n\n const isLow = data.buildCredits <= lowBalanceThreshold;\n\n return (\n <span\n className={className}\n style={{\n ...badgeStyle,\n backgroundColor: isLow ? '#3a1c1c' : '#1a1a1a',\n borderColor: isLow ? '#d44343' : '#333',\n }}\n >\n <span style={{ color: isLow ? '#d44343' : '#43d4a8', fontWeight: 600 }}>\n {data.buildCredits}\n </span>\n <span style={{ color: '#c4bdb3', marginLeft: '4px', fontSize: '12px' }}>\n builds\n </span>\n {isLow && onBuyMore && (\n <button\n onClick={onBuyMore}\n style={{\n marginLeft: '8px',\n padding: '2px 8px',\n borderRadius: '4px',\n border: '1px solid #43d4a8',\n backgroundColor: 'transparent',\n color: '#43d4a8',\n fontSize: '11px',\n cursor: 'pointer',\n }}\n >\n Buy More\n </button>\n )}\n </span>\n );\n}\n\nconst badgeStyle: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n padding: '4px 12px',\n borderRadius: '20px',\n border: '1px solid #333',\n fontSize: '13px',\n fontFamily: 'var(--font-body, Inter, sans-serif)',\n};\n","/**\n * NeedsAgent — gating component for AGENT-token-gated features in built apps.\n *\n * Checks the user's AGENT balance. If sufficient, renders children and calls\n * onProceed when the user activates the gated action. If insufficient, renders\n * a \"Get AGENT\" CTA that deep-links to the OIF /buy page with returnTo + need\n * params so the user lands back in the app after purchasing.\n *\n * Usage:\n * <NeedsAgent amountNeeded={2} onProceed={generateAlbumArt} returnUrl={window.location.href}>\n * <p>Generate a new design for 2 AGENT</p>\n * </NeedsAgent>\n *\n * The user never sees a seed phrase — Privy handles wallet creation on OIF.\n * No auth setup required in the built app: the component works for anonymous users\n * (balance will read 0) and authenticated wallet users alike.\n */\n\nimport React from 'react';\nimport { useAgentBalance } from './useAgentBalance';\nimport type { NeedsAgentProps } from './types';\n\nconst DEFAULT_OIF_BASE = 'https://openinferencefoundation.org';\n\nexport function NeedsAgent({\n amountNeeded,\n onProceed,\n returnUrl,\n children,\n oifBaseUrl = DEFAULT_OIF_BASE,\n}: NeedsAgentProps): React.ReactElement {\n const { data, isLoading } = useAgentBalance();\n const available = data?.available ?? 0;\n const hasSufficient = available >= amountNeeded;\n\n const handleGetAgent = () => {\n const base = oifBaseUrl.replace(/\\/$/, '');\n const returnTo = returnUrl ?? (typeof window !== 'undefined' ? window.location.href : '');\n const url = `${base}/buy?returnTo=${encodeURIComponent(returnTo)}&need=${amountNeeded}`;\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n };\n\n if (isLoading) {\n return (\n <div style={{ opacity: 0.6, pointerEvents: 'none' }}>\n {children}\n </div>\n );\n }\n\n if (hasSufficient) {\n return (\n <div onClick={onProceed} style={{ cursor: 'pointer' }}>\n {children}\n </div>\n );\n }\n\n return (\n <div>\n {children && <div style={{ opacity: 0.5, pointerEvents: 'none' }}>{children}</div>}\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 6 }}>\n <p style={{ margin: 0, fontSize: '0.85em', color: '#888' }}>\n You need {amountNeeded} AGENT to use this feature.\n {data !== null && ` You have ${available.toFixed(2)}.`}\n </p>\n <button\n onClick={handleGetAgent}\n style={{\n background: '#6366f1',\n color: '#fff',\n border: 'none',\n borderRadius: 6,\n padding: '6px 14px',\n fontSize: '0.875em',\n fontWeight: 600,\n cursor: 'pointer',\n }}\n >\n Get AGENT →\n </button>\n </div>\n </div>\n );\n}\n","/**\n * PaymentRequired — shown when user's INFER balance is insufficient (402).\n *\n * Displays current balance and a \"Buy INFER\" CTA.\n */\n\n'use client';\n\nimport React from 'react';\n\ninterface PaymentRequiredProps {\n /** Current balance in query credits */\n queryCredits?: number;\n /** INFER tokens needed per query */\n inferPerQuery?: number;\n /** Callback to open buy flow */\n onBuy?: () => void;\n /** Callback to dismiss */\n onDismiss?: () => void;\n /** CSS class name */\n className?: string;\n}\n\nexport function PaymentRequired({\n queryCredits = 0,\n inferPerQuery = 50,\n onBuy,\n onDismiss,\n className,\n}: PaymentRequiredProps) {\n return (\n <div className={className} style={containerStyle}>\n <div style={{ fontSize: '24px', marginBottom: '8px' }}>0 queries remaining</div>\n <p style={{ color: '#c4bdb3', marginBottom: '16px', lineHeight: 1.5 }}>\n Each query costs {inferPerQuery} INFER. Buy more to continue using Casino.\n </p>\n\n <button onClick={onBuy} style={buyButtonStyle}>\n Buy INFER\n </button>\n\n <p style={{ color: '#666', fontSize: '12px', marginTop: '12px' }}>\n Pay with credit card. No crypto knowledge needed.\n </p>\n\n {onDismiss && (\n <button onClick={onDismiss} style={dismissStyle}>\n Maybe later\n </button>\n )}\n </div>\n );\n}\n\nconst containerStyle: React.CSSProperties = {\n textAlign: 'center',\n padding: '32px 24px',\n backgroundColor: '#111111',\n borderRadius: '12px',\n border: '1px solid #333',\n maxWidth: '400px',\n margin: '0 auto',\n fontFamily: 'var(--font-body, Inter, sans-serif)',\n color: '#f5f0e8',\n};\n\nconst buyButtonStyle: React.CSSProperties = {\n padding: '14px 32px',\n borderRadius: '8px',\n border: 'none',\n backgroundColor: '#d4a843',\n color: '#0a0a0a',\n fontWeight: 700,\n fontSize: '16px',\n cursor: 'pointer',\n width: '100%',\n};\n\nconst dismissStyle: React.CSSProperties = {\n marginTop: '8px',\n padding: '8px',\n background: 'none',\n border: 'none',\n color: '#666',\n fontSize: '13px',\n cursor: 'pointer',\n};\n","/**\n * BuyInferModal — fiat on-ramp widget for purchasing INFER with a credit card.\n *\n * Wraps MoonPay/Transak with Casino-branded pricing tiers.\n */\n\n'use client';\n\nimport React, { useState } from 'react';\nimport { useBuyInfer } from './useBuyInfer';\n\ninterface BuyInferModalProps {\n /** Whether the modal is open */\n isOpen: boolean;\n /** Close callback */\n onClose: () => void;\n /** MoonPay/Transak API key */\n apiKey: string;\n /** sandbox or production */\n environment?: 'sandbox' | 'production';\n /** User's wallet address */\n walletAddress: string;\n /** INFER per query (for pricing display) */\n inferPerQuery?: number;\n /** CSS class name */\n className?: string;\n}\n\nconst TIERS = [\n { queries: 100, infer: 5000, price: 5 },\n { queries: 500, infer: 25000, price: 25 },\n { queries: 2000, infer: 100000, price: 95 },\n];\n\nexport function BuyInferModal({\n isOpen,\n onClose,\n apiKey,\n environment = 'sandbox',\n walletAddress,\n inferPerQuery = 50,\n className,\n}: BuyInferModalProps) {\n const { buy, isBuying, status } = useBuyInfer({\n apiKey,\n environment,\n walletAddress,\n });\n const [selectedTier, setSelectedTier] = useState(1); // Default: 500 queries\n\n if (!isOpen) return null;\n\n return (\n <div style={overlayStyle} onClick={onClose}>\n <div\n className={className}\n style={modalStyle}\n onClick={(e) => e.stopPropagation()}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '24px' }}>\n <h2 style={{ margin: 0, fontSize: '20px', color: '#f5f0e8' }}>Buy Query Credits</h2>\n <button onClick={onClose} style={closeStyle}>&times;</button>\n </div>\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', marginBottom: '24px' }}>\n {TIERS.map((tier, i) => (\n <button\n key={tier.queries}\n onClick={() => setSelectedTier(i)}\n style={{\n ...tierStyle,\n borderColor: selectedTier === i ? '#d4a843' : '#333',\n backgroundColor: selectedTier === i ? '#1a1a0a' : '#1a1a1a',\n }}\n >\n <div style={{ fontWeight: 600, fontSize: '16px', color: '#f5f0e8' }}>\n {tier.queries} queries\n </div>\n <div style={{ color: '#d4a843', fontWeight: 700, fontSize: '18px' }}>\n ${tier.price}\n </div>\n </button>\n ))}\n </div>\n\n <button\n onClick={() => buy(TIERS[selectedTier].price)}\n disabled={isBuying}\n style={{\n ...buyStyle,\n opacity: isBuying ? 0.7 : 1,\n cursor: isBuying ? 'not-allowed' : 'pointer',\n }}\n >\n {isBuying ? 'Processing...' : `Buy ${TIERS[selectedTier].queries} queries — $${TIERS[selectedTier].price}`}\n </button>\n\n <p style={{ color: '#666', fontSize: '12px', textAlign: 'center', marginTop: '12px' }}>\n Powered by MoonPay. Visa, Mastercard, Apple Pay accepted.\n </p>\n </div>\n </div>\n );\n}\n\nconst overlayStyle: React.CSSProperties = {\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.7)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 9999,\n};\n\nconst modalStyle: React.CSSProperties = {\n backgroundColor: '#111111',\n borderRadius: '16px',\n border: '1px solid #333',\n padding: '24px',\n width: '100%',\n maxWidth: '420px',\n fontFamily: 'var(--font-body, Inter, sans-serif)',\n};\n\nconst closeStyle: React.CSSProperties = {\n background: 'none',\n border: 'none',\n color: '#666',\n fontSize: '24px',\n cursor: 'pointer',\n padding: '4px 8px',\n};\n\nconst tierStyle: React.CSSProperties = {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '16px 20px',\n borderRadius: '12px',\n border: '1px solid #333',\n cursor: 'pointer',\n transition: 'border-color 0.15s',\n};\n\nconst buyStyle: React.CSSProperties = {\n padding: '14px 32px',\n borderRadius: '8px',\n border: 'none',\n backgroundColor: '#d4a843',\n color: '#0a0a0a',\n fontWeight: 700,\n fontSize: '16px',\n width: '100%',\n};\n","/**\n * AppPaywall — access gate for monetized built apps (P0-121).\n *\n * Renders children when the end-user has access. When `hasAccess` is false,\n * renders a paywall overlay with the unlock CTA. Listens for the `app_paywall`\n * SSE event emitted by the backend gate and triggers the paywall immediately.\n *\n * Usage (minimal — backend enforces regardless):\n * import { AppPaywall } from 'flowstack-sdk/wallet';\n *\n * function App() {\n * return (\n * <AppPaywall siteId={config.appScope}>\n * <YourAppContent />\n * </AppPaywall>\n * );\n * }\n *\n * The backend's AppAccessGate fires a 402 or an `app_paywall` SSE event if the\n * user is blocked. This component surfaces that as a UI gate. It does NOT replace\n * backend enforcement — the backend always has the final say.\n */\n\nimport React, { useEffect, useState } from 'react';\nimport { useAppAccess } from './useAppAccess';\nimport type { AppPaywallProps } from './types';\n\nexport function AppPaywall({ siteId, builderTenantId, children, onBlocked }: AppPaywallProps) {\n const {\n hasAccess,\n queriesRemaining,\n paymentMode,\n unlockPriceCents,\n unlockPriceLabel,\n isLoading,\n checkout,\n } = useAppAccess(siteId, { builderTenantId });\n\n const [serverBlocked, setServerBlocked] = useState(false);\n const [serverBlockReason, setServerBlockReason] = useState<string | null>(null);\n\n // Listen for app_paywall SSE event dispatched by the useAgent hook\n useEffect(() => {\n function handlePaywall(e: Event) {\n const detail = (e as CustomEvent).detail;\n if (!detail) return;\n if (detail.site_id && detail.site_id !== siteId) return;\n setServerBlocked(true);\n setServerBlockReason(detail.code || 'payment_required');\n onBlocked?.(detail.code || 'payment_required');\n }\n window.addEventListener('flowstack:app_paywall', handlePaywall);\n return () => window.removeEventListener('flowstack:app_paywall', handlePaywall);\n }, [siteId, onBlocked]);\n\n const showPaywall = serverBlocked || (!isLoading && !hasAccess);\n\n if (!showPaywall) {\n return <>{children}</>;\n }\n\n const reason = serverBlockReason || (queriesRemaining === 0 ? 'free_tier_exhausted' : 'payment_required');\n const priceLabel = unlockPriceLabel || (unlockPriceCents ? `$${(unlockPriceCents / 100).toFixed(2)}` : 'Unlock app');\n const showAgentOption = paymentMode === 'agent' || paymentMode === 'both';\n\n return (\n <div\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'rgba(0,0,0,0.72)',\n backdropFilter: 'blur(4px)',\n }}\n >\n <div\n style={{\n background: '#111',\n border: '1px solid #333',\n borderRadius: '12px',\n padding: '32px',\n maxWidth: '360px',\n width: '90vw',\n textAlign: 'center',\n color: '#fff',\n }}\n >\n <p\n style={{\n fontSize: '10px',\n letterSpacing: '0.3em',\n textTransform: 'uppercase',\n color: '#888',\n marginBottom: '12px',\n }}\n >\n {reason === 'free_tier_exhausted' ? 'Free queries used' : 'Access required'}\n </p>\n\n {reason === 'free_tier_exhausted' && (\n <p style={{ fontSize: '13px', color: '#aaa', marginBottom: '20px' }}>\n You've used your free queries for this month.\n Unlock unlimited access below.\n </p>\n )}\n\n {reason === 'payment_required' && (\n <p style={{ fontSize: '13px', color: '#aaa', marginBottom: '20px' }}>\n This app requires payment to access.\n </p>\n )}\n\n {/* Stripe unlock CTA */}\n <button\n onClick={() => checkout()}\n style={{\n width: '100%',\n padding: '12px 24px',\n background: '#6366f1',\n color: '#fff',\n border: 'none',\n borderRadius: '8px',\n fontSize: '13px',\n fontWeight: 600,\n cursor: 'pointer',\n marginBottom: showAgentOption ? '8px' : '0',\n }}\n >\n {priceLabel}\n </button>\n\n {/* AGENT alternative */}\n {showAgentOption && (\n <p\n style={{\n fontSize: '11px',\n color: '#666',\n cursor: 'pointer',\n textDecoration: 'underline',\n }}\n onClick={() => {\n if (typeof window !== 'undefined') {\n window.open(`https://openinferencefoundation.org/buy?returnTo=${encodeURIComponent(window.location.href)}`, '_blank');\n }\n }}\n >\n Or pay with AGENT tokens\n </p>\n )}\n </div>\n </div>\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "flowstack-sdk",
3
+ "version": "0.2.1",
4
+ "description": "Complete Backend-as-a-Service SDK for building AI-powered apps with zero backend code",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./api": {
15
+ "types": "./dist/api/index.d.ts",
16
+ "import": "./dist/api/index.mjs",
17
+ "require": "./dist/api/index.js"
18
+ },
19
+ "./wallet": {
20
+ "types": "./dist/wallet/index.d.ts",
21
+ "import": "./dist/wallet/index.mjs",
22
+ "require": "./dist/wallet/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsup",
32
+ "dev": "tsup src/index.ts src/api/index.ts --format cjs,esm --dts --watch",
33
+ "lint": "eslint src/",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "typecheck": "tsc --noEmit",
37
+ "prepublishOnly": "npm run build"
38
+ },
39
+ "peerDependencies": {
40
+ "@privy-io/react-auth": ">=2.0.0",
41
+ "@privy-io/wagmi": ">=1.0.0",
42
+ "@tanstack/react-query": ">=5.0.0",
43
+ "next": ">=14.0.0",
44
+ "react": ">=18.0.0",
45
+ "react-dom": ">=18.0.0",
46
+ "viem": ">=2.0.0",
47
+ "wagmi": ">=2.0.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "@privy-io/react-auth": {
51
+ "optional": true
52
+ },
53
+ "@privy-io/wagmi": {
54
+ "optional": true
55
+ },
56
+ "wagmi": {
57
+ "optional": true
58
+ },
59
+ "viem": {
60
+ "optional": true
61
+ },
62
+ "@tanstack/react-query": {
63
+ "optional": true
64
+ }
65
+ },
66
+ "dependencies": {
67
+ "jsonwebtoken": "^9.0.2",
68
+ "react-markdown": "^10.1.0",
69
+ "remark-gfm": "^4.0.1"
70
+ },
71
+ "devDependencies": {
72
+ "@privy-io/react-auth": "^2.0.0",
73
+ "@privy-io/wagmi": "^1.0.0",
74
+ "@tanstack/react-query": "^5.0.0",
75
+ "@types/jsonwebtoken": "^9.0.5",
76
+ "@types/node": "^20.10.0",
77
+ "@types/react": "^18.2.0",
78
+ "@types/react-dom": "^18.2.0",
79
+ "next": "^14.2.35",
80
+ "react": "^18.3.1",
81
+ "react-dom": "^18.3.1",
82
+ "react-helmet-async": "^3.0.0",
83
+ "tsup": "^8.0.1",
84
+ "typescript": "^5.3.0",
85
+ "viem": "^2.0.0",
86
+ "vitest": "^4.1.2",
87
+ "wagmi": "^2.0.0"
88
+ },
89
+ "keywords": [
90
+ "flowstack",
91
+ "sdk",
92
+ "react",
93
+ "nextjs",
94
+ "ai",
95
+ "agent",
96
+ "auth",
97
+ "storage",
98
+ "backend-as-a-service"
99
+ ],
100
+ "author": "Flowstack",
101
+ "license": "MIT",
102
+ "repository": {
103
+ "type": "git",
104
+ "url": "https://github.com/flowstack-fun/flowstack-sdk"
105
+ },
106
+ "homepage": "https://flowstack.fun/docs",
107
+ "bugs": {
108
+ "url": "https://github.com/flowstack-fun/flowstack-sdk/issues"
109
+ }
110
+ }