summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-02 22:00:45 +0000
committersoryu <soryu@soryu.co>2026-01-02 22:00:45 +0000
commit2fab6904260099d9a011734763e62ebba91cf448 (patch)
tree5890486b77f209348761ae7dc99a64e974dbcb7c
parente8ebf8f01101905bd9aec84aec94fd8854f8a030 (diff)
downloadsoryu-2fab6904260099d9a011734763e62ebba91cf448.tar.gz
soryu-2fab6904260099d9a011734763e62ebba91cf448.zip
Update LLM to keep context
-rw-r--r--makima/frontend/src/components/files/CliInput.tsx17
-rw-r--r--makima/frontend/src/lib/api.ts12
-rw-r--r--makima/src/server/handlers/chat.rs42
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();