Skip to content

Commit e9284a3

Browse files
committed
Merge branch 'main' into background-server-load
2 parents 05ea3f2 + 1bf0f12 commit e9284a3

File tree

38 files changed

+890
-321
lines changed

38 files changed

+890
-321
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ time = { version = "0.3.39", features = [
144144
"macros",
145145
"serde",
146146
] }
147-
tokio = { version = "1.44.2", features = ["full"] }
147+
tokio = { version = "1.45.0", features = ["full"] }
148148
tokio-tungstenite = "0.26.2"
149149
tokio-util = { version = "0.7.15", features = ["codec", "compat"] }
150150
toml = "0.8.12"

build-scripts/manifest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def app_manifest():
6464
path="Contents/MacOS/qterm",
6565
identifier="com.amazon.qterm",
6666
),
67+
EmbeddedRequirement(
68+
path="Contents/MacOS/qchat",
69+
identifier="com.amazon.qchat",
70+
),
6771
],
6872
)
6973

crates/chat-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ time = { version = "0.3.39", features = [
137137
"macros",
138138
"serde",
139139
] }
140-
tokio = { version = "1.44.2", features = ["full"] }
140+
tokio = { version = "1.45.0", features = ["full"] }
141141
tokio-tungstenite = "0.26.2"
142142
tokio-util = { version = "0.7.15", features = ["codec", "compat"] }
143143
toml = "0.8.12"

crates/chat-cli/src/api_client/model.rs

Lines changed: 207 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1+
use std::collections::HashMap;
2+
13
use aws_smithy_types::{
24
Blob,
3-
Document,
5+
Document as AwsDocument,
6+
};
7+
use serde::de::{
8+
self,
9+
MapAccess,
10+
SeqAccess,
11+
Visitor,
412
};
513
use serde::{
614
Deserialize,
15+
Deserializer,
716
Serialize,
17+
Serializer,
818
};
919

1020
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -125,8 +135,189 @@ impl TryFrom<ChatMessage> for amzn_qdeveloper_streaming_client::types::ChatMessa
125135
}
126136
}
127137

