Merge pull request #24 from garfiec/refactor/file-organization

refactor: extract supporting types and organize into sub-packages
This commit is contained in:
Garfie Chiu 2026-04-07 22:02:59 -05:00 committed by GitHub
commit 2f95d923e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
114 changed files with 789 additions and 641 deletions

View file

@ -0,0 +1,19 @@
package com.garfiec.librechat.core.data.datastore
enum class ChatFontSize {
SMALL, MEDIUM, LARGE;
companion object {
fun fromString(value: String?): ChatFontSize = when (value) {
"small" -> SMALL
"large" -> LARGE
else -> MEDIUM
}
}
fun toStorageString(): String = when (this) {
SMALL -> "small"
MEDIUM -> "medium"
LARGE -> "large"
}
}

View file

@ -5,7 +5,7 @@ import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import com.garfiec.librechat.core.model.EndpointConfig import com.garfiec.librechat.core.model.EndpointConfig
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.MapSerializer import kotlinx.serialization.builtins.MapSerializer

View file

@ -0,0 +1,17 @@
package com.garfiec.librechat.core.data.datastore
enum class LatexRenderer {
NATIVE, KATEX;
companion object {
fun fromString(value: String?): LatexRenderer = when (value) {
"native" -> NATIVE
else -> KATEX
}
}
fun toStorageString(): String = when (this) {
NATIVE -> "native"
KATEX -> "katex"
}
}

View file

