sim_codec_chat/providers/
lm_studio.rs1use std::sync::Arc;
8
9use sim_codec::{DecodeLimits, Decoder, DomainCodecLib, Encoder, Input, Output, ReadCx};
10use sim_kernel::{CodecId, Expr, Lib, LibManifest, Linker, LoadCx, Result, Symbol, WriteCx};
11
12use super::openai::OpenAiCodecOptions;
13use super::openai_compat::{
14 decode_request_for_provider, decode_response_for_provider, decode_stream_for_provider,
15 encode_request_for_provider, encode_response_for_codec, encode_response_for_provider,
16};
17
18const LM_STUDIO_CODEC_ID: CodecId = CodecId(0);
19const PROVIDER: &str = "lm-studio";
20
21pub type LmStudioCodecOptions = OpenAiCodecOptions;
23
24pub type LmStudioRequestOptions = LmStudioCodecOptions;
26
27pub struct LmStudioCodec;
29
30impl Decoder for LmStudioCodec {
31 fn decode(&self, cx: &mut ReadCx<'_>, input: Input) -> Result<Expr> {
32 decode_request_for_provider(cx.codec, input, PROVIDER, cx.limits)
33 }
34}
35
36impl Encoder for LmStudioCodec {
37 fn encode(&self, cx: &mut WriteCx<'_>, expr: &Expr) -> Result<Output> {
38 encode_response_for_codec(cx.codec, expr).map(Output::Text)
39 }
40}
41
42pub struct LmStudioCodecLib {
44 symbol: Symbol,
45 codec_id: CodecId,
46}
47
48impl LmStudioCodecLib {
49 pub fn new(id: CodecId) -> Self {
51 Self {
52 symbol: lm_studio_codec_symbol(),
53 codec_id: id,
54 }
55 }
56
57 fn domain_lib(&self) -> DomainCodecLib {
58 DomainCodecLib::new(
59 self.symbol.clone(),
60 self.codec_id,
61 Arc::new(LmStudioCodec),
62 Arc::new(LmStudioCodec),
63 Symbol::qualified("codec", "LmStudioTranscript"),
64 )
65 }
66}
67
68impl Lib for LmStudioCodecLib {
69 fn manifest(&self) -> LibManifest {
70 self.domain_lib().manifest()
71 }
72
73 fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
74 self.domain_lib().load(cx, linker)
75 }
76}
77
78pub fn lm_studio_codec_symbol() -> Symbol {
80 Symbol::qualified("codec", PROVIDER)
81}
82
83pub fn decode_lm_studio_request(input: Input) -> Result<Expr> {
85 decode_lm_studio_request_with_limits(input, DecodeLimits::default())
86}
87
88pub fn decode_lm_studio_request_with_limits(input: Input, limits: DecodeLimits) -> Result<Expr> {
90 decode_request_for_provider(LM_STUDIO_CODEC_ID, input, PROVIDER, limits)
91}
92
93pub fn encode_lm_studio_request(expr: &Expr, options: &LmStudioRequestOptions) -> Result<Vec<u8>> {
95 encode_request_for_provider(expr, options)
96}
97
98pub fn decode_lm_studio_response(
100 runner: Symbol,
101 model: &str,
102 body: &[u8],
103 include_raw: bool,
104) -> Result<Expr> {
105 decode_lm_studio_response_with_limits(runner, model, body, include_raw, DecodeLimits::default())
106}
107
108pub fn decode_lm_studio_response_with_limits(
110 runner: Symbol,
111 model: &str,
112 body: &[u8],
113 include_raw: bool,
114 limits: DecodeLimits,
115) -> Result<Expr> {
116 decode_response_for_provider(
117 LM_STUDIO_CODEC_ID,
118 runner,
119 model,
120 body,
121 include_raw,
122 PROVIDER,
123 limits,
124 )
125}
126
127pub fn decode_lm_studio_stream(
129 runner: Symbol,
130 model: &str,
131 body: &[u8],
132 include_raw: bool,
133) -> Result<Expr> {
134 decode_lm_studio_stream_with_limits(runner, model, body, include_raw, DecodeLimits::default())
135}
136
137pub fn decode_lm_studio_stream_with_limits(
139 runner: Symbol,
140 model: &str,
141 body: &[u8],
142 include_raw: bool,
143 limits: DecodeLimits,
144) -> Result<Expr> {
145 decode_stream_for_provider(
146 LM_STUDIO_CODEC_ID,
147 runner,
148 model,
149 body,
150 include_raw,
151 PROVIDER,
152 limits,
153 )
154}
155
156pub fn encode_lm_studio_response(expr: &Expr) -> Result<Vec<u8>> {
158 encode_response_for_provider(expr)
159}