Skip to content

Commit 36bea05

Browse files
committed
homepage: keep spider chat history
1 parent ef7a440 commit 36bea05

8 files changed

Lines changed: 173 additions & 216 deletions

File tree

hyperdrive/packages/homepage/api/chat.wit

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,12 @@ use standard.{address};
358358
api-key: string
359359
}
360360

361-
record spider-list-conversations-req {
362-
limit: option<u32>,
363-
offset: option<u32>,
364-
client: option<string>
361+
record spider-history {
362+
messages: list<spider-message>
363+
}
364+
365+
record spider-set-history-req {
366+
messages: list<spider-message>
365367
}
366368

367369
record spider-status-info {
@@ -680,20 +682,6 @@ use standard.{address};
680682
tier: group-tier
681683
}
682684

683-
record spider-conversation {
684-
id: string,
685-
messages: list<spider-message>,
686-
metadata: spider-conversation-metadata,
687-
llm-provider: string,
688-
mcp-servers: list<string>
689-
}
690-
691-
record spider-conversation-metadata {
692-
start-time: string,
693-
client: string,
694-
from-stt: bool
695-
}
696-
697685
record spider-message {
698686
role: string,
699687
content: spider-message-content,
@@ -1437,13 +1425,21 @@ use standard.{address};
14371425
returning: result<spider-connect-result, string>
14381426
}
14391427

1440-
// Function signature for: spider-list-conversations (http)
1441-
// HTTP: POST /api/spider-list-conversations
1442-
// args: (request: spider-list-conversations-req)
1443-
record spider-list-conversations-signature-http {
1428+
// Function signature for: spider-get-history (http)
1429+
// HTTP: POST /api/spider-get-history
1430+
// args: none
1431+
record spider-get-history-signature-http {
1432+
target: string,
1433+
returning: result<spider-history, string>
1434+
}
1435+
1436+
// Function signature for: spider-set-history (http)
1437+
// HTTP: POST /api/spider-set-history
1438+
// args: (request: spider-set-history-req)
1439+
record spider-set-history-signature-http {
14441440
target: string,
1445-
arg-types: tuple<spider-list-conversations-req>,
1446-
returning: result<list<spider-conversation>, string>
1441+
arg-types: tuple<spider-set-history-req>,
1442+
returning: result<_, string>
14471443
}
14481444

14491445
// Function signature for: spider-status (http)

hyperdrive/packages/homepage/chat/src/lib.rs

Lines changed: 9 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use futures::{channel::mpsc::UnboundedReceiver, pin_mut, select, FutureExt, Stre
99
use hyperapp_macro::*;
1010
use hyperware_crdt::yrs::{Decode, Encode, StateVector};
1111
use base64::{engine::general_purpose, Engine as _};
12-
use serde::Deserialize;
1312
use hyperware_process_lib::{
1413
homepage::add_to_homepage,
1514
http::server::WsMessageType,
@@ -62,105 +61,6 @@ const OUR_PROCESS_ID: (&str, &str, &str) = ("chat", "homepage", "sys");
6261
const REPL_RPC_TIMEOUT_SECS: u64 = 2;
6362
const ICON: &str = include_str!("./icon");
6463

65-
#[derive(Deserialize)]
66-
struct SpiderConversationWire {
67-
id: String,
68-
messages: Vec<SpiderMessageWire>,
69-
metadata: SpiderConversationMetadataWire,
70-
#[serde(rename = "llmProvider")]
71-
llm_provider: String,
72-
#[serde(rename = "mcpServers")]
73-
mcp_servers: Vec<String>,
74-
}
75-
76-
#[derive(Deserialize)]
77-
struct SpiderMessageWire {
78-
role: String,
79-
content: serde_json::Value,
80-
#[serde(rename = "toolCallsJson")]
81-
tool_calls_json: Option<String>,
82-
#[serde(rename = "toolResultsJson")]
83-
tool_results_json: Option<String>,
84-
timestamp: u64,
85-
}
86-
87-
#[derive(Deserialize)]
88-
struct SpiderConversationMetadataWire {
89-
#[serde(rename = "startTime")]
90-
start_time: String,
91-
client: String,
92-
#[serde(rename = "fromStt")]
93-
from_stt: bool,
94-
}
95-
96-
fn convert_spider_message_content(content: serde_json::Value) -> SpiderMessageContent {
97-
use serde_json::Value;
98-
99-
match content {
100-
Value::String(text) => SpiderMessageContent {
101-
text: Some(text),
102-
audio: None,
103-
base_six_four_audio: None,
104-
},
105-
Value::Object(map) => {
106-
let text = map
107-
.get("Text")
108-
.or_else(|| map.get("text"))
109-
.and_then(|value| value.as_str())
110-
.map(|value| value.to_string());
111-
let base_six_four_audio = map
112-
.get("BaseSixFourAudio")
113-
.or_else(|| map.get("base_six_four_audio"))
114-
.and_then(|value| value.as_str())
115-
.map(|value| value.to_string());
116-
let audio = map.get("Audio").or_else(|| map.get("audio")).and_then(|value| {
117-
value.as_array().map(|items| {
118-
items
119-
.iter()
120-
.filter_map(|item| item.as_u64().map(|v| v as u8))
121-
.collect::<Vec<u8>>()
122-
})
123-
});
124-
125-
SpiderMessageContent {
126-
text,
127-
audio,
128-
base_six_four_audio,
129-
}
130-
}
131-
_ => SpiderMessageContent {
132-
text: None,
133-
audio: None,
134-
base_six_four_audio: None,
135-
},
136-
}
137-
}
138-
139-
fn convert_spider_conversation(wire: SpiderConversationWire) -> SpiderConversation {
140-
let messages = wire
141-
.messages
142-
.into_iter()
143-
.map(|message| SpiderMessage {
144-
role: message.role,
145-
content: convert_spider_message_content(message.content),
146-
tool_calls_json: message.tool_calls_json,
147-
tool_results_json: message.tool_results_json,
148-
timestamp: message.timestamp,
149-
})
150-
.collect();
151-
152-
SpiderConversation {
153-
id: wire.id,
154-
messages,
155-
metadata: SpiderConversationMetadata {
156-
start_time: wire.metadata.start_time,
157-
client: wire.metadata.client,
158-
from_stt: wire.metadata.from_stt,
159-
},
160-
llm_provider: wire.llm_provider,
161-
mcp_servers: wire.mcp_servers,
162-
}
163-
}
16464

16565
// Helper function to enforce one-way status transitions
16666
fn safe_update_message_status(current: &MessageStatus, new: MessageStatus) -> MessageStatus {
@@ -3302,42 +3202,16 @@ impl ChatState {
33023202
}
33033203

33043204
#[http]
3305-
async fn spider_list_conversations(
3306-
&mut self,
3307-
request: SpiderListConversationsReq,
3308-
) -> Result<Vec<SpiderConversation>, String> {
3309-
const SPIDER_PROCESS_ID: (&str, &str, &str) = ("spider", "spider", "sys");
3310-
3311-
let api_key = match self.spider_api_key.clone() {
3312-
Some(key) => key,
3313-
None => self.spider_connect(Some(false)).await?.api_key,
3314-
};
3315-
3316-
let body = serde_json::json!({
3317-
"ListConversations": {
3318-
"limit": request.limit,
3319-
"offset": request.offset,
3320-
"client": request.client,
3321-
"authKey": api_key,
3322-
}
3323-
});
3324-
3325-
let request = ProcessRequest::to(Address::new("our", SPIDER_PROCESS_ID))
3326-
.body(
3327-
serde_json::to_vec(&body)
3328-
.map_err(|err| format!("failed to serialize list conversations: {err}"))?,
3329-
)
3330-
.expects_response(5);
3331-
3332-
let parsed: Result<Vec<SpiderConversationWire>, String> = hyperapp::send(request)
3333-
.await
3334-
.map_err(|err| format!("failed to contact spider: {err}"))?;
3205+
async fn spider_get_history(&self) -> Result<SpiderHistory, String> {
3206+
Ok(SpiderHistory {
3207+
messages: self.spider_history.clone(),
3208+
})
3209+
}
33353210

3336-
let wire_conversations = parsed?;
3337-
Ok(wire_conversations
3338-
.into_iter()
3339-
.map(convert_spider_conversation)
3340-
.collect())
3211+
#[http]
3212+
async fn spider_set_history(&mut self, request: SpiderSetHistoryReq) -> Result<(), String> {
3213+
self.spider_history = request.messages;
3214+
Ok(())
33413215
}
33423216

33433217
// WEBSOCKET HANDLERS

hyperdrive/packages/homepage/chat/src/types/api.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -601,39 +601,31 @@ pub struct SpiderStatusInfo {
601601

602602
#[derive(Debug, Clone, Serialize, Deserialize)]
603603
pub struct SpiderMessageContent {
604+
#[serde(default)]
604605
pub text: Option<String>,
606+
#[serde(default)]
605607
pub audio: Option<Vec<u8>>,
608+
#[serde(rename = "base-six-four-audio", default)]
606609
pub base_six_four_audio: Option<String>,
607610
}
608611

609612
#[derive(Debug, Clone, Serialize, Deserialize)]
610613
pub struct SpiderMessage {
611614
pub role: String,
612615
pub content: SpiderMessageContent,
616+
#[serde(rename = "tool-calls-json", default)]
613617
pub tool_calls_json: Option<String>,
618+
#[serde(rename = "tool-results-json", default)]
614619
pub tool_results_json: Option<String>,
615620
pub timestamp: u64,
616621
}
617622

618623
#[derive(Debug, Clone, Serialize, Deserialize)]
619-
pub struct SpiderConversationMetadata {
620-
pub start_time: String,
621-
pub client: String,
622-
pub from_stt: bool,
623-
}
624-
625-
#[derive(Debug, Clone, Serialize, Deserialize)]
626-
pub struct SpiderConversation {
627-
pub id: String,
624+
pub struct SpiderHistory {
628625
pub messages: Vec<SpiderMessage>,
629-
pub metadata: SpiderConversationMetadata,
630-
pub llm_provider: String,
631-
pub mcp_servers: Vec<String>,
632626
}
633627

634628
#[derive(Debug, Clone, Serialize, Deserialize)]
635-
pub struct SpiderListConversationsReq {
636-
pub limit: Option<u32>,
637-
pub offset: Option<u32>,
638-
pub client: Option<String>,
629+
pub struct SpiderSetHistoryReq {
630+
pub messages: Vec<SpiderMessage>,
639631
}

hyperdrive/packages/homepage/chat/src/types/state.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@ pub struct ChatState {
320320
#[serde(default)]
321321
pub spider_api_key: Option<String>,
322322
#[serde(default)]
323+
pub spider_history: Vec<SpiderMessage>,
324+
#[serde(default)]
323325
pub message_sequence_counters: HashMap<String, u64>,
324326
#[serde(skip)]
325327
pub delivery_tx: DeliveryTx,
@@ -392,6 +394,7 @@ impl Default for ChatState {
392394
group_join_keys: HashMap::new(),
393395
settings: Settings::default(),
394396
spider_api_key: None,
397+
spider_history: Vec::new(),
395398
message_sequence_counters: HashMap::new(),
396399
delivery_tx,
397400
// represents "still available" versus "already consumed"
@@ -456,6 +459,8 @@ impl<'de> Deserialize<'de> for ChatState {
456459
#[serde(default)]
457460
spider_api_key: Option<String>,
458461
#[serde(default)]
462+
spider_history: Vec<SpiderMessage>,
463+
#[serde(default)]
459464
message_sequence_counters: HashMap<String, u64>,
460465
#[serde(default)]
461466
groups: HashMap<GroupId, Group>,
@@ -523,6 +528,7 @@ impl<'de> Deserialize<'de> for ChatState {
523528
group_join_keys,
524529
settings,
525530
spider_api_key,
531+
spider_history,
526532
message_sequence_counters,
527533
groups,
528534
group_unread,
@@ -537,6 +543,7 @@ impl<'de> Deserialize<'de> for ChatState {
537543
data.group_join_keys,
538544
data.settings,
539545
data.spider_api_key,
546+
data.spider_history,
540547
data.message_sequence_counters,
541548
data.groups,
542549
data.group_unread,
@@ -550,6 +557,7 @@ impl<'de> Deserialize<'de> for ChatState {
550557
HashMap::new(),
551558
data.settings,
552559
None,
560+
Vec::new(),
553561
data.message_sequence_counters,
554562
data.groups,
555563
data.group_unread,
@@ -563,6 +571,7 @@ impl<'de> Deserialize<'de> for ChatState {
563571
HashMap::new(),
564572
data.settings,
565573
None,
574+
Vec::new(),
566575
HashMap::new(),
567576
HashMap::new(),
568577
HashMap::new(),
@@ -581,6 +590,7 @@ impl<'de> Deserialize<'de> for ChatState {
581590
group_join_keys,
582591
settings,
583592
spider_api_key,
593+
spider_history,
584594
message_sequence_counters,
585595
delivery_tx,
586596
delivery_rx: Some(delivery_rx),

hyperdrive/packages/homepage/pkg/manifest.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"request_networking": true,
2323
"request_capabilities": [
2424
"homepage:homepage:sys",
25+
"http-client:distro:sys",
2526
"http-server:distro:sys",
2627
"kv:distro:sys",
2728
"notifications:distro:sys",
@@ -32,6 +33,7 @@
3233
],
3334
"grant_capabilities": [
3435
"homepage:homepage:sys",
36+
"http-client:distro:sys",
3537
"http-server:distro:sys",
3638
"kv:distro:sys",
3739
"notifications:distro:sys",

hyperdrive/packages/homepage/ui/src/components/Spider/SpiderChat.css

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,15 @@
299299

300300
.spider-message.user {
301301
align-self: flex-end;
302-
background: var(--primary-color);
303-
color: var(--message-own-text);
302+
background: var(--message-own, #cbe84a);
303+
color: #0b0f19;
304304
border-bottom-right-radius: 4px;
305305
}
306306

307307
.spider-message.assistant {
308308
align-self: flex-start;
309309
background: var(--surface);
310-
color: var(--text-primary);
310+
color: #e6edf3;
311311
border-bottom-left-radius: 4px;
312312
border: 1px solid var(--border-color);
313313
}
@@ -580,7 +580,14 @@
580580
}
581581

582582
@media (prefers-color-scheme: light) {
583+
.spider-message.user {
584+
background: #1d4ed8;
585+
color: #f5f7ff;
586+
}
587+
583588
.spider-message.assistant {
584-
background: var(--surface);
589+
background: #f4f6fb;
590+
color: #1b1f2a;
591+
border-color: rgba(15, 23, 42, 0.08);
585592
}
586593
}

0 commit comments

Comments
 (0)