@geenius/ai 0.1.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.
Files changed (165) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.env.example +2 -0
  3. package/.github/CODEOWNERS +1 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  7. package/.github/dependabot.yml +11 -0
  8. package/.github/workflows/ci.yml +23 -0
  9. package/.github/workflows/release.yml +29 -0
  10. package/.node-version +1 -0
  11. package/.nvmrc +1 -0
  12. package/.prettierrc +7 -0
  13. package/.project/ACCOUNT.yaml +4 -0
  14. package/.project/IDEAS.yaml +7 -0
  15. package/.project/PROJECT.yaml +11 -0
  16. package/.project/ROADMAP.yaml +15 -0
  17. package/CHANGELOG.md +15 -0
  18. package/CODE_OF_CONDUCT.md +26 -0
  19. package/CONTRIBUTING.md +61 -0
  20. package/LICENSE +21 -0
  21. package/README.md +1 -0
  22. package/SECURITY.md +18 -0
  23. package/SUPPORT.md +14 -0
  24. package/package.json +75 -0
  25. package/packages/convex/package.json +42 -0
  26. package/packages/convex/src/index.ts +8 -0
  27. package/packages/convex/src/mutations/messages.ts +29 -0
  28. package/packages/convex/src/queries/messages.ts +24 -0
  29. package/packages/convex/src/schema.ts +20 -0
  30. package/packages/convex/tsconfig.json +11 -0
  31. package/packages/convex/tsup.config.ts +17 -0
  32. package/packages/react/README.md +1 -0
  33. package/packages/react/package.json +60 -0
  34. package/packages/react/src/components/AILogTable.tsx +90 -0
  35. package/packages/react/src/components/ChatWindow.tsx +118 -0
  36. package/packages/react/src/components/GenerationCard.tsx +73 -0
  37. package/packages/react/src/components/ImageGenerator.tsx +103 -0
  38. package/packages/react/src/components/ModelSelector.tsx +44 -0
  39. package/packages/react/src/components/ModelTestRunner.tsx +148 -0
  40. package/packages/react/src/components/VoiceSelector.tsx +51 -0
  41. package/packages/react/src/components/index.ts +9 -0
  42. package/packages/react/src/hooks/index.ts +12 -0
  43. package/packages/react/src/hooks/useAI.ts +158 -0
  44. package/packages/react/src/hooks/useAILogs.ts +40 -0
  45. package/packages/react/src/hooks/useAIModels.ts +53 -0
  46. package/packages/react/src/hooks/useChat.ts +141 -0
  47. package/packages/react/src/hooks/useContentManager.ts +108 -0
  48. package/packages/react/src/hooks/useImageGeneration.ts +82 -0
  49. package/packages/react/src/hooks/useMemory.ts +161 -0
  50. package/packages/react/src/hooks/useModelTest.ts +126 -0
  51. package/packages/react/src/hooks/useRealtimeAudio.ts +203 -0
  52. package/packages/react/src/hooks/useSkills.ts +114 -0
  53. package/packages/react/src/hooks/useTextToSpeech.ts +99 -0
  54. package/packages/react/src/hooks/useTranscription.ts +119 -0
  55. package/packages/react/src/hooks/useVideoGeneration.ts +79 -0
  56. package/packages/react/src/index.ts +42 -0
  57. package/packages/react/src/pages/AILogsPage.tsx +98 -0
  58. package/packages/react/src/pages/ChatPage.tsx +42 -0
  59. package/packages/react/src/pages/ModelTestPage.tsx +33 -0
  60. package/packages/react/src/pages/index.ts +5 -0
  61. package/packages/react/tsconfig.json +26 -0
  62. package/packages/react/tsup.config.ts +22 -0
  63. package/packages/react-css/README.md +1 -0
  64. package/packages/react-css/package.json +45 -0
  65. package/packages/react-css/src/ai.css +857 -0
  66. package/packages/react-css/src/components/AILogTable.tsx +90 -0
  67. package/packages/react-css/src/components/ChatWindow.tsx +118 -0
  68. package/packages/react-css/src/components/GenerationCard.tsx +73 -0
  69. package/packages/react-css/src/components/ImageGenerator.tsx +103 -0
  70. package/packages/react-css/src/components/ModelSelector.tsx +44 -0
  71. package/packages/react-css/src/components/ModelTestRunner.tsx +148 -0
  72. package/packages/react-css/src/components/VoiceSelector.tsx +51 -0
  73. package/packages/react-css/src/components/index.ts +9 -0
  74. package/packages/react-css/src/hooks/index.ts +12 -0
  75. package/packages/react-css/src/hooks/useAI.ts +153 -0
  76. package/packages/react-css/src/hooks/useAILogs.ts +40 -0
  77. package/packages/react-css/src/hooks/useAIModels.ts +51 -0
  78. package/packages/react-css/src/hooks/useChat.ts +145 -0
  79. package/packages/react-css/src/hooks/useContentManager.ts +108 -0
  80. package/packages/react-css/src/hooks/useImageGeneration.ts +82 -0
  81. package/packages/react-css/src/hooks/useMemory.ts +161 -0
  82. package/packages/react-css/src/hooks/useModelTest.ts +122 -0
  83. package/packages/react-css/src/hooks/useRealtimeAudio.ts +203 -0
  84. package/packages/react-css/src/hooks/useSkills.ts +114 -0
  85. package/packages/react-css/src/hooks/useTextToSpeech.ts +99 -0
  86. package/packages/react-css/src/hooks/useTranscription.ts +119 -0
  87. package/packages/react-css/src/hooks/useVideoGeneration.ts +79 -0
  88. package/packages/react-css/src/index.ts +35 -0
  89. package/packages/react-css/src/pages/AILogsPage.tsx +98 -0
  90. package/packages/react-css/src/pages/ChatPage.tsx +42 -0
  91. package/packages/react-css/src/pages/ModelTestPage.tsx +33 -0
  92. package/packages/react-css/src/pages/index.ts +5 -0
  93. package/packages/react-css/src/styles.css +127 -0
  94. package/packages/react-css/tsconfig.json +26 -0
  95. package/packages/react-css/tsup.config.ts +2 -0
  96. package/packages/shared/README.md +1 -0
  97. package/packages/shared/package.json +71 -0
  98. package/packages/shared/src/__tests__/ai.test.ts +67 -0
  99. package/packages/shared/src/ai-client.ts +243 -0
  100. package/packages/shared/src/config.ts +235 -0
  101. package/packages/shared/src/content.ts +249 -0
  102. package/packages/shared/src/convex/helpers.ts +163 -0
  103. package/packages/shared/src/convex/index.ts +16 -0
  104. package/packages/shared/src/convex/schemas.ts +146 -0
  105. package/packages/shared/src/convex/validators.ts +136 -0
  106. package/packages/shared/src/index.ts +107 -0
  107. package/packages/shared/src/memory.ts +197 -0
  108. package/packages/shared/src/providers/base.ts +103 -0
  109. package/packages/shared/src/providers/elevenlabs.ts +155 -0
  110. package/packages/shared/src/providers/index.ts +28 -0
  111. package/packages/shared/src/providers/openai-compatible.ts +286 -0
  112. package/packages/shared/src/providers/registry.ts +113 -0
  113. package/packages/shared/src/providers/replicate-fal.ts +230 -0
  114. package/packages/shared/src/skills.ts +273 -0
  115. package/packages/shared/src/types.ts +501 -0
  116. package/packages/shared/tsconfig.json +25 -0
  117. package/packages/shared/tsup.config.ts +22 -0
  118. package/packages/shared/vitest.config.ts +4 -0
  119. package/packages/solidjs/README.md +1 -0
  120. package/packages/solidjs/package.json +59 -0
  121. package/packages/solidjs/src/components/ChatWindow.tsx +78 -0
  122. package/packages/solidjs/src/components/GenerationCard.tsx +62 -0
  123. package/packages/solidjs/src/components/ModelTestRunner.tsx +119 -0
  124. package/packages/solidjs/src/components/index.ts +5 -0
  125. package/packages/solidjs/src/index.ts +32 -0
  126. package/packages/solidjs/src/pages/ChatPage.tsx +22 -0
  127. package/packages/solidjs/src/pages/ModelTestPage.tsx +22 -0
  128. package/packages/solidjs/src/pages/index.ts +4 -0
  129. package/packages/solidjs/src/primitives/createAI.ts +79 -0
  130. package/packages/solidjs/src/primitives/createChat.ts +100 -0
  131. package/packages/solidjs/src/primitives/createContentManager.ts +61 -0
  132. package/packages/solidjs/src/primitives/createImageGeneration.ts +46 -0
  133. package/packages/solidjs/src/primitives/createMemory.ts +127 -0
  134. package/packages/solidjs/src/primitives/createModelTest.ts +89 -0
  135. package/packages/solidjs/src/primitives/createSkills.ts +83 -0
  136. package/packages/solidjs/src/primitives/createTextToSpeech.ts +56 -0
  137. package/packages/solidjs/src/primitives/createVideoGeneration.ts +46 -0
  138. package/packages/solidjs/src/primitives/index.ts +8 -0
  139. package/packages/solidjs/tsconfig.json +27 -0
  140. package/packages/solidjs/tsup.config.ts +21 -0
  141. package/packages/solidjs-css/README.md +1 -0
  142. package/packages/solidjs-css/package.json +44 -0
  143. package/packages/solidjs-css/src/ai.css +857 -0
  144. package/packages/solidjs-css/src/components/ChatWindow.tsx +78 -0
  145. package/packages/solidjs-css/src/components/GenerationCard.tsx +62 -0
  146. package/packages/solidjs-css/src/components/ModelTestRunner.tsx +119 -0
  147. package/packages/solidjs-css/src/components/index.ts +5 -0
  148. package/packages/solidjs-css/src/index.ts +26 -0
  149. package/packages/solidjs-css/src/pages/ChatPage.tsx +22 -0
  150. package/packages/solidjs-css/src/pages/ModelTestPage.tsx +22 -0
  151. package/packages/solidjs-css/src/pages/index.ts +4 -0
  152. package/packages/solidjs-css/src/primitives/createAI.ts +79 -0
  153. package/packages/solidjs-css/src/primitives/createChat.ts +100 -0
  154. package/packages/solidjs-css/src/primitives/createContentManager.ts +61 -0
  155. package/packages/solidjs-css/src/primitives/createImageGeneration.ts +46 -0
  156. package/packages/solidjs-css/src/primitives/createMemory.ts +127 -0
  157. package/packages/solidjs-css/src/primitives/createModelTest.ts +89 -0
  158. package/packages/solidjs-css/src/primitives/createSkills.ts +83 -0
  159. package/packages/solidjs-css/src/primitives/createTextToSpeech.ts +56 -0
  160. package/packages/solidjs-css/src/primitives/createVideoGeneration.ts +46 -0
  161. package/packages/solidjs-css/src/primitives/index.ts +1 -0
  162. package/packages/solidjs-css/src/styles.css +127 -0
  163. package/packages/solidjs-css/tsconfig.json +27 -0
  164. package/packages/solidjs-css/tsup.config.ts +2 -0
  165. package/pnpm-workspace.yaml +2 -0