128-
/// Information about a tool that can be used.
138+
/// Wrapper around [aws_smithy_types::Document].
139+
///
140+
/// Used primarily so we can implement [Serialize] and [Deserialize] for
141+
/// [aws_smith_types::Document].
142+
#[derive(Debug, Clone)]
143+
pub struct FigDocument(AwsDocument);
144+
145+
impl From<AwsDocument> for FigDocument {
146+
fn from(value: AwsDocument) -> Self {
147+
Self(value)
148+
}
149+
}
150+
151+
impl From<FigDocument> for AwsDocument {
152+
fn from(value: FigDocument) -> Self {
153+
value.0
154+
}
155+
}
156+
157+
/// Internal type used only during serialization for `FigDocument` to avoid unnecessary cloning.
129158
#[derive(Debug, Clone)]
159+
struct FigDocumentRef<'a>(&'a AwsDocument);
160+
161+
impl Serialize for FigDocumentRef<'_> {
162+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
163+
where
164+
S: Serializer,
165+
{
166+
use aws_smithy_types::Number;
167+
match self.0 {
168+
AwsDocument::Null => serializer.serialize_unit(),
169+
AwsDocument::Bool(b) => serializer.serialize_bool(*b),
170+
AwsDocument::Number(n) => match n {
171+
Number::PosInt(u) => serializer.serialize_u64(*u),
172+
Number::NegInt(i) => serializer.serialize_i64(*i),
173+
Number::Float(f) => serializer.serialize_f64(*f),
174+
},
175+
AwsDocument::String(s) => serializer.serialize_str(s),
176+
AwsDocument::Array(arr) => {
177+
use serde::ser::SerializeSeq;
178+
let mut seq = serializer.serialize_seq(Some(arr.len()))?;
179+
for value in arr {
180+
seq.serialize_element(&Self(value))?;
181+
}
182+
seq.end()
183+
},
184+
AwsDocument::Object(m) => {
185+
use serde::ser::SerializeMap;
186+
let mut map = serializer.serialize_map(Some(m.len()))?;
187+
for (k, v) in m {
188+
map.serialize_entry(k, &Self(v))?;
189+
}
190+
map.end()
191+
},
192+
}
193+
}
194+
}
195+
196+
impl Serialize for FigDocument {
197+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
198+
where
199+
S: Serializer,
200+
{
201+
FigDocumentRef(&self.0).serialize(serializer)
202+
}
203+
}
204+
205+
impl<'de> Deserialize<'de> for FigDocument {
206+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
207+
where
208+
D: Deserializer<'de>,
209+
{
210+
use aws_smithy_types::Number;
211+
212+
struct FigDocumentVisitor;
213+
214+
impl<'de> Visitor<'de> for FigDocumentVisitor {
215+
type Value = FigDocument;
216+
217+
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218+
formatter.write_str("any valid JSON value")
219+
}
220+
221+
fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
222+
where
223+
E: de::Error,
224+
{
225+
Ok(FigDocument(AwsDocument::Bool(value)))
226+
}
227+
228+
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
229+
where
230+
E: de::Error,
231+
{
232+
Ok(FigDocument(AwsDocument::Number(if value < 0 {
233+
Number::NegInt(value)
234+
} else {
235+
Number::PosInt(value as u64)
236+
})))
237+
}
238+
239+
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
240+
where
241+
E: de::Error,
242+
{
243+
Ok(FigDocument(AwsDocument::Number(Number::PosInt(value))))
244+
}
245+
246+
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
247+
where
248+
E: de::Error,
249+
{
250+
Ok(FigDocument(AwsDocument::Number(Number::Float(value))))
251+
}
252+
253+
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
254+
where
255+
E: de::Error,
256+
{
257+
Ok(FigDocument(AwsDocument::String(value.to_owned())))
258+
}
259+
260+
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
261+
where
262+
E: de::Error,
263+
{
264+
Ok(FigDocument(AwsDocument::String(value)))
265+
}
266+
267+
fn visit_none<E>(self) -> Result<Self::Value, E>
268+
where
269+
E: de::Error,
270+
{
271+
Ok(FigDocument(AwsDocument::Null))
272+
}
273+
274+
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
275+
where
276+
D: Deserializer<'de>,
277+
{
278+
Deserialize::deserialize(deserializer)
279+
}
280+
281+
fn visit_unit<E>(self) -> Result<Self::Value, E>
282+
where
283+
E: de::Error,
284+
{
285+
Ok(FigDocument(AwsDocument::Null))
286+
}
287+
288+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
289+
where
290+
A: SeqAccess<'de>,
291+
{
292+
let mut vec = Vec::new();
293+
294+
while let Some(elem) = seq.next_element::<FigDocument>()? {
295+
vec.push(elem.0);
296+
}
297+
298+
Ok(FigDocument(AwsDocument::Array(vec)))
299+
}
300+
301+
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
302+
where
303+
M: MapAccess<'de>,
304+
{
305+
let mut map = HashMap::new();
306+
307+
while let Some((key, value)) = access.next_entry::<String, FigDocument>()? {
308+
map.insert(key, value.0);
309+
}
310+
311+
Ok(FigDocument(AwsDocument::Object(map)))
312+
}
313+
}
314+
315+
deserializer.deserialize_any(FigDocumentVisitor)
316+
}
317+
}
318+
319+
/// Information about a tool that can be used.
320+
#[derive(Debug, Clone, Serialize, Deserialize)]
130321
pub enum Tool {
131322
ToolSpecification(ToolSpecification),
132323
}
@@ -148,7 +339,7 @@ impl From<Tool> for amzn_qdeveloper_streaming_client::types::Tool {
148339
}
149340

