Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 309c388b5b |
@@ -29,9 +29,16 @@ fn engram_numeric_valid(s: String) -> Bool {
|
||||
let dot_count: Int = str_len(body) - str_len(no_dot)
|
||||
if dot_count > 1 { return false }
|
||||
if str_eq(no_dot, "") { return false }
|
||||
// str_to_int on a letter-containing string returns 0; "0" is a valid zero.
|
||||
// str_to_int on a letter-containing string returns 0; "0" and "00..." (e.g. from "0.0")
|
||||
// are valid zeros. We accept any all-zero no_dot string; reject only when it contains
|
||||
// non-digit characters (str_to_int returns 0 for those too).
|
||||
let parsed: Int = str_to_int(no_dot)
|
||||
if parsed == 0 && !str_eq(no_dot, "0") { return false }
|
||||
if parsed == 0 {
|
||||
// Verify no_dot is truly all-digit-zeros, not a letter-contaminated string.
|
||||
// Strip all '0' characters; if anything remains the string is non-numeric.
|
||||
let stripped_zeros: String = str_replace(no_dot, "0", "")
|
||||
if !str_eq(stripped_zeros, "") { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -180,10 +187,16 @@ fn engram_compile(intent: String) -> String {
|
||||
} else {
|
||||
println("[chat] engram_compile: WARN cold-index — activation and search returned no results for intent=" + str_slice(intent, 0, 60))
|
||||
}
|
||||
// Soul-agnostic fallback: search for Persona/Identity nodes by label.
|
||||
let persona_fallback: String = engram_search_json("soul:persona Persona identity", 5)
|
||||
let pf_ok: Bool = !str_eq(persona_fallback, "") && !str_eq(persona_fallback, "[]")
|
||||
let combined: String = if pf_ok { engram_compile_ranked(persona_fallback, 3) } else { "" }
|
||||
// Soul-agnostic fallback: fetch the Persona node by label — immune to cold vector index.
|
||||
// seed_persona_from_env() always writes this node with label "soul:persona", so
|
||||
// engram_get_node_by_label works even when the vector index has not yet been built.
|
||||
// Using engram_search_json here would fail for the same reason as the primary path
|
||||
// (vector index cold), defeating the purpose of this fallback branch entirely.
|
||||
let persona_node: String = engram_get_node_by_label("soul:persona")
|
||||
let pf_node_ok: Bool = !str_eq(persona_node, "") && !str_eq(persona_node, "null")
|
||||
let persona_arr: String = if pf_node_ok { "[" + persona_node + "]" } else { "" }
|
||||
let pf_ok: Bool = pf_node_ok
|
||||
let combined: String = if pf_ok { engram_compile_ranked(persona_arr, 1) } else { "" }
|
||||
if str_eq(combined, "") {
|
||||
println("[chat] engram_compile: WARN cold-start fallback also empty — LLM has no episodic context")
|
||||
}
|
||||
@@ -431,9 +444,11 @@ fn conv_history_persist(hist: String) -> Void {
|
||||
if str_eq(hist, "") { return "" }
|
||||
if str_eq(hist, "[]") { return "" }
|
||||
// Partial-write guard: refuse to persist a blob that is not a complete JSON array.
|
||||
// A truncated write starting with '[' but missing ']' would overwrite a good node.
|
||||
// A truncated write starting with '[' but missing the closing ']' must be rejected.
|
||||
// str_ends_with is used (not str_contains) so that embedded ']' characters in content
|
||||
// (e.g. "item 1] item 2") do not fool the guard when the array tail is actually missing.
|
||||
if !str_starts_with(hist, "[") { return "" }
|
||||
if !str_contains(hist, "]") { return "" }
|
||||
if !str_ends_with(hist, "]") { return "" }
|
||||
let tags: String = "[\"conv-history\",\"persistent\"]"
|
||||
let node_id: String = engram_node_full(
|
||||
hist, "Conversation", "conv:history",
|
||||
@@ -455,7 +470,7 @@ fn conv_history_load() -> String {
|
||||
let label_ok: Bool = !str_eq(label_node, "") && !str_eq(label_node, "null")
|
||||
if label_ok {
|
||||
let label_content: String = json_get(label_node, "content")
|
||||
let label_valid: Bool = str_starts_with(label_content, "[") && str_contains(label_content, "]")
|
||||
let label_valid: Bool = str_starts_with(label_content, "[") && str_ends_with(label_content, "]")
|
||||
if label_valid {
|
||||
return label_content
|
||||
}
|
||||
@@ -471,8 +486,9 @@ fn conv_history_load() -> String {
|
||||
if str_eq(results, "[]") { return "" }
|
||||
let node: String = json_array_get(results, 0)
|
||||
let content: String = json_get(node, "content")
|
||||
// Partial-write guard: require both '[' prefix AND ']' presence.
|
||||
if !str_starts_with(content, "[") || !str_contains(content, "]") {
|
||||
// Partial-write guard: require both '[' prefix AND closing ']' at the tail.
|
||||
// str_ends_with guards against embedded ']' in content fooling the check.
|
||||
if !str_starts_with(content, "[") || !str_ends_with(content, "]") {
|
||||
println("[chat] conv_history_load: vector search result content invalid — treating as first turn")
|
||||
state_set("conv_history_load_failed", "1")
|
||||
return ""
|
||||
@@ -1096,7 +1112,7 @@ fn handle_chat_agentic(body: String) -> String {
|
||||
if str_eq(screen_action, "hard_bell") {
|
||||
safety_log_bell("hard", json_get(screen_result, "reason"), str_slice(message, 0, 80))
|
||||
return "{\"reply\":\"" + json_safe(safety_validate("", "hard_bell")) + "\",\"model\":\"\",\"agentic\":true,\"tools_used\":[]}"
|
||||
|
||||
}
|
||||
|
||||
let req_model: String = json_get(body, "model")
|
||||
let model: String = if str_eq(req_model, "") { chat_default_model() } else { req_model }
|
||||
|
||||
Reference in New Issue
Block a user