@@ -0,0 +1,119 @@
1
+ // @geenius-ai/react — src/hooks/useTranscription.ts
2
+
3
+ /**
4
+ * Audio transcription hook (Whisper, Groq ASR, etc.)
5
+ */
6
+
7
+ import { useState, useCallback, useRef } from 'react'
8
+ import { useAction } from 'convex/react'
9
+
10
+ export interface TranscriptionResult {
11
+ text: string
12
+ timestamp: number
13
+ durationMs: number
14
+ }
15
+
16
+ export interface UseTranscriptionOptions {
17
+ transcribeAction: any
18
+ defaultModel?: string
19
+ /** Enable browser microphone recording */
20
+ enableMicrophone?: boolean
21
+ }
22
+
23
+ export interface UseTranscriptionReturn {
24
+ transcribe: (audioBase64: string, options?: {
25
+ model?: string
26
+ language?: string
27
+ prompt?: string
28
+ }) => Promise<string>
29
+ startRecording: () => Promise<void>
30
+ stopRecording: () => Promise<string>
31
+ isTranscribing: boolean
32
+ isRecording: boolean
33
+ lastResult: TranscriptionResult | null
34
+ error: string | null
35
+ clearError: () => void
36
+ }
37
+
38
+ export function useTranscription(options: UseTranscriptionOptions): UseTranscriptionReturn {
39
+ const [isTranscribing, setIsTranscribing] = useState(false)
40
+ const [isRecording, setIsRecording] = useState(false)
41
+ const [lastResult, setLastResult] = useState<TranscriptionResult | null>(null)
42
+ const [error, setError] = useState<string | null>(null)
43
+ const mediaRecorderRef = useRef<MediaRecorder | null>(null)
44
+ const chunksRef = useRef<Blob[]>([])
45
+ const action = useAction(options.transcribeAction)
46
+
47
+ const transcribe = useCallback(async (audioBase64: string, opts?: {
48
+ model?: string; language?: string; prompt?: string
49
+ }) => {
50
+ setIsTranscribing(true)
51
+ setError(null)
52
+ const start = Date.now()
53
+ try {
54
+ const text = await action({
55
+ audio: audioBase64,
56
+ model: opts?.model ?? options.defaultModel,
57
+ language: opts?.language,
58
+ prompt: opts?.prompt,
59
+ })
60
+ setLastResult({ text, timestamp: Date.now(), durationMs: Date.now() - start })
61
+ return text
62
+ } catch (err) {
63
+ const msg = err instanceof Error ? err.message : 'Transcription failed'
64
+ setError(msg)
65
+ throw err
66
+ } finally {
67
+ setIsTranscribing(false)
68
+ }
69
+ }, [action, options.defaultModel])
70
+
71
+ const startRecording = useCallback(async () => {
72
+ if (!options.enableMicrophone) throw new Error('Microphone not enabled')
73
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
74
+ const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' })
75
+ chunksRef.current = []
76
+ mediaRecorder.ondataavailable = (e) => {
77
+ if (e.data.size > 0) chunksRef.current.push(e.data)
78
+ }
79
+ mediaRecorder.start()
80
+ mediaRecorderRef.current = mediaRecorder
81
+ setIsRecording(true)
82
+ }, [options.enableMicrophone])
83
+
84
+ const stopRecording = useCallback(async () => {
85
+ return new Promise<string>((resolve, reject) => {
86
+ const recorder = mediaRecorderRef.current
87
+ if (!recorder) { reject(new Error('Not recording')); return }
88
+
89
+ recorder.onstop = async () => {
90
+ setIsRecording(false)
91
+ const blob = new Blob(chunksRef.current, { type: 'audio/webm' })
92
+ const arrayBuffer = await blob.arrayBuffer()
93
+ const bytes = new Uint8Array(arrayBuffer)
94
+ let binary = ''
95
+ for (let i = 0; i < bytes.length; i++) {
96
+ binary += String.fromCharCode(bytes[i]!)
97
+ }
98
+ const base64 = btoa(binary)
99
+
100
+ // Stop all tracks
101
+ recorder.stream.getTracks().forEach(t => t.stop())
102
+
103
+ try {
104
+ const text = await transcribe(base64)
105
+ resolve(text)
106
+ } catch (err) {
107
+ reject(err)
108
+ }
109
+ }
110
+ recorder.stop()
111
+ })
112
+ }, [transcribe])
113
+
114
+ return {
115
+ transcribe, startRecording, stopRecording,
116
+ isTranscribing, isRecording, lastResult, error,
117
+ clearError: () => setError(null),
118
+ }
119
+ }
@@ -0,0 +1,79 @@
1
+ // @geenius-ai/react — src/hooks/useVideoGeneration.ts
2
+
3
+ /**
4
+ * Video generation hook (Replicate, Fal, etc.)
5
+ */
6
+
7
+ import { useState, useCallback } from 'react'
8
+ import { useAction } from 'convex/react'
9
+
10
+ export interface GeneratedVideo {
11
+ url: string
12
+ prompt: string
13
+ model: string
14
+ timestamp: number
15
+ }
16
+
17
+ export interface UseVideoGenerationOptions {
18
+ generateVideoAction: any
19
+ defaultModel?: string
20
+ }
21
+
22
+ export interface UseVideoGenerationReturn {
23
+ generate: (prompt: string, options?: {
24
+ model?: string
25
+ duration?: number
26
+ aspectRatio?: '16:9' | '9:16' | '1:1'
27
+ resolution?: '720p' | '1080p' | '4k'
28
+ startImage?: string
29
+ endImage?: string
30
+ }) => Promise<string>
31
+ videos: GeneratedVideo[]
32
+ isGenerating: boolean
33
+ error: string | null
34
+ clearVideos: () => void
35
+ clearError: () => void
36
+ }
37
+
38
+ export function useVideoGeneration(options: UseVideoGenerationOptions): UseVideoGenerationReturn {
39
+ const [videos, setVideos] = useState<GeneratedVideo[]>([])
40
+ const [isGenerating, setIsGenerating] = useState(false)
41
+ const [error, setError] = useState<string | null>(null)
42
+ const action = useAction(options.generateVideoAction)
43
+
44
+ const generate = useCallback(async (prompt: string, opts?: {
45
+ model?: string; duration?: number
46
+ aspectRatio?: '16:9' | '9:16' | '1:1'
47
+ resolution?: '720p' | '1080p' | '4k'
48
+ startImage?: string; endImage?: string
49
+ }) => {
50
+ setIsGenerating(true)
51
+ setError(null)
52
+ try {
53
+ const model = opts?.model ?? options.defaultModel ?? 'minimax/video-01'
54
+ const result = await action({
55
+ prompt, model,
56
+ duration: opts?.duration,
57
+ aspectRatio: opts?.aspectRatio,
58
+ resolution: opts?.resolution,
59
+ startImage: opts?.startImage,
60
+ endImage: opts?.endImage,
61
+ })
62
+ const vid: GeneratedVideo = { url: result, prompt, model, timestamp: Date.now() }
63
+ setVideos(prev => [vid, ...prev])
64
+ return result
65
+ } catch (err) {
66
+ const msg = err instanceof Error ? err.message : 'Video generation failed'
67
+ setError(msg)
68
+ throw err
69
+ } finally {
70
+ setIsGenerating(false)
71
+ }
72
+ }, [action, options.defaultModel])
73
+
74
+ return {
75
+ generate, videos, isGenerating, error,
76
+ clearVideos: () => setVideos([]),
77
+ clearError: () => setError(null),
78
+ }
79
+ }
@@ -0,0 +1,42 @@
1
+ // @geenius-ai/react — src/index.ts
2
+
3
+ /**
4
+ * @geenius-ai/react
5
+ *
6
+ * React hooks, headless components, and page compositions for AI-powered
7
+ * Convex applications. All components are unstyled with data-* attributes
8
+ * for easy CSS targeting.
9
+ */
10
+
11
+ // Hooks — Core
12
+ export { useAI, type UseAIOptions, type UseAIReturn } from './hooks/useAI'
13
+ export { useChat, type UseChatOptions, type UseChatReturn } from './hooks/useChat'
14
+ export { useAILogs, type UseAILogsOptions, type UseAILogsReturn } from './hooks/useAILogs'
15
+ export { useModelTest, type UseModelTestOptions, type UseModelTestReturn, type ModelTestResult } from './hooks/useModelTest'
16
+ export { useAIModels, type UseAIModelsOptions, type UseAIModelsReturn } from './hooks/useAIModels'
17
+
18
+ // Hooks — Multi-modal
19
+ export { useImageGeneration, type UseImageGenerationOptions, type UseImageGenerationReturn, type GeneratedImage } from './hooks/useImageGeneration'
20
+ export { useTextToSpeech, type UseTextToSpeechOptions, type UseTextToSpeechReturn } from './hooks/useTextToSpeech'
21
+ export { useVideoGeneration, type UseVideoGenerationOptions, type UseVideoGenerationReturn, type GeneratedVideo } from './hooks/useVideoGeneration'
22
+ export { useTranscription, type UseTranscriptionOptions, type UseTranscriptionReturn, type TranscriptionResult } from './hooks/useTranscription'
23
+ export { useRealtimeAudio, type UseRealtimeAudioOptions, type UseRealtimeAudioReturn } from './hooks/useRealtimeAudio'
24
+
25
+ // Hooks — Content, Memory, Skills
26
+ export { useContentManager, type UseContentManagerOptions, type UseContentManagerReturn } from './hooks/useContentManager'
27
+ export { useMemory, type UseMemoryOptions, type UseMemoryReturn } from './hooks/useMemory'
28
+ export { useSkills, type UseSkillsOptions, type UseSkillsReturn } from './hooks/useSkills'
29
+
30
+ // Components
31
+ export { ChatWindow, type ChatWindowComponentProps } from './components/ChatWindow'
32
+ export { ModelSelector, type ModelSelectorProps } from './components/ModelSelector'
33
+ export { AILogTable, type AILogTableComponentProps } from './components/AILogTable'
34
+ export { ModelTestRunner, type ModelTestRunnerProps } from './components/ModelTestRunner'
35
+ export { GenerationCard, type GenerationCardProps } from './components/GenerationCard'
36
+ export { ImageGenerator, type ImageGeneratorComponentProps } from './components/ImageGenerator'
37
+ export { VoiceSelector, type VoiceSelectorComponentProps } from './components/VoiceSelector'
38
+
39
+ // Pages
40
+ export { ChatPage, type ChatPageProps } from './pages/ChatPage'
41
+ export { ModelTestPage, type ModelTestPageProps } from './pages/ModelTestPage'
42
+ export { AILogsPage, type AILogsPageProps } from './pages/AILogsPage'
@@ -0,0 +1,98 @@
1
+ // @geenius-ai/react — src/pages/AILogsPage.tsx
2
+
3
+ /**
4
+ * AI logs dashboard page with stats and log table.
5
+ */
6
+
7
+ import { useState } from 'react'
8
+ import { AILogTable } from '../components/AILogTable'
9
+ import { useAILogs, type UseAILogsOptions } from '../hooks/useAILogs'
10
+ import type { AIRequestStatus, AILogEntry } from '@geenius-ai/shared'
11
+
12
+ export interface AILogsPageProps {
13
+ /** Query reference: api.ai.listLogs */
14
+ listLogsQuery: any
15
+ className?: string
16
+ title?: string
17
+ onRowClick?: (log: AILogEntry) => void
18
+ }
19
+
20
+ export function AILogsPage(props: AILogsPageProps) {
21
+ const [modelFilter, setModelFilter] = useState('')
22
+ const [statusFilter, setStatusFilter] = useState<AIRequestStatus | ''>('')
23
+
24
+ const { logs, isLoading } = useAILogs({
25
+ listLogsQuery: props.listLogsQuery,
26
+ filters: {
27
+ model: modelFilter || undefined,
28
+ status: (statusFilter || undefined) as AIRequestStatus | undefined,
29
+ },
30
+ limit: 100,
31
+ })
32
+
33
+ // Calculate quick stats
34
+ const totalCalls = logs.length
35
+ const successCalls = logs.filter(l => l.status === 'success').length
36
+ const errorCalls = totalCalls - successCalls
37
+ const totalCost = logs.reduce((sum, l) => sum + (l.totalCostUsd ?? 0), 0)
38
+ const totalTokens = logs.reduce((sum, l) => sum + (l.totalTokens ?? 0), 0)
39
+
40
+ return (
41
+ <div className={props.className} data-ai-page="logs">
42
+ <div data-ai-page-header>
43
+ <h1 data-ai-page-title>{props.title ?? 'AI Logs'}</h1>
44
+ </div>
45
+
46
+ {/* Stats cards */}
47
+ <div data-ai-stats-grid>
48
+ <div data-ai-stat>
49
+ <span data-ai-stat-label>Total Calls</span>
50
+ <span data-ai-stat-value>{totalCalls}</span>
51
+ </div>
52
+ <div data-ai-stat data-ai-status="success">
53
+ <span data-ai-stat-label>Success</span>
54
+ <span data-ai-stat-value>{successCalls}</span>
55
+ </div>
56
+ <div data-ai-stat data-ai-status="error">
57
+ <span data-ai-stat-label>Errors</span>
58
+ <span data-ai-stat-value>{errorCalls}</span>
59
+ </div>
60
+ <div data-ai-stat>
61
+ <span data-ai-stat-label>Total Cost</span>
62
+ <span data-ai-stat-value>${totalCost.toFixed(2)}</span>
63
+ </div>
64
+ <div data-ai-stat>
65
+ <span data-ai-stat-label>Total Tokens</span>
66
+ <span data-ai-stat-value>{totalTokens.toLocaleString()}</span>
67
+ </div>
68
+ </div>
69
+
70
+ {/* Filters */}
71
+ <div data-ai-filters>
72
+ <input
73
+ type="text"
74
+ placeholder="Filter by model…"
75
+ value={modelFilter}
76
+ onChange={(e) => setModelFilter(e.target.value)}
77
+ data-ai-filter-input
78
+ />
79
+ <select
80
+ value={statusFilter}
81
+ onChange={(e) => setStatusFilter(e.target.value as AIRequestStatus | '')}
82
+ data-ai-filter-select
83
+ >
84
+ <option value="">All statuses</option>
85
+ <option value="success">Success</option>
86
+ <option value="error">Error</option>
87
+ </select>
88
+ </div>
89
+
90
+ {/* Log table */}
91
+ <AILogTable
92
+ logs={logs}
93
+ isLoading={isLoading}
94
+ onRowClick={props.onRowClick}
95
+ />
96
+ </div>
97
+ )
98
+ }
@@ -0,0 +1,42 @@
1
+ // @geenius-ai/react — src/pages/ChatPage.tsx
2
+
3
+ /**
4
+ * Full chatbot page — sidebar + conversation.
5
+ * Compose with your own layout and styling.
6
+ */
7
+
8
+ import { useState } from 'react'
9
+ import { ChatWindow, type ChatWindowComponentProps } from '../components/ChatWindow'
10
+
11
+ export interface ChatPageProps extends Omit<ChatWindowComponentProps, 'conversationId'> {
12
+ className?: string
13
+ /** Initial conversation ID */
14
+ conversationId?: string
15
+ }
16
+
17
+ export function ChatPage(props: ChatPageProps) {
18
+ const [activeConversationId, setActiveConversationId] = useState<string | undefined>(props.conversationId)
19
+
20
+ return (
21
+ <div className={props.className} data-ai-page="chat">
22
+ <div data-ai-page-header>
23
+ <h1 data-ai-page-title>AI Chat</h1>
24
+ <button
25
+ onClick={() => setActiveConversationId(undefined)}
26
+ data-ai-new-chat
27
+ >
28
+ New Chat
29
+ </button>
30
+ </div>
31
+
32
+ <ChatWindow
33
+ {...props}
34
+ conversationId={activeConversationId}
35
+ onNewConversation={(id) => {
36
+ setActiveConversationId(id)
37
+ props.onNewConversation?.(id)
38
+ }}
39
+ />
40
+ </div>
41
+ )
42
+ }
@@ -0,0 +1,33 @@
1
+ // @geenius-ai/react — src/pages/ModelTestPage.tsx
2
+
3
+ /**
4
+ * Model test page — extracted from the pattern used in 15+ apps.
5
+ */
6
+
7
+ import { ModelTestRunner, type ModelTestRunnerProps } from '../components/ModelTestRunner'
8
+ import { DEFAULT_MODELS } from '@geenius-ai/shared'
9
+ import type { AIGenerationType } from '@geenius-ai/shared'
10
+
11
+ export interface ModelTestPageProps extends ModelTestRunnerProps {
12
+ title?: string
13
+ }
14
+
15
+ export function ModelTestPage(props: ModelTestPageProps) {
16
+ const models = props.availableModels ?? DEFAULT_MODELS.map(m => m.id)
17
+
18
+ return (
19
+ <div className={props.className} data-ai-page="model-test">
20
+ <div data-ai-page-header>
21
+ <h1 data-ai-page-title>{props.title ?? 'Model Test Lab'}</h1>
22
+ <p data-ai-page-subtitle>
23
+ Test AI models individually or compare them side-by-side
24
+ </p>
25
+ </div>
26
+
27
+ <ModelTestRunner
28
+ {...props}
29
+ availableModels={models}
30
+ />
31
+ </div>
32
+ )
33
+ }
@@ -0,0 +1,5 @@
1
+ // @geenius-ai/react — src/pages/index.ts
2
+
3
+ export { ChatPage, type ChatPageProps } from './ChatPage'
4
+ export { ModelTestPage, type ModelTestPageProps } from './ModelTestPage'
5
+ export { AILogsPage, type AILogsPageProps } from './AILogsPage'
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "resolveJsonModule": true,
16
+ "isolatedModules": true,
17
+ "jsx": "react-jsx"
18
+ },
19
+ "include": [
20
+ "src"
21
+ ],
22
+ "exclude": [
23
+ "node_modules",
24
+ "dist"
25
+ ]
26
+ }
@@ -0,0 +1,22 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: {
5
+ index: 'src/index.ts',
6
+ 'hooks/index': 'src/hooks/index.ts',
7
+ 'components/index': 'src/components/index.ts',
8
+ 'pages/index': 'src/pages/index.ts',
9
+ },
10
+ format: ['esm'],
11
+ dts: true,
12
+ clean: true,
13
+ sourcemap: true,
14
+ jsx: 'automatic',
15
+ external: [
16
+ 'react',
17
+ 'react-dom',
18
+ 'convex',
19
+ 'convex/react',
20
+ '@geenius-ai/shared',
21
+ ],
22
+ })
@@ -0,0 +1 @@
1
+ # ✦ @geenius-ai/react-css\n\n> Geenius AI — React hooks and components (vanilla CSS variant)\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add @geenius-ai/react-css\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius-ai/react-css';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@geenius-ai/react-css",
3
+ "version": "0.1.0",
4
+ "description": "Geenius AI — React hooks and components (vanilla CSS variant)",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./styles.css": "./dist/styles.css"
16
+ },
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "lint": "tsc --noEmit",
20
+ "clean": "rm -rf dist"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">=18.0.0"
30
+ },
31
+ "dependencies": {
32
+ "@geenius-ai/shared": "workspace:*"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^19.0.0",
36
+ "react": "^19.2.4",
37
+ "tsup": "^8.5.1",
38
+ "typescript": "~6.0.2"
39
+ },
40
+ "author": "Antigravity HQ",
41
+ "license": "MIT",
42
+ "engines": {
43
+ "node": ">=20.0.0"
44
+ }
45
+ }