150341
/// The specification for the tool.
151-
#[derive(Debug, Clone)]
342+
#[derive(Debug, Clone, Serialize, Deserialize)]
152343
pub struct ToolSpecification {
153344
/// The name for the tool.
154345
pub name: String,
@@ -181,41 +372,41 @@ impl From<ToolSpecification> for amzn_qdeveloper_streaming_client::types::ToolSp
181372
}
182373

183374
/// The input schema for the tool in JSON format.
184-
#[derive(Debug, Clone)]
375+
#[derive(Debug, Clone, Serialize, Deserialize)]
185376
pub struct ToolInputSchema {
186-
pub json: Option<Document>,
377+
pub json: Option<FigDocument>,
187378
}
188379

189380
impl From<ToolInputSchema> for amzn_codewhisperer_streaming_client::types::ToolInputSchema {
190381
fn from(value: ToolInputSchema) -> Self {
191-
Self::builder().set_json(value.json).build()
382+
Self::builder().set_json(value.json.map(Into::into)).build()
192383
}
193384
}
194385

195386
impl From<ToolInputSchema> for amzn_qdeveloper_streaming_client::types::ToolInputSchema {
196387
fn from(value: ToolInputSchema) -> Self {
197-
Self::builder().set_json(value.json).build()
388+
Self::builder().set_json(value.json.map(Into::into)).build()
198389
}
199390
}
200391

201392
/// Contains information about a tool that the model is requesting be run. The model uses the result
202393
/// from the tool to generate a response.
203-
#[derive(Debug, Clone)]
394+
#[derive(Debug, Clone, Serialize, Deserialize)]
204395
pub struct ToolUse {
205396
/// The ID for the tool request.
206397
pub tool_use_id: String,
207398
/// The name for the tool.
208399
pub name: String,
209400
/// The input to pass to the tool.
210-
pub input: Document,
401+
pub input: FigDocument,
211402
}
212403

213404
impl From<ToolUse> for amzn_codewhisperer_streaming_client::types::ToolUse {
214405
fn from(value: ToolUse) -> Self {
215406
Self::builder()
216407
.tool_use_id(value.tool_use_id)
217408
.name(value.name)
218-
.input(value.input)
409+
.input(value.input.into())
219410
.build()
220411
.expect("building ToolUse should not fail")
221412
}
@@ -226,7 +417,7 @@ impl From<ToolUse> for amzn_qdeveloper_streaming_client::types::ToolUse {
226417
Self::builder()
227418
.tool_use_id(value.tool_use_id)
228419
.name(value.name)
229-
.input(value.input)
420+
.input(value.input.into())
230421
.build()
231422
.expect("building ToolUse should not fail")
232423
}
@@ -268,7 +459,7 @@ impl From<ToolResult> for amzn_qdeveloper_streaming_client::types::ToolResult {
268459
#[derive(Debug, Clone)]
269460
pub enum ToolResultContentBlock {
270461
/// A tool result that is JSON format data.
271-
Json(Document),
462+
Json(AwsDocument),
272463
/// A tool result that is text.
273464
Text(String),
274465
}
@@ -780,7 +971,7 @@ mod tests {
780971
name: "test tool name".to_string(),
781972
description: "test tool description".to_string(),
782973
input_schema: ToolInputSchema {
783-
json: Some(Document::Null),
974+
json: Some(AwsDocument::Null.into()),
784975
},
785976
})]),
786977
}),
@@ -814,7 +1005,9 @@ mod tests {
8141005
tool_uses: Some(vec![ToolUse {
8151006
tool_use_id: "tooluseid_test".to_string(),
8161007
name: "tool_name_test".to_string(),
817-
input: Document::Object([("key1".to_string(), Document::Null)].into_iter().collect()),
1008+
input: FigDocument(AwsDocument::Object(
1009+
[("key1".to_string(), AwsDocument::Null)].into_iter().collect(),
1010+
)),
8181011
}]),
8191012
};
8201013
let codewhisper_input =

0 commit comments

Comments
 (0)