Fix output truncation bug, add language support for agent responses
Bug 1 — Output truncation:
_run_claude() was replacing raw stdout with parsed sub-field which
could be a dict (not string). run_agent() then saved dict.__repr__
to DB instead of full JSON. Fixed: _run_claude() always returns
string output; run_agent() ensures string before DB write.
Added tests: full_output_saved_to_db, dict_output_saved_as_json_string.
Bug 2 — Language support:
Added projects.language column (TEXT DEFAULT 'ru').
Auto-migration for existing DBs (ALTER TABLE ADD COLUMN).
context_builder passes language in project context.
format_prompt() appends "## Language\nALWAYS respond in {language}"
at the end of every prompt.
CLI: kin project add --language ru (default: ru).
Tests: language in prompt for ru/en, project creation, context.
112 tests, all passing. ~/.kin/kin.db migrated (vdol: language=ru).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
38c252fc1b
commit
c129cf9d95
7 changed files with 117 additions and 18 deletions
|
|
@ -65,12 +65,15 @@ def run_agent(
|
|||
result = _run_claude(prompt, model=model, working_dir=working_dir)
|
||||
duration = int(time.monotonic() - start)
|
||||
|
||||
# Parse output
|
||||
output_text = result.get("output", "")
|
||||
# Parse output — ensure output_text is always a string for DB storage
|
||||
raw_output = result.get("output", "")
|
||||
if not isinstance(raw_output, str):
|
||||
raw_output = json.dumps(raw_output, ensure_ascii=False)
|
||||
output_text = raw_output
|
||||
success = result["returncode"] == 0
|
||||
parsed_output = _try_parse_json(output_text)
|
||||
|
||||
# Log to DB
|
||||
# Log FULL output to DB (no truncation)
|
||||
models.log_agent_run(
|
||||
conn,
|
||||
project_id=project_id,
|
||||
|
|
@ -133,24 +136,24 @@ def _run_claude(
|
|||
"returncode": 124,
|
||||
}
|
||||
|
||||
# Try to extract structured data from JSON output
|
||||
output = proc.stdout or ""
|
||||
# Always preserve the full raw stdout
|
||||
raw_stdout = proc.stdout or ""
|
||||
result: dict[str, Any] = {
|
||||
"output": output,
|
||||
"output": raw_stdout,
|
||||
"error": proc.stderr if proc.returncode != 0 else None,
|
||||
"returncode": proc.returncode,
|
||||
}
|
||||
|
||||
# Parse JSON output from claude --output-format json
|
||||
parsed = _try_parse_json(output)
|
||||
# Parse JSON wrapper from claude --output-format json
|
||||
# Extract metadata (tokens, cost) but keep output as the full content string
|
||||
parsed = _try_parse_json(raw_stdout)
|
||||
if isinstance(parsed, dict):
|
||||
result["tokens_used"] = parsed.get("usage", {}).get("total_tokens")
|
||||
result["cost_usd"] = parsed.get("cost_usd")
|
||||
# The actual content is usually in result or content
|
||||
if "result" in parsed:
|
||||
result["output"] = parsed["result"]
|
||||
elif "content" in parsed:
|
||||
result["output"] = parsed["content"]
|
||||
# Extract the agent's actual response, converting to string if needed
|
||||
content = parsed.get("result") or parsed.get("content")
|
||||
if content is not None:
|
||||
result["output"] = content if isinstance(content, str) else json.dumps(content, ensure_ascii=False)
|
||||
|
||||
return result
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue