nexforge-cli 0.2.6__tar.gz → 0.2.9__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.
Files changed (164) hide show
  1. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/PKG-INFO +4 -1
  2. nexforge_cli-0.2.9/STATS_API.md +209 -0
  3. nexforge_cli-0.2.9/doc//344/273/243/347/240/201/344/274/230/345/214/226/350/256/241/345/210/222.md +142 -0
  4. nexforge_cli-0.2.9/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 +37 -0
  5. nexforge_cli-0.2.9/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 +172 -0
  6. nexforge_cli-0.2.9/manual/01-/345/256/211/350/243/205/344/270/216/351/205/215/347/275/256.md +83 -0
  7. nexforge_cli-0.2.9/manual/02-/347/225/214/351/235/242/344/270/216/345/277/253/346/215/267/351/224/256.md +110 -0
  8. nexforge_cli-0.2.9/manual/03-/346/250/241/345/236/213/351/205/215/347/275/256.md +98 -0
  9. nexforge_cli-0.2.9/manual/04-/345/267/245/345/205/267/345/217/202/350/200/203.md +96 -0
  10. nexforge_cli-0.2.9/manual/05-/346/225/260/346/215/256/344/270/216/346/220/234/347/264/242.md +62 -0
  11. nexforge_cli-0.2.9/manual/06-/346/235/203/351/231/220/344/270/216/346/250/241/345/274/217.md +71 -0
  12. nexforge_cli-0.2.9/manual/07-/344/274/232/350/257/235/344/270/216/350/256/260/345/277/206.md +59 -0
  13. nexforge_cli-0.2.9/manual/08-/350/207/252/345/256/232/344/271/211/351/205/215/347/275/256.md +110 -0
  14. nexforge_cli-0.2.9/manual/09-/345/270/270/350/247/201/351/227/256/351/242/230.md +83 -0
  15. nexforge_cli-0.2.9/manual/README.md +35 -0
  16. nexforge_cli-0.2.9/manual//351/231/204/345/275/225-/345/257/271/346/257/224/345/210/206/346/236/220.md +28 -0
  17. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/pyproject.toml +60 -58
  18. nexforge_cli-0.2.9/src/nexforge/__init__.py +7 -0
  19. nexforge_cli-0.2.9/src/nexforge/app.py +58 -0
  20. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/cli.py +171 -159
  21. nexforge_cli-0.2.9/src/nexforge/config.py +419 -0
  22. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/agent.py +261 -244
  23. nexforge_cli-0.2.9/src/nexforge/core/federation.py +195 -0
  24. nexforge_cli-0.2.9/src/nexforge/core/goal_manager.py +144 -0
  25. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/jobs.py +6 -0
  26. nexforge_cli-0.2.9/src/nexforge/core/memory_engine.py +119 -0
  27. nexforge_cli-0.2.9/src/nexforge/core/project_mapper.py +376 -0
  28. nexforge_cli-0.2.9/src/nexforge/core/provider.py +65 -0
  29. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/session.py +7 -1
  30. nexforge_cli-0.2.9/src/nexforge/core/summarizer.py +96 -0
  31. nexforge_cli-0.2.9/src/nexforge/core/tool_manifest.py +164 -0
  32. nexforge_cli-0.2.9/src/nexforge/features/auto_skills.py +125 -0
  33. nexforge_cli-0.2.9/src/nexforge/features/base.py +38 -0
  34. nexforge_cli-0.2.9/src/nexforge/features/federation_feature.py +45 -0
  35. nexforge_cli-0.2.9/src/nexforge/features/map_feature.py +47 -0
  36. nexforge_cli-0.2.9/src/nexforge/features/memory_feature.py +40 -0
  37. nexforge_cli-0.2.9/src/nexforge/features/mode_features.py +342 -0
  38. nexforge_cli-0.2.9/src/nexforge/features/plan_feature.py +80 -0
  39. nexforge_cli-0.2.9/src/nexforge/features/registry.py +29 -0
  40. nexforge_cli-0.2.9/src/nexforge/features/session_feature.py +182 -0
  41. nexforge_cli-0.2.9/src/nexforge/features/slash_feature.py +27 -0
  42. nexforge_cli-0.2.9/src/nexforge/features/stats_feature.py +24 -0
  43. nexforge_cli-0.2.9/src/nexforge/features/tool_manifest_feature.py +33 -0
  44. nexforge_cli-0.2.9/src/nexforge/provider/__init__.py +101 -0
  45. nexforge_cli-0.2.9/src/nexforge/provider/_retry.py +46 -0
  46. nexforge_cli-0.2.9/src/nexforge/provider/anthropic.py +256 -0
  47. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/provider/deepseek.py +37 -26
  48. nexforge_cli-0.2.9/src/nexforge/provider/openai.py +179 -0
  49. nexforge_cli-0.2.9/src/nexforge/stats/__init__.py +0 -0
  50. nexforge_cli-0.2.9/src/nexforge/stats/heartbeat.py +58 -0
  51. nexforge_cli-0.2.9/src/nexforge/store/session_store.py +355 -0
  52. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/theme.tcss +130 -128
  53. nexforge_cli-0.2.9/src/nexforge/tools/data_tools.py +253 -0
  54. nexforge_cli-0.2.9/src/nexforge/tools/federation.py +85 -0
  55. nexforge_cli-0.2.9/src/nexforge/tools/image_tools.py +150 -0
  56. nexforge_cli-0.2.9/src/nexforge/tools/ops_tools.py +846 -0
  57. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/registry.py +117 -94
  58. nexforge_cli-0.2.9/src/nexforge/tools/search.py +210 -0
  59. nexforge_cli-0.2.9/src/nexforge/tools/shell.py +109 -0
  60. nexforge_cli-0.2.9/src/nexforge/tools/web.py +93 -0
  61. nexforge_cli-0.2.9/src/nexforge/ui/clipboard_image.py +33 -0
  62. nexforge_cli-0.2.9/src/nexforge/ui/screen_api.py +93 -0
  63. nexforge_cli-0.2.9/src/nexforge/ui/screens/chat.py +825 -0
  64. nexforge_cli-0.2.9/src/nexforge/ui/screens/chat_actions.py +232 -0
  65. nexforge_cli-0.2.9/src/nexforge/ui/screens/splash.py +78 -0
  66. nexforge_cli-0.2.9/src/nexforge/ui/slash_handler.py +510 -0
  67. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/banner.py +27 -29
  68. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/diff_modal.py +15 -9
  69. nexforge_cli-0.2.9/src/nexforge/ui/widgets/image_sidebar.py +91 -0
  70. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/messages.py +37 -2
  71. nexforge_cli-0.2.9/src/nexforge/ui/widgets/mode_warning.py +120 -0
  72. nexforge_cli-0.2.9/src/nexforge/ui/widgets/model_sidebar.py +237 -0
  73. nexforge_cli-0.2.9/src/nexforge/ui/widgets/multiline_prompt.py +78 -0
  74. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/plan_sidebar.py +2 -1
  75. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/sidebar.py +2 -1
  76. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/statusbar.py +83 -74
  77. nexforge_cli-0.2.9/src/nexforge/utils/__init__.py +0 -0
  78. nexforge_cli-0.2.9/src/nexforge/utils/logging.py +23 -0
  79. nexforge_cli-0.2.9/src/nexforge/web/__init__.py +0 -0
  80. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/web/server.py +256 -177
  81. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/web/static/index.html +128 -123
  82. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_approval.py +4 -4
  83. nexforge_cli-0.2.9/tests/test_manual_consistency.py +211 -0
  84. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_sidebar.py +2 -2
  85. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_sidebar_actions.py +3 -3
  86. nexforge_cli-0.2.9/tests/test_splash_modal.py +60 -0
  87. nexforge_cli-0.2.6/doc//344/274/232/350/257/235/347/256/241/347/220/206.md +0 -56
  88. nexforge_cli-0.2.6/doc//345/221/275/344/273/244/344/270/216/345/277/253/346/215/267/351/224/256.md +0 -57
  89. nexforge_cli-0.2.6/doc//345/256/211/350/243/205/344/270/216/351/205/215/347/275/256.md +0 -108
  90. nexforge_cli-0.2.6/doc//345/257/271/346/257/224/345/210/206/346/236/220.md +0 -76
  91. nexforge_cli-0.2.6/doc//345/267/245/345/205/267/345/217/202/350/200/203.md +0 -64
  92. nexforge_cli-0.2.6/doc//346/200/273/350/247/210.md +0 -42
  93. nexforge_cli-0.2.6/doc//346/235/203/351/231/220/347/263/273/347/273/237.md +0 -44
  94. nexforge_cli-0.2.6/doc//350/256/241/345/210/222/346/250/241/345/274/217.md +0 -47
  95. nexforge_cli-0.2.6/doc//351/253/230/347/272/247/345/212/237/350/203/275.md +0 -101
  96. nexforge_cli-0.2.6/src/nexforge/__init__.py +0 -7
  97. nexforge_cli-0.2.6/src/nexforge/app.py +0 -38
  98. nexforge_cli-0.2.6/src/nexforge/config.py +0 -192
  99. nexforge_cli-0.2.6/src/nexforge/provider/__init__.py +0 -1
  100. nexforge_cli-0.2.6/src/nexforge/store/session_store.py +0 -208
  101. nexforge_cli-0.2.6/src/nexforge/tools/shell.py +0 -66
  102. nexforge_cli-0.2.6/src/nexforge/tools/web.py +0 -40
  103. nexforge_cli-0.2.6/src/nexforge/ui/screens/chat.py +0 -911
  104. nexforge_cli-0.2.6/src/nexforge/ui/widgets/mode_warning.py +0 -57
  105. nexforge_cli-0.2.6/src/nexforge/ui/widgets/multiline_prompt.py +0 -27
  106. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/.gitignore +0 -0
  107. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/= +0 -0
  108. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/INSTALL.md +0 -0
  109. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/README.md +0 -0
  110. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/agent.svg +0 -0
  111. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/cost.svg +0 -0
  112. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/edit.svg +0 -0
  113. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/err.svg +0 -0
  114. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/file.svg +0 -0
  115. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/model.svg +0 -0
  116. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/ok.svg +0 -0
  117. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/read.svg +0 -0
  118. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/running.svg +0 -0
  119. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/search.svg +0 -0
  120. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/shell.svg +0 -0
  121. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/thinking.svg +0 -0
  122. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/web.svg +0 -0
  123. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/assets/icons/write.svg +0 -0
  124. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/config.example.toml +0 -0
  125. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/devlog/2026-07-07.md +0 -0
  126. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/scripts/publish.sh +0 -0
  127. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/scripts/smoke_provider.py +0 -0
  128. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/scripts/smoke_tui.py +0 -0
  129. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/__main__.py +0 -0
  130. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/__init__.py +0 -0
  131. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/permissions.py +0 -0
  132. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/router.py +0 -0
  133. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/core/types.py +0 -0
  134. {nexforge_cli-0.2.6/src/nexforge/web → nexforge_cli-0.2.9/src/nexforge/features}/__init__.py +0 -0
  135. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/icons.py +0 -0
  136. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/mcp/__init__.py +0 -0
  137. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/provider/balance.py +0 -0
  138. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/skills/loader.py +0 -0
  139. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/store/__init__.py +0 -0
  140. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/store/plan_store.py +0 -0
  141. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/__init__.py +0 -0
  142. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/_paths.py +0 -0
  143. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/background.py +0 -0
  144. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/base.py +0 -0
  145. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/edit_file.py +0 -0
  146. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/fs_ops.py +0 -0
  147. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/git.py +0 -0
  148. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/list_dir.py +0 -0
  149. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/multi_edit.py +0 -0
  150. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/read_file.py +0 -0
  151. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/search_content.py +0 -0
  152. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/search_files.py +0 -0
  153. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/tools/write_file.py +0 -0
  154. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/__init__.py +0 -0
  155. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/screens/__init__.py +0 -0
  156. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/__init__.py +0 -0
  157. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/apikey_modal.py +0 -0
  158. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/confirm_modal.py +0 -0
  159. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/src/nexforge/ui/widgets/multiline_modal.py +0 -0
  160. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_config.py +0 -0
  161. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_icons.py +0 -0
  162. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_m2_tools.py +0 -0
  163. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_tools.py +0 -0
  164. {nexforge_cli-0.2.6 → nexforge_cli-0.2.9}/tests/test_tui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nexforge-cli
