tagword-codeagent 1.1.6__py3-none-any.whl

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 (173) hide show
  1. codeagent/__init__.py +10 -0
  2. codeagent/__main__.py +13 -0
  3. codeagent/cli/__init__.py +13 -0
  4. codeagent/cli/entrypoint.py +161 -0
  5. codeagent/cli/main.py +979 -0
  6. codeagent/core/__init__.py +2 -0
  7. codeagent/core/attachments.py +342 -0
  8. codeagent/core/audio_models.py +50 -0
  9. codeagent/core/bootstrap.py +178 -0
  10. codeagent/core/default_presets.py +159 -0
  11. codeagent/core/env.py +106 -0
  12. codeagent/core/folder_picker.py +151 -0
  13. codeagent/core/image_understanding.py +90 -0
  14. codeagent/core/models.py +6 -0
  15. codeagent/core/paths.py +238 -0
  16. codeagent/core/pricing.py +107 -0
  17. codeagent/core/process_ports.py +258 -0
  18. codeagent/core/seed_bridge.py +21 -0
  19. codeagent/core/settings.py +98 -0
  20. codeagent/core/speech_synth.py +330 -0
  21. codeagent/core/team_config.py +247 -0
  22. codeagent/core/team_manager.py +245 -0
  23. codeagent/core/token_counter.py +41 -0
  24. codeagent/core/tts_voices.py +103 -0
  25. codeagent/core/usage_billing.py +72 -0
  26. codeagent/core/vision_models.py +93 -0
  27. codeagent/memory/diary.py +144 -0
  28. codeagent/persona_defaults/README.md +12 -0
  29. codeagent/persona_defaults/agent.md +352 -0
  30. codeagent/persona_defaults/identity.md +29 -0
  31. codeagent/persona_defaults/memory.md +4 -0
  32. codeagent/persona_defaults/skills.md +325 -0
  33. codeagent/persona_defaults/soul.md +38 -0
  34. codeagent/persona_defaults/tools.md +41 -0
  35. codeagent/persona_defaults/user.md +18 -0
  36. codeagent/runtime/__init__.py +11 -0
  37. codeagent/runtime/agent_context.py +6 -0
  38. codeagent/runtime/agent_runtime.py +21 -0
  39. codeagent/runtime/compact_prompt.py +9 -0
  40. codeagent/runtime/compact_state.py +40 -0
  41. codeagent/runtime/llm_worker.py +132 -0
  42. codeagent/runtime/orchestrator.py +161 -0
  43. codeagent/runtime/prompt_enrichment.py +324 -0
  44. codeagent/runtime/session_manager.py +30 -0
  45. codeagent/runtime/task_split.py +38 -0
  46. codeagent/runtime/turn_loop.py +13 -0
  47. codeagent/runtime/worker.py +48 -0
  48. codeagent/server/__init__.py +505 -0
  49. codeagent/server/app_factory.py +1292 -0
  50. codeagent/server/attachment_api.py +261 -0
  51. codeagent/server/hub.py +175 -0
  52. codeagent/server/icon.png +0 -0
  53. codeagent/server/self_healing.py +143 -0
  54. codeagent/server/team_engine.py +243 -0
  55. codeagent/server/tts_api.py +51 -0
  56. codeagent/server/webui_api_app.py +3180 -0
  57. codeagent/skills/__init__.py +2 -0
  58. codeagent/skills/select.py +144 -0
  59. codeagent/tools/__init__.py +6 -0
  60. codeagent/tools/agent_tools.py +10 -0
  61. codeagent/web/__init__.py +1 -0
  62. codeagent/web/__pycache__/__init__.cpython-313.pyc +0 -0
  63. codeagent/web/__pycache__/app.cpython-313.pyc +0 -0
  64. codeagent/web/__pycache__/auth_impl.cpython-313.pyc +0 -0
  65. codeagent/web/auth_impl.py +326 -0
  66. codeagent/web/static/00-marked.min.js +6 -0
  67. codeagent/web/static/00-mermaid.min.js +2314 -0
  68. codeagent/web/static/00-purify.min.js +3 -0
  69. codeagent/web/static/00-storage.js +83 -0
  70. codeagent/web/static/00-utils.js +51 -0
  71. codeagent/web/static/01-theme.css +96 -0
  72. codeagent/web/static/01a-scroll.js +86 -0
  73. codeagent/web/static/01b-think.js +62 -0
  74. codeagent/web/static/01c-session-identity.js +81 -0
  75. codeagent/web/static/01c-session-thinking.js +61 -0
  76. codeagent/web/static/01c-session-tree-menus.js +349 -0
  77. codeagent/web/static/01c-session-tree.js +531 -0
  78. codeagent/web/static/01c-session-utilities.js +83 -0
  79. codeagent/web/static/01c-vision-model.js +132 -0
  80. codeagent/web/static/01d-image-gen-model.js +84 -0
  81. codeagent/web/static/01e-audio-model.js +97 -0
  82. codeagent/web/static/01f-compose-ui.js +88 -0
  83. codeagent/web/static/01g-tts-settings.js +128 -0
  84. codeagent/web/static/01h-music-model.js +85 -0
  85. codeagent/web/static/01i-model-stack.js +291 -0
  86. codeagent/web/static/01j-video-gen-model.js +85 -0
  87. codeagent/web/static/01k-model-stack-bootstrap.js +66 -0
  88. codeagent/web/static/01k-model-stack-state.js +209 -0
  89. codeagent/web/static/01q-inflight.js +195 -0
  90. codeagent/web/static/02-reset.css +22 -0
  91. codeagent/web/static/02-session-ui.js +201 -0
  92. codeagent/web/static/03-layout-p1.css +2 -0
  93. codeagent/web/static/03-layout-p2.css +2 -0
  94. codeagent/web/static/03a-links-stream.js +88 -0
  95. codeagent/web/static/03b-stream-text.js +119 -0
  96. codeagent/web/static/03c-render-bubble.js +520 -0
  97. codeagent/web/static/03d-agent-bubble.js +126 -0
  98. codeagent/web/static/03e-tool-trace.js +182 -0
  99. codeagent/web/static/03f-timeline.js +54 -0
  100. codeagent/web/static/03g-bubble-tts.js +292 -0
  101. codeagent/web/static/04-components-p1.css +1 -0
  102. codeagent/web/static/04-components-p2b.css +1 -0
  103. codeagent/web/static/04-components-p3.css +2 -0
  104. codeagent/web/static/04-components-p4.css +1 -0
  105. codeagent/web/static/04-components-p5.css +1 -0
  106. codeagent/web/static/04-components-p6.css +58 -0
  107. codeagent/web/static/04-components-p7.css +4 -0
  108. codeagent/web/static/04-components-p8.css +1 -0
  109. codeagent/web/static/04-components-p9.css +1 -0
  110. codeagent/web/static/04-ws-connect.js +351 -0
  111. codeagent/web/static/04-ws-helpers.js +116 -0
  112. codeagent/web/static/05-chat-p1.css +1058 -0
  113. codeagent/web/static/05-chat-p2.css +1 -0
  114. codeagent/web/static/05-chat-p3.css +295 -0
  115. codeagent/web/static/05a-session-history.js +176 -0
  116. codeagent/web/static/05b-session-list.js +114 -0
  117. codeagent/web/static/05c-dialog.js +123 -0
  118. codeagent/web/static/05d-project-create.js +172 -0
  119. codeagent/web/static/05e-project-remote.js +143 -0
  120. codeagent/web/static/06-chat.js +552 -0
  121. codeagent/web/static/06-utilities.css +181 -0
  122. codeagent/web/static/06b-attachments.js +304 -0
  123. codeagent/web/static/06c-camera.js +488 -0
  124. codeagent/web/static/07-activity-bar.css +127 -0
  125. codeagent/web/static/09-git-p1.css +1 -0
  126. codeagent/web/static/09-git-p2.css +1 -0
  127. codeagent/web/static/09a-init-bind.js +110 -0
  128. codeagent/web/static/09b-panel-toggle.js +80 -0
  129. codeagent/web/static/09c-api-refresh.js +100 -0
  130. codeagent/web/static/09d-status-log.js +80 -0
  131. codeagent/web/static/09e-commit.js +80 -0
  132. codeagent/web/static/09f-remote.js +93 -0
  133. codeagent/web/static/11a-cron-parse.js +117 -0
  134. codeagent/web/static/11b-cron-panel.js +100 -0
  135. codeagent/web/static/11c-cron-card.js +133 -0
  136. codeagent/web/static/11d-cron-form.js +105 -0
  137. codeagent/web/static/11e-env-config.js +168 -0
  138. codeagent/web/static/11f-env-llm-a-state.js +136 -0
  139. codeagent/web/static/11f-env-llm-b-form.js +409 -0
  140. codeagent/web/static/11f-env-llm-c-board.js +322 -0
  141. codeagent/web/static/11g-env-paths-git.js +973 -0
  142. codeagent/web/static/11h-env-mcp-a-state.js +161 -0
  143. codeagent/web/static/11h-env-mcp-b-form.js +229 -0
  144. codeagent/web/static/11h-env-mcp-c-board.js +565 -0
  145. codeagent/web/static/12-plugins.js +127 -0
  146. codeagent/web/static/13a-skills.js +156 -0
  147. codeagent/web/static/13a-todo-utils.js +140 -0
  148. codeagent/web/static/13b-todo-fetch.js +106 -0
  149. codeagent/web/static/13b-tools.js +127 -0
  150. codeagent/web/static/13c-todo-crud.js +92 -0
  151. codeagent/web/static/14-activity-bar.js +177 -0
  152. codeagent/web/static/15-plans.css +194 -0
  153. codeagent/web/static/15-plans.js +219 -0
  154. codeagent/web/static/16-mobile.css +612 -0
  155. codeagent/web/static/16-mobile.js +178 -0
  156. codeagent/web/static/17-preset-ux.css +287 -0
  157. codeagent/web/static/18-agent-mgr.css +616 -0
  158. codeagent/web/static/18-agent-mgr.js +204 -0
  159. codeagent/web/static/24-health-dashboard.js +68 -0
  160. codeagent/web/static/99-brand-polish.css +152 -0
  161. codeagent/web/static/body.html +824 -0
  162. codeagent/web/static/setup/setup_form.html +171 -0
  163. codeagent/web/static/setup/setup_head.html +100 -0
  164. codeagent/web/static/setup/setup_tail.html +264 -0
  165. codeagent/web/static/setup/setup_test.html +38 -0
  166. codeagent/web/web_login.html +265 -0
  167. codeagent/web/webui.html +35 -0
  168. tagword_codeagent-1.1.6.dist-info/METADATA +273 -0
  169. tagword_codeagent-1.1.6.dist-info/RECORD +173 -0
  170. tagword_codeagent-1.1.6.dist-info/WHEEL +5 -0
  171. tagword_codeagent-1.1.6.dist-info/entry_points.txt +3 -0
  172. tagword_codeagent-1.1.6.dist-info/licenses/LICENSE +21 -0
  173. tagword_codeagent-1.1.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,824 @@
