nexforge-cli 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/PKG-INFO +8 -7
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/README.md +8 -7
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/config.example.toml +8 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/doc//351/241/271/347/233/256/346/200/273/347/233/221/345/276/252/347/216/257-/345/274/200/345/217/221/350/256/241/345/210/222.md +187 -172
- nexforge_cli-0.5.0/docs/decisions/2026-09-12-/345/206/205/345/256/271/351/207/214/347/232/204/346/240/207/350/256/260/344/270/215/345/276/227/345/275/223/346/210/220/346/266/210/346/201/257/350/276/271/347/225/214.md +65 -0
- nexforge_cli-0.5.0/docs/decisions/2026-09-12-/347/233/256/346/240/207/346/250/241/345/274/217/345/244/261/350/264/245/345/217/257/350/247/201/344/270/216/345/216/206/345/217/262/344/277/235/345/205/250.md +176 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/README.md +2 -0
- nexforge_cli-0.5.0/docs/evidence/release-0.4.0.log +46 -0
- nexforge_cli-0.5.0/docs/evidence/release-0.4.1.log +48 -0
- nexforge_cli-0.5.0/docs/evidence/session-marker-boundary.log +101 -0
- nexforge_cli-0.5.0/docs/evidence/session-marker-boundary_fulltest.log +4 -0
- nexforge_cli-0.5.0/docs/evidence/session-marker-boundary_live.log +84 -0
- nexforge_cli-0.5.0/docs/evidence/session-marker-boundary_report.md +77 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/01-/345/256/211/350/243/205/344/270/216/351/205/215/347/275/256.md +1 -1
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/02-/347/225/214/351/235/242/344/270/216/345/277/253/346/215/267/351/224/256.md +3 -2
- nexforge_cli-0.5.0/manual/06-/346/235/203/351/231/220/344/270/216/346/250/241/345/274/217.md +104 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/README.md +1 -1
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/pyproject.toml +1 -1
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/__init__.py +1 -1
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/config.py +15 -1
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/agent.py +51 -15
- nexforge_cli-0.5.0/src/nexforge/core/goal_manager.py +402 -0
- nexforge_cli-0.5.0/src/nexforge/core/model_window.py +324 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/session.py +67 -48
- nexforge_cli-0.5.0/src/nexforge/core/summarizer.py +219 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/mode_features.py +541 -64
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/i18n.py +26 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/store/session_store.py +95 -18
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/screens/chat.py +198 -30
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/screens/chat_actions.py +13 -6
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/slash_handler.py +74 -2
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/messages.py +39 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_archive_integrity.py +67 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_director_loop.py +6 -3
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_goal_confirm.py +10 -0
- nexforge_cli-0.5.0/tests/test_goal_stability.py +1294 -0
- nexforge_cli-0.5.0/tests/test_model_window.py +358 -0
- nexforge_cli-0.5.0/tests/test_session_repair.py +301 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_session_store.py +157 -0
- nexforge_cli-0.5.0/tests/test_tool_iters.py +75 -0
- nexforge_cli-0.4.0/manual/06-/346/235/203/351/231/220/344/270/216/346/250/241/345/274/217.md +0 -71
- nexforge_cli-0.4.0/src/nexforge/core/goal_manager.py +0 -171
- nexforge_cli-0.4.0/src/nexforge/core/summarizer.py +0 -134
- nexforge_cli-0.4.0/tests/test_session_repair.py +0 -141
- nexforge_cli-0.4.0/tests/test_tool_iters.py +0 -55
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/.gitignore +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/INSTALL.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/STATS_API.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/agent.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/cost.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/edit.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/err.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/file.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/model.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/ok.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/read.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/running.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/search.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/shell.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/thinking.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/web.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/assets/icons/write.svg +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/devlog/2026-07-07.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/doc//344/273/243/347/240/201/344/274/230/345/214/226/350/256/241/345/210/222.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/doc//347/211/271/346/200/247/346/250/241/345/235/227/346/263/250/345/206/214/345/210/266-/345/256/236/346/226/275/350/256/241/345/210/222.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-fails-loud/345/210/206/347/272/247.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/344/274/232/350/257/235/344/270/215/345/217/230/351/207/217.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/344/276/235/350/265/226/344/270/200/350/207/264/346/200/247.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/345/233/236/346/224/276/350/214/203/345/233/264/351/207/215/345/256/232/344/271/211.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/345/256/241/350/256/241/344/273/245/350/260/203/347/224/250/351/223/276/344/270/272/345/207/206.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/350/203/275/345/212/233/345/217/257/347/224/250/346/200/247/344/270/212/346/212/245.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-10-/350/264/250/351/207/217gate/344/275/223/347/263/273.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-11-deepseek/346/241/243/344/275/215/347/256/200/345/214/226.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-11-/346/241/243/344/275/215/347/256/200/345/214/226/344/270/272/345/215/225/346/241/243flash.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-11-/347/273/210/347/253/257/347/212/266/346/200/201/345/205/234/345/272/225/346/201/242/345/244/215.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-11-/351/205/215/347/275/256/346/256/213/347/225/231/345/200/274/346/262/273/347/220/206.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/decisions/2026-09-11-/351/207/215/350/257/225/345/275/222/344/270/200/345/261/202.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D10_acceptance.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D10_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D11_a4.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D11_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D12_audit.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D12_gap.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D13_break.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D13_e2e.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D13_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D13_gaps.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D14_audit.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D14_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D14_recheck.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D15_audit.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_fast.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_hook.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_scene_c.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_scene_d.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D4_scene_e.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D5_audit.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D5_b2_plugin.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D5_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D6_b3_a.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D6_b3_b.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D6_b3_c.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D6_b4_provider.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D6_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D7_dedup.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D7_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D8_audit.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D8_invariant.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D9_after.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D9_before.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D9_decision.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D9_full_test.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/D9_rebuild.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_cap_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_capabilities.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_engines.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_engines_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_tts_availability.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_tts_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_tts_installer.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_vision_channels.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/E_vision_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/F_decisions_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/deps_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/deps_reverse.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/exit-cost.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/final_check_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/final_check_pypi.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/final_check_report.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/fix_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/health_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/health_report.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/health_scan.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/model-sidebar-dot.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/model_rename_check.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/provider-family-check.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/release-0.3.0.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/release_0218_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/release_0218_pypi.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/simplify_tier_fulltest.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/evidence/terminal-leak-conditions.log +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/session-invariant.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/submission/README-/346/212/225/347/250/277/350/257/264/346/230/216.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/submission/nexforge.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/docs/submission/nexforge.zh-CN.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/03-/346/250/241/345/236/213/351/205/215/347/275/256.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/04-/345/267/245/345/205/267/345/217/202/350/200/203.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/05-/346/225/260/346/215/256/344/270/216/346/220/234/347/264/242.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/07-/344/274/232/350/257/235/344/270/216/350/256/260/345/277/206.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/08-/350/207/252/345/256/232/344/271/211/351/205/215/347/275/256.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/09-/345/270/270/350/247/201/351/227/256/351/242/230.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/10-/346/217/222/344/273/266/345/274/200/345/217/221.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual/11-/345/274/200/345/217/221/346/240/241/351/252/214.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/manual//351/231/204/345/275/225-/345/257/271/346/257/224/345/210/206/346/236/220.md" +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/README.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/action.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/base.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/vision.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/guiauto/window.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/install_plugin.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/requirements.txt +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/smoke_safe.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/verify_final.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/verify_host.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_gui_auto/verify_plugin.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_speech_summary/README.md +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_speech_summary/install_plugin.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/plugin_speech_summary/speech_summary.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/check.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/exit_cost_probe.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/exit_smoke.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/base.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/eof_newline.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/example_config.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/hygiene.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/manual_consistency.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/registry_consistency.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/gates/version_sync.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/install_hooks.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/publish.sh +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/smoke_provider.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/scripts/smoke_tui.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/__main__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/app.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/cli.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/capability.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/context.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/federation.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/jobs.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/knowledge_base.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/memory_engine.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/model_catalog.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/permissions.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/plugin.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/project_mapper.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/provider.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/system_inject.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/tool_manifest.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/types.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/core/update_check.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/auto_skills.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/base.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/federation_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/kb_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/map_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/memory_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/plan_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/registry.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/session_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/slash_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/stats_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/features/tool_manifest_feature.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/icons.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/mcp/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/_retry.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/anthropic.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/balance.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/deepseek.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/openai.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/provider/qianwen.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/skills/loader.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/stats/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/stats/heartbeat.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/store/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/store/director_store.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/store/plan_store.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/terminal_guard.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/theme.tcss +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/_paths.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/background.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/base.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/data_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/edit_file.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/federation.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/fs_ops.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/git.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/image_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/kb_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/list_dir.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/multi_edit.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/ops_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/read_file.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/registry.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/screenshot_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/search.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/search_content.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/search_files.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/shell.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/web.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/tools/write_file.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/clipboard_image.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/screen_api.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/screens/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/screens/splash.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/apikey_modal.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/banner.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/confirm_modal.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/diff_modal.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/file_browser.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/file_menu.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/image_sidebar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/mode_warning.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/model_sidebar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/multiline_modal.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/multiline_prompt.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/plan_sidebar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/sidebar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/ui/widgets/statusbar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/utils/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/utils/logging.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/web/__init__.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/web/server.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/src/nexforge/web/static/index.html +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/conftest.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_app_mouse.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_approval.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_capability.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_check_gates.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_config.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_cross_platform.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_deepseek_provider.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_deps.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_director_store.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_dual_panel.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_exit_smoke.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_federation.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_file_browser.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_i18n.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_icons.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_lang_cmd.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_m2_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_manual_consistency.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_model_catalog.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_model_sidebar_dot.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_p2_core.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_plugin.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_plugin_example_tts.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_project_map_prune.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_provider_errors.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_quit_paths.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_retry_policy.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_sanitize.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_screenshot_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_session_invariant.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_session_save_safety.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_sidebar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_sidebar_actions.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_sidebar_align.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_splash_modal.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_statusbar.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_system_inject.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_terminal_guard.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_tools.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_tui.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_update_check.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_vision_capability.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_vision_model.py +0 -0
- {nexforge_cli-0.4.0 → nexforge_cli-0.5.0}/tests/test_vision_tool_retention.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nexforge-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: NexForgeCLI — 一个面向 DeepSeek V4 的终端智能体(TUI + CLI 双模式)
|
|
5
5
|
Project-URL: Homepage, https://gitee.com/Lighthorn/nexforgecli
|
|
6
6
|
Author: NexForge
|
|
@@ -51,13 +51,14 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
|
|
52
52
|
NexForgeCLI 是一个运行在终端里的智能体助手,既支持 DeepSeek/千问等多模型,也是**插件宿主**(plugins 目录即插即用)。既能作为全屏 TUI 交互式对话/编码,也能作为 one-shot 命令行工具嵌进脚本和管道。
|
|
53
53
|
|
|
54
|
-
> 当前版本:**v0.
|
|
54
|
+
> 当前版本:**v0.5.0** · PyPI: `pip install nexforge-cli`
|
|
55
55
|
|
|
56
|
-
**v0.4.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
**v0.4.1 要点(重要修复)**:会话重建时,**内容里出现的 `<!-- nf-msg … -->` 不再被当成消息边界**。
|
|
57
|
+
此前若工具结果 dump 过会话文件(或粘贴过会话内容),加载时那些标记会被解码成额外消息、
|
|
58
|
+
插进工具块中间,导致**每轮请求 400、项目再也打不开**。
|
|
59
|
+
修法:读侧标记识别改为**行首锚定**,写侧对内容里的标记前缀做转义;同时把工具序列修复
|
|
60
|
+
从"只修尾部"升级为"修全序列"(中段违规也能纠正)。
|
|
61
|
+
另含 0.4.0 推出的:本机 TTS 优先/回退、模型随 nf 常驻、`/voice full|brief`、配置残留值自动收敛。
|
|
61
62
|
|
|
62
63
|
---
|
|
63
64
|
|
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
NexForgeCLI 是一个运行在终端里的智能体助手,既支持 DeepSeek/千问等多模型,也是**插件宿主**(plugins 目录即插即用)。既能作为全屏 TUI 交互式对话/编码,也能作为 one-shot 命令行工具嵌进脚本和管道。
|
|
10
10
|
|
|
11
|
-
> 当前版本:**v0.
|
|
12
|
-
|
|
13
|
-
**v0.4.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
> 当前版本:**v0.5.0** · PyPI: `pip install nexforge-cli`
|
|
12
|
+
|
|
13
|
+
**v0.4.1 要点(重要修复)**:会话重建时,**内容里出现的 `<!-- nf-msg … -->` 不再被当成消息边界**。
|
|
14
|
+
此前若工具结果 dump 过会话文件(或粘贴过会话内容),加载时那些标记会被解码成额外消息、
|
|
15
|
+
插进工具块中间,导致**每轮请求 400、项目再也打不开**。
|
|
16
|
+
修法:读侧标记识别改为**行首锚定**,写侧对内容里的标记前缀做转义;同时把工具序列修复
|
|
17
|
+
从"只修尾部"升级为"修全序列"(中段违规也能纠正)。
|
|
18
|
+
另含 0.4.0 推出的:本机 TTS 优先/回退、模型随 nf 常驻、`/voice full|brief`、配置残留值自动收敛。
|
|
18
19
|
|
|
19
20
|
---
|
|
20
21
|
|
|
@@ -16,6 +16,14 @@ thinking = true # 思考模式,默认开
|
|
|
16
16
|
reasoning_effort = "high" # high | max
|
|
17
17
|
max_output_tokens = 32768 # 含思考 token; 别写 8192(思考会吃满 → 正文截断秒停)
|
|
18
18
|
|
|
19
|
+
# 上下文窗口(压缩预算的依据)。**默认不写 = 自动跟随当前模型**:
|
|
20
|
+
# 用户声明(models.toml 的本项 / config.toml 的 context_window)> 实测学习
|
|
21
|
+
# (上游报错里的窗口数字 / 失败请求体量 / 成功响应的 prompt_tokens)> 内置表
|
|
22
|
+
# > 未知模型兜底(1,000,000)。
|
|
23
|
+
# 只有需要**强制覆盖**自动判断时才在这里写(>0 即视为声明, 优先级最高;
|
|
24
|
+
# 但上游若用报错证明窗口更小, 实测值仍会压低它 —— 物理事实优先)。
|
|
25
|
+
# context_window = 1000000
|
|
26
|
+
|
|
19
27
|
# 定价(每百万 token,USD)—— 已核实
|
|
20
28
|
[models.pricing.flash]
|
|
21
29
|
input_cache_hit = 0.0028
|
|
@@ -1,172 +1,187 @@
|
|
|
1
|
-
# 项目总监循环 开发计划
|
|
2
|
-
|
|
3
|
-
> 版本: v1.0 · 创建: 2026-07-16 · 状态: 设计完成,待实现
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 概述
|
|
8
|
-
|
|
9
|
-
在目标模式(`/goal`)下,引入"项目总监 + 开发者"双角色架构。项目总监负责制定计划、审核进展、分发任务;开发者负责具体执行。目标是让 AI 能够自主完成复杂的多轮开发任务,同时保证质量和可追溯性。
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## 角色定义
|
|
14
|
-
|
|
15
|
-
### 项目总监 (Director)
|
|
16
|
-
|
|
17
|
-
- **职责**:审核开发者报告 → 判断进展 → 发布下一条指令
|
|
18
|
-
- **审核维度**:代码质量、性能瓶颈、稳定性、用户体验、逻辑流程
|
|
19
|
-
- **防僵局策略**:当开发者反复说"任务完成"时,从以下方向主动寻找新工作:
|
|
20
|
-
- 边界情况覆盖
|
|
21
|
-
- 测试补充
|
|
22
|
-
- 性能优化
|
|
23
|
-
- 文档/代码注释
|
|
24
|
-
- 代码重构整理
|
|
25
|
-
- 是否真正满足核心需求
|
|
26
|
-
- **停止判断**:若目标已达成,回复 `GOAL_ACHIEVED` 关键词
|
|
27
|
-
|
|
28
|
-
### 开发者 (Developer)
|
|
29
|
-
|
|
30
|
-
- **职责**:执行项目总监的指令 → 完成后提交总结报告
|
|
31
|
-
- **行为约束**:专注执行指令,不做多余的事
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 启动流程 (二步确认)
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
用户输入 /goal
|
|
39
|
-
→ Step 1: 弹出风险警告弹窗(GoalModeModal)
|
|
40
|
-
→ Step 2: 弹出多行输入框,用户输入目标描述
|
|
41
|
-
→ Step 3: 显示目标预览,提示"回复确认开始"
|
|
42
|
-
→ Step 4: 用户回复"确认"/"开始"/"ok"/"yes"
|
|
43
|
-
→ Step 5: 正式启动
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### 启动时操作
|
|
47
|
-
1. `self.config.ui.goal_mode = True`
|
|
48
|
-
2. `self.config.ui.mode = "auto"` (强制全自动)
|
|
49
|
-
3. 保存到项目级 `config.toml`
|
|
50
|
-
4. 创建 `.nexforge/goal/nfgoal.md` (记录最终目标)
|
|
51
|
-
5. 发送首轮指令给 AI:"[项目总监] 制定开发计划并发布第一条指令"
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## 循环流程
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
每个 AI 回合结束 (TURN_DONE)
|
|
59
|
-
→ 如果 goal_mode == True:
|
|
60
|
-
→ 调用 _goal_cycle_continue(last_response)
|
|
61
|
-
→ 检查停止条件
|
|
62
|
-
→ 显示项目总监金色消息
|
|
63
|
-
→ 构造总监 prompt(包含目标+计划+开发者报告)
|
|
64
|
-
→ 启动下一轮 AI
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 停止条件 (任一满足即停止)
|
|
68
|
-
|
|
69
|
-
| 条件 | 检测方式 | 操作 |
|
|
70
|
-
|------|---------|------|
|
|
71
|
-
| 余额耗尽 | `_balance == "0.00"` | 显示"账户余额耗尽",退出目标模式 |
|
|
72
|
-
| 总监判断达成 | `last_response` 含 `GOAL_ACHIEVED` | 显示"项目总监判断目标达成" |
|
|
73
|
-
| 达到最大轮数 | `current >= max_rounds` (默认 100,可通过 `/max N` 设置) | 显示"达到最大轮数" |
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## UI 显示
|
|
78
|
-
|
|
79
|
-
### 项目总监消息 (金色)
|
|
80
|
-
```python
|
|
81
|
-
class DirectorNote(Static):
|
|
82
|
-
"""👔 项目总监: 消息内容 (金色 #FFD700 加粗)"""
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
- 每轮开始前在聊天区显示金色提示条
|
|
86
|
-
- 格式:`第 N/M 轮:项目总监审核`
|
|
87
|
-
|
|
88
|
-
### 状态栏
|
|
89
|
-
- 目标模式开启时显示 `🎯 目标`
|
|
90
|
-
- 运维模式开启时显示 `🔧 运维`
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## 快捷键
|
|
95
|
-
|
|
96
|
-
| 快捷键 | 功能 |
|
|
97
|
-
|--------|------|
|
|
98
|
-
| F7 | 切换运维模式 |
|
|
99
|
-
| F8 | 切换目标模式(开启时强制全自动) |
|
|
100
|
-
| Esc | 目标模式三级停止:停总监 → 停开发者 → 退出 |
|
|
101
|
-
|
|
102
|
-
### Esc 三级停止逻辑
|
|
103
|
-
```
|
|
104
|
-
Esc 第1次:停止项目总监(goal_mode=False,开发者继续当前工作)
|
|
105
|
-
Esc 第2次:取消开发者 worker
|
|
106
|
-
Esc 第3次:弹出退出确认
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## 文件体系 (项目隔离,仅目标模式)
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
<项目>/.nexforge/goal/
|
|
115
|
-
├── nfgoal.md ← 最终目标
|
|
116
|
-
├── plan.md ← 项目总监编写的计划
|
|
117
|
-
└── rounds/
|
|
118
|
-
├── 001.md ← 第1轮:开发者报告 + 总监审核
|
|
119
|
-
├── 002.md ← 第2轮
|
|
120
|
-
└── ...
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
- 非目标模式不创建此目录
|
|
124
|
-
- 离开目标模式后不自动清理(保留历史)
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## 配置项
|
|
129
|
-
|
|
130
|
-
| 配置 | 默认 | 说明 |
|
|
131
|
-
|------|------|------|
|
|
132
|
-
| `ui.goal_mode` | `false` | 是否处于目标模式 |
|
|
133
|
-
| `ui.ops_mode` | `false` | 是否处于运维模式 |
|
|
134
|
-
| `ui.max_rounds` | `100` | 目标模式最大轮数,通过 `/max N` 修改 |
|
|
135
|
-
| `ui.mode` | `review` | 审批模式(review/auto) |
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## 涉及文件
|
|
140
|
-
|
|
141
|
-
| 文件 | 改动 |
|
|
142
|
-
|------|------|
|
|
143
|
-
| `src/nexforge/core/goal_manager.py` | **已创建** — GoalManager 类 |
|
|
144
|
-
| `src/nexforge/ui/screens/chat.py` | 加 `_start_goal_mode`、`_confirm_goal_start`、`_goal_cycle_continue` |
|
|
145
|
-
| `src/nexforge/ui/widgets/messages.py` | **已创建** — DirectorNote 金色组件 |
|
|
146
|
-
| `src/nexforge/ui/widgets/mode_warning.py` | 已有 GoalModeModal、OpsModeModal |
|
|
147
|
-
| `src/nexforge/config.py` | goal_mode/ops_mode/max_rounds 字段 |
|
|
148
|
-
| `src/nexforge/store/session_store.py` | 会话保存过滤系统消息(已实现) |
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## 实现注意事项
|
|
153
|
-
|
|
154
|
-
1. **不要用 heredoc/多行字符串替换编辑 chat.py**——该文件已因反复编辑损坏多次
|
|
155
|
-
2. **使用 `edit_file` 工具逐个精准替换**,每次编辑后编译验证
|
|
156
|
-
3. **`_goal_cycle_continue` 必须独立为类方法**,不能嵌入其他方法中
|
|
157
|
-
4. **字符串拼接用 `+` 而非 f-string 跨行**,避免语法错误
|
|
158
|
-
5. **`save_config` 按项目保存**(`<cwd>/.nexforge/config.toml`),不污染全局
|
|
159
|
-
6. **系统消息不保存到会话文件**(已在 session_store.py 实现)
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 测试验证
|
|
164
|
-
|
|
165
|
-
- [ ] `/goal` → 弹窗 → 输入目标 → "确认" → 项目总监启动
|
|
166
|
-
- [ ] F8 一键切换目标模式
|
|
167
|
-
- [ ] F7 一键切换运维模式
|
|
168
|
-
- [ ] Esc 三级停止(目标模式)
|
|
169
|
-
- [ ] `GOAL_ACHIEVED` 自动停止
|
|
170
|
-
- [ ] `/max 50` 修改轮数上限
|
|
171
|
-
- [ ] 不同项目独立模式状态
|
|
172
|
-
- [ ] 余额耗尽自动停止
|
|
1
|
+
# 项目总监循环 开发计划
|
|
2
|
+
|
|
3
|
+
> 版本: v1.0 · 创建: 2026-07-16 · 状态: 设计完成,待实现
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 概述
|
|
8
|
+
|
|
9
|
+
在目标模式(`/goal`)下,引入"项目总监 + 开发者"双角色架构。项目总监负责制定计划、审核进展、分发任务;开发者负责具体执行。目标是让 AI 能够自主完成复杂的多轮开发任务,同时保证质量和可追溯性。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 角色定义
|
|
14
|
+
|
|
15
|
+
### 项目总监 (Director)
|
|
16
|
+
|
|
17
|
+
- **职责**:审核开发者报告 → 判断进展 → 发布下一条指令
|
|
18
|
+
- **审核维度**:代码质量、性能瓶颈、稳定性、用户体验、逻辑流程
|
|
19
|
+
- **防僵局策略**:当开发者反复说"任务完成"时,从以下方向主动寻找新工作:
|
|
20
|
+
- 边界情况覆盖
|
|
21
|
+
- 测试补充
|
|
22
|
+
- 性能优化
|
|
23
|
+
- 文档/代码注释
|
|
24
|
+
- 代码重构整理
|
|
25
|
+
- 是否真正满足核心需求
|
|
26
|
+
- **停止判断**:若目标已达成,回复 `GOAL_ACHIEVED` 关键词
|
|
27
|
+
|
|
28
|
+
### 开发者 (Developer)
|
|
29
|
+
|
|
30
|
+
- **职责**:执行项目总监的指令 → 完成后提交总结报告
|
|
31
|
+
- **行为约束**:专注执行指令,不做多余的事
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 启动流程 (二步确认)
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
用户输入 /goal
|
|
39
|
+
→ Step 1: 弹出风险警告弹窗(GoalModeModal)
|
|
40
|
+
→ Step 2: 弹出多行输入框,用户输入目标描述
|
|
41
|
+
→ Step 3: 显示目标预览,提示"回复确认开始"
|
|
42
|
+
→ Step 4: 用户回复"确认"/"开始"/"ok"/"yes"
|
|
43
|
+
→ Step 5: 正式启动
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 启动时操作
|
|
47
|
+
1. `self.config.ui.goal_mode = True`
|
|
48
|
+
2. `self.config.ui.mode = "auto"` (强制全自动)
|
|
49
|
+
3. 保存到项目级 `config.toml`
|
|
50
|
+
4. 创建 `.nexforge/goal/nfgoal.md` (记录最终目标)
|
|
51
|
+
5. 发送首轮指令给 AI:"[项目总监] 制定开发计划并发布第一条指令"
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 循环流程
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
每个 AI 回合结束 (TURN_DONE)
|
|
59
|
+
→ 如果 goal_mode == True:
|
|
60
|
+
→ 调用 _goal_cycle_continue(last_response)
|
|
61
|
+
→ 检查停止条件
|
|
62
|
+
→ 显示项目总监金色消息
|
|
63
|
+
→ 构造总监 prompt(包含目标+计划+开发者报告)
|
|
64
|
+
→ 启动下一轮 AI
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 停止条件 (任一满足即停止)
|
|
68
|
+
|
|
69
|
+
| 条件 | 检测方式 | 操作 |
|
|
70
|
+
|------|---------|------|
|
|
71
|
+
| 余额耗尽 | `_balance == "0.00"` | 显示"账户余额耗尽",退出目标模式 |
|
|
72
|
+
| 总监判断达成 | `last_response` 含 `GOAL_ACHIEVED` | 显示"项目总监判断目标达成" |
|
|
73
|
+
| 达到最大轮数 | `current >= max_rounds` (默认 100,可通过 `/max N` 设置) | 显示"达到最大轮数" |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## UI 显示
|
|
78
|
+
|
|
79
|
+
### 项目总监消息 (金色)
|
|
80
|
+
```python
|
|
81
|
+
class DirectorNote(Static):
|
|
82
|
+
"""👔 项目总监: 消息内容 (金色 #FFD700 加粗)"""
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- 每轮开始前在聊天区显示金色提示条
|
|
86
|
+
- 格式:`第 N/M 轮:项目总监审核`
|
|
87
|
+
|
|
88
|
+
### 状态栏
|
|
89
|
+
- 目标模式开启时显示 `🎯 目标`
|
|
90
|
+
- 运维模式开启时显示 `🔧 运维`
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 快捷键
|
|
95
|
+
|
|
96
|
+
| 快捷键 | 功能 |
|
|
97
|
+
|--------|------|
|
|
98
|
+
| F7 | 切换运维模式 |
|
|
99
|
+
| F8 | 切换目标模式(开启时强制全自动) |
|
|
100
|
+
| Esc | 目标模式三级停止:停总监 → 停开发者 → 退出 |
|
|
101
|
+
|
|
102
|
+
### Esc 三级停止逻辑
|
|
103
|
+
```
|
|
104
|
+
Esc 第1次:停止项目总监(goal_mode=False,开发者继续当前工作)
|
|
105
|
+
Esc 第2次:取消开发者 worker
|
|
106
|
+
Esc 第3次:弹出退出确认
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 文件体系 (项目隔离,仅目标模式)
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
<项目>/.nexforge/goal/
|
|
115
|
+
├── nfgoal.md ← 最终目标
|
|
116
|
+
├── plan.md ← 项目总监编写的计划
|
|
117
|
+
└── rounds/
|
|
118
|
+
├── 001.md ← 第1轮:开发者报告 + 总监审核
|
|
119
|
+
├── 002.md ← 第2轮
|
|
120
|
+
└── ...
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- 非目标模式不创建此目录
|
|
124
|
+
- 离开目标模式后不自动清理(保留历史)
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 配置项
|
|
129
|
+
|
|
130
|
+
| 配置 | 默认 | 说明 |
|
|
131
|
+
|------|------|------|
|
|
132
|
+
| `ui.goal_mode` | `false` | 是否处于目标模式 |
|
|
133
|
+
| `ui.ops_mode` | `false` | 是否处于运维模式 |
|
|
134
|
+
| `ui.max_rounds` | `100` | 目标模式最大轮数,通过 `/max N` 修改 |
|
|
135
|
+
| `ui.mode` | `review` | 审批模式(review/auto) |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 涉及文件
|
|
140
|
+
|
|
141
|
+
| 文件 | 改动 |
|
|
142
|
+
|------|------|
|
|
143
|
+
| `src/nexforge/core/goal_manager.py` | **已创建** — GoalManager 类 |
|
|
144
|
+
| `src/nexforge/ui/screens/chat.py` | 加 `_start_goal_mode`、`_confirm_goal_start`、`_goal_cycle_continue` |
|
|
145
|
+
| `src/nexforge/ui/widgets/messages.py` | **已创建** — DirectorNote 金色组件 |
|
|
146
|
+
| `src/nexforge/ui/widgets/mode_warning.py` | 已有 GoalModeModal、OpsModeModal |
|
|
147
|
+
| `src/nexforge/config.py` | goal_mode/ops_mode/max_rounds 字段 |
|
|
148
|
+
| `src/nexforge/store/session_store.py` | 会话保存过滤系统消息(已实现) |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 实现注意事项
|
|
153
|
+
|
|
154
|
+
1. **不要用 heredoc/多行字符串替换编辑 chat.py**——该文件已因反复编辑损坏多次
|
|
155
|
+
2. **使用 `edit_file` 工具逐个精准替换**,每次编辑后编译验证
|
|
156
|
+
3. **`_goal_cycle_continue` 必须独立为类方法**,不能嵌入其他方法中
|
|
157
|
+
4. **字符串拼接用 `+` 而非 f-string 跨行**,避免语法错误
|
|
158
|
+
5. **`save_config` 按项目保存**(`<cwd>/.nexforge/config.toml`),不污染全局
|
|
159
|
+
6. **系统消息不保存到会话文件**(已在 session_store.py 实现)
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 测试验证
|
|
164
|
+
|
|
165
|
+
- [ ] `/goal` → 弹窗 → 输入目标 → "确认" → 项目总监启动
|
|
166
|
+
- [ ] F8 一键切换目标模式
|
|
167
|
+
- [ ] F7 一键切换运维模式
|
|
168
|
+
- [ ] Esc 三级停止(目标模式)
|
|
169
|
+
- [ ] `GOAL_ACHIEVED` 自动停止
|
|
170
|
+
- [ ] `/max 50` 修改轮数上限
|
|
171
|
+
- [ ] 不同项目独立模式状态
|
|
172
|
+
- [ ] 余额耗尽自动停止
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 实现现状补充(2026-09-12)
|
|
177
|
+
|
|
178
|
+
本节记录与上面设计稿**不一致**的最终实现,避免后来者按设计稿误判代码。
|
|
179
|
+
|
|
180
|
+
| 设计稿 | 实现现状 | 原因 |
|
|
181
|
+
|------|---------|------|
|
|
182
|
+
| Esc 三级停止(停总监 → 停开发者 → 退出) | **一次 Esc 停整个目标模式**(停总监循环 + 取消开发者 worker + 关双栏 + 关 goal_mode);空闲时才是退出确认 | 三级停止需记"第几次 Esc"状态,实际使用中用户按第一次没停住会反复按;一次停干净更可预期 |
|
|
183
|
+
| 离开目标模式不自动清理(保留历史) | 停止/关闭/切换时把现场**归档**到 `.nexforge/goal_archive/<时间戳>-<标签>/`,现场清空 | "保留现场"会让下次开启把旧目标误判为"插话"(note_20260825_214722);归档同时满足可回看与不误判 |
|
|
184
|
+
| 余额耗尽检测 `_balance == "0.00"` | `parse_balance()` 数值化,`<=0` 才算耗尽;解析不出则不停止 | 子串匹配会把 `¥100.00`/`¥20.00`/`¥1,000.00` 误判为耗尽 |
|
|
185
|
+
| 总监/开发者回合失败无约定 | 失败必可见:开发者异常结束补"失败回执"交总监决策;总监回合失败重试一次后**暂停**(保留现场,回一句话即续跑) | 失败没有回执通道时,循环停在 `await _wake_event.wait()`,用户看到的是"AI 不动了" |
|
|
186
|
+
|
|
187
|
+
详见 ADR `docs/decisions/2026-09-12-目标模式失败可见与历史保全.md`。
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# 决策:内容里的 `<!-- nf-msg … -->` 不得被当成消息边界
|
|
2
|
+
|
|
3
|
+
> 日期:2026-09-12 · 状态:生效
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
|
|
7
|
+
会话重建的权威是每行消息末尾的结构化标记 `<!-- nf-msg <base64> -->`(`docs/session-invariant.md` §4.1)。
|
|
8
|
+
但解析用的是**全文 `findall`**,于是"内容里出现的标记"与"真正的消息边界"无法区分。
|
|
9
|
+
|
|
10
|
+
触发链(实测,NexForgeCLI 自己的 `session-122357`):
|
|
11
|
+
|
|
12
|
+
1. 工具结果 dump 了某个会话 `.md` 文件(`read_file .nexforge/sessions/session-…md`),
|
|
13
|
+
被 dump 的标记行作为**内容**落进新会话文件;
|
|
14
|
+
2. 下次加载时,这些"内容里的标记"被解码成**额外消息**,且插在
|
|
15
|
+
`assistant(tool_calls)` 与它的 `tool` 响应之间(实测多出 10 份重复助手消息);
|
|
16
|
+
3. 请求违反 OpenAI/DeepSeek 规则——"带 tool_calls 的 assistant 后必须紧跟覆盖全部
|
|
17
|
+
tool_call_id 的 tool 消息"——返回 400
|
|
18
|
+
`insufficient tool messages following tool_calls message`;
|
|
19
|
+
4. `_repair_incomplete_tail` 只修**尾部**,看不见中段违规 → 每轮请求都 400。
|
|
20
|
+
用户侧现象:**"项目再也打不开"**(打开后说什么都报错)。
|
|
21
|
+
|
|
22
|
+
## 决策
|
|
23
|
+
|
|
24
|
+
三层一起上(缺任一层都有残留口子):
|
|
25
|
+
|
|
26
|
+
1. **写侧转义**(`_escape_marker_prefix`):人读部分里出现的 `<!-- nf-msg` 一律插入零宽空格
|
|
27
|
+
`\u200b` 转义。标记内的 base64 负载不受影响 → 重建权威无损
|
|
28
|
+
(§4.1 本就允许人读部分变形/截断)。
|
|
29
|
+
2. **读侧锚定**(`_MARKER_RE` 加 `re.M` 与行首 `^`):只有**独立成行**的标记才是边界。
|
|
30
|
+
真标记必然在行首(所有人类可读块都以换行结尾),全仓库历史会话文件实测零反例。
|
|
31
|
+
3. **全序列修复**(`_repair_incomplete_tail` → `_repair_tool_sequence`,旧名保留为别名):
|
|
32
|
+
修复**整条序列**而不是尾部 —— 夹层消息**保序后移**、缺响应的 tool_call 补"已取消"、
|
|
33
|
+
重复响应与无主孤儿 tool 删除。修复后的序列对 API **恒合法**。
|
|
34
|
+
配套:`agent.py` 的防死循环提示改为在整块工具响应**之后**追加,不再插进 tool 之间。
|
|
35
|
+
|
|
36
|
+
## 理由
|
|
37
|
+
|
|
38
|
+
- **只修尾部不够**:违规可能在中段(本次实测),尾部修复完全看不到。
|
|
39
|
+
- **只加读侧锚定不够**:不带行号前缀的内容(用户把会话文件整段粘进对话、shell 直接
|
|
40
|
+
`type` 出文件)仍能伪造出行首标记。
|
|
41
|
+
- **只加写侧转义不够**:修复前落盘的历史文件里已有的镶嵌标记仍会被解码 → 需要读侧 +
|
|
42
|
+
全序列修复兜底(已用真机 `session-122357` 验证:修复后非法点 0)。
|
|
43
|
+
- **否决"按人读格式严格比对,再判定某个标记是否可信"**:人读格式一旦演进,旧文件会被
|
|
44
|
+
整段判成伪标记 → **静默丢历史**,代价远高于收益(不变量只禁止一件事:无声地丢失)。
|
|
45
|
+
|
|
46
|
+
## 代价与边界
|
|
47
|
+
|
|
48
|
+
- 人读部分与原始内容有肉眼不可见的差异(零宽空格);工具结果原文仍由标记负载精确重建。
|
|
49
|
+
- 夹层消息只"后移"不删除:已积累的重复消息仍占上下文(必要时人工清理)。
|
|
50
|
+
- **复用注意**:`_repair_tool_sequence` 为兼容旧行为会弹出**尾部未配对 user**;因此它之后必须
|
|
51
|
+
紧跟 `add_user`(app 的 `run_turn` 顺序)。若单独调用后直接发请求,列表会以 assistant 结尾,
|
|
52
|
+
thinking 模式下会触发另一条 400 `reasoning_content ... must be passed back`
|
|
53
|
+
(见 `docs/evidence/session-marker-boundary_report.md` §5 坑 1)。
|
|
54
|
+
- **已知未覆盖(本次不改,另行决策)**:`save_session` 不清理"陈旧分段"(列表变短时,
|
|
55
|
+
旧的高编号分段文件仍会被 `load_session` 追加 → 陈旧内容混入 + 可能非法序列)。
|
|
56
|
+
机制已在证据脚本里复现(3 条被加载成 130 条);全序列修复能兜住 400,但内容冗余仍在。
|
|
57
|
+
|
|
58
|
+
## 关联
|
|
59
|
+
|
|
60
|
+
- 模块:`store/session_store.py`(`_MARKER_RE` / `_escape_marker_prefix` / `_format_message`)、
|
|
61
|
+
`core/session.py`(`_repair_tool_sequence`)、`core/agent.py`(提示位置)
|
|
62
|
+
- 文档:`docs/session-invariant.md` §4.1
|
|
63
|
+
- 测试:`tests/test_session_store.py`(往返)、`tests/test_session_repair.py`(全序列)、
|
|
64
|
+
`tests/test_session_invariant.py`
|
|
65
|
+
- 证据:`docs/evidence/session-marker-boundary_report.md` / `.log`
|