@lssm/module.ai-chat 0.0.0-canary-20251217083314 → 0.0.0-canary-20251219202229

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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai-chat.feature.d.ts +2 -1
  3. package/dist/ai-chat.feature.d.ts.map +1 -0
  4. package/dist/ai-chat.feature.js +2 -1
  5. package/dist/ai-chat.feature.js.map +1 -0
  6. package/dist/context/context-builder.d.ts +2 -1
  7. package/dist/context/context-builder.d.ts.map +1 -0
  8. package/dist/context/context-builder.js +2 -1
  9. package/dist/context/context-builder.js.map +1 -0
  10. package/dist/context/file-operations.d.ts +2 -1
  11. package/dist/context/file-operations.d.ts.map +1 -0
  12. package/dist/context/file-operations.js +2 -1
  13. package/dist/context/file-operations.js.map +1 -0
  14. package/dist/context/workspace-context.d.ts +2 -1
  15. package/dist/context/workspace-context.d.ts.map +1 -0
  16. package/dist/context/workspace-context.js +2 -1
  17. package/dist/context/workspace-context.js.map +1 -0
  18. package/dist/core/chat-service.d.ts +2 -1
  19. package/dist/core/chat-service.d.ts.map +1 -0
  20. package/dist/core/chat-service.js +2 -1
  21. package/dist/core/chat-service.js.map +1 -0
  22. package/dist/core/conversation-store.d.ts +2 -1
  23. package/dist/core/conversation-store.d.ts.map +1 -0
  24. package/dist/core/conversation-store.js +2 -1
  25. package/dist/core/conversation-store.js.map +1 -0
  26. package/dist/core/message-types.d.ts +2 -1
  27. package/dist/core/message-types.d.ts.map +1 -0
  28. package/dist/libs/ai-providers/dist/factory.js +23 -22
  29. package/dist/libs/ai-providers/dist/factory.js.map +1 -0
  30. package/dist/libs/ai-providers/dist/models.js +2 -1
  31. package/dist/libs/ai-providers/dist/models.js.map +1 -0
  32. package/dist/libs/ai-providers/dist/validation.js +2 -1
  33. package/dist/libs/ai-providers/dist/validation.js.map +1 -0
  34. package/dist/libs/design-system/dist/_virtual/rolldown_runtime.js +2 -1
  35. package/dist/libs/design-system/dist/_virtual/rolldown_runtime.js.map +1 -0
  36. package/dist/libs/design-system/dist/components/atoms/Button.js +5 -4
  37. package/dist/libs/design-system/dist/components/atoms/Button.js.map +1 -0
  38. package/dist/libs/design-system/dist/components/atoms/Textarea.js +5 -4
  39. package/dist/libs/design-system/dist/components/atoms/Textarea.js.map +1 -0
  40. package/dist/libs/design-system/dist/lib/keyboard.js +2 -1
  41. package/dist/libs/design-system/dist/lib/keyboard.js.map +1 -0
  42. package/dist/libs/design-system/dist/ui-kit-web/dist/ui/button.js +2 -1
  43. package/dist/libs/design-system/dist/ui-kit-web/dist/ui/button.js.map +1 -0
  44. package/dist/libs/design-system/dist/ui-kit-web/dist/ui/textarea.js +2 -1
  45. package/dist/libs/design-system/dist/ui-kit-web/dist/ui/textarea.js.map +1 -0
  46. package/dist/libs/design-system/dist/ui-kit-web/dist/ui-kit-core/dist/utils.js +2 -1
  47. package/dist/libs/design-system/dist/ui-kit-web/dist/ui-kit-core/dist/utils.js.map +1 -0
  48. package/dist/libs/ui-kit-web/dist/ui/avatar.js +2 -1
  49. package/dist/libs/ui-kit-web/dist/ui/avatar.js.map +1 -0
  50. package/dist/libs/ui-kit-web/dist/ui/badge.js +2 -1
  51. package/dist/libs/ui-kit-web/dist/ui/badge.js.map +1 -0
  52. package/dist/libs/ui-kit-web/dist/ui/scroll-area.js +2 -1
  53. package/dist/libs/ui-kit-web/dist/ui/scroll-area.js.map +1 -0
  54. package/dist/libs/ui-kit-web/dist/ui/select.js +2 -1
  55. package/dist/libs/ui-kit-web/dist/ui/select.js.map +1 -0
  56. package/dist/libs/ui-kit-web/dist/ui/skeleton.js +2 -1
  57. package/dist/libs/ui-kit-web/dist/ui/skeleton.js.map +1 -0
  58. package/dist/libs/ui-kit-web/dist/ui/tooltip.js +2 -1
  59. package/dist/libs/ui-kit-web/dist/ui/tooltip.js.map +1 -0
  60. package/dist/libs/ui-kit-web/dist/ui/utils.js +2 -1
  61. package/dist/libs/ui-kit-web/dist/ui/utils.js.map +1 -0
  62. package/dist/libs/ui-kit-web/dist/ui-kit-core/dist/utils.js +2 -1
  63. package/dist/libs/ui-kit-web/dist/ui-kit-core/dist/utils.js.map +1 -0
  64. package/dist/presentation/components/ChatContainer.d.ts +2 -1
  65. package/dist/presentation/components/ChatContainer.d.ts.map +1 -0
  66. package/dist/presentation/components/ChatContainer.js +2 -1
  67. package/dist/presentation/components/ChatContainer.js.map +1 -0
  68. package/dist/presentation/components/ChatInput.d.ts +4 -3
  69. package/dist/presentation/components/ChatInput.d.ts.map +1 -0
  70. package/dist/presentation/components/ChatInput.js +8 -7
  71. package/dist/presentation/components/ChatInput.js.map +1 -0
  72. package/dist/presentation/components/ChatMessage.d.ts +7 -6
  73. package/dist/presentation/components/ChatMessage.d.ts.map +1 -0
  74. package/dist/presentation/components/ChatMessage.js +4 -3
  75. package/dist/presentation/components/ChatMessage.js.map +1 -0
  76. package/dist/presentation/components/CodePreview.d.ts +4 -3
  77. package/dist/presentation/components/CodePreview.d.ts.map +1 -0
  78. package/dist/presentation/components/CodePreview.js +8 -7
  79. package/dist/presentation/components/CodePreview.js.map +1 -0
  80. package/dist/presentation/components/ContextIndicator.d.ts +2 -1
  81. package/dist/presentation/components/ContextIndicator.d.ts.map +1 -0
  82. package/dist/presentation/components/ContextIndicator.js +2 -1
  83. package/dist/presentation/components/ContextIndicator.js.map +1 -0
  84. package/dist/presentation/components/ModelPicker.d.ts +6 -5
  85. package/dist/presentation/components/ModelPicker.d.ts.map +1 -0
  86. package/dist/presentation/components/ModelPicker.js +4 -3
  87. package/dist/presentation/components/ModelPicker.js.map +1 -0
  88. package/dist/presentation/hooks/useChat.d.ts +2 -1
  89. package/dist/presentation/hooks/useChat.d.ts.map +1 -0
  90. package/dist/presentation/hooks/useChat.js +2 -1
  91. package/dist/presentation/hooks/useChat.js.map +1 -0
  92. package/dist/presentation/hooks/useProviders.d.ts +2 -1
  93. package/dist/presentation/hooks/useProviders.d.ts.map +1 -0
  94. package/dist/presentation/hooks/useProviders.js +2 -1
  95. package/dist/presentation/hooks/useProviders.js.map +1 -0
  96. package/dist/providers/chat-utilities.d.ts +2 -1
  97. package/dist/providers/chat-utilities.d.ts.map +1 -0
  98. package/dist/providers/chat-utilities.js +2 -1
  99. package/dist/providers/chat-utilities.js.map +1 -0
  100. package/package.json +13 -12
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelPicker.js","names":["PROVIDER_ICONS: Record<ProviderName, React.ReactNode>","PROVIDER_NAMES: Record<ProviderName, string>","MODE_BADGES: Record<\n ProviderMode,\n { label: string; variant: 'default' | 'secondary' | 'outline' }\n>","models: ModelInfo[]"],"sources":["../../../src/presentation/components/ModelPicker.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '@lssm/lib.ui-kit-web/ui/utils';\nimport { Button } from '@lssm/lib.design-system';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@lssm/lib.ui-kit-web/ui/select';\nimport { Badge } from '@lssm/lib.ui-kit-web/ui/badge';\nimport { Bot, Cpu, Cloud, Sparkles } from 'lucide-react';\nimport {\n type ProviderName,\n type ProviderMode,\n type ModelInfo,\n getModelsForProvider,\n} from '@lssm/lib.ai-providers';\n\nexport interface ModelSelection {\n provider: ProviderName;\n model: string;\n mode: ProviderMode;\n}\n\nexport interface ModelPickerProps {\n /** Currently selected provider/model */\n value: ModelSelection;\n /** Called when selection changes */\n onChange: (value: ModelSelection) => void;\n /** Available providers (with availability info) */\n availableProviders?: {\n provider: ProviderName;\n available: boolean;\n mode: ProviderMode;\n reason?: string;\n }[];\n /** Additional class name */\n className?: string;\n /** Compact mode (smaller) */\n compact?: boolean;\n}\n\nconst PROVIDER_ICONS: Record<ProviderName, React.ReactNode> = {\n ollama: <Cpu className=\"h-4 w-4\" />,\n openai: <Bot className=\"h-4 w-4\" />,\n anthropic: <Sparkles className=\"h-4 w-4\" />,\n mistral: <Cloud className=\"h-4 w-4\" />,\n gemini: <Sparkles className=\"h-4 w-4\" />,\n};\n\nconst PROVIDER_NAMES: Record<ProviderName, string> = {\n ollama: 'Ollama (Local)',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n mistral: 'Mistral',\n gemini: 'Google Gemini',\n};\n\nconst MODE_BADGES: Record<\n ProviderMode,\n { label: string; variant: 'default' | 'secondary' | 'outline' }\n> = {\n local: { label: 'Local', variant: 'secondary' },\n byok: { label: 'BYOK', variant: 'outline' },\n managed: { label: 'Managed', variant: 'default' },\n};\n\n/**\n * Model picker component for selecting AI provider and model\n */\nexport function ModelPicker({\n value,\n onChange,\n availableProviders,\n className,\n compact = false,\n}: ModelPickerProps) {\n const providers = availableProviders ?? [\n { provider: 'ollama' as const, available: true, mode: 'local' as const },\n { provider: 'openai' as const, available: true, mode: 'byok' as const },\n { provider: 'anthropic' as const, available: true, mode: 'byok' as const },\n { provider: 'mistral' as const, available: true, mode: 'byok' as const },\n { provider: 'gemini' as const, available: true, mode: 'byok' as const },\n ];\n\n const models: ModelInfo[] = getModelsForProvider(value.provider);\n const selectedModel = models.find((m) => m.id === value.model);\n\n const handleProviderChange = React.useCallback(\n (providerName: string) => {\n const provider = providerName as ProviderName;\n const providerInfo = providers.find((p) => p.provider === provider);\n const providerModels = getModelsForProvider(provider);\n const defaultModel = providerModels[0]?.id ?? '';\n\n onChange({\n provider,\n model: defaultModel,\n mode: providerInfo?.mode ?? 'byok',\n });\n },\n [onChange, providers]\n );\n\n const handleModelChange = React.useCallback(\n (modelId: string) => {\n onChange({\n ...value,\n model: modelId,\n });\n },\n [onChange, value]\n );\n\n if (compact) {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n <Select value={value.provider} onValueChange={handleProviderChange}>\n <SelectTrigger className=\"w-[140px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {providers.map((p) => (\n <SelectItem\n key={p.provider}\n value={p.provider}\n disabled={!p.available}\n >\n <div className=\"flex items-center gap-2\">\n {PROVIDER_ICONS[p.provider]}\n <span>{PROVIDER_NAMES[p.provider]}</span>\n </div>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select value={value.model} onValueChange={handleModelChange}>\n <SelectTrigger className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {models.map((m) => (\n <SelectItem key={m.id} value={m.id}>\n {m.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n }\n\n return (\n <div className={cn('flex flex-col gap-3', className)}>\n {/* Provider selection */}\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"text-sm font-medium\">Provider</label>\n <div className=\"flex flex-wrap gap-2\">\n {providers.map((p) => (\n <Button\n key={p.provider}\n variant={value.provider === p.provider ? 'default' : 'outline'}\n size=\"sm\"\n onPress={() => p.available && handleProviderChange(p.provider)}\n disabled={!p.available}\n className={cn(!p.available && 'opacity-50')}\n >\n {PROVIDER_ICONS[p.provider]}\n <span>{PROVIDER_NAMES[p.provider]}</span>\n <Badge variant={MODE_BADGES[p.mode].variant} className=\"ml-1\">\n {MODE_BADGES[p.mode].label}\n </Badge>\n </Button>\n ))}\n </div>\n </div>\n\n {/* Model selection */}\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"text-sm font-medium\">Model</label>\n <Select value={value.model} onValueChange={handleModelChange}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select a model\" />\n </SelectTrigger>\n <SelectContent>\n {models.map((m) => (\n <SelectItem key={m.id} value={m.id}>\n <div className=\"flex items-center gap-2\">\n <span>{m.name}</span>\n <span className=\"text-muted-foreground text-xs\">\n {Math.round(m.contextWindow / 1000)}K\n </span>\n {m.capabilities.vision && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Vision\n </Badge>\n )}\n {m.capabilities.reasoning && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Reasoning\n </Badge>\n )}\n </div>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Model info */}\n {selectedModel && (\n <div className=\"text-muted-foreground flex flex-wrap gap-2 text-xs\">\n <span>\n Context: {Math.round(selectedModel.contextWindow / 1000)}K tokens\n </span>\n {selectedModel.capabilities.vision && <span>• Vision</span>}\n {selectedModel.capabilities.tools && <span>• Tools</span>}\n {selectedModel.capabilities.reasoning && <span>• Reasoning</span>}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -63,4 +63,5 @@ interface UseChatReturn {
63
63
  */
