diff --git a/chat.el b/chat.el index fe3369d..8d7d2c6 100644 --- a/chat.el +++ b/chat.el @@ -799,6 +799,15 @@ fn handle_chat(body: String) -> String { let summary_nodes: String = engram_search_json("SessionSummary session:summary previous-session recent", 3) let profile_ok: Bool = !str_eq(profile_nodes, "") && !str_eq(profile_nodes, "[]") + + // Issue 1: typed work query — WorkItem with in_progress label first. + let work_nodes_typed: String = engram_search_json("WorkItem status:in_progress active work", 6) + let work_ok_typed: Bool = !str_eq(work_nodes_typed, "") && !str_eq(work_nodes_typed, "[]") + let work_nodes: String = if work_ok_typed { + work_nodes_typed + } else { + engram_search_json("active project task current in_progress", 6) + } let work_ok: Bool = !str_eq(work_nodes, "") && !str_eq(work_nodes, "[]") let project_ok: Bool = !str_eq(project_nodes, "") && !str_eq(project_nodes, "[]") let summary_ok: Bool = !str_eq(summary_nodes, "") && !str_eq(summary_nodes, "[]") @@ -1426,7 +1435,53 @@ fn handle_chat_agentic(body: String) -> String { let ctx: String = engram_compile(ag_seed) let identity: String = state_get("soul_identity") - let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct.\n\n" + ctx + + // Issue 9: agentic first-message session preload — mirrors handle_chat grounding. + let ag_session_preload: String = if agentic_hist_len == 0 { + let ag_profile_nodes: String = engram_search_json("Persona soul:persona identity principal", 8) + let ag_profile_ok: Bool = !str_eq(ag_profile_nodes, "") && !str_eq(ag_profile_nodes, "[]") + let ag_profile_nodes2: String = if ag_profile_ok { ag_profile_nodes } else { + engram_search_json("user profile preferences name", 8) + } + let ag_work_nodes: String = engram_search_json("WorkItem status:in_progress active work", 6) + let ag_work_ok: Bool = !str_eq(ag_work_nodes, "") && !str_eq(ag_work_nodes, "[]") + let ag_work_nodes2: String = if ag_work_ok { ag_work_nodes } else { + engram_search_json("active project task current in_progress", 6) + } + let ag_continuity_nodes: String = engram_search_json("last-session-topic session:emotional-summary conv:history last session", 3) + let ag_continuity_ok: Bool = !str_eq(ag_continuity_nodes, "") && !str_eq(ag_continuity_nodes, "[]") + let ag_continuity_snip: String = if ag_continuity_ok { + let acn0: String = json_array_get(ag_continuity_nodes, 0) + let acc: String = json_get(acn0, "content") + if str_len(acc) > 350 { str_slice(acc, 0, 350) } else { acc } + } else { "" } + let ag_profile_bullets: String = session_preload_bullets(ag_profile_nodes2, 8, 350) + let ag_work_bullets: String = session_preload_bullets(ag_work_nodes2, 6, 350) + let ag_has_profile: Bool = !str_eq(ag_profile_bullets, "") + let ag_has_work: Bool = !str_eq(ag_work_bullets, "") + let ag_has_cont: Bool = !str_eq(ag_continuity_snip, "") + if ag_has_profile || ag_has_work || ag_has_cont { + let p: String = if ag_has_profile { "[USER CONTEXT — from memory] +" + ag_profile_bullets + " + +" } else { "" } + let w: String = if ag_has_work { "[ACTIVE WORK — from memory] +" + ag_work_bullets + " + +" } else { "" } + let c: String = if ag_has_cont { "[CONTINUING FROM LAST SESSION] +" + ag_continuity_snip + " + +" } else { "" } + " + +" + p + w + c + } else { "" } + } else { "" } + + let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct. + +" + ctx + ag_session_preload let api_key: String = agentic_api_key() let tools_json: String = agentic_tools_all() @@ -1833,7 +1888,8 @@ fn handle_dharma_room_turn(body: String) -> String { } // The soul's own memories, activated by what it's reading — not injected. - let engram_ctx: String = engram_compile(transcript) + // Issue 6 fix: distill_transcript() extracts salient tail+question from full transcript + let engram_ctx: String = engram_compile(distill_transcript(transcript)) let system_prompt: String = if str_eq(engram_ctx, "") { identity } else { @@ -1885,7 +1941,8 @@ fn handle_dharma_room_turn_agentic(body: String) -> String { return "{\"error\":\"transcript is required\",\"response\":\"\",\"cgi_id\":\"" + cgi_id + "\"}" } - let ctx: String = engram_compile(transcript) + // Issue 6 fix: distill_transcript() extracts salient tail+question from full transcript + let ctx: String = engram_compile(distill_transcript(transcript)) let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct and stay in character.\n\n" + ctx let api_key: String = agentic_api_key() diff --git a/sessions.el b/sessions.el index 37029f5..ea5c931 100644 --- a/sessions.el +++ b/sessions.el @@ -492,6 +492,38 @@ fn session_hist_save(session_id: String, hist: String) -> Void { state_set(summary_written_key, "1") } } + + // Issue 5 fix: write a last-session-topic Conversation node so future sessions can + // find the most recent session's topic via engram search. This enables cross-session + // continuity — chat.el searches for "last-session-topic" and shows a [CONTINUING FROM + // LAST SESSION] section on the first message of a new session. + let hist_arr_len: Int = if str_eq(hist, "") { 0 } else { json_array_len(hist) } + if hist_arr_len >= 2 { + let last_entry: String = json_array_get(hist, hist_arr_len - 1) + let last_role: String = json_get(last_entry, "role") + let last_content: String = json_get(last_entry, "content") + let topic_snip: String = if str_len(last_content) > 200 { str_slice(last_content, 0, 200) } else { last_content } + let safe_topic: String = str_replace(topic_snip, """, "'") + let ts_now: String = int_to_str(time_now()) + let topic_content: String = "last-session-topic | ts:" + ts_now + " | session:" + session_id + " | topic:" + safe_topic + let topic_tags: String = "["last-session-topic","conv:history","Conversation","session:topic"]" + let topic_label: String = "last-session-topic:" + session_id + // Delete old last-session-topic node for this session before writing fresh + let old_topic: String = engram_search_json("last-session-topic:" + session_id, 2) + let ot_len: Int = if str_eq(old_topic, "") { 0 } else { json_array_len(old_topic) } + let oti: Int = 0 + while oti < ot_len { + let ot_node: String = json_array_get(old_topic, oti) + let ot_id: String = json_get(ot_node, "id") + if !str_eq(ot_id, "") { engram_forget(ot_id) } + let oti = oti + 1 + } + let discard_topic: String = engram_node_full( + topic_content, "Conversation", topic_label, + el_from_float(0.7), el_from_float(0.7), el_from_float(0.9), + "Episodic", topic_tags + ) + } } // session_update_meta_timestamp — update the updated_at field in the session:meta node.