diff options
| author | soryu <soryu@soryu.co> | 2026-01-02 22:00:45 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-02 22:00:45 +0000 |
| commit | 2fab6904260099d9a011734763e62ebba91cf448 (patch) | |
| tree | 5890486b77f209348761ae7dc99a64e974dbcb7c | |
| parent | e8ebf8f01101905bd9aec84aec94fd8854f8a030 (diff) | |
| download | soryu-2fab6904260099d9a011734763e62ebba91cf448.tar.gz soryu-2fab6904260099d9a011734763e62ebba91cf448.zip | |
Update LLM to keep context
| -rw-r--r-- | makima/frontend/src/components/files/CliInput.tsx | 17 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 12 | ||||
| -rw-r--r-- | makima/src/server/handlers/chat.rs | 42 |
3 files changed, 61 insertions, 10 deletions
diff --git a/makima/frontend/src/components/files/CliInput.tsx b/makima/frontend/src/components/files/CliInput.tsx index 0ac840a..c1e6b6d 100644 --- a/makima/frontend/src/components/files/CliInput.tsx +++ b/makima/frontend/src/components/files/CliInput.tsx @@ -1,5 +1,5 @@ import { useState, useCallback, useRef, useEffect } from "react"; -import { chatWithFile, type BodyElement, type LlmModel } from "../../lib/api"; +import { chatWithFile, type BodyElement, type LlmModel, type ChatMessage } from "../../lib/api"; import { SimpleMarkdown } from "../SimpleMarkdown"; interface CliInputProps { @@ -26,6 +26,8 @@ export function CliInput({ fileId, onUpdate }: CliInputProps) { const [messages, setMessages] = useState<Message[]>([]); const [expanded, setExpanded] = useState(false); const [model, setModel] = useState<LlmModel>("claude-opus"); + // Track conversation history for context continuity + const [conversationHistory, setConversationHistory] = useState<ChatMessage[]>([]); const inputRef = useRef<HTMLInputElement>(null); const messagesRef = useRef<HTMLDivElement>(null); @@ -55,7 +57,8 @@ export function CliInput({ fileId, onUpdate }: CliInputProps) { setLoading(true); try { - const response = await chatWithFile(fileId, userMessage, model); + // Send request with conversation history for context + const response = await chatWithFile(fileId, userMessage, model, conversationHistory); // Add assistant response const assistantMsgId = (Date.now() + 1).toString(); @@ -73,6 +76,13 @@ export function CliInput({ fileId, onUpdate }: CliInputProps) { }, ]); + // Update conversation history for next request + setConversationHistory((prev) => [ + ...prev, + { role: "user", content: userMessage }, + { role: "assistant", content: response.response }, + ]); + // Update parent with new body/summary onUpdate(response.updatedBody, response.updatedSummary); } catch (err) { @@ -90,11 +100,12 @@ export function CliInput({ fileId, onUpdate }: CliInputProps) { inputRef.current?.focus(); } }, - [input, loading, fileId, model, onUpdate] + [input, loading, fileId, model, onUpdate, conversationHistory] ); const clearMessages = useCallback(() => { setMessages([]); + setConversationHistory([]); }, []); return ( diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index 931981b..eb8d908 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -136,9 +136,15 @@ export class VersionConflictError extends Error { export type LlmModel = "claude-sonnet" | "claude-opus" | "groq"; // Chat API types +export interface ChatMessage { + role: "user" | "assistant"; + content: string; +} + export interface ChatRequest { message: string; model?: LlmModel; + history?: ChatMessage[]; } export interface ToolCallInfo { @@ -219,12 +225,16 @@ export async function deleteFile(id: string): Promise<void> { export async function chatWithFile( id: string, message: string, - model?: LlmModel + model?: LlmModel, + history?: ChatMessage[] ): Promise<ChatResponse> { const body: ChatRequest = { message }; if (model) { body.model = model; } + if (history && history.length > 0) { + body.history = history; + } const res = await fetch(`${API_BASE}/api/v1/files/${id}/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, diff --git a/makima/src/server/handlers/chat.rs b/makima/src/server/handlers/chat.rs index 306093a..158805b 100644 --- a/makima/src/server/handlers/chat.rs +++ b/makima/src/server/handlers/chat.rs @@ -33,6 +33,15 @@ const CONTEXT_COMPACTION_THRESHOLD: f32 = 0.90; /// Approximate characters per token (rough estimate for English text) const CHARS_PER_TOKEN: usize = 4; +#[derive(Debug, Clone, Deserialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct ChatHistoryMessage { + /// Role: "user" or "assistant" + pub role: String, + /// Message content + pub content: String, +} + #[derive(Debug, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct ChatRequest { @@ -41,6 +50,9 @@ pub struct ChatRequest { /// Optional model selection: "claude-sonnet" (default), "claude-opus", or "groq" #[serde(default)] pub model: Option<String>, + /// Optional conversation history for context continuity + #[serde(default)] + pub history: Option<Vec<ChatHistoryMessage>>, } #[derive(Debug, Serialize, ToSchema)] @@ -276,14 +288,32 @@ You have access to tools for: tool_calls: None, tool_call_id: None, }, - Message { - role: "user".to_string(), - content: Some(request.message.clone()), - tool_calls: None, - tool_call_id: None, - }, ]; + // Add conversation history if provided (for context continuity) + if let Some(history) = &request.history { + for hist_msg in history { + messages.push(Message { + role: hist_msg.role.clone(), + content: Some(hist_msg.content.clone()), + tool_calls: None, + tool_call_id: None, + }); + } + tracing::info!( + history_messages = history.len(), + "Loaded conversation history" + ); + } + + // Add current user message + messages.push(Message { + role: "user".to_string(), + content: Some(request.message.clone()), + tool_calls: None, + tool_call_id: None, + }); + // State for tracking changes let mut current_body = file.body.clone(); let mut current_summary = file.summary.clone(); |