64
64
  declare function useChat(options?: UseChatOptions): UseChatReturn;
65
65
  //#endregion
66
- export { UseChatOptions, UseChatReturn, useChat };
66
+ export { UseChatOptions, UseChatReturn, useChat };
67
+ //# sourceMappingURL=useChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChat.d.ts","names":[],"sources":["../../../src/presentation/hooks/useChat.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAkBA;AAEa,UAFI,cAAA,CAEJ;EAEJ;EAcY,QAAA,CAAA,EAhBR,YAgBQ;EAEI;EAEL,IAAA,CAAA,EAlBX,YAkBW;EAAK;EAQR,KAAA,CAAA,EAAA,MAAA;EAEL;EAEI,MAAA,CAAA,EAAA,MAAA;EAIP;EAIS,QAAA,CAAA,EAAA,MAAA;EACX;EAMa,cAAA,CAAA,EAAA,MAAA;EAAO;EAQX,YAAO,CAAA,EAAA,MAAA;;;;qBAvCF;;yBAEI;;oBAEL;;;;;;;;;;UAQH,aAAA;;YAEL;;gBAEI;;;;SAIP;;+CAIS,qBACX;;;;;;oBAMa;;;;;;;iBAQJ,OAAA,WAAiB,iBAAsB"}
@@ -168,4 +168,5 @@ function useChat(options = {}) {
168
168
  }
169
169
 
170
170
  //#endregion
171
- export { useChat };
171
+ export { useChat };
172
+ //# sourceMappingURL=useChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChat.js","names":["userMessage: ChatMessage","assistantMessage: ChatMessage","error"],"sources":["../../../src/presentation/hooks/useChat.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport type {\n ChatMessage,\n ChatConversation,\n ChatAttachment,\n} from '../../core/message-types';\nimport { ChatService } from '../../core/chat-service';\nimport {\n type ProviderName,\n type ProviderMode,\n createProvider,\n} from '@lssm/lib.ai-providers';\n\n/**\n * Options for useChat hook\n */\nexport interface UseChatOptions {\n /** Provider to use */\n provider?: ProviderName;\n /** Provider mode */\n mode?: ProviderMode;\n /** Model to use */\n model?: string;\n /** API key for BYOK mode */\n apiKey?: string;\n /** API proxy URL for managed mode */\n proxyUrl?: string;\n /** Initial conversation ID to resume */\n conversationId?: string;\n /** System prompt override */\n systemPrompt?: string;\n /** Enable streaming */\n streaming?: boolean;\n /** Called when a message is sent */\n onSend?: (message: ChatMessage) => void;\n /** Called when a response is received */\n onResponse?: (message: ChatMessage) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n /** Called when usage is recorded */\n onUsage?: (usage: { inputTokens: number; outputTokens: number }) => void;\n}\n\n/**\n * Return type for useChat hook\n */\nexport interface UseChatReturn {\n /** Current messages */\n messages: ChatMessage[];\n /** Current conversation */\n conversation: ChatConversation | null;\n /** Whether currently loading/streaming */\n isLoading: boolean;\n /** Current error */\n error: Error | null;\n /** Send a message */\n sendMessage: (\n content: string,\n attachments?: ChatAttachment[]\n ) => Promise<void>;\n /** Clear conversation and start fresh */\n clearConversation: () => void;\n /** Set conversation ID to resume */\n setConversationId: (id: string | null) => void;\n /** Regenerate last response */\n regenerate: () => Promise<void>;\n /** Stop current generation */\n stop: () => void;\n}\n\n/**\n * Hook for managing AI chat state\n */\nexport function useChat(options: UseChatOptions = {}): UseChatReturn {\n const {\n provider = 'openai',\n mode = 'byok',\n model,\n apiKey,\n proxyUrl,\n conversationId: initialConversationId,\n systemPrompt,\n streaming = true,\n onSend,\n onResponse,\n onError,\n onUsage,\n } = options;\n\n const [messages, setMessages] = React.useState<ChatMessage[]>([]);\n const [conversation, setConversation] =\n React.useState<ChatConversation | null>(null);\n const [isLoading, setIsLoading] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n const [conversationId, setConversationId] = React.useState<string | null>(\n initialConversationId ?? null\n );\n\n const abortControllerRef = React.useRef<AbortController | null>(null);\n const chatServiceRef = React.useRef<ChatService | null>(null);\n\n // Initialize chat service\n React.useEffect(() => {\n const chatProvider = createProvider({\n provider,\n model,\n apiKey,\n proxyUrl,\n });\n\n chatServiceRef.current = new ChatService({\n provider: chatProvider,\n systemPrompt,\n onUsage,\n });\n }, [provider, mode, model, apiKey, proxyUrl, systemPrompt, onUsage]);\n\n // Load existing conversation\n React.useEffect(() => {\n if (!conversationId || !chatServiceRef.current) return;\n\n const loadConversation = async () => {\n const conv =\n await chatServiceRef.current!.getConversation(conversationId);\n if (conv) {\n setConversation(conv);\n setMessages(conv.messages);\n }\n };\n\n loadConversation().catch(console.error);\n }, [conversationId]);\n\n const sendMessage = React.useCallback(\n async (content: string, attachments?: ChatAttachment[]) => {\n if (!chatServiceRef.current) {\n throw new Error('Chat service not initialized');\n }\n\n setIsLoading(true);\n setError(null);\n\n // Create abort controller\n abortControllerRef.current = new AbortController();\n\n try {\n // Add user message immediately\n const userMessage: ChatMessage = {\n id: `msg_${Date.now()}`,\n conversationId: conversationId ?? '',\n role: 'user',\n content,\n status: 'completed',\n createdAt: new Date(),\n updatedAt: new Date(),\n attachments,\n };\n setMessages((prev) => [...prev, userMessage]);\n onSend?.(userMessage);\n\n if (streaming) {\n // Streaming mode\n const result = await chatServiceRef.current.stream({\n conversationId: conversationId ?? undefined,\n content,\n attachments,\n });\n\n // Update conversation ID if new\n if (!conversationId) {\n setConversationId(result.conversationId);\n }\n\n // Add placeholder for assistant message\n const assistantMessage: ChatMessage = {\n id: result.messageId,\n conversationId: result.conversationId,\n role: 'assistant',\n content: '',\n status: 'streaming',\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n setMessages((prev) => [...prev, assistantMessage]);\n\n // Process stream\n let fullContent = '';\n for await (const chunk of result.stream) {\n if (chunk.type === 'text' && chunk.content) {\n fullContent += chunk.content;\n setMessages((prev) =>\n prev.map((m) =>\n m.id === result.messageId ? { ...m, content: fullContent } : m\n )\n );\n } else if (chunk.type === 'done') {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === result.messageId\n ? {\n ...m,\n status: 'completed',\n usage: chunk.usage,\n updatedAt: new Date(),\n }\n : m\n )\n );\n onResponse?.(\n messages.find((m) => m.id === result.messageId) ??\n assistantMessage\n );\n } else if (chunk.type === 'error') {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === result.messageId\n ? {\n ...m,\n status: 'error',\n error: chunk.error,\n updatedAt: new Date(),\n }\n : m\n )\n );\n if (chunk.error) {\n const err = new Error(chunk.error.message);\n setError(err);\n onError?.(err);\n }\n }\n }\n } else {\n // Non-streaming mode\n const result = await chatServiceRef.current.send({\n conversationId: conversationId ?? undefined,\n content,\n attachments,\n });\n\n setConversation(result.conversation);\n setMessages(result.conversation.messages);\n\n if (!conversationId) {\n setConversationId(result.conversation.id);\n }\n\n onResponse?.(result.message);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onError?.(error);\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n },\n [conversationId, streaming, onSend, onResponse, onError, messages]\n );\n\n const clearConversation = React.useCallback(() => {\n setMessages([]);\n setConversation(null);\n setConversationId(null);\n setError(null);\n }, []);\n\n const regenerate = React.useCallback(async () => {\n // Find the last user message\n const lastUserMessageIndex = messages.findLastIndex(\n (m) => m.role === 'user'\n );\n if (lastUserMessageIndex === -1) return;\n\n const lastUserMessage = messages[lastUserMessageIndex];\n if (!lastUserMessage) return;\n\n // Remove the last assistant message\n setMessages((prev) => prev.slice(0, lastUserMessageIndex + 1));\n\n // Resend\n await sendMessage(lastUserMessage.content, lastUserMessage.attachments);\n }, [messages, sendMessage]);\n\n const stop = React.useCallback(() => {\n abortControllerRef.current?.abort();\n setIsLoading(false);\n }, []);\n\n return {\n messages,\n conversation,\n isLoading,\n error,\n sendMessage,\n clearConversation,\n setConversationId,\n regenerate,\n stop,\n };\n}\n"],"mappings":";;;;;;;;;;;AA2EA,SAAgB,QAAQ,UAA0B,EAAE,EAAiB;CACnE,MAAM,EACJ,WAAW,UACX,OAAO,QACP,OACA,QACA,UACA,gBAAgB,uBAChB,cACA,YAAY,MACZ,QACA,YACA,SACA,YACE;CAEJ,MAAM,CAAC,UAAU,eAAe,MAAM,SAAwB,EAAE,CAAC;CACjE,MAAM,CAAC,cAAc,mBACnB,MAAM,SAAkC,KAAK;CAC/C,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,MAAM;CACvD,MAAM,CAAC,OAAO,YAAY,MAAM,SAAuB,KAAK;CAC5D,MAAM,CAAC,gBAAgB,qBAAqB,MAAM,SAChD,yBAAyB,KAC1B;CAED,MAAM,qBAAqB,MAAM,OAA+B,KAAK;CACrE,MAAM,iBAAiB,MAAM,OAA2B,KAAK;AAG7D,OAAM,gBAAgB;AAQpB,iBAAe,UAAU,IAAI,YAAY;GACvC,UARmB,eAAe;IAClC;IACA;IACA;IACA;IACD,CAAC;GAIA;GACA;GACD,CAAC;IACD;EAAC;EAAU;EAAM;EAAO;EAAQ;EAAU;EAAc;EAAQ,CAAC;AAGpE,OAAM,gBAAgB;AACpB,MAAI,CAAC,kBAAkB,CAAC,eAAe,QAAS;EAEhD,MAAM,mBAAmB,YAAY;GACnC,MAAM,OACJ,MAAM,eAAe,QAAS,gBAAgB,eAAe;AAC/D,OAAI,MAAM;AACR,oBAAgB,KAAK;AACrB,gBAAY,KAAK,SAAS;;;AAI9B,oBAAkB,CAAC,MAAM,QAAQ,MAAM;IACtC,CAAC,eAAe,CAAC;CAEpB,MAAM,cAAc,MAAM,YACxB,OAAO,SAAiB,gBAAmC;AACzD,MAAI,CAAC,eAAe,QAClB,OAAM,IAAI,MAAM,+BAA+B;AAGjD,eAAa,KAAK;AAClB,WAAS,KAAK;AAGd,qBAAmB,UAAU,IAAI,iBAAiB;AAElD,MAAI;GAEF,MAAMA,cAA2B;IAC/B,IAAI,OAAO,KAAK,KAAK;IACrB,gBAAgB,kBAAkB;IAClC,MAAM;IACN;IACA,QAAQ;IACR,2BAAW,IAAI,MAAM;IACrB,2BAAW,IAAI,MAAM;IACrB;IACD;AACD,gBAAa,SAAS,CAAC,GAAG,MAAM,YAAY,CAAC;AAC7C,YAAS,YAAY;AAErB,OAAI,WAAW;IAEb,MAAM,SAAS,MAAM,eAAe,QAAQ,OAAO;KACjD,gBAAgB,kBAAkB;KAClC;KACA;KACD,CAAC;AAGF,QAAI,CAAC,eACH,mBAAkB,OAAO,eAAe;IAI1C,MAAMC,mBAAgC;KACpC,IAAI,OAAO;KACX,gBAAgB,OAAO;KACvB,MAAM;KACN,SAAS;KACT,QAAQ;KACR,2BAAW,IAAI,MAAM;KACrB,2BAAW,IAAI,MAAM;KACtB;AACD,iBAAa,SAAS,CAAC,GAAG,MAAM,iBAAiB,CAAC;IAGlD,IAAI,cAAc;AAClB,eAAW,MAAM,SAAS,OAAO,OAC/B,KAAI,MAAM,SAAS,UAAU,MAAM,SAAS;AAC1C,oBAAe,MAAM;AACrB,kBAAa,SACX,KAAK,KAAK,MACR,EAAE,OAAO,OAAO,YAAY;MAAE,GAAG;MAAG,SAAS;MAAa,GAAG,EAC9D,CACF;eACQ,MAAM,SAAS,QAAQ;AAChC,kBAAa,SACX,KAAK,KAAK,MACR,EAAE,OAAO,OAAO,YACZ;MACE,GAAG;MACH,QAAQ;MACR,OAAO,MAAM;MACb,2BAAW,IAAI,MAAM;MACtB,GACD,EACL,CACF;AACD,kBACE,SAAS,MAAM,MAAM,EAAE,OAAO,OAAO,UAAU,IAC7C,iBACH;eACQ,MAAM,SAAS,SAAS;AACjC,kBAAa,SACX,KAAK,KAAK,MACR,EAAE,OAAO,OAAO,YACZ;MACE,GAAG;MACH,QAAQ;MACR,OAAO,MAAM;MACb,2BAAW,IAAI,MAAM;MACtB,GACD,EACL,CACF;AACD,SAAI,MAAM,OAAO;MACf,MAAM,MAAM,IAAI,MAAM,MAAM,MAAM,QAAQ;AAC1C,eAAS,IAAI;AACb,gBAAU,IAAI;;;UAIf;IAEL,MAAM,SAAS,MAAM,eAAe,QAAQ,KAAK;KAC/C,gBAAgB,kBAAkB;KAClC;KACA;KACD,CAAC;AAEF,oBAAgB,OAAO,aAAa;AACpC,gBAAY,OAAO,aAAa,SAAS;AAEzC,QAAI,CAAC,eACH,mBAAkB,OAAO,aAAa,GAAG;AAG3C,iBAAa,OAAO,QAAQ;;WAEvB,KAAK;GACZ,MAAMC,UAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;AACjE,YAASA,QAAM;AACf,aAAUA,QAAM;YACR;AACR,gBAAa,MAAM;AACnB,sBAAmB,UAAU;;IAGjC;EAAC;EAAgB;EAAW;EAAQ;EAAY;EAAS;EAAS,CACnE;AA+BD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,mBAnCwB,MAAM,kBAAkB;AAChD,eAAY,EAAE,CAAC;AACf,mBAAgB,KAAK;AACrB,qBAAkB,KAAK;AACvB,YAAS,KAAK;KACb,EAAE,CAAC;EA+BJ;EACA,YA9BiB,MAAM,YAAY,YAAY;GAE/C,MAAM,uBAAuB,SAAS,eACnC,MAAM,EAAE,SAAS,OACnB;AACD,OAAI,yBAAyB,GAAI;GAEjC,MAAM,kBAAkB,SAAS;AACjC,OAAI,CAAC,gBAAiB;AAGtB,gBAAa,SAAS,KAAK,MAAM,GAAG,uBAAuB,EAAE,CAAC;AAG9D,SAAM,YAAY,gBAAgB,SAAS,gBAAgB,YAAY;KACtE,CAAC,UAAU,YAAY,CAAC;EAgBzB,MAdW,MAAM,kBAAkB;AACnC,sBAAmB,SAAS,OAAO;AACnC,gBAAa,MAAM;KAClB,EAAE,CAAC;EAYL"}
@@ -34,4 +34,5 @@ interface UseProvidersReturn {
34
34
  */
35
35
  declare function useProviders(): UseProvidersReturn;
36
36
  //#endregion
37
- export { UseProvidersReturn, useProviders };
37
+ export { UseProvidersReturn, useProviders };
38
+ //# sourceMappingURL=useProviders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProviders.d.ts","names":[],"sources":["../../../src/presentation/hooks/useProviders.tsx"],"sourcesContent":[],"mappings":";;;;;;AAcA;AACY,UADK,YAAA,CACL;EAEJ,QAAA,EAFI,YAEJ;EAEE,SAAA,EAAA,OAAA;EAAS,IAAA,EAFX,YAEW;EAMF,MAAA,CAAA,EAAA,MAAA;EAEJ,MAAA,EARH,SAQG,EAAA;;;;;AAUI,UAZA,kBAAA,CAYA;EAAO;EAMR,SAAA,EAhBH,YAgBe,EAAA;;sBAdN;;0BAEI;;wBAEF,iBAAiB;;;;iBAIxB;;;;;iBAMD,YAAA,CAAA,GAAgB"}
@@ -39,4 +39,5 @@ function useProviders() {
39
39
  }
40
40
 
41
41
  //#endregion
42
- export { useProviders };
42
+ export { useProviders };
43
+ //# sourceMappingURL=useProviders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProviders.js","names":[],"sources":["../../../src/presentation/hooks/useProviders.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n type ProviderName,\n type ProviderMode,\n type ModelInfo,\n getAvailableProviders,\n getModelsForProvider,\n} from '@lssm/lib.ai-providers';\n\n/**\n * Provider availability info\n */\nexport interface ProviderInfo {\n provider: ProviderName;\n available: boolean;\n mode: ProviderMode;\n reason?: string;\n models: ModelInfo[];\n}\n\n/**\n * Return type for useProviders hook\n */\nexport interface UseProvidersReturn {\n /** All providers with availability info */\n providers: ProviderInfo[];\n /** Available providers only */\n availableProviders: ProviderInfo[];\n /** Check if a provider is available */\n isAvailable: (provider: ProviderName) => boolean;\n /** Get models for a provider */\n getModels: (provider: ProviderName) => ModelInfo[];\n /** Loading state */\n isLoading: boolean;\n /** Refresh provider availability */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook for managing AI provider information\n */\nexport function useProviders(): UseProvidersReturn {\n const [providers, setProviders] = React.useState<ProviderInfo[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n\n const loadProviders = React.useCallback(async () => {\n setIsLoading(true);\n try {\n const available = getAvailableProviders();\n const providersWithModels: ProviderInfo[] = available.map((p) => ({\n ...p,\n models: getModelsForProvider(p.provider),\n }));\n setProviders(providersWithModels);\n } catch (error) {\n console.error('Failed to load providers:', error);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n React.useEffect(() => {\n loadProviders();\n }, [loadProviders]);\n\n const availableProviders = React.useMemo(\n () => providers.filter((p) => p.available),\n [providers]\n );\n\n const isAvailable = React.useCallback(\n (provider: ProviderName) =>\n providers.some((p) => p.provider === provider && p.available),\n [providers]\n );\n\n const getModelsCallback = React.useCallback(\n (provider: ProviderName) =>\n providers.find((p) => p.provider === provider)?.models ?? [],\n [providers]\n );\n\n return {\n providers,\n availableProviders,\n isAvailable,\n getModels: getModelsCallback,\n isLoading,\n refresh: loadProviders,\n };\n}\n"],"mappings":";;;;;;;;;;;AA2CA,SAAgB,eAAmC;CACjD,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAyB,EAAE,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,KAAK;CAEtD,MAAM,gBAAgB,MAAM,YAAY,YAAY;AAClD,eAAa,KAAK;AAClB,MAAI;AAMF,gBALkB,uBAAuB,CACa,KAAK,OAAO;IAChE,GAAG;IACH,QAAQ,qBAAqB,EAAE,SAAS;IACzC,EAAE,CAC8B;WAC1B,OAAO;AACd,WAAQ,MAAM,6BAA6B,MAAM;YACzC;AACR,gBAAa,MAAM;;IAEpB,EAAE,CAAC;AAEN,OAAM,gBAAgB;AACpB,iBAAe;IACd,CAAC,cAAc,CAAC;AAmBnB,QAAO;EACL;EACA,oBAnByB,MAAM,cACzB,UAAU,QAAQ,MAAM,EAAE,UAAU,EAC1C,CAAC,UAAU,CACZ;EAiBC,aAfkB,MAAM,aACvB,aACC,UAAU,MAAM,MAAM,EAAE,aAAa,YAAY,EAAE,UAAU,EAC/D,CAAC,UAAU,CACZ;EAYC,WAVwB,MAAM,aAC7B,aACC,UAAU,MAAM,MAAM,EAAE,aAAa,SAAS,EAAE,UAAU,EAAE,EAC9D,CAAC,UAAU,CACZ;EAOC;EACA,SAAS;EACV"}
@@ -11,4 +11,5 @@ declare function supportsLocalMode(provider: ProviderName): boolean;
11
11
  */
12
12
  declare function isStudioAvailable(provider: ProviderName): boolean;
13
13
  //#endregion
14
- export { isStudioAvailable, supportsLocalMode };
14
+ export { isStudioAvailable, supportsLocalMode };
15
+ //# sourceMappingURL=chat-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-utilities.d.ts","names":[],"sources":["../../src/providers/chat-utilities.ts"],"sourcesContent":[],"mappings":";;;;AAeA;;;iBAPgB,iBAAA,WAA4B;;;;iBAO5B,iBAAA,WAA4B"}
@@ -13,4 +13,5 @@ function isStudioAvailable(provider) {
13
13
  }
14
14
 
15
15
  //#endregion
16
- export { isStudioAvailable, supportsLocalMode };
16
+ export { isStudioAvailable, supportsLocalMode };
17
+ //# sourceMappingURL=chat-utilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-utilities.js","names":[],"sources":["../../src/providers/chat-utilities.ts"],"sourcesContent":["/**\n * Chat-specific provider utilities\n */\nimport type { ProviderName } from '@lssm/lib.ai-providers';\n\n/**\n * Check if a provider supports local mode\n */\nexport function supportsLocalMode(provider: ProviderName): boolean {\n return provider === 'ollama';\n}\n\n/**\n * Check if a provider is available in Studio (cloud only)\n */\nexport function isStudioAvailable(provider: ProviderName): boolean {\n return provider !== 'ollama';\n}\n\n/**\n * Get a human-readable provider name\n */\nexport function getProviderDisplayName(provider: ProviderName): string {\n switch (provider) {\n case 'ollama':\n return 'Ollama (Local)';\n case 'openai':\n return 'OpenAI';\n case 'anthropic':\n return 'Anthropic Claude';\n case 'mistral':\n return 'Mistral AI';\n case 'gemini':\n return 'Google Gemini';\n default:\n return provider;\n }\n}\n\n/**\n * Get provider icon name (for Lucide icons)\n */\nexport function getProviderIcon(\n provider: ProviderName\n): 'bot' | 'brain' | 'sparkles' | 'zap' | 'cpu' {\n switch (provider) {\n case 'ollama':\n return 'cpu';\n case 'openai':\n return 'brain';\n case 'anthropic':\n return 'sparkles';\n case 'mistral':\n return 'zap';\n case 'gemini':\n return 'bot';\n default:\n return 'bot';\n }\n}\n\n/**\n * Get provider color class for styling\n */\nexport function getProviderColor(provider: ProviderName): string {\n switch (provider) {\n case 'ollama':\n return 'text-neutral-500';\n case 'openai':\n return 'text-emerald-500';\n case 'anthropic':\n return 'text-orange-500';\n case 'mistral':\n return 'text-blue-500';\n case 'gemini':\n return 'text-purple-500';\n default:\n return 'text-neutral-400';\n }\n}\n"],"mappings":";;;;AAQA,SAAgB,kBAAkB,UAAiC;AACjE,QAAO,aAAa;;;;;AAMtB,SAAgB,kBAAkB,UAAiC;AACjE,QAAO,aAAa"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/module.ai-chat",
3
- "version": "0.0.0-canary-20251217083314",
3
+ "version": "0.0.0-canary-20251219202229",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,13 +23,13 @@
23
23
  "test": "bun test"
24
24
  },
