feat: Implement lesson generation feature and update status display
- Added functionality to generate lessons based on code reviews, including prompts and instructions for the reviewer. - Updated the `.gitignore` to exclude lesson documentation files. - Removed the `/lesson` command from the help menu and command parsing. - Enhanced the status bar to display a message when a lesson is being generated. - Introduced a new `lesson_running` state to track lesson generation progress. - Updated various components to handle the new lesson generation workflow, including subagent events and token usage tracking.
This commit is contained in:
+37
-24
@@ -134,7 +134,7 @@ pub struct ToolFunction {
|
||||
/// LIFO stack for `{`/`[` → append missing `"`, `]`, `}` in the right
|
||||
/// (reverse nesting) order.
|
||||
///
|
||||
/// Why: LLM output can be cut off mid‑JSON (max_tokens hit, connection
|
||||
/// Why: LLM output can be cut off mid‑JSON (`max_tokens` hit, connection
|
||||
/// drop). This gives tools a chance to act on whatever was emitted.
|
||||
///
|
||||
/// Why LIFO vs. depth counters: `{` inside `[` must close with `}` before
|
||||
@@ -205,29 +205,42 @@ fn repair_json(s: &str) -> String {
|
||||
pub fn sanitize_tool_arguments(args: &Value) -> Value {
|
||||
match args {
|
||||
Value::String(s) => {
|
||||
match serde_json::from_str::<Value>(s) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
// Try to repair truncated JSON before giving up.
|
||||
let repaired = repair_json(s);
|
||||
match serde_json::from_str::<Value>(&repaired) {
|
||||
Ok(v) => {
|
||||
tracing::warn!(
|
||||
"tool argument string was truncated — repaired \
|
||||
successfully: {}",
|
||||
e,
|
||||
);
|
||||
v
|
||||
}
|
||||
Err(e2) => {
|
||||
tracing::error!(
|
||||
"tool argument is a JSON string but failed to parse: {} \
|
||||
(after repair: {}). Wrapping in object. Raw (first 200): {}",
|
||||
e, e2, s.chars().take(200).collect::<String>(),
|
||||
);
|
||||
serde_json::json!({"_raw": s, "_parse_error": e.to_string()})
|
||||
}
|
||||
}
|
||||
// Attempt 1: direct parse.
|
||||
if let Ok(v) = serde_json::from_str::<Value>(s) {
|
||||
return v;
|
||||
}
|
||||
// Attempt 2: strip control chars (0x00-0x1F except \t, \n)
|
||||
// that some LLM providers emit as literal bytes in JSON strings
|
||||
// (e.g. multi-line commit messages), then retry.
|
||||
let cleaned: String = s.chars()
|
||||
.filter(|&c| !c.is_control() || c == '\t' || c == '\n' || c == '\r')
|
||||
.collect();
|
||||
if cleaned.len() != s.len() {
|
||||
if let Ok(v) = serde_json::from_str::<Value>(&cleaned) {
|
||||
tracing::warn!(
|
||||
"tool argument contained control characters — stripped \
|
||||
and reparsed successfully",
|
||||
);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
// Attempt 3: repair truncated JSON and retry.
|
||||
let input = if cleaned.len() == s.len() { s } else { &cleaned };
|
||||
let repaired = repair_json(input);
|
||||
match serde_json::from_str::<Value>(&repaired) {
|
||||
Ok(v) => {
|
||||
tracing::warn!(
|
||||
"tool argument string was truncated — repaired successfully",
|
||||
);
|
||||
v
|
||||
}
|
||||
Err(e2) => {
|
||||
tracing::error!(
|
||||
"tool argument is a JSON string but failed to parse. \
|
||||
Wrapping in object. Error: {}. Raw (first 200): {}",
|
||||
e2, s.chars().take(200).collect::<String>(),
|
||||
);
|
||||
serde_json::json!({"_raw": s, "_parse_error": e2.to_string()})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user