文件最后提交记录最后更新时间
feat(datalog): record session_id; unify session id generation Tag datalog with the same session id that rides the request header and telemetry, and collapse the two session-id generators into one. - DatalogWriter gains a session_id (set via the agent's SetSessionId handler). It's written into each turn's .md env header (session=…) and the _requests.jsonl dump. - log_llm_request (the llm/*.json writer) takes the session id from the provider (new LlmProvider::session_id() getter) and records it, so the per-call json — the one used for cache-hit analysis — is attributable to a session. - Agent::new no longer mints its own raw uuid; it reuses the single generator SessionId::new() as a bootstrap value (the agent is built before the Session exists, so the UI's SetSessionId still supplies the real session-file id). Net: one generation site, and header / datalog / telemetry / hooks all share the session-file id at runtime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 2 天前
feat(daemon): update daemon and vscode extension Co-Authored-By: AtomCode (deepseek-v4-flash) <noreply@atomgit.com 16 天前
fix(tool-args): Windows 路径预转义仅对单反斜杠路径生效,修复多行 content 换行被毁 pre_escape_windows_paths_in_json 会对参数里每个字符串都跑。当 write_file 的 content 是多行脚本、里面又引用了已正确转义的 Windows 路径(如 r'C:\\Users\\Administrator\\Desktop\\文章.xlsx')时,looks_like_windows_path 在 整段 content 上命中,rewrite_windows_path_body 把整段里所有真实 \n 翻倍成字面 \n,文件落盘成一行坏掉的 Python(报告里的 813 bytes, 1 lines),python exit 1, 模型误判成换行编码问题后用 echo/Add-Content/powershell 反复折腾直到网关 403。 收紧触发条件:仅当盘符冒号后是单个反斜杠(X:\,会被 serde 误解码)才重写; 正斜杠 X:/ 和已转义的 X:\\(合法 JSON、解码正确)一律跳过。这样多行 content 里正确转义的路径不再触发整段重写,旁边的换行得以保留。 与已回退的 7771f66c 正交:那次用"body 含 \n/\r 即非路径"判据,会误杀 D:\readme.txt / D:\new 等目录名带 r/n 的纯路径而被回退;本次只看冒号后反斜杠 单/双,防回退 pin 测试 repair_tool_args_loose_windows_path_with_n_dir_name_still_rewrites 仍通过。新增回归测试覆盖截图场景。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 1 天前
feat(datalog): record session_id; unify session id generation Tag datalog with the same session id that rides the request header and telemetry, and collapse the two session-id generators into one. - DatalogWriter gains a session_id (set via the agent's SetSessionId handler). It's written into each turn's .md env header (session=…) and the _requests.jsonl dump. - log_llm_request (the llm/*.json writer) takes the session id from the provider (new LlmProvider::session_id() getter) and records it, so the per-call json — the one used for cache-hit analysis — is attributable to a session. - Agent::new no longer mints its own raw uuid; it reuses the single generator SessionId::new() as a bootstrap value (the agent is built before the Session exists, so the UI's SetSessionId still supplies the real session-file id). Net: one generation site, and header / datalog / telemetry / hooks all share the session-file id at runtime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 2 天前
fix(core): cross-batch tool-call loop guard + JSON-canonical dedup Weak models (deepseek-v4-flash in particular) get stuck on the same (name, args) pair across many sequential batches with no progress between them — the 22-identical-Bash(cargo check) screenshot symptom. The existing in-batch is_dup gate only catches duplicates within one assistant message, so cross-turn loops slipped through and burned turn budget. Two layers added: 1. turn/loop_guard.rs — new module. Per-turn rolling window keyed on (name, normalised_args) with two trigger thresholds: * THRESHOLD = 3: identical (name, args, output, success) repeats block on the 3rd attempt. Catches deterministic loops where output is byte-stable. * HARD_THRESHOLD = 6: identical (name, args) regardless of output drift. Catches the cargo/test/lint polling case where warning order, paths, or cache state make output vary slightly even though the model is clearly stuck. The previous deletion commit 9339cf1 warned this could re-introduce false positives — addressed via: - args-must-match-exactly (no token-streak fuzziness, which was the bit that wrongly caught ssh ls/cat/sshpass batches), - intervening successful state-changing tool with a NEW key clears the window (edit/write/create/search_replace count as progress; spam-edit of the same key still triggers). The agent clears the window at every user-message boundary. 2. runner.rs::normalize_tool_args — JSON-canonicalise both the in-batch is_dup key and the cross-batch loop_guard key. Streaming models routinely re-emit the same call with whitespace / key-order variation; serde_json::Value (BTreeMap-backed without the preserve_order feature) yields identical canonical strings for {"a":1,"b":2} and {"b":2, "a":1}. Non-JSON args fall through unchanged. Plumbing: * LoopGuardState is a field on TurnRunner (5 constructor sites updated: agent/mod.rs, agent/background.rs, agent/sub_agent.rs, daemon/main.rs, turn/tests.rs × 2). * agent::DisciplineState::recent_calls (dead-code Vec, only cleared never written) deleted; replaced by turn_runner.loop_guard.clear() at the same per-user-message reset point. Tests: * 11 unit tests in loop_guard.rs covering: 3rd-identical block, rotating cargo-check filters (false-positive pin from 9339cf1), ssh ls/cat/sshpass batch (other 9339cf1 false-positive), output-drift hard cap, polling below cap, intervening state change reset, repeated state-changing keys still trigger, clear() resets, JSON-whitespace variants collapse cross-batch, name-collision separator works. * 5 normalize_tool_args tests in runner.rs (whitespace, key order, nested objects, semantically distinct args, non-JSON pass-through). * 1 integration test through the actual run_with_filter dispatch loop — 3 sequential run() calls with the same MockProvider produce 1st/2nd execute, 3rd blocked with a [Loop guard] synthetic ToolResult. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> 27 天前
fix(core): cross-batch tool-call loop guard + JSON-canonical dedup Weak models (deepseek-v4-flash in particular) get stuck on the same (name, args) pair across many sequential batches with no progress between them — the 22-identical-Bash(cargo check) screenshot symptom. The existing in-batch is_dup gate only catches duplicates within one assistant message, so cross-turn loops slipped through and burned turn budget. Two layers added: 1. turn/loop_guard.rs — new module. Per-turn rolling window keyed on (name, normalised_args) with two trigger thresholds: * THRESHOLD = 3: identical (name, args, output, success) repeats block on the 3rd attempt. Catches deterministic loops where output is byte-stable. * HARD_THRESHOLD = 6: identical (name, args) regardless of output drift. Catches the cargo/test/lint polling case where warning order, paths, or cache state make output vary slightly even though the model is clearly stuck. The previous deletion commit 9339cf1 warned this could re-introduce false positives — addressed via: - args-must-match-exactly (no token-streak fuzziness, which was the bit that wrongly caught ssh ls/cat/sshpass batches), - intervening successful state-changing tool with a NEW key clears the window (edit/write/create/search_replace count as progress; spam-edit of the same key still triggers). The agent clears the window at every user-message boundary. 2. runner.rs::normalize_tool_args — JSON-canonicalise both the in-batch is_dup key and the cross-batch loop_guard key. Streaming models routinely re-emit the same call with whitespace / key-order variation; serde_json::Value (BTreeMap-backed without the preserve_order feature) yields identical canonical strings for {"a":1,"b":2} and {"b":2, "a":1}. Non-JSON args fall through unchanged. Plumbing: * LoopGuardState is a field on TurnRunner (5 constructor sites updated: agent/mod.rs, agent/background.rs, agent/sub_agent.rs, daemon/main.rs, turn/tests.rs × 2). * agent::DisciplineState::recent_calls (dead-code Vec, only cleared never written) deleted; replaced by turn_runner.loop_guard.clear() at the same per-user-message reset point. Tests: * 11 unit tests in loop_guard.rs covering: 3rd-identical block, rotating cargo-check filters (false-positive pin from 9339cf1), ssh ls/cat/sshpass batch (other 9339cf1 false-positive), output-drift hard cap, polling below cap, intervening state change reset, repeated state-changing keys still trigger, clear() resets, JSON-whitespace variants collapse cross-batch, name-collision separator works. * 5 normalize_tool_args tests in runner.rs (whitespace, key order, nested objects, semantically distinct args, non-JSON pass-through). * 1 integration test through the actual run_with_filter dispatch loop — 3 sequential run() calls with the same MockProvider produce 1st/2nd execute, 3rd blocked with a [Loop guard] synthetic ToolResult. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> 27 天前
feat: add --dangerously-skip-permissions / -y flag - Add CLI flag --dangerously-skip-permissions (alias -y) to auto-approve all tool calls without permission prompts - InteractivePermissionDecider honors the flag in decide() and will_auto_approve() - OpenAtomcode telemetry event includes dangerously_skip_permissions field - TUI status bar shows SKIP badge on the right side (separate from PLAN) - TUI scrollback warning banner on startup - Headless mode stderr warning - Add i18n messages (en/zh) for bypass warnings and badge - Add comprehensive unit tests for permission logic and status bar rendering 5 天前
feat(datalog): record session_id; unify session id generation Tag datalog with the same session id that rides the request header and telemetry, and collapse the two session-id generators into one. - DatalogWriter gains a session_id (set via the agent's SetSessionId handler). It's written into each turn's .md env header (session=…) and the _requests.jsonl dump. - log_llm_request (the llm/*.json writer) takes the session id from the provider (new LlmProvider::session_id() getter) and records it, so the per-call json — the one used for cache-hit analysis — is attributable to a session. - Agent::new no longer mints its own raw uuid; it reuses the single generator SessionId::new() as a bootstrap value (the agent is built before the Session exists, so the UI's SetSessionId still supplies the real session-file id). Net: one generation site, and header / datalog / telemetry / hooks all share the session-file id at runtime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 2 天前
chore(core): 清理既有编译告警 合并后 cargo check 暴露的存量告警(均在 atomcode-core,与本次合并无关): - 移除未使用 import(glob/bash/hook_test/webhook_test/hook_integration_test) - 去掉多余 mut、未使用变量改 _result(turn/tests、plugin/loader) - 死代码测试辅助函数加 #[allow(dead_code)](engine、config_loader) - RAII Guard 的 TempDir 字段加 #[allow(dead_code)](plugin_integration) - script_runner trait-bound 断言 require_hook::<ScriptHook>(); 改为真正调用, 消除 path_statement 告警 - hook_integration_test::create_test_runner 改 async 并 .await registry.register (register 是 async,原先 future 被丢弃,MockEchoTool 实际从未注册——顺手修掉) 验证:cargo check --workspace --exclude atomcode-codingplan-crypto --tests 零告警零错误。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> 2 天前