25
25
  "dependencies": {
26
- "@lssm/lib.ai-agent": "0.0.0-canary-20251217083314",
27
- "@lssm/lib.ai-providers": "0.0.0-canary-20251217083314",
28
- "@lssm/lib.contracts": "0.0.0-canary-20251217083314",
29
- "@lssm/lib.metering": "0.0.0-canary-20251217083314",
30
- "@lssm/lib.cost-tracking": "0.0.0-canary-20251217083314",
31
- "@lssm/lib.design-system": "0.0.0-canary-20251217083314",
32
- "@lssm/lib.ui-kit-web": "0.0.0-canary-20251217083314",
26
+ "@lssm/lib.ai-agent": "0.0.0-canary-20251219202229",
27
+ "@lssm/lib.ai-providers": "0.0.0-canary-20251219202229",
28
+ "@lssm/lib.contracts": "0.0.0-canary-20251219202229",
29
+ "@lssm/lib.metering": "0.0.0-canary-20251219202229",
30
+ "@lssm/lib.cost-tracking": "0.0.0-canary-20251219202229",
31
+ "@lssm/lib.design-system": "0.0.0-canary-20251219202229",
32
+ "@lssm/lib.ui-kit-web": "0.0.0-canary-20251219202229",
33
33
  "@ai-sdk/react": "beta",
34
34
  "ai": "beta",
35
35
  "lucide-react": "^0.535.0",
@@ -37,10 +37,10 @@
37
37
  "zod": "^4.1.13"
38
38
  },
39
39
  "devDependencies": {
40
- "@lssm/tool.tsdown": "0.0.0-canary-20251217083314",
41
- "@lssm/tool.typescript": "0.0.0-canary-20251217083314",
40
+ "@lssm/tool.tsdown": "0.0.0-canary-20251219202229",
41
+ "@lssm/tool.typescript": "0.0.0-canary-20251219202229",
42
42
  "@types/react": "^19.0.14",
43
- "tsdown": "^0.17.4",
43
+ "tsdown": "^0.18.1",
44
44
  "typescript": "^5.9.3"
45
45
  },
46
46
  "peerDependencies": {
@@ -68,5 +68,6 @@
68
68
  "./providers": "./dist/providers/index.js",
69
69
  "./*": "./*"
70
70
  }
71
- }
71
+ },
72
+ "license": "MIT"
72
73
  }