3
- Version: 0.2.6
3
+ Version: 0.2.9
4
4
  Summary: NexForgeCLI — 一个面向 DeepSeek V4 的终端智能体(TUI + CLI 双模式)
5
5
  Project-URL: Homepage, https://gitee.com/Lighthorn/nexforgecli
6
6
  Author: NexForge
@@ -21,10 +21,13 @@ Classifier: Topic :: Terminals
21
21
  Requires-Python: >=3.11
22
22
  Requires-Dist: httpx>=0.27
23
23
  Requires-Dist: openai>=1.40
24
+ Requires-Dist: pillow>=10.0
24
25
  Requires-Dist: pydantic>=2.6
25
26
  Requires-Dist: pyperclip>=1.8
26
27
  Requires-Dist: rich>=13.7
27
28
  Requires-Dist: textual>=0.60
29
+ Provides-Extra: anthropic
30
+ Requires-Dist: anthropic>=0.50; extra == 'anthropic'
28
31
  Provides-Extra: dev
29
32
  Requires-Dist: build>=1.2; extra == 'dev'
30
33
  Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
@@ -0,0 +1,209 @@
1
+ # NexTech 软件统计 API 文档
2
+
3
+ > 版本: 1.0
4
+ > 基础路径: `https://nextech.club/api/stats.php`
5
+
6
+ ---
7
+
8
+ ## 概述
9
+
10
+ 轻量级软件在线统计服务,用于采集和查询软件客户端的下载量、在线用户数等指标。采用 **SQLite** 存储 + **POST 心跳** 机制,支持万级并发。
11
+
12
+ ### 设计原则
13
+
14
+ - 最小资源消耗:单条 SQLite `INSERT OR REPLACE` 写入,无 MySQL 开销
15
+ - 自动过期清理:120 秒无心跳自动标记离线
16
+ - 批量清理:每 10 次心跳触发一次过期记录删除
17
+
18
+ ---
19
+
20
+ ## 接口列表
21
+
22
+ ### 1. 软件心跳上报
23
+
24
+ ```
25
+ POST /api/stats.php?action=heartbeat
26
+ Content-Type: application/json
27
+ ```
28
+
29
+ 上报软件客户端的在线状态,建议每 **60 秒** 调用一次。
30
+
31
+ #### 请求参数
32
+
33
+ | 字段 | 类型 | 必填 | 说明 |
34
+ |------|------|------|------|
35
+ | `software` | string | 是 | 软件名称(如 `NexAgent`、`NexClient`) |
36
+ | `client_id` | string | 是 | 客户端唯一标识(每台设备的 ID) |
37
+
38
+ #### 请求示例
39
+
40
+ ```bash
41
+ curl -X POST https://nextech.club/api/stats.php?action=heartbeat \
42
+ -H "Content-Type: application/json" \
43
+ -d '{"software":"NexAgent","client_id":"device-001"}'
44
+ ```
45
+
46
+ #### 响应示例
47
+
48
+ ```json
49
+ {
50
+ "ok": true,
51
+ "online_total": 42,
52
+ "cleaned": 3
53
+ }
54
+ ```
55
+
56
+ | 字段 | 类型 | 说明 |
57
+ |------|------|------|
58
+ | `ok` | bool | 是否成功 |
59
+ | `online_total` | int | 当前总在线数 |
60
+ | `cleaned` | int | 本次清理的过期记录数 |
61
+
62
+ #### 错误响应
63
+
64
+ ```json
65
+ {
66
+ "ok": false,
67
+ "error": "software 和 client_id 不能为空"
68
+ }
69
+ ```
70
+
71
+ HTTP 状态码: `400`
72
+
73
+ ---
74
+
75
+ ### 2. 获取统计
76
+
77
+ ```
78
+ GET /api/stats.php
79
+ ```
80
+
81
+ 返回当前在线用户数(按软件分组)和今日软件下载量。
82
+
83
+ #### 请求示例
84
+
85
+ ```bash
86
+ curl https://nextech.club/api/stats.php
87
+ ```
88
+
89
+ #### 响应示例
90
+
91
+ ```json
92
+ {
93
+ "ok": true,
94
+ "time": "2026-07-21 06:48:00",
95
+ "online": {
96
+ "total": 42,
97
+ "by_software": {
98
+ "NexAgent": 30,
99
+ "NexClient": 12
100
+ }
101
+ },
102
+ "downloads": [
103
+ {
104
+ "name": "nexhttp-1.0.0.zip",
105
+ "count": 4,
106
+ "size_mb": 23.37
107
+ }
108
+ ]
109
+ }
110
+ ```
111
+
112
+ | 字段 | 类型 | 说明 |
113
+ |------|------|------|
114
+ | `online.total` | int | 总在线数(120 秒内有心跳) |
115
+ | `online.by_software` | object | 按软件名称分组的在线数 |
116
+ | `downloads[]` | array | 今日下载统计列表 |
117
+ | `downloads[].name` | string | 下载文件名 |
118
+ | `downloads[].count` | int | 今日下载次数 |
119
+ | `downloads[].size_mb` | float | 文件大小(MB) |
120
+
121
+ ---
122
+
123
+ ## 客户端接入示例
124
+
125
+ ### Python
126
+
127
+ ```python
128
+ import requests
129
+ import time
130
+ import uuid
131
+
132
+ CLIENT_ID = str(uuid.uuid4()) # 每台设备固定一个 ID
133
+
134
+ def heartbeat():
135
+ while True:
136
+ try:
137
+ r = requests.post(
138
+ "https://nextech.club/api/stats.php?action=heartbeat",
139
+ json={"software": "NexAgent", "client_id": CLIENT_ID},
140
+ timeout=5
141
+ )
142
+ print(f"心跳成功: {r.json()['online_total']} 在线")
143
+ except Exception as e:
144
+ print(f"心跳失败: {e}")
145
+ time.sleep(60) # 每 60 秒上报一次
146
+ ```
147
+
148
+ ### JavaScript / Node.js
149
+
150
+ ```javascript
151
+ const CLIENT_ID = 'device-' + Math.random().toString(36).substr(2, 9);
152
+
153
+ setInterval(async () => {
154
+ try {
155
+ const res = await fetch('https://nextech.club/api/stats.php?action=heartbeat', {
156
+ method: 'POST',
157
+ headers: { 'Content-Type': 'application/json' },
158
+ body: JSON.stringify({ software: 'NexClient', client_id: CLIENT_ID })
159
+ });
160
+ const data = await res.json();
161
+ console.log(`心跳成功: ${data.online_total} 在线`);
162
+ } catch (e) {
163
+ console.error('心跳失败:', e);
164
+ }
165
+ }, 60000);
166
+ ```
167
+
168
+ ### C / C++(libcurl)
169
+
170
+ ```c
171
+ #include <curl/curl.h>
172
+
173
+ void heartbeat() {
174
+ CURL *curl = curl_easy_init();
175
+ if (!curl) return;
176
+
177
+ char json[256];
178
+ snprintf(json, sizeof(json),
179
+ "{\"software\":\"NexAgent\",\"client_id\":\"%s\"}", DEVICE_ID);
180
+
181
+ curl_easy_setopt(curl, CURLOPT_URL,
182
+ "https://nextech.club/api/stats.php?action=heartbeat");
183
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
184
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
185
+ curl_easy_perform(curl);
186
+ curl_easy_cleanup(curl);
187
+ }
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 性能参考
193
+
194
+ | 并发数 | 每次心跳 | SQLite 写入 | 服务器负载 |
195
+ |--------|----------|-------------|-----------|
196
+ | 100 | 60 秒 | 1.7 次/秒 | < 0.1% CPU |
197
+ | 1,000 | 60 秒 | 17 次/秒 | < 0.5% CPU |
198
+ | 10,000 | 60 秒 | 167 次/秒 | ~3% CPU |
199
+ | 50,000 | 60 秒 | 833 次/秒 | ~15% CPU |
200
+
201
+ ---
202
+
203
+ ## 技术细节
204
+
205
+ - **数据库**: SQLite3 `/tmp/software_online.db`
206
+ - **表结构**: `heartbeats(id, software, client_id, last_seen, ip)`
207
+ - **过期 TTL**: 120 秒
208
+ - **清理策略**: 每 10 次心跳批量 `DELETE WHERE last_seen < now - 120`
209
+ - **索引**: `idx_last_seen`、`idx_software`
@@ -0,0 +1,142 @@
1
+ # NexForgeCLI 代码优化计划
2
+
3
+ > 审计日期: 2026-07-16 · 当前版本: v0.2.x · 目标: 稳定、可扩展
4
+
5
+ ---
6
+
7
+ ## 审计发现总结
8
+
9
+ | 严重度 | 数量 | 说明 |
10
+ |--------|------|------|
11
+ | 🔴 致命 | 1 | `chat.py` 949行 God Screen,包含20+ slash命令/会话管理/审批/滚动等全部逻辑 |
12
+ | 🟡 重要 | 4 | 死代码(12行)、重复方法体(8行)、未使用import、test gap 60% |
13
+ | 🟢 优化 | 8 | 硬编码常量、静默异常吞噬、模块内聚性差 |
14
+
15
+ ---
16
+
17
+ ## 优化计划 (分3阶段)
18
+
19
+ ### 阶段1: 清理 (P0, 立即执行, ~30 min)
20
+
21
+ **目标**: 消除死代码和安全隐患,不改变任何功能
22
+
23
+ | # | 文件 | 操作 | 收益 |
24
+ |---|------|------|------|
25
+ | 1.1 | `chat.py` L298-311 | 删除 `/perm` 后不可达的12行死代码 | 减少混淆 |
26
+ | 1.2 | `chat.py` L455-462 | 删除 `_set_follow` 重复方法体 | 修复潜在 bug |
27
+ | 1.3 | `chat.py` L6 | 删除未使用的 `from pathlib import Path` | 清理导入 |
28
+ | 1.4 | `chat.py` L19 | `import asyncio` 移到 stdlib 块顶部 | PEP 8 |
29
+ | 1.5 | `stats/heartbeat.py` L53 | `except Exception: pass` → 至少日志记录 | 可观测性 |
30
+ | 1.6 | `chat.py` `_refresh_status` | `query_one("#status")` 加 try/except | 防崩溃 |
31
+
32
+ ---
33
+
34
+ ### 阶段2: 拆分 (P1, 核心重构, ~2 hr)
35
+
36
+ **目标**: 将 God Screen `chat.py` 拆分为5个独立模块
37
+
38
+ #### 2.1 拆分 `SlashCommandHandler`
39
+
40
+ ```
41
+ src/nexforge/ui/slash_handler.py (新建, ~200 lines)
42
+ ```
43
+
44
+ **迁移内容**:
45
+ - `_handle_slash` 全部逻辑(159-370行)
46
+ - `HELP` 字符串(建议改为 `slash_handler.HELP`)
47
+ - 每个命令的处理函数独立为 `_cmd_xxx()` 方法
48
+
49
+ **接口**: `SlashCommandHandler(screen)` — 依赖注入 screen
50
+
51
+ #### 2.2 拆分 `SessionManager`
52
+
53
+ ```
54
+ src/nexforge/ui/session_manager.py (新建, ~130 lines)
55
+ ```
56
+
57
+ **迁移内容**:
58
+ - `_do_new_session`, `_do_delete_session`, `_do_switch_session`
59
+ - `_auto_save`, `_auto_resume`, `_save_as`
60
+ - 与 `store/session_store.py` 直接通信
61
+
62
+ #### 2.3 拆分 `ApprovalManager`
63
+
64
+ ```
65
+ src/nexforge/ui/approval_manager.py (新建, ~70 lines)
66
+ ```
67
+
68
+ **迁移内容**:
69
+ - `_ask_approve`, `_make_diff`, `_unified`
70
+ - 依赖于 `confirm_modal`, `diff_modal`
71
+
72
+ #### 2.4 拆分 `ScrollController` (Mixin)
73
+
74
+ ```
75
+ src/nexforge/ui/scroll_controller.py (新建, ~60 lines)
76
+ ```
77
+
78
+ **迁移内容**:
79
+ - `_scroll`, `_set_follow`, `_scroll_to_bottom`, `_reset_scroll_safety`
80
+
81
+ #### 2.5 精简后的 `ChatScreen`
82
+
83
+ ```
84
+ src/nexforge/ui/screens/chat.py (~250 lines)
85
+ ```
86
+
87
+ **保留内容**:
88
+ - compose, on_mount
89
+ - _run_agent (Agent 事件流)
90
+ - 组合上述4个组件
91
+ - _init_provider, _refresh_status
92
+
93
+ ---
94
+
95
+ ### 阶段3: 加固 (P2, 质量提升, ~1 hr)
96
+
97
+ | # | 操作 | 收益 |
98
+ |---|------|------|
99
+ | 3.1 | 7个硬编码常量提取到 `config.py`(`MAX_WIDGETS`, `MAX_HITS`, 等) | 可配置 |
100
+ | 3.2 | 8处静默 `except: pass` 改 `except Exception: log.warning(...)` | 可调试 |
101
+ | 3.3 | `tools/*.py` 加 `PluginBase` 抽象基类 | 可扩展 |
102
+ | 3.4 | 添加 `src/nexforge/utils/logging.py` 统一日志模块 | 统一 |
103
+ | 3.5 | `HELP` 字符串改为 `resources/help.md` 外部文件 | 可维护 |
104
+ | 3.6 | `DEFAULT_SYSTEM` prompt 改为 `resources/system_prompt.md` | 可调整 |
105
+
106
+ ---
107
+
108
+ ## 涉及文件清单
109
+
110
+ | 文件 | 阶段 | 改动类型 |
111
+ |------|------|---------|
112
+ | `src/nexforge/ui/screens/chat.py` | 1+2 | 删死代码 + 拆出200行 → 最终 ~250行 |
113
+ | `src/nexforge/ui/slash_handler.py` | 2 | **新建** (~200行) |
114
+ | `src/nexforge/ui/session_manager.py` | 2 | **新建** (~130行) |
115
+ | `src/nexforge/ui/approval_manager.py` | 2 | **新建** (~70行) |
116
+ | `src/nexforge/ui/scroll_controller.py` | 2 | **新建** (~60行) |
117
+ | `src/nexforge/stats/heartbeat.py` | 1 | 静默异常 → 日志 |
118
+ | `src/nexforge/config.py` | 3 | 加可配置常量 |
119
+ | `src/nexforge/utils/logging.py` | 3 | **新建** |
120
+ | `resources/help.md` | 3 | **新建** |
121
+ | `resources/system_prompt.md` | 3 | **新建** |
122
+
123
+ ---
124
+
125
+ ## 风险控制
126
+
127
+ - **阶段1 零风险**:纯删除/移动代码,不改变功能
128
+ - **阶段2 低风险**:拆分后立即运行全量测试(47个),任一失败回滚
129
+ - **阶段3 可分批**:常量提取和日志模块单独 commit,便于回退
130
+
131
+ ---
132
+
133
+ ## 预期效果
134
+
135
+ | 指标 | 当前 | 目标 |
136
+ |------|------|------|
137
+ | `chat.py` 行数 | 949 | ~250 |
138
+ | 单文件最大行数 | 949 | ~270 |
139
+ | 死代码行数 | 20+ | 0 |
140
+ | 静默异常 | 12处 | 0处(全部日志) |
141
+ | 可配置常量 | 0 | 7个 |
142
+ | 模块间依赖 | 全耦合在 Screen | 依赖注入 |
@@ -0,0 +1,37 @@
1
+ # 特性模块注册制 实施计划
2
+
3
+ ## 目标
4
+
5
+ 将 ChatScreen 所有特性解耦为可插拔模块,后续新增功能无需改 ChatScreen。
6
+
7
+ ## 架构
8
+
9
+ ```
10
+ ChatScreen (控制器, <200 行)
11
+ └── FeatureRegistry
12
+ ├── SlashFeature → /commands
13
+ ├── GoalModeFeature → 目标模式
14
+ ├── OpsModeFeature → 运维模式
15
+ ├── StatsFeature → 心跳
16
+ └── SessionFeature → 会话管理
17
+ ```
18
+
19
+ ## 需要做的事情
20
+
21
+ 1. **创建 Feature 基类** (`src/nexforge/features/base.py`)
22
+ 2. **创建 FeatureRegistry** (`src/nexforge/features/registry.py`)
23
+ 3. **提取现有特性为 Feature**
24
+ - SlashFeature (已有 SlashCommandHandler)
25
+ - GoalModeFeature (目标循环)
26
+ - OpsModeFeature (运维模式)
27
+ - StatsFeature (心跳)
28
+ - SessionFeature (会话管理)
29
+ 4. **精简 ChatScreen** (只保留 compose/on_mount/_run_agent/_refresh_status)
30
+ 5. **ChatScreen.on_mount 注册所有 Feature**
31
+
32
+ 每个 Feature 只暴露 3 个钩子:
33
+ - `register(screen)` → 注入引用
34
+ - `on_mount()` → 启动时初始化
35
+ - `bindings()` → 返回需要的快捷键
36
+
37
+ 新增功能: 只需写一个 Feature 类 + 注册,不改 ChatScreen。
@@ -0,0 +1,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
+ - [ ] 余额耗尽自动停止
@@ -0,0 +1,83 @@
1
+ # 安装与配置
2
+
3
+ > NexForgeCLI v0.2.9
4
+
5
+ ## 环境要求
6
+
7
+ - Python **3.11+**
8
+ - 终端:Windows Terminal / macOS Terminal / Linux 任意终端
9
+ - 网络:能访问 API 端点
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ # 方式一:Pip 安装(推荐)
15
+ pip install nexforge-cli
16
+
17
+ # 方式二:源码安装(开发)
18
+ git clone https://gitee.com/Lighthorn/nexforgecli.git
19
+ cd nexforgecli
20
+ pip install -e .
21
+ ```
22
+
23
+ ## 运行
24
+
25
+ ```bash
26
+ nf
27
+ # 或全称
28
+ nexforge
29
+ ```
30
+
31
+ ## 配置 API Key
32
+
33
+ 首次启动会弹出 API Key 输入面板,直接粘贴 Key 即可。
34
+
35
+ 也可以手动配置:
36
+
37
+ **通过命令行**
38
+ ```
39
+ /key sk-你的密钥 # 在 nf 输入框里输入
40
+ ```
41
+
42
+ **通过环境变量**
43
+ ```bash
44
+ export DEEPSEEK_API_KEY="sk-你的密钥" # Linux/macOS
45
+ set DEEPSEEK_API_KEY=sk-你的密钥 # Windows CMD
46
+ $env:DEEPSEEK_API_KEY="sk-你的密钥" # PowerShell
47
+ ```
48
+
49
+ **获取 Key**
50
+
51
+ DeepSeek:https://platform.deepseek.com/api_keys
52
+
53
+ 其他模型(Kimi/GPT/Claude):参见 [03-模型配置](03-模型配置.md)
54
+
55
+ API Key 保存在 `~/.nexforge/auth.toml`,不会被 Git 追踪。
56
+
57
+ ## 首次运行自动生成
58
+
59
+ 首次运行 nf 会自动生成以下配置文件:
60
+
61
+ | 文件 | 位置 | 内容 |
62
+ |------|------|------|
63
+ | models.toml | `~/.nexforge/` | 多模型配置模板(只读) |
64
+ | config.toml | `~/.nexforge/` | 用户级 UI 配置 |
65
+ | tools.json | `~/.nexforge/` | 外部工具清单模板 |
66
+
67
+ 均不会覆盖已有文件。
68
+
69
+ ## 升级
70
+
71
+ ```bash
72
+ pip install --upgrade nexforge-cli
73
+ ```
74
+
75
+ ## 卸载
76
+
77
+ ```bash
78
+ pip uninstall nexforge-cli -y
79
+ ```
80
+
81
+ 配置文件和数据保留在以下目录,需手动删除:
82
+ - `~/.nexforge/`(用户级配置和会话)
83
+ - 项目目录下的 `.nexforge/`(项目级配置和会话)