@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,78 @@
1
+ // @geenius-ai/solidjs — src/components/ChatWindow.tsx
2
+
3
+ /**
4
+ * SolidJS chat window component.
5
+ */
6
+
7
+ import { createSignal, For, Show, type Component, type JSX } from 'solid-js'
8
+ import type { AIChatMessage } from '@geenius-ai/shared'
9
+ import { createChat, type CreateChatOptions } from '../primitives/createChat'
10
+
11
+ export interface SolidChatWindowProps extends CreateChatOptions {
12
+ className?: string
13
+ renderMessage?: (message: AIChatMessage) => JSX.Element
14
+ }
15
+
16
+ export const ChatWindow: Component<SolidChatWindowProps> = (props) => {
17
+ const [input, setInput] = createSignal('')
18
+ const chat = createChat(props)
19
+
20
+ const handleSubmit = async (e: Event) => {
21
+ e.preventDefault()
22
+ const content = input().trim()
23
+ if (!content || chat.isSending()) return
24
+ setInput('')
25
+ await chat.sendMessage(content)
26
+ }
27
+
28
+ return (
29
+ <div class={props.className} data-ai-component="chat-window">
30
+ <div data-ai-messages>
31
+ <Show when={chat.messages().length === 0}>
32
+ <div data-ai-empty><p>Start a conversation</p></div>
33
+ </Show>
34
+
35
+ <For each={chat.messages()}>
36
+ {(msg) => props.renderMessage ? props.renderMessage(msg) : (
37
+ <div data-ai-message data-ai-role={msg.role}>
38
+ <div data-ai-message-role>{msg.role}</div>
39
+ <div data-ai-message-content>{msg.content}</div>
40
+ </div>
41
+ )}
42
+ </For>
43
+
44
+ <Show when={chat.isSending()}>
45
+ <div data-ai-message data-ai-role="assistant" data-ai-loading>
46
+ <span>Thinking…</span>
47
+ </div>
48
+ </Show>
49
+ </div>
50
+
51
+ <Show when={chat.error()}>
52
+ <div data-ai-error role="alert">
53
+ <span>{chat.error()}</span>
54
+ <button onClick={chat.clearError}>×</button>
55
+ </div>
56
+ </Show>
57
+
58
+ <form onSubmit={handleSubmit} data-ai-input-form>
59
+ <textarea
60
+ value={input()}
61
+ onInput={(e) => setInput(e.currentTarget.value)}
62
+ placeholder="Type a message…"
63
+ disabled={chat.isSending()}
64
+ data-ai-input
65
+ onKeyDown={(e) => {
66
+ if (e.key === 'Enter' && !e.shiftKey) {
67
+ e.preventDefault()
68
+ handleSubmit(e)
69
+ }
70
+ }}
71
+ />
72
+ <button type="submit" disabled={chat.isSending() || !input().trim()} data-ai-send>
73
+ {chat.isSending() ? 'Sending…' : 'Send'}
74
+ </button>
75
+ </form>
76
+ </div>
77
+ )
78
+ }
@@ -0,0 +1,62 @@
1
+ // @geenius-ai/solidjs — src/components/GenerationCard.tsx
2
+
3
+ /**
4
+ * SolidJS generation result card.
5
+ */
6
+
7
+ import { Show, type Component } from 'solid-js'
8
+ import type { AIGenerationType } from '@geenius-ai/shared'
9
+
10
+ export interface SolidGenerationCardProps {
11
+ type: AIGenerationType
12
+ content: string
13
+ model?: string
14
+ durationMs?: number
15
+ tokens?: number
16
+ cost?: number
17
+ error?: string
18
+ className?: string
19
+ }
20
+
21
+ export const GenerationCard: Component<SolidGenerationCardProps> = (props) => {
22
+ return (
23
+ <div class={props.className} data-ai-component="generation-card" data-ai-type={props.type}>
24
+ <div data-ai-card-header>
25
+ <span data-ai-card-type>{props.type}</span>
26
+ <Show when={props.model}><span data-ai-card-model>{props.model}</span></Show>
27
+ <Show when={props.durationMs != null}><span data-ai-card-duration>{props.durationMs}ms</span></Show>
28
+ </div>
29
+
30
+ <Show when={props.error} fallback={
31
+ <div data-ai-card-content>
32
+ <Show when={props.type === 'image'}
33
+ fallback={
34
+ <Show when={props.type === 'audio' || props.type === 'speech'}
35
+ fallback={<pre data-ai-card-text>{props.content}</pre>}
36
+ >
37
+ <audio controls data-ai-card-audio>
38
+ <source src={props.content.startsWith('http') ? props.content : `data:audio/mp3;base64,${props.content}`} />
39
+ </audio>
40
+ </Show>
41
+ }
42
+ >
43
+ <img
44
+ src={props.content.startsWith('http') ? props.content : `data:image/png;base64,${props.content}`}
45
+ alt="AI Generated"
46
+ data-ai-card-image
47
+ />
48
+ </Show>
49
+ </div>
50
+ }>
51
+ <div data-ai-card-error role="alert">{props.error}</div>
52
+ </Show>
53
+
54
+ <Show when={props.tokens || props.cost != null}>
55
+ <div data-ai-card-footer>
56
+ <Show when={props.tokens}><span>{props.tokens} tokens</span></Show>
57
+ <Show when={props.cost != null}><span>${props.cost!.toFixed(4)}</span></Show>
58
+ </div>
59
+ </Show>
60
+ </div>
61
+ )
62
+ }
@@ -0,0 +1,119 @@
1
+ // @geenius-ai/solidjs — src/components/ModelTestRunner.tsx
2
+
3
+ /**
4
+ * SolidJS model test runner with tabs.
5
+ */
6
+
7
+ import { createSignal, For, Show, type Component } from 'solid-js'
8
+ import type { AIGenerationType } from '@geenius-ai/shared'
9
+ import { createModelTest, type CreateModelTestOptions, type ModelTestResult } from '../primitives/createModelTest'
10
+
11
+ export interface SolidModelTestRunnerProps extends CreateModelTestOptions {
12
+ className?: string
13
+ availableModels?: string[]
14
+ defaultTab?: AIGenerationType
15
+ }
16
+
17
+ const TABS: { id: AIGenerationType; label: string }[] = [
18
+ { id: 'text', label: 'Text' },
19
+ { id: 'image', label: 'Image' },
20
+ { id: 'audio', label: 'Audio' },
21
+ { id: 'transcription', label: 'ASR' },
22
+ { id: 'video', label: 'Video' },
23
+ ]
24
+
25
+ export const ModelTestRunner: Component<SolidModelTestRunnerProps> = (props) => {
26
+ const [activeTab, setActiveTab] = createSignal<AIGenerationType>(props.defaultTab ?? 'text')
27
+ const [prompt, setPrompt] = createSignal('')
28
+ const [selectedModel, setSelectedModel] = createSignal('')
29
+ const [batchMode, setBatchMode] = createSignal(false)
30
+
31
+ const test = createModelTest(props)
32
+
33
+ const handleSubmit = async (e: Event) => {
34
+ e.preventDefault()
35
+ if (!prompt().trim()) return
36
+ if (batchMode() && props.availableModels) {
37
+ await test.runBatchTest(props.availableModels, prompt().trim())
38
+ } else if (selectedModel()) {
39
+ await test.runTest(selectedModel(), prompt().trim(), activeTab())
40
+ }
41
+ }
42
+
43
+ return (
44
+ <div class={props.className} data-ai-component="model-test-runner">
45
+ <div data-ai-tabs role="tablist">
46
+ <For each={TABS}>
47
+ {(tab) => (
48
+ <button
49
+ role="tab"
50
+ aria-selected={activeTab() === tab.id}
51
+ onClick={() => setActiveTab(tab.id)}
52
+ data-ai-tab
53
+ >
54
+ {tab.label}
55
+ </button>
56
+ )}
57
+ </For>
58
+ </div>
59
+
60
+ <form onSubmit={handleSubmit} data-ai-test-form>
61
+ <select
62
+ value={selectedModel()}
63
+ onChange={(e) => setSelectedModel(e.currentTarget.value)}
64
+ disabled={test.isRunning() || batchMode()}
65
+ data-ai-input
66
+ >
67
+ <option value="">Select model…</option>
68
+ <For each={props.availableModels ?? []}>
69
+ {(m) => <option value={m}>{m}</option>}
70
+ </For>
71
+ </select>
72
+
73
+ <textarea
74
+ value={prompt()}
75
+ onInput={(e) => setPrompt(e.currentTarget.value)}
76
+ placeholder="Enter test prompt…"
77
+ disabled={test.isRunning()}
78
+ data-ai-input
79
+ />
80
+
81
+ <div data-ai-actions>
82
+ <label>
83
+ <input
84
+ type="checkbox"
85
+ checked={batchMode()}
86
+ onChange={(e) => setBatchMode(e.currentTarget.checked)}
87
+ />
88
+ Test all models
89
+ </label>
90
+ <button type="submit" disabled={test.isRunning() || !prompt().trim()} data-ai-submit>
91
+ {test.isRunning() ? 'Running…' : 'Run Test'}
92
+ </button>
93
+ <Show when={test.results().length > 0}>
94
+ <button type="button" onClick={test.clearResults} data-ai-clear>Clear</button>
95
+ </Show>
96
+ </div>
97
+ </form>
98
+
99
+ <Show when={test.results().length > 0}>
100
+ <div data-ai-test-results>
101
+ <For each={test.results()}>
102
+ {(result) => (
103
+ <div data-ai-test-result data-ai-status={result.error ? 'error' : 'success'}>
104
+ <div data-ai-result-header>
105
+ <span>{result.model}</span>
106
+ <span>{result.durationMs}ms</span>
107
+ <Show when={result.error}><span data-ai-result-error>{result.error}</span></Show>
108
+ </div>
109
+ <Show when={!result.error}>
110
+ <pre data-ai-result-text>{result.result}</pre>
111
+ </Show>
112
+ </div>
113
+ )}
114
+ </For>
115
+ </div>
116
+ </Show>
117
+ </div>
118
+ )
119
+ }
@@ -0,0 +1,5 @@
1
+ // @geenius-ai/solidjs — src/components/index.ts
2
+
3
+ export { ChatWindow, type SolidChatWindowProps } from './ChatWindow'
4
+ export { ModelTestRunner, type SolidModelTestRunnerProps } from './ModelTestRunner'
5
+ export { GenerationCard, type SolidGenerationCardProps } from './GenerationCard'
@@ -0,0 +1,26 @@
1
+ // @geenius-ai/solidjs-css — Independent barrel (vanilla CSS variant)
2
+ // ALL imports from LOCAL files + @geenius-ai/shared — NOT from @geenius-ai/solidjs
3
+
4
+ // Primitives — Core
5
+ export { createAI, type CreateAIOptions, type CreateAIReturn } from './primitives/createAI'
6
+ export { createChat, type CreateChatOptions, type CreateChatReturn } from './primitives/createChat'
7
+ export { createModelTest, type CreateModelTestOptions, type CreateModelTestReturn, type ModelTestResult } from './primitives/createModelTest'
8
+
9
+ // Primitives — Multi-modal
10
+ export { createImageGeneration, type CreateImageGenerationOptions, type GeneratedImage } from './primitives/createImageGeneration'
11
+ export { createTextToSpeech, type CreateTextToSpeechOptions } from './primitives/createTextToSpeech'
12
+ export { createVideoGeneration, type CreateVideoGenerationOptions, type GeneratedVideo } from './primitives/createVideoGeneration'
13
+
14
+ // Primitives — Content, Memory, Skills
15
+ export { createContentManager, type CreateContentManagerOptions } from './primitives/createContentManager'
16
+ export { createMemory, type CreateMemoryOptions } from './primitives/createMemory'
17
+ export { createSkills, type CreateSkillsOptions } from './primitives/createSkills'
18
+
19
+ // Components
20
+ export { ChatWindow, type SolidChatWindowProps } from './components/ChatWindow'
21
+ export { ModelTestRunner, type SolidModelTestRunnerProps } from './components/ModelTestRunner'
22
+ export { GenerationCard, type SolidGenerationCardProps } from './components/GenerationCard'
23
+
24
+ // Pages
25
+ export { ChatPage, type SolidChatPageProps } from './pages/ChatPage'
26
+ export { ModelTestPage, type SolidModelTestPageProps } from './pages/ModelTestPage'
@@ -0,0 +1,22 @@
1
+ // @geenius-ai/solidjs — src/pages/ChatPage.tsx
2
+
3
+ import { createSignal, type Component } from 'solid-js'
4
+ import { ChatWindow, type SolidChatWindowProps } from '../components/ChatWindow'
5
+
6
+ export interface SolidChatPageProps extends Omit<SolidChatWindowProps, 'className'> {
7
+ className?: string
8
+ }
9
+
10
+ export const ChatPage: Component<SolidChatPageProps> = (props) => {
11
+ const [_, setConversationId] = createSignal<string | undefined>(undefined)
12
+
13
+ return (
14
+ <div class={props.className} data-ai-page="chat">
15
+ <div data-ai-page-header>
16
+ <h1 data-ai-page-title>AI Chat</h1>
17
+ <button onClick={() => setConversationId(undefined)} data-ai-new-chat>New Chat</button>
18
+ </div>
19
+ <ChatWindow {...props} />
20
+ </div>
21
+ )
22
+ }
@@ -0,0 +1,22 @@
1
+ // @geenius-ai/solidjs — src/pages/ModelTestPage.tsx
2
+
3
+ import { type Component } from 'solid-js'
4
+ import { ModelTestRunner, type SolidModelTestRunnerProps } from '../components/ModelTestRunner'
5
+ import { DEFAULT_MODELS } from '@geenius-ai/shared'
6
+
7
+ export interface SolidModelTestPageProps extends SolidModelTestRunnerProps {
8
+ title?: string
9
+ }
10
+
11
+ export const ModelTestPage: Component<SolidModelTestPageProps> = (props) => {
12
+ const models = props.availableModels ?? DEFAULT_MODELS.map(m => m.id)
13
+
14
+ return (
15
+ <div class={props.className} data-ai-page="model-test">
16
+ <div data-ai-page-header>
17
+ <h1 data-ai-page-title>{props.title ?? 'Model Test Lab'}</h1>
18
+ </div>
19
+ <ModelTestRunner {...props} availableModels={models} />
20
+ </div>
21
+ )
22
+ }
@@ -0,0 +1,4 @@
1
+ // @geenius-ai/solidjs — src/pages/index.ts
2
+
3
+ export { ChatPage, type SolidChatPageProps } from './ChatPage'
4
+ export { ModelTestPage, type SolidModelTestPageProps } from './ModelTestPage'
@@ -0,0 +1,79 @@
1
+ // @geenius-ai/solidjs — src/primitives/createAI.ts
2
+
3
+ /**
4
+ * Core AI primitive — signal-based multi-modal generation.
5
+ */
6
+
7
+ import { createSignal } from 'solid-js'
8
+ import type { AIGenerationType } from '@geenius-ai/shared'
9
+
10
+ export interface CreateAIOptions {
11
+ /** Convex action caller for text */
12
+ callGenerateText?: (args: any) => Promise<string>
13
+ callGenerateImage?: (args: any) => Promise<string>
14
+ callGenerateAudio?: (args: any) => Promise<string>
15
+ callTranscribeAudio?: (args: any) => Promise<string>
16
+ callGenerateVideo?: (args: any) => Promise<string>
17
+ }
18
+
19
+ export interface CreateAIReturn {
20
+ generateText: (args: { model: string; messages: any[]; temperature?: number; maxTokens?: number; caller?: string }) => Promise<string>
21
+ generateImage: (prompt: string, model?: string) => Promise<string>
22
+ generateAudio: (prompt: string, voice?: string) => Promise<string>
23
+ transcribeAudio: (audio: string) => Promise<string>
24
+ generateVideo: (prompt: string) => Promise<string>
25
+ isLoading: () => boolean
26
+ error: () => string | null
27
+ lastResult: () => string | null
28
+ lastType: () => AIGenerationType | null
29
+ clearError: () => void
30
+ }
31
+
32
+ export function createAI(options: CreateAIOptions = {}): CreateAIReturn {
33
+ const [isLoading, setIsLoading] = createSignal(false)
34
+ const [error, setError] = createSignal<string | null>(null)
35
+ const [lastResult, setLastResult] = createSignal<string | null>(null)
36
+ const [lastType, setLastType] = createSignal<AIGenerationType | null>(null)
37
+
38
+ async function wrap(type: AIGenerationType, fn: () => Promise<string>): Promise<string> {
39
+ setIsLoading(true)
40
+ setError(null)
41
+ try {
42
+ const result = await fn()
43
+ setLastResult(result)
44
+ setLastType(type)
45
+ return result
46
+ } catch (err) {
47
+ const msg = err instanceof Error ? err.message : `${type} generation failed`
48
+ setError(msg)
49
+ throw err
50
+ } finally {
51
+ setIsLoading(false)
52
+ }
53
+ }
54
+
55
+ return {
56
+ generateText: (args) => wrap('text', () => {
57
+ if (!options.callGenerateText) throw new Error('callGenerateText not provided')
58
+ return options.callGenerateText(args)
59
+ }),
60
+ generateImage: (prompt, model) => wrap('image', () => {
61
+ if (!options.callGenerateImage) throw new Error('callGenerateImage not provided')
62
+ return options.callGenerateImage({ prompt, model })
63
+ }),
64
+ generateAudio: (prompt, voice) => wrap('audio', () => {
65
+ if (!options.callGenerateAudio) throw new Error('callGenerateAudio not provided')
66
+ return options.callGenerateAudio({ prompt, voice })
67
+ }),
68
+ transcribeAudio: (audio) => wrap('transcription', () => {
69
+ if (!options.callTranscribeAudio) throw new Error('callTranscribeAudio not provided')
70
+ return options.callTranscribeAudio({ audio })
71
+ }),
72
+ generateVideo: (prompt) => wrap('video', () => {
73
+ if (!options.callGenerateVideo) throw new Error('callGenerateVideo not provided')
74
+ return options.callGenerateVideo({ prompt })
75
+ }),
76
+ isLoading, error, lastResult, lastType,
77
+ clearError: () => setError(null),
78
+ }
79
+ }
@@ -0,0 +1,100 @@
1
+ // @geenius-ai/solidjs — src/primitives/createChat.ts
2
+
3
+ /**
4
+ * Chat primitive — signal-based conversation management.
5
+ */
6
+
7
+ import { createSignal } from 'solid-js'
8
+ import type { AIChatMessage } from '@geenius-ai/shared'
9
+
10
+ export interface CreateChatOptions {
11
+ model?: string
12
+ systemPrompt?: string
13
+ callSendMessage?: (args: any) => Promise<void>
14
+ callGenerateText?: (args: any) => Promise<string>
15
+ callCreateConversation?: (args: any) => Promise<string>
16
+ onNewConversation?: (id: string) => void
17
+ }
18
+
19
+ export interface CreateChatReturn {
20
+ messages: () => AIChatMessage[]
21
+ isSending: () => boolean
22
+ error: () => string | null
23
+ conversationId: () => string | null
24
+ sendMessage: (content: string) => Promise<void>
25
+ clearError: () => void
26
+ }
27
+
28
+ export function createChat(options: CreateChatOptions = {}): CreateChatReturn {
29
+ const [messages, setMessages] = createSignal<AIChatMessage[]>([])
30
+ const [isSending, setIsSending] = createSignal(false)
31
+ const [error, setError] = createSignal<string | null>(null)
32
+ const [conversationId, setConversationId] = createSignal<string | null>(null)
33
+
34
+ async function sendMessage(content: string) {
35
+ setIsSending(true)
36
+ setError(null)
37
+
38
+ try {
39
+ let activeId = conversationId()
40
+
41
+ if (!activeId && options.callCreateConversation) {
42
+ activeId = await options.callCreateConversation({
43
+ title: content.substring(0, 100),
44
+ model: options.model ?? 'gpt-4o',
45
+ systemPrompt: options.systemPrompt,
46
+ })
47
+ setConversationId(activeId)
48
+ options.onNewConversation?.(activeId!)
49
+ }
50
+
51
+ // Add user message locally
52
+ const userMsg: AIChatMessage = {
53
+ id: `msg-${Date.now()}`,
54
+ conversationId: activeId ?? 'local',
55
+ userId: 'local',
56
+ role: 'user',
57
+ content,
58
+ createdAt: Date.now(),
59
+ }
60
+ setMessages(prev => [...prev, userMsg])
61
+
62
+ if (options.callSendMessage && activeId) {
63
+ await options.callSendMessage({ conversationId: activeId, content })
64
+ }
65
+
66
+ // Generate AI response
67
+ if (options.callGenerateText) {
68
+ const allMessages = messages()
69
+ const aiResponse = await options.callGenerateText({
70
+ model: options.model ?? 'gpt-4o',
71
+ messages: [
72
+ ...(options.systemPrompt ? [{ role: 'system', content: options.systemPrompt }] : []),
73
+ ...allMessages.map(m => ({ role: m.role, content: m.content })),
74
+ ],
75
+ caller: 'chat',
76
+ })
77
+
78
+ const assistantMsg: AIChatMessage = {
79
+ id: `msg-${Date.now()}-ai`,
80
+ conversationId: activeId ?? 'local',
81
+ userId: 'ai',
82
+ role: 'assistant',
83
+ content: aiResponse,
84
+ model: options.model ?? 'gpt-4o',
85
+ createdAt: Date.now(),
86
+ }
87
+ setMessages(prev => [...prev, assistantMsg])
88
+ }
89
+ } catch (err) {
90
+ setError(err instanceof Error ? err.message : 'Failed to send message')
91
+ } finally {
92
+ setIsSending(false)
93
+ }
94
+ }
95
+
96
+ return {
97
+ messages, isSending, error, conversationId, sendMessage,
98
+ clearError: () => setError(null),
99
+ }
100
+ }
@@ -0,0 +1,61 @@
1
+ // @geenius-ai/solidjs — src/primitives/createContentManager.ts
2
+
3
+ import { createSignal } from 'solid-js'
4
+ import type {
5
+ ContentAction,
6
+ ContentTone,
7
+ ContentType,
8
+ ContentGenerateOptions,
9
+ ContentResult,
10
+ } from '@geenius-ai/shared'
11
+
12
+ export interface CreateContentManagerOptions {
13
+ generateFn: (options: ContentGenerateOptions) => Promise<ContentResult>
14
+ defaultType?: ContentType
15
+ defaultTone?: ContentTone
16
+ defaultModel?: string
17
+ }
18
+
19
+ export function createContentManager(options: CreateContentManagerOptions) {
20
+ const { generateFn, defaultType = 'text', defaultTone, defaultModel } = options
21
+ const [result, setResult] = createSignal<ContentResult | null>(null)
22
+ const [isGenerating, setIsGenerating] = createSignal(false)
23
+ const [error, setError] = createSignal<Error | null>(null)
24
+
25
+ const execute = async (action: ContentAction, input: string, extra?: Partial<ContentGenerateOptions>) => {
26
+ setIsGenerating(true)
27
+ setError(null)
28
+ try {
29
+ const res = await generateFn({
30
+ action,
31
+ input,
32
+ type: extra?.type ?? defaultType,
33
+ tone: extra?.tone ?? defaultTone,
34
+ model: extra?.model ?? defaultModel,
35
+ ...extra,
36
+ })
37
+ setResult(res)
38
+ return res
39
+ } catch (err) {
40
+ const e = err instanceof Error ? err : new Error(String(err))
41
+ setError(e)
42
+ throw e
43
+ } finally {
44
+ setIsGenerating(false)
45
+ }
46
+ }
47
+
48
+ return {
49
+ generate: (input: string, opts?: Partial<ContentGenerateOptions>) => execute('generate', input, opts),
50
+ rewrite: (text: string, instructions?: string) => execute('rewrite', text, { instructions }),
51
+ translate: (text: string, language: string) => execute('translate', text, { language }),
52
+ summarize: (text: string) => execute('summarize', text),
53
+ variations: (text: string, count: number = 3) => execute('variations', text, { variations: count }),
54
+ changeTone: (text: string, tone: ContentTone) => execute('change-tone', text, { tone }),
55
+ proofread: (text: string) => execute('proofread', text),
56
+ result,
57
+ isGenerating,
58
+ error,
59
+ reset: () => { setResult(null); setError(null) },
60
+ }
61
+ }
@@ -0,0 +1,46 @@
1
+ // @geenius-ai/solidjs — src/primitives/createImageGeneration.ts
2
+
3
+ import { createSignal } from 'solid-js'
4
+
5
+ export interface GeneratedImage {
6
+ url: string
7
+ prompt: string
8
+ model: string
9
+ timestamp: number
10
+ }
11
+
12
+ export interface CreateImageGenerationOptions {
13
+ callGenerateImage: (args: any) => Promise<string>
14
+ defaultModel?: string
15
+ }
16
+
17
+ export function createImageGeneration(options: CreateImageGenerationOptions) {
18
+ const [images, setImages] = createSignal<GeneratedImage[]>([])
19
+ const [isGenerating, setIsGenerating] = createSignal(false)
20
+ const [error, setError] = createSignal<string | null>(null)
21
+
22
+ async function generate(prompt: string, opts?: {
23
+ model?: string; size?: string; quality?: 'standard' | 'hd'; negativePrompt?: string; seed?: number
24
+ }) {
25
+ setIsGenerating(true)
26
+ setError(null)
27
+ try {
28
+ const model = opts?.model ?? options.defaultModel ?? 'dall-e-3'
29
+ const result = await options.callGenerateImage({ prompt, model, ...opts })
30
+ const url = result.startsWith('http') ? result : `data:image/png;base64,${result}`
31
+ setImages(prev => [{ url, prompt, model, timestamp: Date.now() }, ...prev])
32
+ return url
33
+ } catch (err) {
34
+ setError(err instanceof Error ? err.message : 'Image generation failed')
35
+ throw err
36
+ } finally {
37
+ setIsGenerating(false)
38
+ }
39
+ }
40
+
41
+ return {
42
+ generate, images, isGenerating, error,
43
+ clearImages: () => setImages([]),
44
+ clearError: () => setError(null),
45
+ }
46
+ }