1
+ <div class="app">
2
+ <nav class="activity-bar" id="activityBar" aria-label="活动栏">
3
+ <div class="activity-bar__top">
4
+ <button type="button" class="activity-btn active" data-mode="chat" title="聊天">
5
+ <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 018.5-8.5 8.38 8.38 0 013.8.9z" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/></svg>
6
+ </button>
7
+ <button type="button" class="activity-btn" data-mode="tasks" title="计划">
8
+ <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="1.75"/><path d="M12 7v6l4 2" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg>
9
+ </button>
10
+ <button type="button" class="activity-btn" data-mode="agent" title="Agent">
11
+ <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><path d="M12 5v2M10 3h4" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/><rect x="6" y="8" width="12" height="12" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.75"/><circle cx="9.5" cy="13.5" r="1.2" fill="currentColor"/><circle cx="14.5" cy="13.5" r="1.2" fill="currentColor"/><path d="M9 18h6" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/><path d="M10 20v2h4v-2" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg>
12
+ </button>
13
+ <button type="button" class="activity-btn" data-mode="config" title="配置">
14
+ <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="1.75"/><path d="M12 2v2m0 18v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m18 0h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg>
15
+ </button>
16
+ </div>
17
+ <div class="activity-bar__bottom">
18
+ <button type="button" class="activity-btn" id="btnLogout" title="退出登录">
19
+ <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/></svg>
20
+ </button>
21
+ </div>
22
+ </nav>
23
+ <aside class="sidebar" aria-label="主导航">
24
+ <div class="sidebar__head">
25
+ <div class="brand">
26
+ <img class="brand__logo" src="/icon.png" alt="" width="34" height="34" decoding="async"/>
27
+ <div class="brand__text">
28
+ <div class="brand__name">CodeAgent</div>
29
+ <div class="brand__slogan">对话 · 工作台</div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <aside id="chatSidebar" class="sess-panel" style="display:none;" aria-label="会话列表">
35
+ <!-- 搜索栏 -->
36
+ <div class="search-bar">
37
+ <span class="search-bar__icon">
38
+ <svg viewBox="0 0 20 20" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true">
39
+ <circle cx="9" cy="9" r="4.5"/>
40
+ <path d="M13 13l3 3"/>
41
+ </svg>
42
+ </span>
43
+ <input type="text" id="treeSearchInput" class="search-bar__input" placeholder="搜索项目或会话... Ctrl+K">
44
+ <button type="button" class="search-bar__clear" id="treeSearchClear" style="display:none;" aria-label="清除搜索">×</button>
45
+ </div>
46
+ <!-- 项目树 -->
47
+ <div id="projectTree" class="project-tree" role="tree">
48
+ <div class="project-tree__empty">加载中...</div>
49
+ </div>
50
+ <!-- 费用汇总 -->
51
+ <div id="sidebarCost" class="sidebar-cost" style="display:none;">
52
+ <div class="sidebar-cost__title">运行费用</div>
53
+ <div class="sidebar-cost__body"></div>
54
+ </div>
55
+ <div class="project-tree__footer">
56
+ <button class="tree-footer-btn" id="btnNewProject">+ 新建项目</button>
57
+ <button class="tree-footer-btn" id="btnNewSession">+ 新建会话</button>
58
+ </div>
59
+
60
+
61
+ </aside>
62
+
63
+ <section id="sidebarFiles" class="sidebar-mode" style="display:none;">
64
+ <div class="sidebar-mode__scroll">
65
+ <div class="sidebar__head" style="padding-bottom:0;">
66
+ <div class="sidebar__section-label">文件浏览器</div>
67
+ </div>
68
+ <div id="fileTreeContainer" class="file-tree">
69
+ <div class="file-tree__loading">加载中...</div>
70
+ </div>
71
+ </div>
72
+ </section>
73
+ <section id="sidebarGit" class="sidebar-mode" style="display:none;">
74
+ <div class="sidebar-mode__scroll">
75
+ <div class="sidebar__head" style="padding-bottom:0;">
76
+ <div class="sidebar__section-label">源代码管理</div>
77
+ </div>
78
+ <div class="git-panel">
79
+ <div class="git-panel__branch" id="gitBranch">🌿 main</div>
80
+ <div class="git-panel__actions">
81
+ <button class="btn btn--sm btn--subtle" id="gitBtnRefresh" title="刷新">🔄</button>
82
+ <button class="btn btn--sm btn--subtle" id="gitBtnPull" title="拉取">⬇</button>
83
+ <button class="btn btn--sm btn--subtle" id="gitBtnPush" title="推送">⬆</button>
84
+ </div>
85
+ <div class="git-panel__status" id="gitStatus">
86
+ <div class="git-panel__loading">加载中...</div>
87
+ </div>
88
+ <div class="git-panel__commit">
89
+ <textarea id="gitCommitMsg" class="git-panel__commit-input" rows="3" placeholder="提交信息..."></textarea>
90
+ <button class="btn btn--primary btn--sm" id="gitBtnCommit" style="width:100%;">提交</button>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </section>
95
+
96
+ </aside>
97
+
98
+ <div class="sidebar-backdrop" id="sidebarBackdrop" aria-hidden="true"></div>
99
+
100
+ <main class="workspace">
101
+ <header class="topbar">
102
+ <button type="button" class="topbar__sidebar-btn" id="btnToggleSidebar" title="会话列表" aria-label="打开会话列表">
103
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
104
+ <path d="M4 6h16M4 12h16M4 18h16"/>
105
+ </svg>
106
+ </button>
107
+ <div class="topbar__title-group">
108
+ <h2 class="topbar__title" id="currentConvTitle">新对话</h2>
109
+ <span class="channel-pill" id="currentConvChannel">Web 聊天</span>
110
+ <span class="topbar__project-path" id="currentProjectPath" style="display:none"></span>
111
+ </div>
112
+ <div class="topbar__meta">
113
+ <button type="button" class="topbar__todo-btn" id="btnToggleFiles" title="文件浏览器">
114
+ <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
115
+ <path d="M14 3v4a1 1 0 0 1-1 1h-4"/>
116
+ <path d="M13 15H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h6l4 4v8a2 2 0 0 1-2 2z"/>
117
+ </svg>
118
+ </button>
119
+ <button type="button" class="topbar__todo-btn" id="btnTogglePlans" title="项目规划面板">
120
+ <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
121
+ <path d="M3 2.5h10v11H3z"/>
122
+ <path d="M6 5.5h4M6 8h4M6 10.5h2"/>
123
+ </svg>
124
+ </button>
125
+ <button type="button" class="topbar__todo-btn" id="btnToggleTodos" title="待办事项面板">
126
+ <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
127
+ <path d="M3 4.5h10M3 8h10M3 11.5h10"/>
128
+ <circle cx="5.5" cy="4.5" r="1.2"/>
129
+ <circle cx="5.5" cy="8" r="1.2"/>
130
+ <circle cx="5.5" cy="11.5" r="1.2"/>
131
+ </svg>
132
+ </button>
133
+ <button type="button" class="topbar__todo-btn" id="btnToggleGit" title="Git 版本控制">
134
+ <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
135
+ <path d="M15 8l-6.5 6.5a1.5 1.5 0 0 1-2 0L2 9.5a1.5 1.5 0 0 1 0-2L8.5 1"/>
136
+ <circle cx="8" cy="8" r="1.5"/>
137
+ </svg>
138
+ </button>
139
+ </div>
140
+ <div class="oa-global-progress" id="chatGlobalProgress" aria-hidden="true"></div>
141
+ </header>
142
+
143
+ <section id="page-chat" class="page active">
144
+ <div class="chat-workspace">
145
+ <div id="log" class="chat-log" role="log" aria-live="polite"></div>
146
+ <button id="btnNewMessages" class="new-msg-btn" style="display:none" title="有新消息,点击回到最新">
147
+ <span class="new-msg-btn__dot"></span>
148
+ <span class="new-msg-btn__text">新消息 ↓</span>
149
+ </button>
150
+ <div class="compose">
151
+ <div class="compose__head" id="composeHead" hidden>
152
+ <div id="composeAttachments" class="compose__attachments" style="display:none"></div>
153
+ </div>
154
+ <div class="compose__box" id="composeBox">
155
+ <div class="compose__editor">
156
+ <textarea id="msg" rows="1" placeholder="输入消息,Enter 发送 · Shift+Enter 换行" autocomplete="off" spellcheck="true"></textarea>
157
+ </div>
158
+ <div class="compose__dock">
159
+ <div class="compose__dock-tools">
160
+ <button type="button" class="compose__tool-btn" id="attachBtnInline" title="附加文件">
161
+ <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>
162
+ </button>
163
+ </div>
164
+ <div class="compose__dock-chips">
165
+ <button type="button" class="compose__chip compose__chip--think think-toggle" id="thinkToggle" aria-pressed="true" title="思考:开启时先推理再回答">
166
+ <span class="compose__chip-leading" aria-hidden="true">
167
+ <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1.8a4.5 4.5 0 0 0-3 7.9V11h6V9.7a4.5 4.5 0 0 0-3-7.9z"/><path d="M6.5 13.5h3M7 15h2"/></svg>
168
+ </span>
169
+ <span class="compose__chip-label think-toggle__label">思考</span>
170
+ <span class="compose__switch" aria-hidden="true">
171
+ <span class="compose__switch-track"><span class="compose__switch-thumb"></span></span>
172
+ </span>
173
+ </button>
174
+ <button type="button" class="compose__chip compose__chip--model compose__model-pill" id="composeModelTrigger" aria-expanded="false" aria-controls="composeSettingsSheet" title="模型栈设置">
175
+ <span class="compose__chip-leading" aria-hidden="true">
176
+ <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="2.2"/><path d="M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2M3.4 3.4l1.4 1.4M11.2 11.2l1.4 1.4M3.4 12.6l1.4-1.4M11.2 4.8l1.4-1.4"/></svg>
177
+ </span>
178
+ <span class="compose__chip-label compose__model-pill-label" id="composeModelPillLabel">默认模型</span>
179
+ <span class="compose__chip-extra" id="composeModelPillExtra" hidden aria-hidden="true"></span>
180
+ <span class="compose__chip-badge compose__model-pill-pin" id="composeModelPillPin" hidden aria-hidden="true" title="本会话已自定义模型"></span>
181
+ <svg class="compose__chip-chevron compose__model-pill-chevron" viewBox="0 0 16 16" width="10" height="10" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
182
+ </button>
183
+ </div>
184
+ <div class="compose__dock-actions">
185
+ <span id="tokenUsage" class="token-usage token-usage--seg token-usage--compact" role="meter" aria-label="上下文占用" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" title="上下文占用" style="display:none">
186
+ <svg class="token-usage__icon" viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
187
+ <path d="M8 2L2 5.5v5L8 14l6-3.5v-5L8 2z"/>
188
+ <path d="M8 8L2 5.5M8 8l6-3.5M8 8v6"/>
189
+ </svg>
190
+ <span class="token-usage__segs" aria-hidden="true">
191
+ <span class="token-usage__seg"></span>
192
+ <span class="token-usage__seg"></span>
193
+ <span class="token-usage__seg"></span>
194
+ <span class="token-usage__seg"></span>
195
+ <span class="token-usage__seg"></span>
196
+ </span>
197
+ <span class="token-usage__pct">0%</span>
198
+ </span>
199
+ <button type="button" class="btn btn--primary btn--icon btn--send" id="send" title="发送 (Enter)">
200
+ <svg class="compose__send-icon" viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg>
201
+ <svg class="compose__stop-icon" viewBox="0 0 16 16" width="14" height="14" fill="currentColor" aria-hidden="true" style="display:none"><rect x="2" y="2" width="12" height="12" rx="2"/></svg>
202
+ <span class="btn__send-label">发送</span>
203
+ </button>
204
+ </div>
205
+ </div>
206
+ <div class="compose__sheet" id="composeSettingsSheet" hidden>
207
+ <div class="compose__sheet-head">
208
+ <span class="compose__sheet-title">模型栈</span>
209
+ <button type="button" class="compose__sheet-close" id="composeSettingsClose" aria-label="关闭">&times;</button>
210
+ </div>
211
+ <div class="compose__sheet-grid compose-stack-grid">
212
+ <div class="compose-stack-primary compose__field compose__field--wide">
213
+ <span class="compose__field-label">主模型 · 对话</span>
214
+ <select id="modelSelect" class="compose__field-select" title="选择 LLM 模型预设"><option value="__default__">默认模型</option></select>
215
+ </div>
216
+ <details class="compose-stack-panel compose__field--wide" id="composeStackTools">
217
+ <summary class="compose-stack-panel__summary">工具模型</summary>
218
+ <div class="compose-stack-panel__body">
219
+ <label class="compose-stack-row">
220
+ <span class="compose-stack-row__label">识图</span>
221
+ <select id="visionModelSelect" class="compose__field-select" title="识图:多模态 LLM 或 MiniMax MCP" disabled><option value="">未配置识图</option></select>
222
+ </label>
223
+ <label class="compose-stack-row">
224
+ <span class="compose-stack-row__label">生图</span>
225
+ <select id="imageGenModelSelect" class="compose__field-select" title="图片生成模型(image_generate 工具)" disabled><option value="">未配置生图模型</option></select>
226
+ </label>
227
+ <label class="compose-stack-row">
228
+ <span class="compose-stack-row__label">音频</span>
229
+ <select id="audioModelSelect" class="compose__field-select" title="音频转写(audio_transcribe / video_analyze)" disabled><option value="">未配置音频模型</option></select>
230
+ </label>
231
+ <label class="compose-stack-row">
232
+ <span class="compose-stack-row__label">音乐</span>
233
+ <select id="musicModelSelect" class="compose__field-select" title="音乐生成(music_generate 工具)" disabled><option value="">未配置音乐模型</option></select>
234
+ </label>
235
+ <label class="compose-stack-row">
236
+ <span class="compose-stack-row__label">视频生成</span>
237
+ <select id="videoGenModelSelect" class="compose__field-select" title="视频生成(video_generate 工具)" disabled><option value="">未配置视频生成模型</option></select>
238
+ </label>
239
+ <p class="compose-stack-missing" id="composeStackMissingHint" hidden>
240
+ 部分能力未配置。<a href="#fieldsetLlmPresets" class="compose-stack-missing__link">去配置页添加</a>
241
+ </p>
242
+ <div class="compose-stack-actions" id="composeStackActions">
243
+ <button type="button" class="btn btn--ghost btn--sm" id="composeClearOverridesBtn" hidden title="把当前会话的所有模型选择恢复到全局默认">
244
+ <svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>
245
+ 清除本会话覆盖(恢复全局默认)
246
+ </button>
247
+ <span class="compose-stack-actions__hint" id="composeStackActionsHint"></span>
248
+ </div>
249
+ </div>
250
+ </details>
251
+ <details class="compose-stack-panel compose__field--wide" id="composeStackTts">
252
+ <summary class="compose-stack-panel__summary">朗读</summary>
253
+ <div class="compose-stack-panel__body compose-stack-panel__body--grid">
254
+ <label class="compose__field">
255
+ <span class="compose__field-label">朗读音色</span>
256
+ <select id="ttsVoiceSelect" class="compose__field-select" title="MiniMax 朗读音色(系统音色)" disabled><option value="">加载中…</option></select>
257
+ </label>
258
+ <label class="compose__field">
259
+ <span class="compose__field-label">朗读模型</span>
260
+ <select id="ttsModelSelect" class="compose__field-select" title="MiniMax 语音合成模型" disabled><option value="">加载中…</option></select>
261
+ </label>
262
+ <p class="compose__field-hint compose__field--wide" id="ttsVoiceHint">
263
+ Token Plan Key 可聊天;MiniMax 朗读需在配置页填写「开放平台按量 API Key」。
264
+ </p>
265
+ </div>
266
+ </details>
267
+ <label class="compose__field compose__field--wide">
268
+ <span class="compose__field-label">推理强度</span>
269
+ <select id="reasoningEffortSelect" class="compose__field-select compose__reasoning-effort" title="推理强度(DeepSeek 思考模式)" disabled>
270
+ <option value="high">高</option>
271
+ <option value="max">最高</option>
272
+ </select>
273
+ </label>
274
+ </div>
275
+ </div>
276
+ <input type="file" id="attachFileInput" accept="image/*,video/*,audio/*,.pdf,.txt,.md" multiple hidden />
277
+ <input type="file" id="attachFolderInput" webkitdirectory multiple hidden />
278
+ <input type="file" id="nativeCameraInput" accept="image/*" capture="environment" hidden />
279
+ <input type="file" id="nativeVideoInput" accept="video/*" capture="environment" hidden />
280
+ </div><!-- .compose__box -->
281
+ <div class="compose__attach-popup" id="attachPopup" style="display:none" role="menu">
282
+ <button type="button" class="compose__attach-option" data-action="file" role="menuitem">
283
+ <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 4.5A1.5 1.5 0 0 1 3.5 3H6l1.5 1.5H12.5A1.5 1.5 0 0 1 14 6v6.5A1.5 1.5 0 0 1 12.5 14h-9A1.5 1.5 0 0 1 2 12.5V4.5z"/></svg>
284
+ 选择文件
285
+ </button>
286
+ <button type="button" class="compose__attach-option" data-action="camera" role="menuitem">
287
+ <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 5.5h2.2L5.5 4h5l1.3 1.5H14v7H2v-7z"/><circle cx="8" cy="9" r="2.2"/></svg>
288
+ 拍照
289
+ </button>
290
+ <button type="button" class="compose__attach-option" data-action="video" role="menuitem">
291
+ <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 4h8a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z"/><path d="M11 7l3-2v6l-3-2"/></svg>
292
+ 录制视频
293
+ </button>
294
+ </div>
295
+ <div id="cameraModal" class="modal-overlay camera-modal" style="display:none" role="dialog" aria-label="摄像头">
296
+ <div class="modal-dialog camera-modal__dialog">
297
+ <div class="modal-dialog__header">
298
+ <span class="modal-dialog__title" id="cameraModalTitle">摄像头</span>
299
+ <button type="button" class="modal-dialog__close" id="cameraModalClose" aria-label="关闭">&times;</button>
300
+ </div>
301
+ <div class="modal-dialog__body camera-modal__body">
302
+ <div class="camera-modal__mode" id="cameraModeBar" role="tablist" aria-label="模式">
303
+ <button type="button" class="camera-modal__mode-btn is-active" data-mode="photo" role="tab" aria-selected="true">拍照</button>
304
+ <button type="button" class="camera-modal__mode-btn" data-mode="video" role="tab" aria-selected="false">录像</button>
305
+ </div>
306
+ <div class="camera-modal__stage" id="cameraStage">
307
+ <video id="cameraPreview" class="camera-modal__video" autoplay playsinline muted></video>
308
+ <div class="camera-modal__rec-indicator" id="cameraRecIndicator" hidden>
309
+ <span class="camera-modal__rec-dot"></span>
310
+ <span id="cameraRecTimer">00:00</span>
311
+ </div>
312
+ <canvas id="cameraCanvas" style="display:none" aria-hidden="true"></canvas>
313
+ <p id="cameraStatus" class="camera-modal__status"></p>
314
+ <button type="button" class="btn btn--ghost btn--sm camera-modal__fallback" id="cameraFallbackBtn" hidden>从文件选择</button>
315
+ </div>
316
+ </div>
317
+ <div class="modal-dialog__footer camera-modal__footer" id="cameraFooterPhoto">
318
+ <button type="button" class="btn btn--ghost btn--sm" id="cameraToggleInterval">定时截帧</button>
319
+ <button type="button" class="btn btn--primary btn--sm" id="cameraCaptureBtn">拍照</button>
320
+ <button type="button" class="btn btn--subtle btn--sm" id="cameraModalDone">完成</button>
321
+ </div>
322
+ <div class="modal-dialog__footer camera-modal__footer" id="cameraFooterVideo" hidden>
323
+ <button type="button" class="btn btn--primary btn--sm" id="cameraRecordBtn">开始录制</button>
324
+ <button type="button" class="btn btn--subtle btn--sm" id="cameraModalDoneVideo">完成</button>
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </div>
329
+ </div>
330
+ </div>
331
+ <aside id="todoPanel" class="todo-panel" style="display:none;" aria-label="待办事项">
332
+ <div class="todo-panel__header">
333
+ <span>待办事项</span>
334
+ <div class="todo-scope-toggle" id="todoScopeToggle">
335
+ <button type="button" class="todo-scope-btn is-active" data-scope="session">当前会话</button>
336
+ <button type="button" class="todo-scope-btn" data-scope="project">全部</button>
337
+ </div>
338
+ </div>
339
+ <div class="todo-panel__list" id="todoList"></div>
340
+ <div class="todo-panel__footer">
341
+ <button type="button" class="btn btn--ghost btn--sm" id="btnTodoRefresh">刷新</button>
342
+ </div>
343
+ </aside>
344
+ <aside id="planPanel" class="plan-panel" style="display:none;" aria-label="项目规划">
345
+ <div class="plan-panel__header">
346
+ <span>📋 项目规划</span>
347
+ <span id="planStatus" style="font-weight:400;font-size:12px;color:var(--text-muted);"></span>
348
+ </div>
349
+ <div class="plan-panel__list" id="planList"></div>
350
+ <div class="plan-panel__footer">
351
+ <button type="button" class="btn btn--ghost btn--sm" id="btnPlanRefresh">刷新</button>
352
+ </div>
353
+ </aside>
354
+ <aside id="gitPanel" class="git-slide-panel" style="display:none;" aria-label="Git 版本控制">
355
+ <div class="git-slide-panel__header">
356
+ <span>⎇ Git 版本控制</span>
357
+ <div style="display:flex;gap:4px;align-items:center;">
358
+ <span id="gitPanelBranch" style="font-size:11px;color:var(--text-muted);font-weight:400;"></span>
359
+ <button type="button" class="btn btn--ghost btn--sm" id="gitPanelRefresh" title="刷新">⟳</button>
360
+ </div>
361
+ </div>
362
+ <div class="git-slide-panel__remote" id="gitPanelRemote">
363
+ <!-- 远程信息展示(只读,编辑请到配置页) -->
364
+ <div class="git-slide-panel__remote-info" id="gitRemoteInfoBar" style="display:none;">
365
+ <span id="gitRemoteDisplay" style="font-size:11px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;"></span>
366
+ <button type="button" class="btn btn--ghost btn--xs" id="gitRemoteTestBtn" title="测试连接">🔌</button>
367
+ <a href="#" id="gitRemoteConfigLink" style="font-size:10px;color:var(--accent);text-decoration:none;white-space:nowrap;" title="到配置页管理远程仓库">配置 ›</a>
368
+ </div>
369
+ <!-- 未配置时的提示栏 -->
370
+ <div class="git-slide-panel__remote-info" id="gitRemoteEmptyBar">
371
+ <span style="font-size:11px;color:var(--text-muted);">🔗 未配置远程仓库</span>
372
+ <a href="#" id="gitRemoteConfigLinkEmpty" style="font-size:10px;color:var(--accent);text-decoration:none;margin-left:auto;">到配置页设置 ›</a>
373
+ </div>
374
+ </div>
375
+ <div class="git-slide-panel__commit">
376
+ <textarea id="gitPanelCommitMsg" class="git-panel__commit-input" rows="2" placeholder="提交信息... (Ctrl+Enter)" spellcheck="false"></textarea>
377
+ <div style="display:flex;gap:4px;align-items:center;flex-wrap:wrap;">
378
+ <button type="button" class="btn btn--primary btn--sm" id="gitPanelCommit">提交</button>
379
+ <button type="button" class="btn btn--ghost btn--sm" id="gitPanelPush">↑ 推送</button>
380
+ <button type="button" class="btn btn--ghost btn--sm" id="gitPanelPull">↓ 拉取</button>
381
+ <span id="gitPanelHint" style="font-size:11px;color:var(--text-muted,#888);margin-left:auto;"></span>
382
+ </div>
383
+ </div>
384
+ <div class="git-slide-panel__tabs">
385
+ <button type="button" class="git-slide-panel__tab is-active" data-view="status">状态</button>
386
+ <button type="button" class="git-slide-panel__tab" data-view="log">历史</button>
387
+ <button type="button" class="git-slide-panel__tab" data-view="diff">差异</button>
388
+ </div>
389
+ <div class="git-slide-panel__content" id="gitPanelContent">
390
+ <div class="git-panel__loading">加载状态中...</div>
391
+ </div>
392
+ </aside>
393
+ </section>
394
+
395
+ <section id="page-config" class="page page--scroll">
396
+ <div class="content-max">
397
+ <fieldset class="section" id="fieldsetChatSessions">
398
+ <div class="section__header">
399
+ <h3 class="section__title">聊天与会话</h3>
400
+ </div>
401
+ <p class="section__desc" style="margin-bottom:var(--sp-4);">
402
+ 在这里调整聊天的行为,比如对话太长时自动总结、工具调用超出上限后自动继续等。改完点"保存"就能生效。
403
+ </p>
404
+ <div class="chat-env-form" id="chatEnvForm">
405
+ <!-- 工具轮次 -->
406
+ <label class="checkbox-row">
407
+ <input type="checkbox" id="chkAutoContinue"/>
408
+ <span>工具轮次上限时自动续接</span>
409
+ </label>
410
+ <div class="sub-rows" id="rowToolRounds" style="display:none;">
411
+ <div class="form-row sub-row">
412
+ <label class="form-label" for="inpAutoContinueMax">最大续接段数</label>
413
+ <input type="number" id="inpAutoContinueMax" class="form-input-sm" min="0" max="200" value="4"/>
414
+ <span class="form-hint">0 表示不限,直到任务完成或被手动停止</span>
415
+ </div>
416
+ <div class="form-row sub-row">
417
+ <label class="form-label" for="inpMaxToolRounds">每轮最大工具调用次数</label>
418
+ <input type="number" id="inpMaxToolRounds" class="form-input-sm" min="1" max="400" value="16"/>
419
+ <span class="form-hint">1-400 次</span>
420
+ </div>
421
+ <div class="form-row sub-row">
422
+ <label class="form-label" for="inpMaxOutputTokens">最大输出 tokens</label>
423
+ <input type="number" id="inpMaxOutputTokens" class="form-input-sm" min="256" max="65536" step="512" value="8192"/>
424
+ <span class="form-hint">LLM 单次最大响应 token 数(保存即生效,下次对话生效)</span>
425
+ </div>
426
+ </div>
427
+
428
+ <!-- 上下文压缩 -->
429
+ <label class="checkbox-row">
430
+ <input type="checkbox" id="chkContextCompact"/>
431
+ <span>启用智能上下文压缩</span>
432
+ </label>
433
+ <div class="sub-rows" id="compactSubRows" style="display:none;">
434
+ <p style="font-size:12px;color:var(--text-muted);margin:var(--sp-2) 0;">
435
+ 启用后,当满足任一触发条件时,用 LLM 对早期对话进行摘要压缩,释放上下文空间。
436
+ </p>
437
+ <div class="form-row sub-row">
438
+ <label class="form-label" for="inpCompactMinBytes">上下文 token 触发阈值</label>
439
+ <input type="number" id="inpCompactMinBytes" class="form-input-sm" min="0" max="500000" value="30000"/>
440
+ <span class="form-hint">消息长度超过此字节数时触发(0=禁用)</span>
441
+ </div>
442
+ <div class="form-row sub-row">
443
+ <label class="form-label" for="selCompactSummarizer">摘要模型</label>
444
+ <select id="selCompactSummarizer" class="md-select" style="max-width:180px;">
445
+ </select>
446
+ </div>
447
+ <div class="form-row sub-row">
448
+ <label class="form-label" for="inpCompactSummarizerMaxTokens">摘要最大 tokens</label>
449
+ <input type="number" id="inpCompactSummarizerMaxTokens" class="form-input-sm" min="256" max="65536" value="4096"/>
450
+ <span class="form-hint">压缩摘要的输出长度限制</span>
451
+ </div>
452
+ </div>
453
+ </div>
454
+ <div class="row-actions" style="margin-top:var(--sp-4);">
455
+ <button type="button" class="btn btn--primary btn--sm" id="btnChatEnvSave">保存</button>
456
+ </div>
457
+ <div id="chatEnvStatus" class="status-line"></div>
458
+ </fieldset>
459
+
460
+ <fieldset class="section" id="fieldsetLlmPresets">
461
+ <div class="section__header">
462
+ <h3 class="section__title">多模型预设</h3>
463
+ <div class="row-actions" style="display:flex;gap:var(--sp-2);margin:0;">
464
+ <button type="button" class="btn btn--primary btn--sm" id="btnLlmPresetAdd">+ 新增</button>
465
+ <button type="button" class="btn btn--ghost btn--sm" id="btnLlmPresetRefresh">刷新</button>
466
+ </div>
467
+ </div>
468
+ <p class="section__desc">
469
+ 按能力添加模型:先选<strong>用途</strong>(对话 / 识图 / 生图…),再选服务商并填写连接信息。自部署(Ollama、OpenAI 兼容等)与云厂商使用同一表单,保存后自动标记能力,无需手改 JSON。聊天页「模型栈」中选用各能力 preset。
470
+ </p>
471
+ <div id="llmPresetList" class="preset-board" style="margin-bottom: var(--sp-4);"></div>
472
+ <div id="llmPresetStatus" class="status-line"></div>
473
+ </fieldset>
474
+
475
+ <fieldset class="section" id="fieldsetMcp">
476
+ <div class="section__header">
477
+ <h3 class="section__title">MCP 服务</h3>
478
+ <div class="row-actions" style="display:flex;gap:var(--sp-2);margin:0;align-items:center;">
479
+ <button type="button" class="btn btn--primary btn--sm" id="btnMcpAdd">+ 新增</button>
480
+ <button type="button" class="btn btn--ghost btn--sm" id="btnMcpEnvRefresh">刷新</button>
481
+ </div>
482
+ </div>
483
+ <p class="form-hint" id="mcpUvxHint" style="margin:var(--sp-2) 0;"></p>
484
+ <p class="form-hint" style="margin:0 0 var(--sp-3);">配置文件:<code id="mcpConfigPath"></code></p>
485
+ <div id="mcpServerBoard" class="mcp-board"></div>
486
+ <div id="mcpEnvStatus" class="status-line"></div>
487
+ </fieldset>
488
+
489
+ <fieldset class="section" id="fieldsetPaths">
490
+ <div class="section__header">
491
+ <h3 class="section__title">目录与权限</h3>
492
+ </div>
493
+ <div id="configPathsDisplay" style="margin-bottom:var(--sp-3);"></div>
494
+ <div id="allowlistConfig"></div>
495
+ </fieldset>
496
+
497
+ <fieldset class="section" id="fieldsetGitRemote">
498
+ <div class="section__header">
499
+ <h3 class="section__title">🔗 Git 远程仓库</h3>
500
+ </div>
501
+ <p class="section__desc">
502
+ 预设方案整合了远程地址、SSH 连通性和 PAT 凭据。每个方案就是一整套 Git 远程配置,创建项目时一步到位。
503
+ </p>
504
+
505
+ <!-- Git 远程预设方案(集成版) -->
506
+ <div style="margin-bottom:var(--sp-3);padding:var(--sp-3);border:1px solid var(--border);border-radius:6px;">
507
+ <select id="selGitDefaultProvider" style="display:none;"></select>
508
+ <select id="selConfigCredProvider" style="display:none;"></select>
509
+ <div style="font-weight:500;font-size:12px;margin-bottom:var(--sp-2);">📋 预设方案</div>
510
+ <p style="font-size:11px;color:var(--text-muted);margin:0 0 var(--sp-2);">
511
+ 每个方案包含平台、所有者、主机地址、SSH 连通状态和 PAT 凭据——全套一起管理。
512
+ </p>
513
+ <label class="checkbox-row" style="margin-bottom:var(--sp-2);">
514
+ <input type="checkbox" id="chkGitDefaultEnabled"/>
515
+ <span>新建项目时默认启用远程仓库</span>
516
+ </label>
517
+ <div id="gitDefaultsForm" style="display:none;">
518
+
519
+ <!-- 方案列表 -->
520
+ <div id="gitPresetList"></div>
521
+
522
+ <!-- PAT 内联表单 -->
523
+ <div id="gitPatForm" style="display:none;border:1px solid var(--border);border-radius:4px;padding:var(--sp-2);margin-bottom:var(--sp-2);">
524
+ <div style="font-size:11px;font-weight:500;margin-bottom:var(--sp-1);">🔐 PAT 配置 — <span id="patFormHostLabel"></span></div>
525
+ <div class="form-row">
526
+ <label class="form-label" for="inpPatUser">用户名</label>
527
+ <input type="text" id="inpPatUser" class="form-input-sm" placeholder="用户名或邮箱" style="max-width:200px;">
528
+ </div>
529
+ <div class="form-row">
530
+ <label class="form-label" for="inpPatToken">Token / 密码</label>
531
+ <input type="password" id="inpPatToken" class="form-input-sm" placeholder="Personal Access Token" style="max-width:250px;">
532
+ </div>
533
+ <div class="row-actions">
534
+ <button type="button" class="btn btn--primary btn--sm" id="btnPatSave">保存</button>
535
+ <button type="button" class="btn btn--ghost btn--sm" id="btnPatCancel">取消</button>
536
+ <span id="patFormStatus" class="status-line" style="display:inline;margin-left:8px;"></span>
537
+ </div>
538
+ </div>
539
+
540
+ <!-- 方案编辑表单 -->
541
+ <div id="gitPresetEditor" style="display:none;border:1px solid var(--border);border-radius:4px;padding:var(--sp-2);margin-bottom:var(--sp-2);">
542
+ <div style="font-size:11px;font-weight:500;margin-bottom:var(--sp-1);" id="gitPresetEditorTitle">添加方案</div>
543
+ <div class="form-row">
544
+ <label class="form-label" for="inpPresetName">方案名称</label>
545
+ <input type="text" id="inpPresetName" class="form-input-sm" placeholder="例如: GitHub 主号" style="max-width:200px;">
546
+ </div>
547
+ <div class="form-row">
548
+ <label class="form-label" for="selPresetProvider">平台</label>
549
+ <select id="selPresetProvider" class="md-select" style="max-width:160px;">
550
+ <option value="github">GitHub</option>
551
+ <option value="gitlab">GitLab</option>
552
+ <option value="gitee">Gitee</option>
553
+ <option value="bitbucket">Bitbucket</option>
554
+ <option value="custom">自定义</option>
555
+ </select>
556
+ </div>
557
+ <div class="form-row" id="rowPresetHost" style="display:none;">
558
+ <label class="form-label" for="inpPresetHost">主机地址</label>
559
+ <input type="text" id="inpPresetHost" class="form-input-sm" placeholder="例如 git.tagword.cn" style="max-width:250px;">
560
+ <span class="form-hint">选「自定义」时必填</span>
561
+ </div>
562
+ <div class="form-row">
563
+ <label class="form-label" for="inpPresetOwner">所有者</label>
564
+ <input type="text" id="inpPresetOwner" class="form-input-sm" placeholder="用户名或组织名" style="max-width:200px;">
565
+ </div>
566
+ <div class="form-row">
567
+ <label class="form-label">协议</label>
568
+ <div style="display:flex;gap:12px;align-items:center;">
569
+ <label style="font-size:12px;display:flex;align-items:center;gap:4px;cursor:pointer;">
570
+ <input type="radio" name="presetProtocol" value="ssh" checked> SSH
571
+ </label>
572
+ <label style="font-size:12px;display:flex;align-items:center;gap:4px;cursor:pointer;">
573
+ <input type="radio" name="presetProtocol" value="https"> HTTPS
574
+ </label>
575
+ </div>
576
+ </div>
577
+ <label class="checkbox-row">
578
+ <input type="checkbox" id="chkPresetAutoPush"/>
579
+ <span>创建后自动推送初始提交</span>
580
+ </label>
581
+ <div class="row-actions" style="margin-top:var(--sp-1);">
582
+ <button type="button" class="btn btn--primary btn--sm" id="btnPresetSave">保存方案</button>
583
+ <button type="button" class="btn btn--ghost btn--sm" id="btnPresetCancel">取消</button>
584
+ <span id="presetFormStatus" class="status-line" style="display:inline;margin-left:8px;"></span>
585
+ </div>
586
+ </div>
587
+
588
+ <button type="button" class="btn btn--ghost btn--sm" id="btnPresetAdd">+ 添加方案</button>
589
+ </div>
590
+ </div>
591
+
592
+ <!-- Git 代理设置 -->
593
+ <div style="margin-bottom:var(--sp-3);padding:var(--sp-3);border:1px solid var(--border);border-radius:6px;">
594
+ <div style="font-weight:500;font-size:12px;margin-bottom:var(--sp-2);">🌐 Git 代理</div>
595
+ <p style="font-size:11px;color:var(--text-muted);margin-bottom:var(--sp-2);">
596
+ 如果你的网络需要代理才能访问 GitHub/GitLab 等,在这里设置。例如 <code>http://127.0.0.1:1087</code>
597
+ </p>
598
+ <label class="checkbox-row" style="margin-bottom:var(--sp-2);">
599
+ <input type="checkbox" id="chkGitProxyEnabled"/>
600
+ <span>启用代理</span>
601
+ </label>
602
+ <div id="gitProxyForm" style=""> <!-- toggled by JS -->
603
+ <div class="form-row">
604
+ <label class="form-label" for="inpGitHttpProxy">HTTP 代理</label>
605
+ <input type="text" id="inpGitHttpProxy" class="form-input-sm" placeholder="http://127.0.0.1:1087" style="max-width:280px;font-family:monospace;font-size:11px;">
606
+ <button type="button" class="btn btn--ghost btn--xs" id="btnGitHttpProxyClear" title="清除">✕</button>
607
+ </div>
608
+ <div class="form-row">
609
+ <label class="form-label" for="inpGitHttpsProxy">HTTPS 代理</label>
610
+ <input type="text" id="inpGitHttpsProxy" class="form-input-sm" placeholder="http://127.0.0.1:1087" style="max-width:280px;font-family:monospace;font-size:11px;">
611
+ <button type="button" class="btn btn--ghost btn--xs" id="btnGitHttpsProxyClear" title="清除">✕</button>
612
+ </div>
613
+ <div class="row-actions" style="margin-top:var(--sp-2);">
614
+ <button type="button" class="btn btn--primary btn--sm" id="btnGitProxySave">保存代理设置</button>
615
+ <span id="gitProxyStatus" class="status-line" style="display:inline;margin-left:8px;"></span>
616
+ </div>
617
+ </div><!-- /gitProxyForm -->
618
+ </div>
619
+ </fieldset>
620
+ </div>
621
+ </section>
622
+
623
+ <section id="page-tasks" class="page page--scroll">
624
+ <div class="content-max">
625
+ <fieldset class="section" id="fieldsetCron">
626
+ <div class="section__header">
627
+ <h3 class="section__title">定时任务</h3>
628
+ <div class="row-actions" style="display:flex;gap:var(--sp-2);margin:0;align-items:center;">
629
+ <span id="cronGlobalToggle" class="toggle-switch off" title="点击切换总开关"></span>
630
+ <button type="button" class="btn btn--primary btn--sm" id="btnCronJobAdd">+ 新增</button>
631
+ <button type="button" class="btn btn--ghost btn--sm" id="btnCronRefresh">刷新</button>
632
+ </div>
633
+ </div>
634
+ <p class="section__desc">
635
+ 设置 Agent 在指定的时间自动干活,比如每天早晨发报告、定期检查消息。每个任务可以单独开关,也可以随时修改。
636
+ </p>
637
+ <div id="cronJobList" class="cron-list" style="margin-bottom: var(--sp-4);"></div>
638
+ <div id="cronUiStatus" class="status-line"></div>
639
+ </fieldset>
640
+ </div>
641
+ </section>
642
+
643
+ <section id="page-agent" class="page page--scroll">
644
+ <div class="content-max">
645
+
646
+ <!-- Current agent detail (always visible, single-agent mode) -->
647
+ <fieldset class="section" id="fieldsetAgentDetail">
648
+ <div class="section__header">
649
+ <h3 class="section__title" id="agentDetailTitle">Agent 配置</h3>
650
+ </div>
651
+ <div id="agentDetailContent"></div>
652
+ <div id="agentStatus" class="status-line"></div>
653
+ </fieldset>
654
+
655
+ <!-- Skills section -->
656
+ <fieldset class="section" id="fieldsetAgentSkills">
657
+ <div class="section__header">
658
+ <h3 class="section__title">📚 知识 / 技能</h3>
659
+ <div class="row-actions" style="display:flex;gap:var(--sp-2);margin:0;">
660
+ <button type="button" class="btn btn--primary btn--sm" id="btnSkillAdd">+ 新增</button>
661
+ <button type="button" class="btn btn--ghost btn--sm" id="btnSkillRefresh">刷新</button>
662
+ </div>
663
+ </div>
664
+ <p class="section__desc">
665
+ 技能文件是 Markdown 文档,教导 Agent 如何完成特定任务。仅对当前 Agent 生效,可独立启用/停用。
666
+ </p>
667
+ <div id="skillList" class="skill-list" style="margin-bottom:var(--sp-3);"></div>
668
+ <div id="skillStatus" class="status-line"></div>
669
+ </fieldset>
670
+
671
+ <!-- System Prompt MD files -->
672
+ <fieldset class="section" id="fieldsetSysPromptMd">
673
+ <div class="section__header">
674
+ <h3 class="section__title">📄 身份配置文件</h3>
675
+ </div>
676
+ <p class="section__desc">
677
+ 编辑当前 Agent 的身份/行为配置文件(Markdown)。所有文档默认参与<strong>系统提示</strong>,保存后<strong>下一轮对话</strong>生效。
678
+ </p>
679
+ <div id="mdFileList"></div>
680
+ <div id="mdFileStatus" class="status-line"></div>
681
+ </fieldset>
682
+
683
+ </div>
684
+ </section>
685
+
686
+ <section id="page-files" class="page">
687
+ <div class="file-editor-layout">
688
+ <div class="file-editor">
689
+ <div class="file-editor__tabs" id="editorTabs">
690
+ <div class="file-editor__tabs-empty">选择一个文件查看</div>
691
+ </div>
692
+ <div id="editorContainer" class="file-editor__container">
693
+ <div class="file-editor__welcome">
694
+ <h3>文件浏览器</h3>
695
+ <p>左侧边栏选择文件进行编辑</p>
696
+ </div>
697
+ </div>
698
+ <div class="file-editor__status" id="editorStatus"></div>
699
+ </div>
700
+ </div>
701
+ </section>
702
+
703
+ <!-- ===== 新建项目对话框 ===== -->
704
+ <div id="newProjectDialog" class="modal-overlay" style="display:none">
705
+ <div class="modal-dialog" style="max-width:520px;position:relative;">
706
+ <!-- 进度提示覆盖层 -->
707
+ <div id="projectProgressOverlay" style="display:none;position:absolute;inset:0;background:var(--bg);border-radius:8px;z-index:10;flex-direction:column;align-items:center;justify-content:center;padding:32px;">
708
+ <div id="projectProgressText" style="font-size:14px;font-weight:500;text-align:center;margin-bottom:8px;">正在准备...</div>
709
+ <div id="projectProgressDetail" style="font-size:11px;color:var(--text-muted);text-align:center;max-width:360px;line-height:1.5;"></div>
710
+ <div style="margin-top:16px;width:200px;height:4px;background:var(--border);border-radius:2px;overflow:hidden;">
711
+ <div id="projectProgressBar" style="width:0%;height:100%;background:var(--accent);border-radius:2px;transition:width 0.5s;"></div>
712
+ </div>
713
+ </div>
714
+ <div class="modal-dialog__header">
715
+ <span class="modal-dialog__title">新建项目</span>
716
+ <button class="modal-dialog__close" id="btnNewProjectDialogClose">&times;</button>
717
+ </div>
718
+ <div class="modal-dialog__body">
719
+ <!-- 项目名称 -->
720
+ <div class="modal-field">
721
+ <label class="modal-field__label" for="inpNewProjectName">项目名称 <span class="required">*</span></label>
722
+ <input type="text" id="inpNewProjectName" class="modal-field__input" placeholder="例如:my-awesome-project" autofocus />
723
+ </div>
724
+
725
+ <!-- 项目来源 -->
726
+ <div class="modal-field">
727
+ <label class="modal-field__label">项目来源</label>
728
+ <div style="display:flex;flex-direction:column;gap:4px;margin-top:4px;">
729
+ <label class="modal-radio-row" style="display:flex;align-items:center;gap:8px;cursor:pointer;padding:6px 8px;border:1px solid var(--border);border-radius:6px;">
730
+ <input type="radio" name="projectSource" value="scratch" checked>
731
+ <span>📁 从零创建 <span style="font-size:11px;color:var(--text-muted);">— 本地空项目</span></span>
732
+ </label>
733
+ <label class="modal-radio-row" style="display:flex;align-items:center;gap:8px;cursor:pointer;padding:6px 8px;border:1px solid var(--border);border-radius:6px;">
734
+ <input type="radio" name="projectSource" value="clone">
735
+ <span>📥 从远程仓库克隆</span>
736
+ </label>
737
+ <label class="modal-radio-row" style="display:flex;align-items:center;gap:8px;cursor:pointer;padding:6px 8px;border:1px solid var(--border);border-radius:6px;">
738
+ <input type="radio" name="projectSource" value="template">
739
+ <span>🏗️ 从模板创建</span>
740
+ </label>
741
+ </div>
742
+ </div>
743
+
744
+ <!-- 文件系统路径(所有来源共用) -->
745
+ <div class="modal-field" id="fieldProjectPath">
746
+ <label class="modal-field__label" for="inpNewProjectPath">工作目录 <span class="optional">(可不填,稍后在项目菜单绑定)</span></label>
747
+ <div class="modal-field__input-row">
748
+ <input type="text" id="inpNewProjectPath" class="modal-field__input" placeholder="留空表示暂不绑定;需要时在项目 ⋮ → 项目目录 中设置" />
749
+ <button type="button" id="btnBrowseDir" class="modal-btn modal-btn--browse" title="浏览选择目录">📁 浏览</button>
750
+ </div>
751
+ </div>
752
+
753
+ <!-- 克隆 URL(仅克隆模式) -->
754
+ <div class="modal-field" id="fieldCloneUrl" style="display:none;">
755
+ <label class="modal-field__label" for="inpCloneUrl">仓库 URL</label>
756
+ <input type="text" id="inpCloneUrl" class="modal-field__input" placeholder="https://github.com/user/repo.git 或 git@github.com:user/repo.git" />
757
+ </div>
758
+
759
+ <!-- 模板选择(仅模板模式) -->
760
+ <div class="modal-field" id="fieldTemplate" style="display:none;">
761
+ <label class="modal-field__label" for="selProjectTemplate">模板</label>
762
+ <select id="selProjectTemplate" class="modal-field__input">
763
+ <option value="fastapi">FastAPI</option>
764
+ <option value="flask">Flask</option>
765
+ <option value="cli">CLI 工具</option>
766
+ <option value="package">Python 包</option>
767
+ </select>
768
+ </div>
769
+
770
+ <!-- 关联远程仓库(从零创建和模板模式可用,克隆模式隐藏) -->
771
+ <div class="modal-field" id="fieldProjectRemote" style="display:none;">
772
+ <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px;">
773
+ <span style="font-size:12px;font-weight:500;">🔗 关联远程仓库</span>
774
+ <label style="font-size:11px;color:var(--text-muted);display:flex;align-items:center;gap:4px;cursor:pointer;">
775
+ <input type="checkbox" id="chkProjectRemoteEnable"> 启用
776
+ </label>
777
+ </div>
778
+ <div id="projectRemoteForm" style="display:none;padding:8px;border:1px solid var(--border);border-radius:6px;">
779
+ <div id="presetSelectorRow" style="display:none;margin-bottom:6px;">
780
+ <select id="selProjectPreset" class="modal-field__input" style="flex:1;min-width:140px;">
781
+ <option value="">— 选择方案 —</option>
782
+ </select>
783
+ <span style="font-size:10px;color:var(--text-muted);margin-left:4px;">自动填充下方</span>
784
+ </div>
785
+ <div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px;">
786
+ <select id="selProjectRemoteProvider" class="modal-field__input" style="flex:1;min-width:100px;">
787
+ <option value="github">GitHub</option>
788
+ <option value="gitlab">GitLab</option>
789
+ <option value="gitee">Gitee</option>
790
+ <option value="bitbucket">Bitbucket</option>
791
+ <option value="custom">自定义</option>
792
+ </select>
793
+ <input type="text" id="inpProjectRemoteHost" class="modal-field__input" placeholder="主机地址" style="flex:1;min-width:100px;display:none;">
794
+ <input type="text" id="inpProjectRemoteOwner" class="modal-field__input" placeholder="所有者" style="flex:1;min-width:100px;">
795
+ <span style="line-height:32px;color:var(--text-muted);">/</span>
796
+ <input type="text" id="inpProjectRemoteRepo" class="modal-field__input" placeholder="仓库名" style="flex:1;min-width:100px;">
797
+ </div>
798
+ <div style="display:flex;gap:12px;align-items:center;">
799
+ <label style="font-size:11px;color:var(--text-muted);display:flex;align-items:center;gap:4px;cursor:pointer;">
800
+ <input type="radio" name="projectRemoteProtocol" value="ssh" checked> SSH
801
+ </label>
802
+ <label style="font-size:11px;color:var(--text-muted);display:flex;align-items:center;gap:4px;cursor:pointer;">
803
+ <input type="radio" name="projectRemoteProtocol" value="https"> HTTPS
804
+ </label>
805
+ <label style="font-size:11px;color:var(--text-muted);display:flex;align-items:center;gap:4px;cursor:pointer;margin-left:auto;">
806
+ <input type="checkbox" id="chkProjectAutoPush"> 创建后自动推送
807
+ </label>
808
+ </div>
809
+ <div id="projectRemoteUrlPreview" style="font-size:10px;color:var(--text-muted);font-family:monospace;margin-top:4px;"></div>
810
+ </div>
811
+ </div>
812
+
813
+ <!-- 路径提示 -->
814
+ <div class="modal-field__hint" style="margin-top:4px;">关联源代码目录后,文件树和 Git 面板可直接操作项目文件</div>
815
+ </div>
816
+ <div class="modal-dialog__footer">
817
+ <button class="modal-btn modal-btn--cancel" id="btnNewProjectCancel">取消</button>
818
+ <button class="modal-btn modal-btn--confirm" id="btnNewProjectConfirm">创建项目</button>
819
+ </div>
820
+ </div>
821
+ </div>
822
+
823
+ </main>
824
+ </div>