@ -10,40 +10,6 @@ import androidx.datastore.preferences.core.stringSetPreferencesKey
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
enum class LatexRenderer {
NATIVE, KATEX;
companion object {
fun fromString(value: String?): LatexRenderer = when (value) {
"native" -> NATIVE
else -> KATEX
}
}
fun toStorageString(): String = when (this) {
NATIVE -> "native"
KATEX -> "katex"
}
}
enum class ChatFontSize {
SMALL, MEDIUM, LARGE;
companion object {
fun fromString(value: String?): ChatFontSize = when (value) {
"small" -> SMALL
"large" -> LARGE
else -> MEDIUM
}
}
fun toStorageString(): String = when (this) {
SMALL -> "small"
MEDIUM -> "medium"
LARGE -> "large"
}
}
class SettingsDataStore( class SettingsDataStore(
private val dataStore: DataStore<Preferences>, private val dataStore: DataStore<Preferences>,
) { ) {

View file

@ -11,10 +11,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
enum class ThemeMode {
SYSTEM, LIGHT, DARK
}
class ThemeDataStore( class ThemeDataStore(
private val dataStore: DataStore<Preferences>, private val dataStore: DataStore<Preferences>,
) { ) {

View file

@ -0,0 +1,5 @@
package com.garfiec.librechat.core.data.datastore
enum class ThemeMode {
SYSTEM, LIGHT, DARK
}

View file

@ -5,7 +5,7 @@ import com.garfiec.librechat.core.model.Attachment
import com.garfiec.librechat.core.model.Feedback import com.garfiec.librechat.core.model.Feedback
import com.garfiec.librechat.core.model.FileReference import com.garfiec.librechat.core.model.FileReference
import com.garfiec.librechat.core.model.Message import com.garfiec.librechat.core.model.Message
import com.garfiec.librechat.core.model.MessageContentPart import com.garfiec.librechat.core.model.content.MessageContentPart
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer

View file

@ -2,7 +2,7 @@ package com.garfiec.librechat.core.data.repository
import com.garfiec.librechat.core.common.result.Result import com.garfiec.librechat.core.common.result.Result
import com.garfiec.librechat.core.model.EndpointConfig import com.garfiec.librechat.core.model.EndpointConfig
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
/** /**

View file

@ -6,7 +6,7 @@ import com.garfiec.librechat.core.common.result.Result
import com.garfiec.librechat.core.common.result.safeApiCall import com.garfiec.librechat.core.common.result.safeApiCall
import com.garfiec.librechat.core.data.datastore.ConfigCacheDataStore import com.garfiec.librechat.core.data.datastore.ConfigCacheDataStore
import com.garfiec.librechat.core.model.EndpointConfig import com.garfiec.librechat.core.model.EndpointConfig
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import com.garfiec.librechat.core.network.api.ConfigApi import com.garfiec.librechat.core.network.api.ConfigApi
import io.ktor.client.plugins.HttpRequestTimeoutException import io.ktor.client.plugins.HttpRequestTimeoutException
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow

View file

@ -0,0 +1,37 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class ContentType {
@SerialName("text")
TEXT,
@SerialName("think")
THINK,
@SerialName("text_delta")
TEXT_DELTA,
@SerialName("tool_call")
TOOL_CALL,
@SerialName("image_file")
IMAGE_FILE,
@SerialName("image_url")
IMAGE_URL,
@SerialName("video_url")
VIDEO_URL,
@SerialName("input_audio")
INPUT_AUDIO,
@SerialName("agent_update")
AGENT_UPDATE,
@SerialName("error")
ERROR,
}

View file

@ -0,0 +1,34 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class EModelEndpoint {
@SerialName("azureOpenAI")
AZURE_OPENAI,
@SerialName("openAI")
OPENAI,
@SerialName("google")
GOOGLE,
@SerialName("anthropic")
ANTHROPIC,
@SerialName("assistants")
ASSISTANTS,
@SerialName("azureAssistants")
AZURE_ASSISTANTS,
@SerialName("agents")
AGENTS,
@SerialName("custom")
CUSTOM,
@SerialName("bedrock")
BEDROCK,
}

View file

@ -1,142 +0,0 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class EModelEndpoint {
@SerialName("azureOpenAI")
AZURE_OPENAI,
@SerialName("openAI")
OPENAI,
@SerialName("google")
GOOGLE,
@SerialName("anthropic")
ANTHROPIC,
@SerialName("assistants")
ASSISTANTS,
@SerialName("azureAssistants")
AZURE_ASSISTANTS,
@SerialName("agents")
AGENTS,
@SerialName("custom")
CUSTOM,
@SerialName("bedrock")
BEDROCK,
}
@Serializable
enum class ContentType {
@SerialName("text")
TEXT,
@SerialName("think")
THINK,
@SerialName("text_delta")
TEXT_DELTA,
@SerialName("tool_call")
TOOL_CALL,
@SerialName("image_file")
IMAGE_FILE,
@SerialName("image_url")
IMAGE_URL,
@SerialName("video_url")
VIDEO_URL,
@SerialName("input_audio")
INPUT_AUDIO,
@SerialName("agent_update")
AGENT_UPDATE,
@SerialName("error")
ERROR,
}
@Serializable
enum class StepType {
@SerialName("tool_calls")
TOOL_CALLS,
@SerialName("message_creation")
MESSAGE_CREATION,
}
@Serializable
enum class ToolCallType {
@SerialName("function")
FUNCTION,
@SerialName("retrieval")
RETRIEVAL,
@SerialName("file_search")
FILE_SEARCH,
@SerialName("code_interpreter")
CODE_INTERPRETER,
@SerialName("tool_call")
TOOL_CALL,
}
@Serializable
enum class FeedbackRating {
@SerialName("thumbsUp")
THUMBS_UP,
@SerialName("thumbsDown")
THUMBS_DOWN,
}
@Serializable
enum class Provider {
@SerialName("openAI")
OPENAI,
@SerialName("anthropic")
ANTHROPIC,
@SerialName("azureOpenAI")
AZURE,
@SerialName("google")
GOOGLE,
@SerialName("vertexai")
VERTEXAI,
@SerialName("bedrock")
BEDROCK,
@SerialName("mistralai")
MISTRALAI,
@SerialName("mistral")
MISTRAL,
@SerialName("deepseek")
DEEPSEEK,
@SerialName("moonshot")
MOONSHOT,
@SerialName("openrouter")
OPENROUTER,
@SerialName("xai")
XAI,
}

View file

@ -0,0 +1,13 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class FeedbackRating {
@SerialName("thumbsUp")
THUMBS_UP,
@SerialName("thumbsDown")
THUMBS_DOWN,
}

View file

@ -1,5 +1,6 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model
import com.garfiec.librechat.core.model.content.MessageContentPart
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject

View file

@ -1,76 +0,0 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
data class MessageContentPart(
val type: ContentType,
val text: String? = null,
val think: String? = null,
val error: String? = null,
@SerialName("tool_call_ids") val toolCallIds: List<String>? = null,
@SerialName("tool_call") val toolCall: AgentToolCall? = null,
@SerialName("image_file") val imageFile: ImageFileContent? = null,
@SerialName("image_url") val imageUrl: ImageUrlContent? = null,
@SerialName("video_url") val videoUrl: VideoUrlContent? = null,
@SerialName("input_audio") val inputAudio: InputAudioContent? = null,
@SerialName("agent_update") val agentUpdate: AgentUpdateContent? = null,
val agentId: String? = null,
val groupId: Int? = null,
val stepIndex: Int? = null,
val siblingIndex: Int? = null,
)
@Serializable
data class AgentToolCall(
val type: ToolCallType? = null,
val name: String? = null,
val args: JsonElement? = null,
val id: String? = null,
val output: String? = null,
val auth: String? = null,
@SerialName("expires_at") val expiresAt: Long? = null,
val function: FunctionCall? = null,
)
@Serializable
data class FunctionCall(
val name: String? = null,
val arguments: String? = null,
val output: String? = null,
)
@Serializable
data class ImageFileContent(
@SerialName("file_id") val fileId: String? = null,
val filepath: String? = null,
val filename: String? = null,
val width: Int? = null,
val height: Int? = null,
)
@Serializable
data class ImageUrlContent(
val url: String? = null,
val detail: String? = null,
)
@Serializable
data class VideoUrlContent(
val url: String? = null,
)
@Serializable
data class InputAudioContent(
val data: String? = null,
val format: String? = null,
)
@Serializable
data class AgentUpdateContent(
val index: Int? = null,
val runId: String? = null,
val agentId: String? = null,
)

View file

@ -0,0 +1,43 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class Provider {
@SerialName("openAI")
OPENAI,
@SerialName("anthropic")
ANTHROPIC,
@SerialName("azureOpenAI")
AZURE,
@SerialName("google")
GOOGLE,
@SerialName("vertexai")
VERTEXAI,
@SerialName("bedrock")
BEDROCK,
@SerialName("mistralai")
MISTRALAI,
@SerialName("mistral")
MISTRAL,
@SerialName("deepseek")
DEEPSEEK,
@SerialName("moonshot")
MOONSHOT,
@SerialName("openrouter")
OPENROUTER,
@SerialName("xai")
XAI,
}

View file

@ -1,5 +1,6 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model
import com.garfiec.librechat.core.model.content.MessageContentPart
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject

View file

@ -0,0 +1,13 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class StepType {
@SerialName("tool_calls")
TOOL_CALLS,
@SerialName("message_creation")
MESSAGE_CREATION,
}

View file

@ -1,5 +1,7 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model
import com.garfiec.librechat.core.model.content.MessageContentPart
sealed interface StreamEvent { sealed interface StreamEvent {
data class ContentDelta( data class ContentDelta(
val chunk: String, val chunk: String,

View file

@ -0,0 +1,22 @@
package com.garfiec.librechat.core.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class ToolCallType {
@SerialName("function")
FUNCTION,
@SerialName("retrieval")
RETRIEVAL,
@SerialName("file_search")
FILE_SEARCH,
@SerialName("code_interpreter")
CODE_INTERPRETER,
@SerialName("tool_call")
TOOL_CALL,
}

View file

@ -0,0 +1,13 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class BalanceConfig(
val enabled: Boolean = false,
val startBalance: Long? = null,
val autoRefillEnabled: Boolean = false,
val refillIntervalValue: Int? = null,
val refillIntervalUnit: String? = null,
val refillAmount: Long? = null,
)

View file

@ -0,0 +1,27 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
data class InterfaceConfig(
val privacyPolicy: PrivacyPolicyConfig? = null,
val termsOfService: TermsOfServiceConfig? = null,
val endpointsMenu: Boolean = true,
val modelSelect: Boolean = true,
val parameters: Boolean = true,
val presets: Boolean = true,
val sidePanel: Boolean = true,
val bookmarks: Boolean = true,
val prompts: JsonElement? = null,
val agents: JsonElement? = null,
val multiConvo: Boolean = true,
val memories: Boolean = true,
val temporaryChat: Boolean = true,
val runCode: Boolean = true,
val webSearch: Boolean = true,
val fileSearch: Boolean = true,
val fileCitations: Boolean = true,
val customWelcome: String? = null,
val remoteAgents: JsonElement? = null,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class LdapConfig(
val enabled: Boolean = false,
val username: Boolean? = null,
)

View file

@ -0,0 +1,13 @@
package com.garfiec.librechat.core.model.config
import com.garfiec.librechat.core.model.Preset
import kotlinx.serialization.Serializable
@Serializable
data class ModelSpec(
val name: String,
val label: String? = null,
val preset: Preset? = null,
val iconURL: String? = null,
val description: String? = null,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class ModelSpecs(
val list: List<ModelSpec> = emptyList(),
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class PrivacyPolicyConfig(
val externalUrl: String? = null,
val openNewTab: Boolean? = null,
)

View file

@ -1,8 +1,8 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model.config
import com.garfiec.librechat.core.model.Preset
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
@Serializable @Serializable
@ -52,79 +52,3 @@ data class StartupConfig(
/** Backend version, if the server includes it in the config response (not yet standard). */ /** Backend version, if the server includes it in the config response (not yet standard). */
val version: String? = null, val version: String? = null,
) )
@Serializable
data class ModelSpecs(
val list: List<ModelSpec> = emptyList(),
)
@Serializable
data class ModelSpec(
val name: String,
val label: String? = null,
val preset: Preset? = null,
val iconURL: String? = null,
val description: String? = null,
)
@Serializable
data class InterfaceConfig(
val privacyPolicy: PrivacyPolicyConfig? = null,
val termsOfService: TermsOfServiceConfig? = null,
val endpointsMenu: Boolean = true,
val modelSelect: Boolean = true,
val parameters: Boolean = true,
val presets: Boolean = true,
val sidePanel: Boolean = true,
val bookmarks: Boolean = true,
val prompts: JsonElement? = null,
val agents: JsonElement? = null,
val multiConvo: Boolean = true,
val memories: Boolean = true,
val temporaryChat: Boolean = true,
val runCode: Boolean = true,
val webSearch: Boolean = true,
val fileSearch: Boolean = true,
val fileCitations: Boolean = true,
val customWelcome: String? = null,
val remoteAgents: JsonElement? = null,
)
@Serializable
data class PrivacyPolicyConfig(
val externalUrl: String? = null,
val openNewTab: Boolean? = null,
)
@Serializable
data class TermsOfServiceConfig(
val externalUrl: String? = null,
)
@Serializable
data class TurnstileConfig(
val siteKey: String? = null,
val options: TurnstileOptions? = null,
)
@Serializable
data class TurnstileOptions(
val language: String? = null,
val size: String? = null,
)
@Serializable
data class BalanceConfig(
val enabled: Boolean = false,
val startBalance: Long? = null,
val autoRefillEnabled: Boolean = false,
val refillIntervalValue: Int? = null,
val refillIntervalUnit: String? = null,
val refillAmount: Long? = null,
)
@Serializable
data class LdapConfig(
val enabled: Boolean = false,
val username: Boolean? = null,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class TermsOfServiceConfig(
val externalUrl: String? = null,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class TurnstileConfig(
val siteKey: String? = null,
val options: TurnstileOptions? = null,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.config
import kotlinx.serialization.Serializable
@Serializable
data class TurnstileOptions(
val language: String? = null,
val size: String? = null,
)

View file

@ -0,0 +1,18 @@
package com.garfiec.librechat.core.model.content
import com.garfiec.librechat.core.model.ToolCallType
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
data class AgentToolCall(
val type: ToolCallType? = null,
val name: String? = null,
val args: JsonElement? = null,
val id: String? = null,
val output: String? = null,
val auth: String? = null,
@SerialName("expires_at") val expiresAt: Long? = null,
val function: FunctionCall? = null,
)

View file

@ -0,0 +1,10 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.Serializable
@Serializable
data class AgentUpdateContent(
val index: Int? = null,
val runId: String? = null,
val agentId: String? = null,
)

View file

@ -0,0 +1,10 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.Serializable
@Serializable
data class FunctionCall(
val name: String? = null,
val arguments: String? = null,
val output: String? = null,
)

View file

@ -0,0 +1,13 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ImageFileContent(
@SerialName("file_id") val fileId: String? = null,
val filepath: String? = null,
val filename: String? = null,
val width: Int? = null,
val height: Int? = null,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.Serializable
@Serializable
data class ImageUrlContent(
val url: String? = null,
val detail: String? = null,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.Serializable
@Serializable
data class InputAudioContent(
val data: String? = null,
val format: String? = null,
)

View file

@ -0,0 +1,24 @@
package com.garfiec.librechat.core.model.content
import com.garfiec.librechat.core.model.ContentType
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class MessageContentPart(
val type: ContentType,
val text: String? = null,
val think: String? = null,
val error: String? = null,
@SerialName("tool_call_ids") val toolCallIds: List<String>? = null,
@SerialName("tool_call") val toolCall: AgentToolCall? = null,
@SerialName("image_file") val imageFile: ImageFileContent? = null,
@SerialName("image_url") val imageUrl: ImageUrlContent? = null,
@SerialName("video_url") val videoUrl: VideoUrlContent? = null,
@SerialName("input_audio") val inputAudio: InputAudioContent? = null,
@SerialName("agent_update") val agentUpdate: AgentUpdateContent? = null,
val agentId: String? = null,
val groupId: Int? = null,
val stepIndex: Int? = null,
val siblingIndex: Int? = null,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.model.content
import kotlinx.serialization.Serializable
@Serializable
data class VideoUrlContent(
val url: String? = null,
)

View file

@ -0,0 +1,44 @@
package com.garfiec.librechat.core.model.mcp
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** Maps to backend apiKey object: { source, authorization_type, key?, custom_header? }. */
@Serializable
data class McpApiKeyConfig(
val source: McpApiKeySource = McpApiKeySource.USER,
@SerialName("authorization_type") val authorizationType: McpAuthorizationType = McpAuthorizationType.BEARER,
val key: String? = null,
@SerialName("custom_header") val customHeader: String? = null,
)
@Serializable
enum class McpApiKeySource {
@SerialName("admin")
ADMIN,
@SerialName("user")
USER,
}
@Serializable
enum class McpAuthorizationType {
@SerialName("bearer")
BEARER,
@SerialName("basic")
BASIC,
@SerialName("custom")
CUSTOM,
}
/** Maps to backend oauth object. Only the most common fields are exposed in the UI. */
@Serializable
data class McpOAuthConfig(
@SerialName("authorization_url") val authorizationUrl: String? = null,
@SerialName("token_url") val tokenUrl: String? = null,
@SerialName("client_id") val clientId: String? = null,
@SerialName("client_secret") val clientSecret: String? = null,
val scope: String? = null,
)

View file

@ -0,0 +1,4 @@
package com.garfiec.librechat.core.model.mcp
/** Auth mode for the MCP server add/edit dialog. */
enum class McpAuthMode { NONE, API_KEY, OAUTH }

View file

@ -1,8 +1,5 @@
package com.garfiec.librechat.core.model.mcp package com.garfiec.librechat.core.model.mcp
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** /**
* Represents an MCP server as shown in the UI. * Represents an MCP server as shown in the UI.
* The backend returns a map of server name -> config from GET /api/mcp/servers. * The backend returns a map of server name -> config from GET /api/mcp/servers.
@ -20,64 +17,3 @@ data class McpServer(
val apiKey: McpApiKeyConfig? = null, val apiKey: McpApiKeyConfig? = null,
val oauth: McpOAuthConfig? = null, val oauth: McpOAuthConfig? = null,
) )
@Serializable
enum class McpServerType {
@SerialName("sse")
SSE,
@SerialName("streamable-http")
STREAMABLE_HTTP,
@SerialName("http")
HTTP,
@SerialName("stdio")
STDIO,
@SerialName("websocket")
WEBSOCKET,
}
/** Auth mode for the MCP server add/edit dialog. */
enum class McpAuthMode { NONE, API_KEY, OAUTH }
/** Maps to backend apiKey object: { source, authorization_type, key?, custom_header? }. */
@Serializable
data class McpApiKeyConfig(
val source: McpApiKeySource = McpApiKeySource.USER,
@SerialName("authorization_type") val authorizationType: McpAuthorizationType = McpAuthorizationType.BEARER,
val key: String? = null,
@SerialName("custom_header") val customHeader: String? = null,
)
@Serializable
enum class McpApiKeySource {
@SerialName("admin")
ADMIN,
@SerialName("user")
USER,
}
@Serializable
enum class McpAuthorizationType {
@SerialName("bearer")
BEARER,
@SerialName("basic")
BASIC,
@SerialName("custom")
CUSTOM,
}
/** Maps to backend oauth object. Only the most common fields are exposed in the UI. */
@Serializable
data class McpOAuthConfig(
@SerialName("authorization_url") val authorizationUrl: String? = null,
@SerialName("token_url") val tokenUrl: String? = null,
@SerialName("client_id") val clientId: String? = null,
@SerialName("client_secret") val clientSecret: String? = null,
val scope: String? = null,
)

View file

@ -0,0 +1,22 @@
package com.garfiec.librechat.core.model.mcp
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class McpServerType {
@SerialName("sse")
SSE,
@SerialName("streamable-http")
STREAMABLE_HTTP,
@SerialName("http")
HTTP,
@SerialName("stdio")
STDIO,
@SerialName("websocket")
WEBSOCKET,
}

View file

@ -1,5 +1,6 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model
import com.garfiec.librechat.core.model.content.MessageContentPart
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive

View file

@ -1,5 +1,7 @@
package com.garfiec.librechat.core.model package com.garfiec.librechat.core.model
import com.garfiec.librechat.core.model.content.AgentToolCall
import com.garfiec.librechat.core.model.content.MessageContentPart
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive

View file

@ -1,5 +1,8 @@
package com.garfiec.librechat.core.network.api package com.garfiec.librechat.core.network.api
import com.garfiec.librechat.core.network.api.dto.LoginResult
import com.garfiec.librechat.core.network.api.dto.RefreshResult
import com.garfiec.librechat.core.network.api.dto.TwoFactorConfirmRequest
import com.garfiec.librechat.core.model.request.LoginRequest import com.garfiec.librechat.core.model.request.LoginRequest
import com.garfiec.librechat.core.model.request.OtpVerificationRequest import com.garfiec.librechat.core.model.request.OtpVerificationRequest
import com.garfiec.librechat.core.model.request.PasswordResetRequest import com.garfiec.librechat.core.model.request.PasswordResetRequest
@ -15,23 +18,10 @@ import com.garfiec.librechat.core.model.response.TwoFactorSetupResponse
import com.garfiec.librechat.core.network.client.CookieHelper import com.garfiec.librechat.core.network.client.CookieHelper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.header import io.ktor.client.request.header
import io.ktor.client.request.post import io.ktor.client.request.post
import io.ktor.client.request.setBody import io.ktor.client.request.setBody
import io.ktor.http.path import io.ktor.http.path
import kotlinx.serialization.Serializable
data class LoginResult(
val response: LoginResponse,
val refreshToken: String?,
)
data class RefreshResult(
val response: RefreshResponse,
/** New refresh token from Set-Cookie header, if the backend rotated it. */
val newRefreshToken: String?,
)
class AuthApi constructor( class AuthApi constructor(
private val client: HttpClient, private val client: HttpClient,
@ -169,8 +159,3 @@ class AuthApi constructor(
} }
} }
} }
@Serializable
data class TwoFactorConfirmRequest(
val token: String,
)

View file

@ -1,7 +1,7 @@
package com.garfiec.librechat.core.network.api package com.garfiec.librechat.core.network.api
import com.garfiec.librechat.core.model.EndpointConfig import com.garfiec.librechat.core.model.EndpointConfig
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import com.garfiec.librechat.core.model.response.Category import com.garfiec.librechat.core.model.response.Category
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.body import io.ktor.client.call.body

View file

@ -1,5 +1,8 @@
package com.garfiec.librechat.core.network.api package com.garfiec.librechat.core.network.api
import com.garfiec.librechat.core.network.api.dto.UpdateFavoritesRequest
import com.garfiec.librechat.core.network.api.dto.UpdatePluginsRequest
import com.garfiec.librechat.core.network.api.dto.UserUpdateRequest
import com.garfiec.librechat.core.model.User import com.garfiec.librechat.core.model.User
import com.garfiec.librechat.core.model.UserFavorite import com.garfiec.librechat.core.model.UserFavorite
import com.garfiec.librechat.core.model.request.OtpVerificationRequest import com.garfiec.librechat.core.model.request.OtpVerificationRequest
@ -17,23 +20,6 @@ import io.ktor.client.request.setBody
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders
import io.ktor.http.path import io.ktor.http.path
import kotlinx.serialization.Serializable
@Serializable
data class UserUpdateRequest(
val name: String? = null,
val username: String? = null,
)
@Serializable
data class UpdateFavoritesRequest(
val favorites: List<UserFavorite>,
)
@Serializable
data class UpdatePluginsRequest(
val plugins: List<String>,
)
class UserApi constructor( class UserApi constructor(
private val client: HttpClient, private val client: HttpClient,

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.network.api.dto
import com.garfiec.librechat.core.model.response.LoginResponse
data class LoginResult(
val response: LoginResponse,
val refreshToken: String?,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.network.api.dto
import com.garfiec.librechat.core.model.response.RefreshResponse
data class RefreshResult(
val response: RefreshResponse,
/** New refresh token from Set-Cookie header, if the backend rotated it. */
val newRefreshToken: String?,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.network.api.dto
import kotlinx.serialization.Serializable
@Serializable
data class TwoFactorConfirmRequest(
val token: String,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.network.api.dto
import com.garfiec.librechat.core.model.UserFavorite
import kotlinx.serialization.Serializable
@Serializable
data class UpdateFavoritesRequest(
val favorites: List<UserFavorite>,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.core.network.api.dto
import kotlinx.serialization.Serializable
@Serializable
data class UpdatePluginsRequest(
val plugins: List<String>,
)

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.core.network.api.dto
import kotlinx.serialization.Serializable
@Serializable
data class UserUpdateRequest(
val name: String? = null,
val username: String? = null,
)

View file

@ -210,7 +210,7 @@ class SseEventMapper(private val json: Json) {
aggregatedContent.mapNotNull { element -> aggregatedContent.mapNotNull { element ->
try { try {
json.decodeFromJsonElement( json.decodeFromJsonElement(
com.garfiec.librechat.core.model.MessageContentPart.serializer(), com.garfiec.librechat.core.model.content.MessageContentPart.serializer(),
element, element,
) )
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -82,6 +82,3 @@ class SseLineParser(
const val DEFAULT_LINE_READ_TIMEOUT_MS = 120_000L const val DEFAULT_LINE_READ_TIMEOUT_MS = 120_000L
} }
} }
/** Cross-platform exception for SSE stream errors (replaces java.io.IOException). */
class SseStreamException(message: String, cause: Throwable? = null) : Exception(message, cause)

View file

@ -0,0 +1,4 @@
package com.garfiec.librechat.core.network.sse
/** Cross-platform exception for SSE stream errors (replaces java.io.IOException). */
class SseStreamException(message: String, cause: Throwable? = null) : Exception(message, cause)

View file

@ -32,12 +32,7 @@ import androidx.compose.ui.unit.dp
import librechat_mobile.feature.agents.generated.resources.Res import librechat_mobile.feature.agents.generated.resources.Res
import librechat_mobile.feature.agents.generated.resources.* import librechat_mobile.feature.agents.generated.resources.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
import com.garfiec.librechat.feature.agents.components.model.AgentAdvancedSettings
data class AgentAdvancedSettings(
val temperature: Float? = null,
val topP: Float? = null,
val maxTokens: Int? = null,
)
@Composable @Composable
fun AgentAdvancedPanel( fun AgentAdvancedPanel(

View file

@ -20,13 +20,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import librechat_mobile.feature.agents.generated.resources.Res import librechat_mobile.feature.agents.generated.resources.Res
import librechat_mobile.feature.agents.generated.resources.* import librechat_mobile.feature.agents.generated.resources.*
import com.garfiec.librechat.feature.agents.components.model.AgentCapabilities
data class AgentCapabilities(
val artifacts: Boolean = false,
val endAfterTools: Boolean = false,
val hideSequentialOutputs: Boolean = false,
val recursionLimit: Int = 25,
)
@Composable @Composable
fun AgentCapabilitiesSection( fun AgentCapabilitiesSection(

View file

@ -33,18 +33,8 @@ import org.jetbrains.compose.resources.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import librechat_mobile.feature.agents.generated.resources.Res import librechat_mobile.feature.agents.generated.resources.Res
import librechat_mobile.feature.agents.generated.resources.* import librechat_mobile.feature.agents.generated.resources.*
import com.garfiec.librechat.feature.agents.components.model.AgentSharingState
enum class AgentVisibility(val label: String) { import com.garfiec.librechat.feature.agents.components.model.AgentVisibility
PRIVATE("Private"),
TEAM("Team"),
PUBLIC("Public"),
}
@androidx.compose.runtime.Immutable
data class AgentSharingState(
val visibility: AgentVisibility = AgentVisibility.PRIVATE,
val isCollaborative: Boolean = false,
)
/** Visibility (Private/Team/Public) and collaborative toggle; maps to agent model isPublic/isCollaborative. */ /** Visibility (Private/Team/Public) and collaborative toggle; maps to agent model isPublic/isCollaborative. */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)

View file

@ -13,12 +13,7 @@ import org.jetbrains.compose.resources.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import librechat_mobile.feature.agents.generated.resources.Res import librechat_mobile.feature.agents.generated.resources.Res
import librechat_mobile.feature.agents.generated.resources.* import librechat_mobile.feature.agents.generated.resources.*
import com.garfiec.librechat.feature.agents.components.model.SupportContactState
@androidx.compose.runtime.Immutable
data class SupportContactState(
val name: String = "",
val email: String = "",
)
@Composable @Composable
fun AgentSupportContactSection( fun AgentSupportContactSection(

View file

@ -25,12 +25,7 @@ import org.jetbrains.compose.resources.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import librechat_mobile.feature.agents.generated.resources.Res import librechat_mobile.feature.agents.generated.resources.Res
import librechat_mobile.feature.agents.generated.resources.* import librechat_mobile.feature.agents.generated.resources.*
import com.garfiec.librechat.feature.agents.components.model.AgentVersion
data class AgentVersion(
val version: Int,
val updatedAt: String?,
val isCurrent: Boolean = false,
)
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable

View file

@ -0,0 +1,7 @@
package com.garfiec.librechat.feature.agents.components.model
data class AgentAdvancedSettings(
val temperature: Float? = null,
val topP: Float? = null,
val maxTokens: Int? = null,
)

View file

@ -0,0 +1,8 @@
package com.garfiec.librechat.feature.agents.components.model
data class AgentCapabilities(
val artifacts: Boolean = false,
val endAfterTools: Boolean = false,
val hideSequentialOutputs: Boolean = false,
val recursionLimit: Int = 25,
)

View file

@ -0,0 +1,7 @@
package com.garfiec.librechat.feature.agents.components.model
@androidx.compose.runtime.Immutable
data class AgentSharingState(
val visibility: AgentVisibility = AgentVisibility.PRIVATE,
val isCollaborative: Boolean = false,
)

View file

@ -0,0 +1,7 @@
package com.garfiec.librechat.feature.agents.components.model
data class AgentVersion(
val version: Int,
val updatedAt: String?,
val isCurrent: Boolean = false,
)

View file

@ -0,0 +1,7 @@
package com.garfiec.librechat.feature.agents.components.model
enum class AgentVisibility(val label: String) {
PRIVATE("Private"),
TEAM("Team"),
PUBLIC("Public"),
}

View file

@ -0,0 +1,7 @@
package com.garfiec.librechat.feature.agents.components.model
@androidx.compose.runtime.Immutable
data class SupportContactState(
val name: String = "",
val email: String = "",
)

View file

@ -0,0 +1,12 @@
package com.garfiec.librechat.feature.agents.util
import com.garfiec.librechat.core.model.request.FunctionTool
/**
* Result of parsing an OpenAPI spec.
*/
data class OpenApiParseResult(
val domain: String,
val functions: List<FunctionTool>,
val errors: List<String> = emptyList(),
)

View file

@ -12,25 +12,6 @@ import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
/**
* Result of parsing an OpenAPI spec.
*/
data class OpenApiParseResult(
val domain: String,
val functions: List<FunctionTool>,
val errors: List<String> = emptyList(),
)
/**
* Represents a parsed function for display in the available actions table.
*/
data class ParsedFunctionInfo(
val name: String,
val method: String,
val path: String,
val description: String,
)
/** /**
* Parses an OpenAPI specification and extracts function definitions. * Parses an OpenAPI specification and extracts function definitions.
* *

View file

@ -0,0 +1,11 @@
package com.garfiec.librechat.feature.agents.util
/**
* Represents a parsed function for display in the available actions table.
*/
data class ParsedFunctionInfo(
val name: String,
val method: String,
val path: String,
val description: String,
)

View file

@ -24,13 +24,13 @@ import com.garfiec.librechat.core.model.request.UpdateAgentRequest
import com.garfiec.librechat.feature.agents.AgentActionDisplayData import com.garfiec.librechat.feature.agents.AgentActionDisplayData
import com.garfiec.librechat.feature.agents.AgentHandoffDisplayData import com.garfiec.librechat.feature.agents.AgentHandoffDisplayData
import com.garfiec.librechat.feature.agents.AgentToolDisplayData import com.garfiec.librechat.feature.agents.AgentToolDisplayData
import com.garfiec.librechat.feature.agents.components.AgentAdvancedSettings
import com.garfiec.librechat.feature.agents.components.AgentCapabilities
import com.garfiec.librechat.feature.agents.components.AgentSharingState
import com.garfiec.librechat.feature.agents.components.AgentVersion
import com.garfiec.librechat.feature.agents.components.AgentVisibility
import com.garfiec.librechat.feature.agents.components.ModelOption import com.garfiec.librechat.feature.agents.components.ModelOption
import com.garfiec.librechat.feature.agents.components.SupportContactState import com.garfiec.librechat.feature.agents.components.model.AgentAdvancedSettings
import com.garfiec.librechat.feature.agents.components.model.AgentCapabilities
import com.garfiec.librechat.feature.agents.components.model.AgentSharingState
import com.garfiec.librechat.feature.agents.components.model.AgentVersion
import com.garfiec.librechat.feature.agents.components.model.AgentVisibility
import com.garfiec.librechat.feature.agents.components.model.SupportContactState
import com.garfiec.librechat.feature.agents.util.OpenApiSpecParser import com.garfiec.librechat.feature.agents.util.OpenApiSpecParser
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow

View file

@ -6,7 +6,7 @@ import com.garfiec.librechat.core.data.datastore.ServerDataStore
import com.garfiec.librechat.core.data.repository.AuthRepository import com.garfiec.librechat.core.data.repository.AuthRepository
import com.garfiec.librechat.core.data.repository.ConfigRepository import com.garfiec.librechat.core.data.repository.ConfigRepository
import com.garfiec.librechat.core.model.LoginOutcome import com.garfiec.librechat.core.model.LoginOutcome
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import com.garfiec.librechat.core.model.User import com.garfiec.librechat.core.model.User
import com.garfiec.librechat.feature.auth.oauth.OAuthLauncher import com.garfiec.librechat.feature.auth.oauth.OAuthLauncher
import io.mockk.coEvery import io.mockk.coEvery

View file

@ -4,7 +4,7 @@ import com.google.common.truth.Truth.assertThat
import com.garfiec.librechat.core.common.result.Result import com.garfiec.librechat.core.common.result.Result
import com.garfiec.librechat.core.data.repository.AuthRepository import com.garfiec.librechat.core.data.repository.AuthRepository
import com.garfiec.librechat.core.data.repository.ConfigRepository import com.garfiec.librechat.core.data.repository.ConfigRepository
import com.garfiec.librechat.core.model.StartupConfig import com.garfiec.librechat.core.model.config.StartupConfig
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.every import io.mockk.every

View file

@ -51,8 +51,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*
import java.io.File import java.io.File

View file

@ -3,7 +3,7 @@ package com.garfiec.librechat.feature.chat.components
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.LayoutCoordinates import androidx.compose.ui.layout.LayoutCoordinates
import com.garfiec.librechat.core.model.MessageContentPart import com.garfiec.librechat.core.model.content.MessageContentPart
@Composable @Composable
actual fun ContentPartRenderer( actual fun ContentPartRenderer(

View file

@ -74,7 +74,7 @@ import com.garfiec.librechat.core.common.EndpointConstants
import com.garfiec.librechat.core.data.datastore.ChatFontSize import com.garfiec.librechat.core.data.datastore.ChatFontSize
import com.garfiec.librechat.core.data.datastore.LatexRenderer import com.garfiec.librechat.core.data.datastore.LatexRenderer
import com.garfiec.librechat.core.model.ContentType import com.garfiec.librechat.core.model.ContentType
import com.garfiec.librechat.core.model.MessageContentPart import com.garfiec.librechat.core.model.content.MessageContentPart
import com.garfiec.librechat.core.ui.components.LoadingIndicator import com.garfiec.librechat.core.ui.components.LoadingIndicator
import com.garfiec.librechat.core.ui.components.ModelParameterSheet import com.garfiec.librechat.core.ui.components.ModelParameterSheet
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res

View file

@ -1,26 +0,0 @@
package com.garfiec.librechat.feature.chat
import androidx.compose.runtime.Immutable
@Immutable
data class PresetDisplayData(
val presetId: String?,
val title: String,
val endpointLabel: String?,
val model: String?,
)
@Immutable
data class PromptMentionDisplayData(
val name: String,
val command: String?,
val oneliner: String?,
)
@Immutable
data class McpServerDisplayData(
val name: String,
val title: String?,
val description: String?,
val isConnected: Boolean,
)

View file

@ -52,7 +52,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.garfiec.librechat.core.common.ToolConstants import com.garfiec.librechat.core.common.ToolConstants
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*

View file

@ -1,6 +1,6 @@
package com.garfiec.librechat.feature.chat.components package com.garfiec.librechat.feature.chat.components
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
/** /**
* Extracts the @mention query from the input text. * Extracts the @mention query from the input text.

View file

@ -35,7 +35,7 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.core.common.ToolConstants import com.garfiec.librechat.core.common.ToolConstants
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*

View file

@ -54,7 +54,7 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.core.common.ToolConstants import com.garfiec.librechat.core.common.ToolConstants
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*

View file

@ -41,7 +41,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.cd_send_message import librechat_mobile.feature.chat.generated.resources.cd_send_message
import librechat_mobile.feature.chat.generated.resources.cd_start_voice_recording import librechat_mobile.feature.chat.generated.resources.cd_start_voice_recording

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*

View file

@ -5,7 +5,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.LayoutCoordinates import androidx.compose.ui.layout.LayoutCoordinates
import com.garfiec.librechat.core.common.ChatLayoutConstants import com.garfiec.librechat.core.common.ChatLayoutConstants
import com.garfiec.librechat.core.model.Message import com.garfiec.librechat.core.model.Message
import com.garfiec.librechat.core.model.MessageContentPart import com.garfiec.librechat.core.model.content.MessageContentPart
/** Platform-specific message bubble. */ /** Platform-specific message bubble. */
@Composable @Composable

View file

@ -28,7 +28,7 @@ import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.resources.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.feature.chat.PresetDisplayData import com.garfiec.librechat.feature.chat.model.PresetDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.* import librechat_mobile.feature.chat.generated.resources.*

View file

@ -48,7 +48,7 @@ import coil3.compose.SubcomposeAsyncImage
import com.garfiec.librechat.core.common.ToolConstants import com.garfiec.librechat.core.common.ToolConstants
import com.garfiec.librechat.core.model.Attachment import com.garfiec.librechat.core.model.Attachment
import com.garfiec.librechat.core.model.ContentType import com.garfiec.librechat.core.model.ContentType
import com.garfiec.librechat.core.model.MessageContentPart import com.garfiec.librechat.core.model.content.MessageContentPart
import com.garfiec.librechat.feature.chat.components.artifact.Artifact import com.garfiec.librechat.feature.chat.components.artifact.Artifact
import com.garfiec.librechat.feature.chat.components.artifact.ArtifactButton import com.garfiec.librechat.feature.chat.components.artifact.ArtifactButton
import com.garfiec.librechat.feature.chat.components.artifact.ArtifactPanel import com.garfiec.librechat.feature.chat.components.artifact.ArtifactPanel

View file

@ -10,7 +10,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
/** /**
* Dropdown menu showing slash command suggestions. * Dropdown menu showing slash command suggestions.

View file

@ -1,6 +1,6 @@
package com.garfiec.librechat.feature.chat.components package com.garfiec.librechat.feature.chat.components
import com.garfiec.librechat.core.model.AgentToolCall import com.garfiec.librechat.core.model.content.AgentToolCall
import com.garfiec.librechat.core.model.Attachment import com.garfiec.librechat.core.model.Attachment
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray

View file

@ -0,0 +1,26 @@
package com.garfiec.librechat.feature.chat.components.artifact
/**
* Parsed artifact extracted from message content. Artifacts are marked in LLM
* responses using the remark-directive markdown format:
*
* ```
* :::artifact{identifier="id" type="mime-type" title="Title"}
* ```language
* ...content...
* ```
* :::
* ```
*
* Supported types: text/html, image/svg+xml, application/vnd.react,
* application/vnd.mermaid, text/markdown, text/md, text/plain,
* application/vnd.code-html.
*/
data class Artifact(
val identifier: String,
val type: String,
val title: String,
val language: String?,
val content: String,
val version: Int = 1,
)

View file

@ -1,38 +1,5 @@
package com.garfiec.librechat.feature.chat.components.artifact package com.garfiec.librechat.feature.chat.components.artifact
/**
* Parsed artifact extracted from message content. Artifacts are marked in LLM
* responses using the remark-directive markdown format:
*
* ```
* :::artifact{identifier="id" type="mime-type" title="Title"}
* ```language
* ...content...
* ```
* :::
* ```
*
* Supported types: text/html, image/svg+xml, application/vnd.react,
* application/vnd.mermaid, text/markdown, text/md, text/plain,
* application/vnd.code-html.
*/
data class Artifact(
val identifier: String,
val type: String,
val title: String,
val language: String?,
val content: String,
val version: Int = 1,
)
/**
* Segment of message text that is either plain content or an artifact.
*/
sealed interface ArtifactSegment {
data class Text(val text: String) : ArtifactSegment
data class ArtifactReference(val artifact: Artifact) : ArtifactSegment
}
/** /**
* Matches the remark-directive artifact format: * Matches the remark-directive artifact format:
* :::artifact{key="value" ...} * :::artifact{key="value" ...}

View file

@ -0,0 +1,9 @@
package com.garfiec.librechat.feature.chat.components.artifact
/**
* Segment of message text that is either plain content or an artifact.
*/
sealed interface ArtifactSegment {
data class Text(val text: String) : ArtifactSegment
data class ArtifactReference(val artifact: Artifact) : ArtifactSegment
}

View file

@ -0,0 +1,11 @@
package com.garfiec.librechat.feature.chat.model
import androidx.compose.runtime.Immutable
@Immutable
data class McpServerDisplayData(
val name: String,
val title: String?,
val description: String?,
val isConnected: Boolean,
)

View file

@ -0,0 +1,11 @@
package com.garfiec.librechat.feature.chat.model
import androidx.compose.runtime.Immutable
@Immutable
data class PresetDisplayData(
val presetId: String?,
val title: String,
val endpointLabel: String?,
val model: String?,
)

View file

@ -0,0 +1,10 @@
package com.garfiec.librechat.feature.chat.model
import androidx.compose.runtime.Immutable
@Immutable
data class PromptMentionDisplayData(
val name: String,
val command: String?,
val oneliner: String?,
)

View file

@ -8,9 +8,9 @@ import com.garfiec.librechat.core.data.datastore.LatexRenderer
import com.garfiec.librechat.core.model.Agent import com.garfiec.librechat.core.model.Agent
import com.garfiec.librechat.core.model.EndpointConfig import com.garfiec.librechat.core.model.EndpointConfig
import com.garfiec.librechat.core.ui.components.ModelParameters import com.garfiec.librechat.core.ui.components.ModelParameters
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import com.garfiec.librechat.feature.chat.PresetDisplayData import com.garfiec.librechat.feature.chat.model.PresetDisplayData
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
import com.garfiec.librechat.feature.chat.util.MessageNode import com.garfiec.librechat.feature.chat.util.MessageNode
enum class ChatScreenState { LANDING, LOADING, ACTIVE } enum class ChatScreenState { LANDING, LOADING, ACTIVE }

View file

@ -27,8 +27,8 @@ import com.garfiec.librechat.core.model.Preset
import com.garfiec.librechat.core.model.StreamEvent import com.garfiec.librechat.core.model.StreamEvent
import com.garfiec.librechat.core.model.request.EphemeralAgent import com.garfiec.librechat.core.model.request.EphemeralAgent
import com.garfiec.librechat.core.ui.components.ModelParameters import com.garfiec.librechat.core.ui.components.ModelParameters
import com.garfiec.librechat.feature.chat.PresetDisplayData import com.garfiec.librechat.feature.chat.model.PresetDisplayData
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
import com.garfiec.librechat.feature.chat.components.AttachedFile import com.garfiec.librechat.feature.chat.components.AttachedFile
import com.garfiec.librechat.feature.chat.util.NEW_CHAT_DRAFT_KEY import com.garfiec.librechat.feature.chat.util.NEW_CHAT_DRAFT_KEY
import com.garfiec.librechat.feature.chat.util.buildActiveMessagePath import com.garfiec.librechat.feature.chat.util.buildActiveMessagePath

View file

@ -0,0 +1,15 @@
package com.garfiec.librechat.feature.chat.viewmodel.delegate
import com.garfiec.librechat.core.model.EModelEndpoint
internal fun EModelEndpoint.toSerialName(): String = when (this) {
EModelEndpoint.AZURE_OPENAI -> "azureOpenAI"
EModelEndpoint.OPENAI -> "openAI"
EModelEndpoint.GOOGLE -> "google"
EModelEndpoint.ANTHROPIC -> "anthropic"
EModelEndpoint.ASSISTANTS -> "assistants"
EModelEndpoint.AZURE_ASSISTANTS -> "azureAssistants"
EModelEndpoint.AGENTS -> "agents"
EModelEndpoint.CUSTOM -> "custom"
EModelEndpoint.BEDROCK -> "bedrock"
}

View file

@ -11,7 +11,7 @@ import com.garfiec.librechat.core.model.EModelEndpoint
import com.garfiec.librechat.core.model.mcp.McpServer import com.garfiec.librechat.core.model.mcp.McpServer
import com.garfiec.librechat.core.model.request.AddedConversation import com.garfiec.librechat.core.model.request.AddedConversation
import com.garfiec.librechat.core.ui.components.ModelParameters import com.garfiec.librechat.core.ui.components.ModelParameters
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import com.garfiec.librechat.feature.chat.viewmodel.ChatScreenState import com.garfiec.librechat.feature.chat.viewmodel.ChatScreenState
import com.garfiec.librechat.feature.chat.viewmodel.ChatStateHandle import com.garfiec.librechat.feature.chat.viewmodel.ChatStateHandle
import com.garfiec.librechat.feature.chat.viewmodel.ComparisonState import com.garfiec.librechat.feature.chat.viewmodel.ComparisonState
@ -343,15 +343,3 @@ internal fun McpServer.toDisplayData() = McpServerDisplayData(
description = description, description = description,
isConnected = isConnected, isConnected = isConnected,
) )
internal fun EModelEndpoint.toSerialName(): String = when (this) {
EModelEndpoint.AZURE_OPENAI -> "azureOpenAI"
EModelEndpoint.OPENAI -> "openAI"
EModelEndpoint.GOOGLE -> "google"
EModelEndpoint.ANTHROPIC -> "anthropic"
EModelEndpoint.ASSISTANTS -> "assistants"
EModelEndpoint.AZURE_ASSISTANTS -> "azureAssistants"
EModelEndpoint.AGENTS -> "agents"
EModelEndpoint.CUSTOM -> "custom"
EModelEndpoint.BEDROCK -> "bedrock"
}

View file

@ -6,8 +6,8 @@ import com.garfiec.librechat.core.data.repository.PromptRepository
import com.garfiec.librechat.core.model.EModelEndpoint import com.garfiec.librechat.core.model.EModelEndpoint
import com.garfiec.librechat.core.model.Preset import com.garfiec.librechat.core.model.Preset
import com.garfiec.librechat.core.model.PromptGroup import com.garfiec.librechat.core.model.PromptGroup
import com.garfiec.librechat.feature.chat.PresetDisplayData import com.garfiec.librechat.feature.chat.model.PresetDisplayData
import com.garfiec.librechat.feature.chat.PromptMentionDisplayData import com.garfiec.librechat.feature.chat.model.PromptMentionDisplayData
import com.garfiec.librechat.feature.chat.viewmodel.ChatStateHandle import com.garfiec.librechat.feature.chat.viewmodel.ChatStateHandle
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger

View file

@ -26,7 +26,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.garfiec.librechat.feature.chat.McpServerDisplayData import com.garfiec.librechat.feature.chat.model.McpServerDisplayData
import librechat_mobile.feature.chat.generated.resources.Res import librechat_mobile.feature.chat.generated.resources.Res
import librechat_mobile.feature.chat.generated.resources.cd_attach_file import librechat_mobile.feature.chat.generated.resources.cd_attach_file
import librechat_mobile.feature.chat.generated.resources.cd_paste_image import librechat_mobile.feature.chat.generated.resources.cd_paste_image

Some files were not shown because too many files have changed in this diff Show more