@agentunion/kite 1.5.0 → 1.6.0

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 (573) hide show
  1. package/.claude/skills/kite/checklists/feature-checklist.md +496 -0
  2. package/.claude/skills/kite/references/event-patterns.md +180 -0
  3. package/.claude/skills/kite/references/health-check.md +202 -0
  4. package/.claude/skills/kite/references/http-service.md +199 -0
  5. package/.claude/skills/kite/references/module-md-spec.md +172 -0
  6. package/.claude/skills/kite/references/multi-connection.md +147 -0
  7. package/.claude/skills/kite/references/rpc-patterns.md +199 -0
  8. package/.claude/skills/kite/references/shutdown-sequence.md +146 -0
  9. package/.claude/skills/kite/references/stdin-protocol.md +147 -0
  10. package/.claude/skills/kite/references/test-center-integration.md +178 -0
  11. package/.claude/skills/kite/references/ws-lifecycle.md +301 -0
  12. package/.claude/skills/kite/skill.md +272 -0
  13. package/.claude/skills/kite/templates/go/README.md +20 -0
  14. package/.claude/skills/kite/templates/node/entry.js +134 -0
  15. package/.claude/skills/kite/templates/node/module.md +16 -0
  16. package/.claude/skills/kite/templates/node/server.js +351 -0
  17. package/.claude/skills/kite/templates/node/server_http.js +90 -0
  18. package/.claude/skills/kite/templates/python/entry.py +425 -0
  19. package/.claude/skills/kite/templates/python/module.md +26 -0
  20. package/.claude/skills/kite/templates/python/server.py +447 -0
  21. package/.claude/skills/kite/templates/python/server_http.py +433 -0
  22. package/cli.js +38 -4
  23. package/core/env_checker.py +96 -0
  24. package/docs/05-/347/237/255/344/277/241/350/256/244/350/257/201/344/270/216/347/224/250/346/210/267/344/277/241/346/201/257/346/216/245/345/217/243/346/226/207/346/241/243.md +507 -0
  25. package/docs/ACP/345/215/217/350/256/256/345/205/274/345/256/271/346/226/271/346/241/210.md +138 -0
  26. package/docs/CI/344/270/216AI/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/346/226/271/346/241/210.md +75 -0
  27. package/docs/CLI/345/274/200/345/217/221/350/256/241/345/210/222.md +595 -0
  28. package/docs/ClaudeCode/350/277/234/347/250/213/345/215/217/344/275/234/347/263/273/347/273/237-/346/212/200/346/234/257/350/257/204/344/274/260.md +535 -0
  29. package/docs/ClaudeCode/350/277/234/347/250/213/345/215/217/344/275/234/347/263/273/347/273/237/350/256/276/350/256/241.md +631 -0
  30. package/docs/Evol-App/344/275/277/347/224/250KernelClient/346/224/271/351/200/240/345/256/214/346/210/220.md +342 -0
  31. package/docs/Evol/346/216/247/345/210/266/345/217/260/346/217/222/344/273/266/345/214/226/346/236/266/346/236/204/346/246/202/350/246/201.md +604 -0
  32. package/docs/Evol/346/216/247/345/210/266/345/217/260/346/217/222/344/273/266/345/214/226/346/236/266/346/236/204/350/256/276/350/256/241.md +1708 -0
  33. package/docs/Evol/346/250/241/345/235/227/350/256/276/350/256/241/346/226/271/346/241/210.md +1154 -0
  34. package/docs/Evol/351/241/265/351/235/242/346/217/222/344/273/266/345/214/226-Evol/346/250/241/345/235/227/345/256/236/346/226/275/346/214/207/345/215/227.md +403 -0
  35. package/docs/Evol/351/241/265/351/235/242/346/217/222/344/273/266/345/214/226-/345/244/226/351/203/250/346/250/241/345/235/227/346/216/245/345/205/245/346/214/207/345/215/227.md +468 -0
  36. package/docs/HTTP-RPC/350/277/201/347/247/273/345/210/260WebSocket/350/256/241/345/210/222.md +318 -0
  37. package/docs/INDEX.md +388 -0
  38. package/docs/KITE_DOCS_GUIDE.md +33 -0
  39. package/docs/Kernel-Client-Kite-Token/346/224/257/346/214/201/345/256/236/346/226/275/345/256/214/346/210/220.md +330 -0
  40. package/docs/Kernel/344/270/273/345/212/250Ping/346/234/272/345/210/266-/346/255/243/347/241/256/345/256/236/347/216/260.md +235 -0
  41. package/docs/Kernel/344/270/273/345/212/250Ping/346/234/272/345/210/266/345/256/236/346/226/275/346/200/273/347/273/223.md +204 -0
  42. package/docs/Kite/345/256/211/350/243/205/351/227/256/351/242/230/350/247/243/345/206/263/346/226/271/346/241/210.md +362 -0
  43. package/docs/Kite/346/216/247/345/210/266/345/217/260/346/217/222/344/273/266/345/214/226/346/236/266/346/236/204/350/256/276/350/256/241-/347/273/210/346/236/201/347/233/256/346/240/207.md +721 -0
  44. package/docs/Kite/346/216/247/345/210/266/345/217/260/347/273/237/344/270/200WebSocket/346/224/271/351/200/240/346/226/271/346/241/210.md +821 -0
  45. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/01-/346/241/206/346/236/266/345/256/232/344/275/215.md +12 -0
  46. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/02-/346/240/270/345/277/203/346/246/202/345/277/265.md +341 -0
  47. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/03-/347/263/273/347/273/237/346/236/266/346/236/204.md +257 -0
  48. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/04-/346/250/241/345/235/227/350/247/204/350/214/203.md +263 -0
  49. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/05-/346/240/270/345/277/203/346/265/201/347/250/213-/346/226/260/347/211/210.md +267 -0
  50. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/05-/346/240/270/345/277/203/346/265/201/347/250/213.md +149 -0
  51. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/06-/347/233/256/345/275/225/347/273/223/346/236/204.md +231 -0
  52. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/07-/346/225/260/346/215/256/346/250/241/345/236/213.md +68 -0
  53. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/08-/346/211/251/345/261/225/346/200/247.md +34 -0
  54. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/09-/344/270/216/345/205/267/344/275/223/345/272/224/347/224/250/347/232/204/345/205/263/347/263/273.md +22 -0
  55. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/README.md +46 -0
  56. package/docs/Kite/347/263/273/347/273/237/345/220/257/345/212/250/346/265/201/347/250/213.md +567 -0
  57. package/docs/Launcher/345/220/257/345/212/250/345/231/250/346/226/207/346/241/243.md +745 -0
  58. package/docs/Polyglot/350/277/220/350/241/214/346/227/266/344/270/216Clawdbot/345/205/274/345/256/271/346/200/247/350/256/276/350/256/241.md +321 -0
  59. package/docs/Redis/344/270/216/346/250/241/345/235/227/345/244/232/345/256/236/344/276/213/346/226/271/346/241/210.md +438 -0
  60. package/docs/Relay-Kite-Token/350/256/244/350/257/201/345/256/236/346/226/275/345/256/214/346/210/220.md +178 -0
  61. package/docs/Relay-Token/346/235/203/351/231/220/351/205/215/347/275/256/351/252/214/350/257/201.md +113 -0
  62. package/docs/Watchdog/345/201/245/345/272/267/346/243/200/346/237/245/344/270/216WebSocket-Ping/346/234/272/345/210/266/345/210/206/346/236/220.md +367 -0
  63. package/docs/Watchdog/350/265/204/346/272/220/347/233/221/346/216/247/347/255/226/347/225/245.md +92 -0
  64. package/docs/WebSocket/346/216/245/346/224/266/345/276/252/347/216/257/346/255/273/351/224/201/351/230/262/350/214/203/350/247/204/350/214/203.md +357 -0
  65. package/docs/WebSocket/350/277/236/346/216/245/351/237/247/346/200/247/344/270/216/351/207/215/350/277/236/346/234/272/345/210/266/345/256/214/346/225/264/346/226/271/346/241/210.md +531 -0
  66. package/docs/WebSocket/350/277/236/346/216/245/351/237/247/346/200/247/346/226/271/346/241/210.md +169 -0
  67. package/docs/WebSocket/351/207/215/350/277/236/346/234/272/345/210/266/346/265/213/350/257/225/346/212/245/345/221/212.md +169 -0
  68. package/docs/WebSocket/351/207/215/350/277/236/351/200/200/351/201/277/346/234/272/345/210/266/346/226/271/346/241/210.md +394 -0
  69. package/docs/Web/346/250/241/345/235/227/344/270/216Evol/346/250/241/345/235/227/351/207/215/346/236/204/345/210/206/346/236/220.md +521 -0
  70. package/docs/audit-api-guide.md +68 -0
  71. package/docs/audit-module-design.md +315 -0
  72. package/docs/audit-module-implementation-summary.md +149 -0
  73. package/docs/llm-context-design.md +52 -0
  74. package/docs/llm-test-enhancement-plan.md +970 -0
  75. package/docs/logs-api-guide.md +42 -0
  76. package/docs/npm/345/214/205Python/347/216/257/345/242/203/347/256/241/347/220/206/346/226/271/346/241/210.md +302 -0
  77. package/docs/npm/345/217/221/345/270/203/344/270/216CLI/344/275/277/347/224/250/346/214/207/345/215/227.md +245 -0
  78. package/docs/stdio/344/270/216/347/253/257/345/217/243/345/217/221/347/216/260/351/207/215/346/236/204.md +480 -0
  79. package/docs/web/346/250/241/345/235/227/344/270/255/350/275/254/346/234/215/345/212/241/350/256/276/350/256/241/346/226/271/346/241/210.md +449 -0
  80. package/docs//344/272/213/344/273/266/345/244/204/347/220/206/346/234/272/345/210/266.md +388 -0
  81. package/docs//344/272/213/344/273/266/345/244/204/347/220/206/350/247/204/350/214/203.md +113 -0
  82. package/docs//344/272/213/344/273/266/350/256/242/351/230/205/351/200/232/351/205/215/347/254/246/350/247/204/350/214/203.md +256 -0
  83. package/docs//344/272/213/344/273/266/351/230/237/345/210/227/345/274/271/346/200/247/347/256/241/347/220/206.md +449 -0
  84. package/docs//344/272/244/344/272/222/345/274/217/347/273/210/347/253/257/346/216/247/345/210/266/346/226/271/346/241/210.md +301 -0
  85. package/docs//344/273/243/347/220/206/345/220/257/345/212/250/345/231/250/344/270/216/345/256/271/345/231/250/345/214/226.md +140 -0
  86. package/docs//344/273/243/347/240/201/347/273/237/350/256/241/345/267/245/345/205/267/344/275/277/347/224/250/350/257/264/346/230/216.md +217 -0
  87. package/docs//344/274/230/351/233/205/351/200/200/345/207/272/350/247/204/350/214/203.md +362 -0
  88. package/docs//344/276/235/350/265/226/347/256/241/347/220/206/350/257/264/346/230/216.md +141 -0
  89. package/docs//344/277/256/345/244/215/346/235/203/351/231/220/351/227/256/351/242/230-evol-RPC/346/235/203/351/231/220.md +268 -0
  90. package/docs//345/210/240/351/231/244kernel-client-example/345/256/214/346/210/220.md +309 -0
  91. package/docs//345/210/240/351/231/244ws-management/345/256/214/346/210/220.md +418 -0
  92. package/docs//345/220/257/345/212/250/344/274/230/345/214/226/346/226/271/346/241/210.md +522 -0
  93. package/docs//345/220/257/345/212/250/344/276/235/350/265/226/344/270/216/346/216/222/345/272/217.md +105 -0
  94. package/docs//345/256/211/350/243/205/350/204/232/346/234/254/345/274/200/345/217/221/346/226/207/346/241/243.md +643 -0
  95. package/docs//345/256/214/346/225/264/345/220/257/345/212/250/346/265/201/347/250/213/350/256/276/350/256/241.md +452 -0
  96. package/docs//345/256/236/347/216/260/350/247/204/345/210/222.md +195 -0
  97. package/docs//345/277/203/350/267/263/346/234/272/345/210/266/351/207/215/346/236/204/346/200/273/347/273/223.md +166 -0
  98. package/docs//346/217/241/346/211/213/350/256/244/350/257/201/346/226/271/346/241/210-/345/256/211/345/205/250/345/256/241/346/237/245.md +176 -0
  99. package/docs//346/217/241/346/211/213/350/256/244/350/257/201/346/226/271/346/241/210.md +908 -0
  100. package/docs//346/226/207/346/241/243/346/233/264/346/226/260/346/270/205/345/215/225.md +83 -0
  101. package/docs//346/227/245/345/277/227/344/270/216/345/274/202/345/270/270/345/244/204/347/220/206/350/247/204/350/214/203.md +829 -0
  102. package/docs//346/227/245/345/277/227/350/260/203/350/257/225/345/256/236/346/210/230/346/214/207/345/215/227.md +25 -0
  103. package/docs//346/236/266/346/236/204/345/200/237/351/211/264/346/214/207/345/215/227.md +977 -0
  104. package/docs//346/236/266/346/236/204/346/224/271/351/200/240-/345/256/214/346/210/220/346/200/273/347/273/223.md +440 -0
  105. package/docs//346/236/266/346/236/204/347/216/260/347/212/266/344/270/216/347/273/210/346/236/201/347/233/256/346/240/207/345/257/271/346/257/224/345/210/206/346/236/220.md +508 -0
  106. package/docs//346/250/241/345/235/227/345/244/232/350/277/236/346/216/245/346/216/247/345/210/266/347/255/226/347/225/245.md +220 -0
  107. package/docs//346/250/241/345/235/227/345/256/211/350/243/205/346/234/272/345/210/266/350/256/276/350/256/241.md +500 -0
  108. package/docs//346/250/241/345/235/227/345/274/200/345/217/221/346/214/207/345/215/227.md +1824 -0
  109. package/docs//346/250/241/345/235/227/347/203/255/346/233/264/346/226/260.md +89 -0
  110. package/docs//346/250/241/345/235/227/350/277/234/347/250/213/351/203/250/347/275/262/345/274/200/345/217/221/350/247/204/350/214/203.md +460 -0
  111. package/docs//346/250/241/345/235/227/351/200/200/345/207/272/346/234/272/345/210/266/345/256/214/346/225/264/346/226/271/346/241/210.md +303 -0
  112. package/docs//346/250/241/345/235/227/351/205/215/347/275/256/345/212/240/350/275/275/344/270/216/347/203/255/351/207/215/350/275/275/350/247/204/350/214/203.md +369 -0
  113. package/docs//346/265/213/350/257/225/344/270/255/345/277/203/346/267/273/345/212/240/346/250/241/345/235/227/346/265/213/350/257/225/346/214/207/345/215/227.md +147 -0
  114. package/docs//347/211/210/346/234/254/351/224/201/345/256/232/347/216/257/345/242/203/347/256/241/347/220/206/346/226/271/346/241/210.md +331 -0
  115. package/docs//347/216/257/345/242/203/345/217/230/351/207/217/344/270/216/350/277/220/350/241/214/346/227/266/347/233/256/345/275/225/350/256/276/350/256/241.md +499 -0
  116. package/docs//347/216/257/345/242/203/347/256/241/347/220/206/345/256/214/346/225/264/346/226/271/346/241/210.md +334 -0
  117. package/docs//350/231/232/346/213/237/346/250/241/345/235/227/344/270/255/350/275/254/346/234/215/345/212/241/345/256/214/346/225/264/350/256/276/350/256/241.md +1496 -0
  118. package/docs//350/231/232/346/213/237/347/216/257/345/242/203/345/267/245/344/275/234/345/216/237/347/220/206.md +163 -0
  119. package/docs//350/256/241/345/210/222/347/256/241/347/220/206/345/231/250/344/275/277/347/224/250/346/214/207/345/215/227.md +196 -0
  120. package/docs//350/256/244/350/257/201/346/250/241/345/235/227/344/270/216Gateway/350/256/276/350/256/241/346/226/271/346/241/210.md +765 -0
  121. package/docs//350/277/234/347/250/213/346/250/241/345/235/227/350/256/276/350/256/241-/346/227/247/347/211/210.md +1117 -0
  122. package/docs//350/277/234/347/250/213/346/250/241/345/235/227/350/256/276/350/256/241.md +451 -0
  123. package/docs//351/207/215/346/236/204/346/234/272/345/210/266/346/270/205/345/215/225.md +192 -0
  124. package/docs//351/223/276/350/267/257/350/277/275/350/270/252/346/226/271/346/241/210.md +242 -0
  125. package/docs//351/231/215/347/272/247/347/255/226/347/225/245/350/256/276/350/256/241/346/226/271/346/241/210.md +618 -0
  126. package/extensions/agents/assistant/entry.py +113 -14
  127. package/extensions/agents/assistant/module.md +27 -22
  128. package/extensions/agents/assistant/server.py +291 -105
  129. package/extensions/channels/acp_channel/entry.py +114 -16
  130. package/extensions/channels/acp_channel/module.md +4 -0
  131. package/extensions/channels/acp_channel/server.py +396 -105
  132. package/extensions/channels/phone_channel/__init__.py +1 -0
  133. package/extensions/channels/phone_channel/entry.py +503 -0
  134. package/extensions/channels/phone_channel/module.md +31 -0
  135. package/extensions/channels/phone_channel/server.py +686 -0
  136. package/extensions/event_hub_bench/entry.py +55 -12
  137. package/extensions/event_hub_bench/module.md +27 -27
  138. package/extensions/services/audit/README.md +134 -0
  139. package/extensions/services/audit/collector.py +73 -0
  140. package/extensions/services/audit/entry.py +444 -0
  141. package/extensions/services/audit/module.md +66 -0
  142. package/extensions/services/audit/query_audit.py +111 -0
  143. package/extensions/services/audit/routes/__init__.py +1 -0
  144. package/extensions/services/audit/routes/routes_audit.py +113 -0
  145. package/extensions/services/audit/schemas/__init__.py +5 -0
  146. package/extensions/services/audit/schemas/audit_event.py +92 -0
  147. package/extensions/services/audit/server.py +542 -0
  148. package/extensions/services/audit/storage.py +95 -0
  149. package/extensions/services/auth/entry.py +1054 -0
  150. package/extensions/services/auth/module.md +31 -0
  151. package/extensions/services/auth/token_store.py +185 -0
  152. package/extensions/services/auth/verifiers/evol_account.py +101 -0
  153. package/extensions/services/auth/verifiers/kite_token.py +38 -0
  154. package/extensions/services/auth/verifiers/pairing_code.py +71 -0
  155. package/extensions/services/backup/entry.py +494 -197
  156. package/extensions/services/backup/module.md +4 -2
  157. package/extensions/services/dataclaw/api/__init__.py +0 -0
  158. package/extensions/services/dataclaw/api/admin.py +367 -0
  159. package/extensions/services/dataclaw/api/copyright.py +175 -0
  160. package/extensions/services/dataclaw/api/credits.py +177 -0
  161. package/extensions/services/dataclaw/api/data.py +179 -0
  162. package/extensions/services/dataclaw/api/demands.py +269 -0
  163. package/extensions/services/dataclaw/api/feeds.py +262 -0
  164. package/extensions/services/dataclaw/api/identity.py +505 -0
  165. package/extensions/services/dataclaw/api/notifications.py +104 -0
  166. package/extensions/services/dataclaw/api/reviews.py +138 -0
  167. package/extensions/services/dataclaw/api/search.py +153 -0
  168. package/extensions/services/dataclaw/api/subscriptions.py +157 -0
  169. package/extensions/services/dataclaw/config.json5 +96 -0
  170. package/extensions/services/dataclaw/core/__init__.py +0 -0
  171. package/extensions/services/dataclaw/core/auth.py +95 -0
  172. package/extensions/services/dataclaw/core/config.py +50 -0
  173. package/extensions/services/dataclaw/core/database.py +70 -0
  174. package/extensions/services/dataclaw/entry.py +416 -0
  175. package/extensions/services/dataclaw/gofeed/351/241/271/347/233/256/346/211/200/346/234/211/346/235/203/350/275/254/347/247/273/346/265/201/347/250/213/350/257/264/346/230/216.md +309 -0
  176. package/extensions/services/dataclaw/migrate.py +283 -0
  177. package/extensions/services/dataclaw/models/__init__.py +0 -0
  178. package/extensions/services/dataclaw/module.md +49 -0
  179. package/extensions/services/dataclaw/requirements.txt +18 -0
  180. package/extensions/services/dataclaw/server.py +759 -0
  181. package/extensions/services/dataclaw/services/__init__.py +0 -0
  182. package/extensions/services/dataclaw/services/agent_service.py +132 -0
  183. package/extensions/services/dataclaw/services/credit_service.py +235 -0
  184. package/extensions/services/dataclaw/services/email_service.py +140 -0
  185. package/extensions/services/dataclaw/services/feed_service.py +259 -0
  186. package/extensions/services/dataclaw/services/notification_service.py +209 -0
  187. package/extensions/services/dataclaw/services/oauth_service.py +275 -0
  188. package/extensions/services/dataclaw/services/pricing.py +102 -0
  189. package/extensions/services/dataclaw/services/quality.py +79 -0
  190. package/extensions/services/dataclaw/services/reputation.py +142 -0
  191. package/extensions/services/dataclaw/services/sms_service.py +174 -0
  192. package/extensions/services/dataclaw/static/css/common.css +853 -0
  193. package/extensions/services/dataclaw/static/css/themes/blue.css +42 -0
  194. package/extensions/services/dataclaw/static/css/themes/dark.css +42 -0
  195. package/extensions/services/dataclaw/static/css/themes/light.css +35 -0
  196. package/extensions/services/dataclaw/static/js/api.js +103 -0
  197. package/extensions/services/dataclaw/static/js/common.js +321 -0
  198. package/extensions/services/dataclaw/static/js/i18n.js +95 -0
  199. package/extensions/services/dataclaw/static/js/pages/admin.js +152 -0
  200. package/extensions/services/dataclaw/static/js/pages/dashboard.js +82 -0
  201. package/extensions/services/dataclaw/static/js/pages/feed-detail.js +180 -0
  202. package/extensions/services/dataclaw/static/js/pages/feed-manage.js +158 -0
  203. package/extensions/services/dataclaw/static/js/theme.js +46 -0
  204. package/extensions/services/dataclaw/static/locales/en-US.json +464 -0
  205. package/extensions/services/dataclaw/static/locales/ja-JP.json +464 -0
  206. package/extensions/services/dataclaw/static/locales/zh-CN.json +464 -0
  207. package/extensions/services/dataclaw/templates/admin/index.html +90 -0
  208. package/extensions/services/dataclaw/templates/base.html +136 -0
  209. package/extensions/services/dataclaw/templates/credits/balance.html +106 -0
  210. package/extensions/services/dataclaw/templates/credits/deposit.html +164 -0
  211. package/extensions/services/dataclaw/templates/credits/history.html +90 -0
  212. package/extensions/services/dataclaw/templates/dashboard.html +52 -0
  213. package/extensions/services/dataclaw/templates/demands/create.html +78 -0
  214. package/extensions/services/dataclaw/templates/demands/detail.html +136 -0
  215. package/extensions/services/dataclaw/templates/demands/list.html +94 -0
  216. package/extensions/services/dataclaw/templates/feeds/create.html +95 -0
  217. package/extensions/services/dataclaw/templates/feeds/detail.html +110 -0
  218. package/extensions/services/dataclaw/templates/feeds/list.html +110 -0
  219. package/extensions/services/dataclaw/templates/feeds/manage.html +88 -0
  220. package/extensions/services/dataclaw/templates/index.html +185 -0
  221. package/extensions/services/dataclaw/templates/login.html +246 -0
  222. package/extensions/services/dataclaw/templates/register.html +164 -0
  223. package/extensions/services/dataclaw/templates/settings/notifications.html +96 -0
  224. package/extensions/services/dataclaw/templates/settings/profile.html +167 -0
  225. package/extensions/services/dataclaw/templates/subscriptions/list.html +64 -0
  226. package/extensions/services/dataclaw/tests/__init__.py +0 -0
  227. package/extensions/services/dataclaw/tests/conftest.py +68 -0
  228. package/extensions/services/dataclaw/tests/integration/__init__.py +0 -0
  229. package/extensions/services/dataclaw/tests/integration/test_workflows.py +239 -0
  230. package/extensions/services/dataclaw/tests/unit/__init__.py +0 -0
  231. package/extensions/services/dataclaw/tests/unit/test_admin.py +70 -0
  232. package/extensions/services/dataclaw/tests/unit/test_copyright.py +63 -0
  233. package/extensions/services/dataclaw/tests/unit/test_credits.py +80 -0
  234. package/extensions/services/dataclaw/tests/unit/test_data.py +98 -0
  235. package/extensions/services/dataclaw/tests/unit/test_demands.py +106 -0
  236. package/extensions/services/dataclaw/tests/unit/test_feeds.py +98 -0
  237. package/extensions/services/dataclaw/tests/unit/test_identity.py +88 -0
  238. package/extensions/services/dataclaw/tests/unit/test_notifications.py +36 -0
  239. package/extensions/services/dataclaw/tests/unit/test_reviews.py +68 -0
  240. package/extensions/services/dataclaw/tests/unit/test_search.py +64 -0
  241. package/extensions/services/dataclaw/tests/unit/test_subscriptions.py +65 -0
  242. package/extensions/services/dataclaw/tests/unit/test_system.py +106 -0
  243. package/extensions/services/dataclaw/utils/__init__.py +0 -0
  244. package/extensions/services/dataclaw/utils/crypto.py +38 -0
  245. package/extensions/services/dataclaw/utils/id_generator.py +52 -0
  246. package/extensions/services/dataclaw/ws/__init__.py +0 -0
  247. package/extensions/services/dataclaw/ws/handler.py +163 -0
  248. package/extensions/services/dataclaw//345/215/217/350/256/2561-/351/241/271/347/233/256/346/235/241/344/273/266/346/216/210/346/235/203/344/270/216/350/202/241/346/235/203/345/257/271/344/273/267/345/215/217/350/256/256.md +243 -0
  249. package/extensions/services/dataclaw//345/215/217/350/256/2562-/351/241/271/347/233/256/350/264/255/344/271/260/346/235/203/344/270/216/345/244/226/345/214/205/345/247/224/346/211/230/345/274/200/345/217/221/345/215/217/350/256/256.md +434 -0
  250. package/extensions/services/evol/__init__.py +1 -0
  251. package/extensions/services/evol/async_http.py +551 -0
  252. package/extensions/services/evol/auth_manager.py +602 -443
  253. package/extensions/services/evol/config.json5 +16 -0
  254. package/extensions/services/evol/entry.py +568 -406
  255. package/extensions/services/evol/evol_api.py +969 -173
  256. package/extensions/services/evol/mfa_totp.py +77 -0
  257. package/extensions/services/evol/module.md +150 -32
  258. package/extensions/services/evol/nonce_pool.py +113 -0
  259. package/extensions/services/evol/oauth_manager.py +223 -0
  260. package/extensions/services/evol/pairing.py +3 -2
  261. package/extensions/services/evol/pairing_codes.jsonl +1 -0
  262. package/extensions/services/evol/relay.py +1031 -682
  263. package/extensions/services/evol/relay_config.json5 +85 -67
  264. package/extensions/services/evol/routes/routes_llm.py +231 -0
  265. package/extensions/services/evol/routes/routes_rpc.py +90 -89
  266. package/extensions/services/evol/routes/routes_test.py +11 -4
  267. package/extensions/services/evol/server.py +2426 -875
  268. package/extensions/services/evol/static/assets/CommissionView-Cs_ys6Gm.js +1 -0
  269. package/extensions/services/evol/static/assets/CommissionView-DACet_Oo.css +1 -0
  270. package/extensions/services/evol/static/assets/IframePage-DbO11U9G.js +1 -0
  271. package/extensions/services/evol/static/assets/IframePage-c572lT8i.css +1 -0
  272. package/extensions/services/evol/static/assets/TeamDetailView-DULrGD7k.css +1 -0
  273. package/extensions/services/evol/static/assets/TeamDetailView-gy_MBEqG.js +139 -0
  274. package/extensions/services/evol/static/assets/element-plus-Bd7pZkkM.js +63 -0
  275. package/extensions/services/evol/static/assets/index-CmMONKzG.css +1 -0
  276. package/extensions/services/evol/static/assets/index-D44bBe__.js +2 -0
  277. package/extensions/services/evol/static/assets/vue-vendor-DtF-__I4.js +29 -0
  278. package/extensions/services/evol/static/index.html +16 -781
  279. package/extensions/services/evol/static/logo.png +0 -0
  280. package/extensions/services/evol/stats_manager.py +243 -240
  281. package/extensions/services/evol/web/README.md +89 -0
  282. package/extensions/services/evol/web/build.bat +44 -0
  283. package/extensions/services/evol/web/index.html +13 -0
  284. package/extensions/services/evol/web/package-lock.json +1718 -0
  285. package/extensions/services/evol/web/package.json +26 -0
  286. package/extensions/services/evol/web/public/logo.png +0 -0
  287. package/extensions/services/evol/web/src/App.vue +7 -0
  288. package/extensions/services/evol/web/src/components/layout/AppHeader.vue +202 -0
  289. package/extensions/services/evol/web/src/components/layout/AppLayout.vue +61 -0
  290. package/extensions/services/evol/web/src/components/layout/AppSidebar.vue +115 -0
  291. package/extensions/services/evol/web/src/components/login/LoginPage.vue +271 -0
  292. package/extensions/services/evol/web/src/components/team/AddMemberModal.vue +181 -0
  293. package/extensions/services/evol/web/src/components/team/GroupTreeNode.vue +156 -0
  294. package/extensions/services/evol/web/src/components/team/TeamAlertConfig.vue +221 -0
  295. package/extensions/services/evol/web/src/components/team/TeamBillModal.vue +165 -0
  296. package/extensions/services/evol/web/src/components/team/TeamMembersAndGroups.vue +499 -0
  297. package/extensions/services/evol/web/src/components/team/TeamStatsPanel.vue +907 -0
  298. package/extensions/services/evol/web/src/components/team/TreeNode.vue +331 -0
  299. package/extensions/services/evol/web/src/components/team/stats/StatsExportProgress.vue +44 -0
  300. package/extensions/services/evol/web/src/components/team/stats/StatsHeader.vue +89 -0
  301. package/extensions/services/evol/web/src/components/team/stats/StatsMemberDetail.vue +415 -0
  302. package/extensions/services/evol/web/src/components/team/stats/StatsSummary.vue +42 -0
  303. package/extensions/services/evol/web/src/components/team/stats/helpers.ts +195 -0
  304. package/extensions/services/evol/web/src/components/team/stats/stats.css +741 -0
  305. package/extensions/services/evol/web/src/components/team/stats/useStatsApi.ts +114 -0
  306. package/extensions/services/evol/web/src/components/team/stats/useStatsCharts.ts +242 -0
  307. package/extensions/services/evol/web/src/components/team/stats/useStatsExport.ts +232 -0
  308. package/extensions/services/evol/web/src/composables/useFormatters.ts +42 -0
  309. package/extensions/services/evol/web/src/composables/useTheme.ts +52 -0
  310. package/extensions/services/evol/web/src/env.d.ts +7 -0
  311. package/extensions/services/evol/web/src/i18n/en.ts +361 -0
  312. package/extensions/services/evol/web/src/i18n/index.ts +36 -0
  313. package/extensions/services/evol/web/src/i18n/zh.ts +379 -0
  314. package/extensions/services/evol/web/src/main.ts +21 -0
  315. package/extensions/services/evol/web/src/router/index.ts +81 -0
  316. package/extensions/services/evol/web/src/services/kernel-client.ts +406 -0
  317. package/extensions/services/evol/web/src/stores/auth.ts +189 -0
  318. package/extensions/services/evol/web/src/stores/connection.ts +134 -0
  319. package/extensions/services/evol/web/src/stores/pages.ts +79 -0
  320. package/extensions/services/evol/web/src/styles/base.css +213 -0
  321. package/extensions/services/evol/web/src/styles/variables.css +138 -0
  322. package/extensions/services/evol/web/src/types/rpc.ts +35 -0
  323. package/extensions/services/evol/web/src/types/token.ts +87 -0
  324. package/extensions/services/evol/web/src/views/AccountView.vue +1532 -0
  325. package/extensions/services/evol/web/src/views/AiServiceView.vue +219 -0
  326. package/extensions/services/evol/web/src/views/CommissionView.vue +1220 -0
  327. package/extensions/services/evol/web/src/views/CreditsView.vue +131 -0
  328. package/extensions/services/evol/web/src/views/EndpointView.vue +163 -0
  329. package/extensions/services/evol/web/src/views/IframePage.vue +120 -0
  330. package/extensions/services/evol/web/src/views/TeamDetailView.vue +473 -0
  331. package/extensions/services/evol/web/src/views/TeamView.vue +332 -0
  332. package/extensions/services/evol/web/tsconfig.json +31 -0
  333. package/extensions/services/evol/web/tsconfig.node.json +10 -0
  334. package/extensions/services/evol/web/vite.config.ts +49 -0
  335. package/extensions/services/evolmem/__init__.py +0 -0
  336. package/extensions/services/evolmem/entry.py +387 -0
  337. package/extensions/services/evolmem/hooks/__init__.py +0 -0
  338. package/extensions/services/evolmem/hooks/assistant_stop.py +228 -0
  339. package/extensions/services/evolmem/hooks/common.py +76 -0
  340. package/extensions/services/evolmem/hooks/pre_tool_use.py +56 -0
  341. package/extensions/services/evolmem/hooks/session_end.py +133 -0
  342. package/extensions/services/evolmem/hooks/session_start.py +229 -0
  343. package/extensions/services/evolmem/hooks/user_prompt.py +122 -0
  344. package/extensions/services/evolmem/module.md +48 -0
  345. package/extensions/services/evolmem/prompts/00-server-info.md +28 -0
  346. package/extensions/services/evolmem/prompts/01-behavior.md +46 -0
  347. package/extensions/services/evolmem/prompts/02-summary-format.md +112 -0
  348. package/extensions/services/evolmem/prompts/03-file-query.md +92 -0
  349. package/extensions/services/evolmem/prompts/04-topic-stats.md +11 -0
  350. package/extensions/services/evolmem/prompts/05-recent-topics.md +84 -0
  351. package/extensions/services/evolmem/scripts/__init__.py +0 -0
  352. package/extensions/services/evolmem/scripts/extract_keywords.py +40 -0
  353. package/extensions/services/evolmem/scripts/search_topics.py +91 -0
  354. package/extensions/services/evolmem/server.py +641 -0
  355. package/extensions/services/gateway/entry.py +964 -0
  356. package/extensions/services/gateway/module.md +29 -0
  357. package/extensions/services/gateway/nonce_pool.py +65 -0
  358. package/extensions/services/gateway/relay.py +133 -0
  359. package/extensions/services/gateway/ws_server.py +285 -0
  360. package/extensions/services/kite_console/auth_manager.py +603 -0
  361. package/extensions/services/kite_console/config.json5 +19 -0
  362. package/extensions/services/kite_console/config_loader.py +117 -0
  363. package/extensions/services/kite_console/entry.py +528 -0
  364. package/extensions/services/kite_console/evol_api.py +179 -0
  365. package/extensions/services/kite_console/evol_config.json5 +29 -0
  366. package/extensions/services/kite_console/mfa_totp.py +77 -0
  367. package/extensions/services/kite_console/migrate_tokens.py +122 -0
  368. package/extensions/services/kite_console/module.md +37 -0
  369. package/extensions/services/kite_console/nonce_pool.py +113 -0
  370. package/extensions/services/kite_console/oauth_manager.py +223 -0
  371. package/extensions/services/kite_console/pairing.py +280 -0
  372. package/extensions/services/kite_console/pairing_codes.jsonl +2 -0
  373. package/extensions/services/kite_console/relay.py +1350 -0
  374. package/extensions/services/kite_console/relay_config.json5 +96 -0
  375. package/extensions/services/kite_console/routes/__init__.py +1 -0
  376. package/extensions/services/kite_console/routes/routes_llm.py +231 -0
  377. package/extensions/services/kite_console/routes/routes_proxy.py +115 -0
  378. package/extensions/services/kite_console/routes/routes_rpc.py +89 -0
  379. package/extensions/services/kite_console/routes/routes_test.py +68 -0
  380. package/extensions/services/kite_console/server.py +1742 -0
  381. package/extensions/services/{evol → kite_console}/static/css/style.css +656 -2
  382. package/extensions/services/kite_console/static/index.html +1524 -0
  383. package/extensions/services/{evol → kite_console}/static/js/dialog.js +11 -4
  384. package/extensions/services/kite_console/static/js/evol-app.js +7740 -0
  385. package/extensions/services/{evol/static/js/evol-app.js → kite_console/static/js/evol-app.js.backup} +2777 -1949
  386. package/extensions/services/kite_console/static/js/kernel-client.js +560 -0
  387. package/extensions/services/{evol/static/js/kernel-client.js → kite_console/static/js/kernel-client.js.backup} +41 -3
  388. package/extensions/services/{evol → kite_console}/static/js/registry-tests.js +7 -0
  389. package/extensions/services/kite_console/static/js/tests/ARCHITECTURE.md +67 -0
  390. package/extensions/services/kite_console/static/js/tests/README.md +140 -0
  391. package/extensions/services/kite_console/static/js/tests/index.js +161 -0
  392. package/extensions/services/kite_console/static/js/tests/integration/auth.js +120 -0
  393. package/extensions/services/kite_console/static/js/tests/integration/channel-interaction.js +188 -0
  394. package/extensions/services/kite_console/static/js/tests/integration/elastic-connection.js +115 -0
  395. package/extensions/services/kite_console/static/js/tests/integration/full-workflow.js +43 -0
  396. package/extensions/services/kite_console/static/js/tests/integration/multi-instance.js +304 -0
  397. package/extensions/services/kite_console/static/js/tests/integration/nested-rpc.js +266 -0
  398. package/extensions/services/kite_console/static/js/tests/integration/pingpong.js +25 -0
  399. package/extensions/services/kite_console/static/js/tests/integration/redis.js +227 -0
  400. package/extensions/services/kite_console/static/js/tests/integration/registry-core.js +52 -0
  401. package/extensions/services/kite_console/static/js/tests/integration/remote-deploy.js +85 -0
  402. package/extensions/services/kite_console/static/js/tests/integration/require-init.js +96 -0
  403. package/extensions/services/kite_console/static/js/tests/integration/scaling-control.js +193 -0
  404. package/extensions/services/kite_console/static/js/tests/integration/trace.js +109 -0
  405. package/extensions/services/kite_console/static/js/tests/modules/acp_channel.js +339 -0
  406. package/extensions/services/kite_console/static/js/tests/modules/auth.js +96 -0
  407. package/extensions/services/kite_console/static/js/tests/modules/backup.js +49 -0
  408. package/extensions/services/kite_console/static/js/tests/modules/gateway.js +41 -0
  409. package/extensions/services/kite_console/static/js/tests/modules/kernel.js +90 -0
  410. package/extensions/services/kite_console/static/js/tests/modules/launcher.js +75 -0
  411. package/extensions/services/kite_console/static/js/tests/modules/multi_instance.js +129 -0
  412. package/extensions/services/kite_console/static/js/tests/modules/phone_channel.js +364 -0
  413. package/extensions/services/kite_console/static/js/tests/modules/redis.js +178 -0
  414. package/extensions/services/kite_console/static/js/tests/modules/watchdog.js +60 -0
  415. package/extensions/services/kite_console/static/js/tests/modules/web.js +70 -0
  416. package/extensions/services/kite_console/static/js/tests/test-runner.js +123 -0
  417. package/extensions/services/kite_console/static/js/virtual-list.js +200 -0
  418. package/extensions/services/kite_console/static/test_kernel_client_token.html +352 -0
  419. package/extensions/services/kite_console/stats_manager.py +247 -0
  420. package/extensions/services/logs/README.md +215 -0
  421. package/extensions/services/logs/api_logger.py +37 -0
  422. package/extensions/services/logs/baseline.py +121 -0
  423. package/extensions/services/logs/cleaner.py +76 -0
  424. package/extensions/services/logs/entry.py +449 -0
  425. package/extensions/services/logs/formatter.py +129 -0
  426. package/extensions/services/logs/module.md +38 -0
  427. package/extensions/services/logs/quick_diagnostic.py +128 -0
  428. package/extensions/services/logs/routes/__init__.py +1 -0
  429. package/extensions/services/logs/routes/routes_logs.py +218 -0
  430. package/extensions/services/logs/routes/routes_logs.py.backup +173 -0
  431. package/extensions/services/logs/scanner.py +100 -0
  432. package/extensions/services/logs/searcher.py +263 -0
  433. package/extensions/services/logs/server.py +553 -0
  434. package/extensions/services/logs.zip +0 -0
  435. package/extensions/services/model_service/config.json5 +30 -0
  436. package/extensions/services/model_service/entry.py +620 -171
  437. package/extensions/services/model_service/module.md +11 -2
  438. package/extensions/services/proxy/__init__.py +0 -0
  439. package/extensions/services/proxy/aid_manager.py +419 -0
  440. package/extensions/services/proxy/auth_bridge.py +182 -0
  441. package/extensions/services/proxy/config_store.py +79 -0
  442. package/extensions/services/proxy/entry.py +528 -0
  443. package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +2 -2
  444. package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +18 -28
  445. package/extensions/services/proxy/evol/presenter/configPresenter.py +80 -1127
  446. package/extensions/services/proxy/evol/presenter/userPresenter.py +71 -477
  447. package/extensions/services/proxy/evol/server/claude_proxy_async.py +11 -7
  448. package/extensions/services/proxy/module.md +151 -0
  449. package/extensions/services/proxy/server.py +952 -271
  450. package/extensions/services/redis/ALIGNMENT_CHECKLIST.md +121 -0
  451. package/extensions/services/redis/ALIGNMENT_STATUS.md +548 -0
  452. package/extensions/services/redis/config.json5 +8 -0
  453. package/extensions/services/redis/entry.py +1509 -0
  454. package/extensions/services/redis/entry.py.backup +405 -0
  455. package/extensions/services/redis/module.md +48 -0
  456. package/extensions/services/redis/redis_builtin.py +332 -0
  457. package/extensions/services/redis/redis_external.py +164 -0
  458. package/extensions/services/testUi/entry.py +446 -0
  459. package/extensions/services/testUi/module.md +18 -0
  460. package/extensions/services/testUi/ui/cards.html +131 -0
  461. package/extensions/services/testUi/ui/index.html +22 -0
  462. package/extensions/services/testUi/ui/particles.html +143 -0
  463. package/extensions/services/watchdog/entry.py +1258 -793
  464. package/extensions/services/watchdog/module.md +2 -0
  465. package/extensions/services/watchdog/monitor.py +465 -87
  466. package/extensions/services/web/auth_manager.py +602 -0
  467. package/extensions/services/web/config.json5 +11 -0
  468. package/extensions/services/web/entry.py +598 -478
  469. package/extensions/services/web/mfa_totp.py +77 -0
  470. package/extensions/services/web/module.md +16 -13
  471. package/extensions/services/web/nonce_pool.py +113 -0
  472. package/extensions/services/web/oauth_manager.py +223 -0
  473. package/extensions/services/web/pairing.py +3 -2
  474. package/extensions/services/web/pairing_codes.jsonl +1 -0
  475. package/extensions/services/web/relay.py +442 -63
  476. package/extensions/services/web/relay_config.json5 +1 -2
  477. package/extensions/services/web/routes/routes_rpc.py +6 -6
  478. package/extensions/services/web/server.py +360 -173
  479. package/extensions/services/web/static/index.html +1752 -1738
  480. package/extensions/services/web/static/js/app.js +32 -0
  481. package/extensions/services/web/static/js/kernel-client.js +48 -9
  482. package/extensions/services/web/vendor/bluetooth/audio.py +1 -1
  483. package/extensions/services/web/vendor/config.py +2 -2
  484. package/extensions/services/web/vendor/storage/identity.py +1 -1
  485. package/kernel/entry.py +77 -23
  486. package/kernel/event_hub.py +1122 -74
  487. package/kernel/module.md +2 -1
  488. package/kernel/registry_store.py +208 -11
  489. package/kernel/rpc_router.py +1400 -491
  490. package/kernel/server.py +1021 -134
  491. package/kite_cli/builders/__init__.py +4 -0
  492. package/kite_cli/builders/base.py +67 -0
  493. package/kite_cli/builders/custom.py +31 -0
  494. package/kite_cli/builders/detector.py +56 -0
  495. package/kite_cli/builders/go.py +34 -0
  496. package/kite_cli/builders/gradle.py +41 -0
  497. package/kite_cli/builders/maven.py +36 -0
  498. package/kite_cli/builders/npm.py +44 -0
  499. package/kite_cli/builders/python.py +37 -0
  500. package/kite_cli/commands/BUILD_GUIDE.md +109 -0
  501. package/kite_cli/commands/build.py +142 -0
  502. package/kite_cli/commands/check.py +60 -0
  503. package/kite_cli/commands/config.py +156 -0
  504. package/kite_cli/commands/deps.py +58 -0
  505. package/kite_cli/commands/deps_install.py +7 -7
  506. package/kite_cli/commands/disable.py +162 -0
  507. package/kite_cli/commands/enable.py +162 -0
  508. package/kite_cli/commands/export.py +96 -0
  509. package/kite_cli/commands/import_cmd.py +110 -0
  510. package/kite_cli/commands/install.py +50 -23
  511. package/kite_cli/commands/install_skill.py +107 -0
  512. package/kite_cli/commands/list.py +128 -31
  513. package/kite_cli/commands/outdated.py +202 -0
  514. package/kite_cli/commands/search.py +33 -17
  515. package/kite_cli/commands/update.py +115 -2
  516. package/kite_cli/commands/venv_setup.py +6 -6
  517. package/kite_cli/commands/why.py +48 -0
  518. package/kite_cli/core/config_manager.py +145 -0
  519. package/kite_cli/core/downloader.py +32 -2
  520. package/kite_cli/main.py +151 -5
  521. package/kite_cli/utils/colors.py +153 -0
  522. package/kite_cli/utils/dependency_graph.py +209 -0
  523. package/kite_cli/utils/process.py +55 -0
  524. package/kite_cli/utils/progress.py +207 -0
  525. package/kite_cli/utils/table.py +101 -0
  526. package/launcher/count_lines.py +192 -43
  527. package/launcher/entry.py +4543 -2802
  528. package/launcher/logging_setup.py +54 -1
  529. package/launcher/module.md +32 -6
  530. package/launcher/module_scanner.py +93 -20
  531. package/launcher/process_manager.py +355 -76
  532. package/main.py +6 -0
  533. package/package.json +4 -1
  534. package/requirements.txt +41 -38
  535. package/scripts/auto-fix-deps.py +128 -0
  536. package/scripts/env-manager.js +25 -2
  537. package/scripts/final-test.js +78 -0
  538. package/scripts/setup-python-env.js +700 -191
  539. package/scripts/test-alluser.js +48 -0
  540. package/scripts/test-different-version.js +86 -0
  541. package/scripts/test-direct.js +63 -0
  542. package/scripts/test-extract-installer.js +28 -0
  543. package/scripts/test-install-log.js +54 -0
  544. package/scripts/test-installer.js +39 -0
  545. package/scripts/test-integration.js +250 -0
  546. package/scripts/test-real-install.js +210 -0
  547. package/scripts/test-targetdir.js +49 -0
  548. package/scripts/test-venv-real.js +47 -0
  549. package/scripts/test-venv-simple.js +57 -0
  550. package/scripts/test-wait.js +49 -0
  551. package/scripts/test-with-log.js +63 -0
  552. package/extensions/services/evol/config.yaml +0 -149
  553. package/extensions/services/evol/routes/routes_management_ws.py +0 -127
  554. package/extensions/services/evol/static/index_evol.html +0 -14
  555. package/extensions/services/evol/static/js/app.js +0 -6304
  556. package/extensions/services/evol/static/js/auth.js +0 -326
  557. package/extensions/services/evol/static/js/evol-app-fixed.js +0 -50
  558. package/extensions/services/evol/static/js/evol-app.js.bak +0 -1800
  559. package/extensions/services/evol/static/js/kernel-client-example.js +0 -228
  560. package/extensions/services/evol/static/js/main.js +0 -141
  561. package/extensions/services/evol/static/js/stats.js +0 -217
  562. package/extensions/services/evol/static/js/token-manager.js +0 -175
  563. package/extensions/services/proxy/CHANGELOG_20260308.md +0 -258
  564. package/extensions/services/proxy/_fix_prints.py +0 -133
  565. package/extensions/services/proxy/_fix_prints2.py +0 -87
  566. package/extensions/services/proxy/console_auth.py +0 -109
  567. package/extensions/services/proxy/logs/websocket.log +0 -260
  568. package/extensions/services/proxy/main.py +0 -240
  569. package/extensions/services/proxy/requirements.txt +0 -13
  570. package/extensions/services/web/config.yaml +0 -149
  571. /package/extensions/services/{evol → kite_console}/static/pairing.html +0 -0
  572. /package/extensions/services/{evol → kite_console}/static/test_registry.html +0 -0
  573. /package/extensions/services/{evol → kite_console}/static/test_relay.html +0 -0
@@ -1,1738 +1,1752 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AI Phone Agent</title>
7
- <link rel="stylesheet" href="css/style.css?v=41">
8
- </head>
9
- <body>
10
-
11
- <!-- ===== Top Header Bar ===== -->
12
- <header id="app-header">
13
- <div class="header-left">
14
- <button id="sidebar-toggle" class="icon-btn" title="Toggle Sidebar">&#9776;</button>
15
- <h1 class="header-title">AI Phone Agent</h1>
16
- </div>
17
- <div class="header-right">
18
- <span id="ws-indicator" style="font-size:13px;color:var(--gray-400);margin-right:16px;" title="Kite 连接状态">○ 未连线</span>
19
- <span id="header-bt-status" class="bt-indicator" title="Bluetooth Status">
20
- <span class="bt-icon">BT</span>
21
- <span class="bt-label">未连接</span>
22
- </span>
23
- </div>
24
- </header>
25
-
26
- <!-- ===== Layout Container ===== -->
27
- <div id="app-layout">
28
-
29
- <!-- ===== Left Sidebar Navigation ===== -->
30
- <nav id="sidebar">
31
- <ul class="nav-list">
32
- <li class="nav-item active" data-page="dashboard">
33
- <span class="nav-label">仪表盘</span>
34
- <span class="nav-sublabel">Dashboard</span>
35
- </li>
36
- <li class="nav-item" data-page="calls">
37
- <span class="nav-label">通话</span>
38
- <span class="nav-sublabel">Calls</span>
39
- </li>
40
- <li class="nav-item" data-page="sms">
41
- <span class="nav-label">短信</span>
42
- <span class="nav-sublabel">SMS</span>
43
- </li>
44
- <li class="nav-item" data-page="contacts">
45
- <span class="nav-label">联系人</span>
46
- <span class="nav-sublabel">Contacts</span>
47
- </li>
48
- <li class="nav-item" data-page="config">
49
- <span class="nav-label">配置</span>
50
- <span class="nav-sublabel">Config</span>
51
- </li>
52
- <li class="nav-item" data-page="bluetooth">
53
- <span class="nav-label">蓝牙</span>
54
- <span class="nav-sublabel">Bluetooth</span>
55
- </li>
56
- <li class="nav-item" data-page="modules">
57
- <span class="nav-label">模块</span>
58
- <span class="nav-sublabel">Modules</span>
59
- </li>
60
- <li class="nav-item" data-page="voicechat">
61
- <span class="nav-label">语音测试</span>
62
- <span class="nav-sublabel">Voice Chat</span>
63
- </li>
64
- <li class="nav-item" data-page="devlog">
65
- <span class="nav-label">开发记录</span>
66
- <span class="nav-sublabel">Dev Log</span>
67
- </li>
68
- </ul>
69
- </nav>
70
-
71
- <!-- ===== Main Content Area ===== -->
72
- <main id="main-content">
73
-
74
- <!-- ==================== Dashboard ==================== -->
75
- <section id="page-dashboard" class="page active">
76
- <h2 class="page-title">仪表盘</h2>
77
-
78
- <!-- Stats Cards -->
79
- <div class="stats-row">
80
- <div class="stat-card">
81
- <div class="stat-value" id="stat-total-calls">0</div>
82
- <div class="stat-label">总通话数</div>
83
- </div>
84
- <div class="stat-card">
85
- <div class="stat-value" id="stat-today-calls">0</div>
86
- <div class="stat-label">今日通话</div>
87
- </div>
88
- <div class="stat-card">
89
- <div class="stat-value" id="stat-avg-duration">0s</div>
90
- <div class="stat-label">平均时长</div>
91
- </div>
92
- <div class="stat-card">
93
- <div class="stat-value" id="stat-total-contacts">0</div>
94
- <div class="stat-label">联系人数</div>
95
- </div>
96
- </div>
97
-
98
- <!-- Calls by Result Breakdown -->
99
- <div class="panel">
100
- <h3 class="panel-title">通话结果分布</h3>
101
- <ul id="calls-result-breakdown" class="breakdown-list">
102
- <li><span class="breakdown-label">已完成</span><span class="breakdown-value" id="breakdown-completed">0</span></li>
103
- <li><span class="breakdown-label">未接听</span><span class="breakdown-value" id="breakdown-no-answer">0</span></li>
104
- <li><span class="breakdown-label">占线</span><span class="breakdown-value" id="breakdown-busy">0</span></li>
105
- <li><span class="breakdown-label">失败</span><span class="breakdown-value" id="breakdown-failed">0</span></li>
106
- <li><span class="breakdown-label">进行中</span><span class="breakdown-value" id="breakdown-in-progress">0</span></li>
107
- </ul>
108
- </div>
109
-
110
- <!-- Recent Calls Table -->
111
- <div class="panel">
112
- <h3 class="panel-title">最近通话</h3>
113
- <div class="table-wrapper">
114
- <table class="data-table" id="dashboard-recent-calls">
115
- <thead>
116
- <tr>
117
- <th>时间</th>
118
- <th>联系人/号码</th>
119
- <th>方向</th>
120
- <th>时长</th>
121
- <th>结果</th>
122
- </tr>
123
- </thead>
124
- <tbody>
125
- <!-- Populated by JS -->
126
- </tbody>
127
- </table>
128
- </div>
129
- </div>
130
- </section>
131
-
132
- <!-- ==================== Calls ==================== -->
133
- <section id="page-calls" class="page">
134
- <h2 class="page-title">通话</h2>
135
-
136
- <!-- Calls List View -->
137
- <div id="calls-list-view">
138
- <div class="page-actions">
139
- <button class="btn btn-primary" id="btn-new-call">新建通话</button>
140
- </div>
141
-
142
- <!-- New Call Form (inline, hidden by default) -->
143
- <div id="new-call-form" class="form-section hidden">
144
- <h3 class="form-title">新建通话</h3>
145
- <form id="form-new-call">
146
- <div class="form-group">
147
- <label for="call-phone">电话号码 (可选)</label>
148
- <input type="tel" id="call-phone" name="phone" placeholder="输入电话号码">
149
- </div>
150
- <div class="form-group">
151
- <label for="call-purpose">通话目的 <span class="required">*</span></label>
152
- <textarea id="call-purpose" name="purpose" rows="3" placeholder="描述通话目的" required></textarea>
153
- </div>
154
- <div class="form-group">
155
- <label for="call-system-prompt">系统提示词 (可选)</label>
156
- <textarea id="call-system-prompt" name="system_prompt" rows="4" placeholder="自定义系统提示词"></textarea>
157
- </div>
158
- <div class="form-group">
159
- <label for="call-play-text">播放文本 (可选)</label>
160
- <textarea id="call-play-text" name="play_text" rows="3" placeholder="通话开始时播放的文本"></textarea>
161
- </div>
162
- <div class="form-group">
163
- <label for="call-webhook">Webhook URL (可选)</label>
164
- <input type="url" id="call-webhook" name="webhook_url" placeholder="https://example.com/webhook">
165
- </div>
166
- <div class="form-group">
167
- <label for="call-max-duration">最大时长: <span id="call-max-duration-value">300</span>秒</label>
168
- <input type="range" id="call-max-duration" name="max_duration" min="60" max="600" value="300" step="10">
169
- </div>
170
- <div class="form-actions">
171
- <button type="submit" class="btn btn-primary">发起通话</button>
172
- <button type="button" class="btn btn-secondary" id="btn-cancel-new-call">取消</button>
173
- </div>
174
- </form>
175
- </div>
176
-
177
- <!-- Calls History Table -->
178
- <div class="panel">
179
- <div class="table-wrapper">
180
- <table class="data-table" id="calls-history-table">
181
- <thead>
182
- <tr>
183
- <th>时间</th>
184
- <th>联系人/号码</th>
185
- <th>方向</th>
186
- <th>时长</th>
187
- <th>结果</th>
188
- <th>操作</th>
189
- </tr>
190
- </thead>
191
- <tbody>
192
- <!-- Populated by JS -->
193
- </tbody>
194
- </table>
195
- </div>
196
- <!-- Pagination -->
197
- <div class="pagination" id="calls-pagination">
198
- <button class="btn btn-sm" id="calls-prev" disabled>上一页</button>
199
- <span class="pagination-info" id="calls-page-info">第 1 页</span>
200
- <button class="btn btn-sm" id="calls-next">下一页</button>
201
- </div>
202
- </div>
203
- </div>
204
-
205
- <!-- Call Detail View (hidden by default) -->
206
- <div id="call-detail-view" class="hidden">
207
- <div class="page-actions">
208
- <button class="btn btn-secondary" id="btn-back-to-calls">&larr; 返回列表</button>
209
- </div>
210
-
211
- <!-- Call Info Header -->
212
- <div class="panel" id="call-detail-header">
213
- <div class="call-info-grid">
214
- <div class="call-info-item">
215
- <span class="info-label">电话号码</span>
216
- <span class="info-value" id="detail-phone">--</span>
217
- </div>
218
- <div class="call-info-item">
219
- <span class="info-label">联系人</span>
220
- <span class="info-value" id="detail-contact">--</span>
221
- </div>
222
- <div class="call-info-item">
223
- <span class="info-label">方向</span>
224
- <span class="info-value" id="detail-direction">--</span>
225
- </div>
226
- <div class="call-info-item">
227
- <span class="info-label">时间</span>
228
- <span class="info-value" id="detail-time">--</span>
229
- </div>
230
- <div class="call-info-item">
231
- <span class="info-label">时长</span>
232
- <span class="info-value" id="detail-duration">--</span>
233
- </div>
234
- <div class="call-info-item">
235
- <span class="info-label">结果</span>
236
- <span class="info-value" id="detail-result">--</span>
237
- </div>
238
- </div>
239
- </div>
240
-
241
- <!-- Summary -->
242
- <div class="panel">
243
- <h3 class="panel-title">通话摘要</h3>
244
- <div id="detail-summary" class="summary-content">
245
- <p class="text-muted">暂无摘要</p>
246
- </div>
247
- </div>
248
-
249
- <!-- Transcript -->
250
- <div class="panel">
251
- <h3 class="panel-title">通话记录</h3>
252
- <div id="detail-transcript" class="transcript-container">
253
- <!-- Chat-style transcript: AI messages right, human messages left -->
254
- </div>
255
- </div>
256
-
257
- <!-- Audio Player -->
258
- <div class="panel">
259
- <h3 class="panel-title">通话录音</h3>
260
- <div id="detail-audio-container">
261
- <audio id="detail-audio" controls>
262
- <source src="" type="audio/wav">
263
- 您的浏览器不支持音频播放
264
- </audio>
265
- <p class="text-muted" id="detail-no-audio">暂无录音</p>
266
- </div>
267
- </div>
268
-
269
- <!-- MCP Tool Calls -->
270
- <div class="panel">
271
- <h3 class="panel-title">MCP 工具调用</h3>
272
- <div id="detail-tool-calls" class="tool-calls-container">
273
- <p class="text-muted">暂无工具调用记录</p>
274
- </div>
275
- </div>
276
- </div>
277
- </section>
278
-
279
- <!-- ==================== SMS ==================== -->
280
- <section id="page-sms" class="page">
281
- <h2 class="page-title">短信</h2>
282
-
283
- <div class="page-actions">
284
- <button class="btn btn-primary" id="btn-new-sms">新建短信</button>
285
- </div>
286
-
287
- <!-- New SMS Form (hidden by default) -->
288
- <div id="new-sms-form" class="form-section hidden">
289
- <h3 class="form-title">发送短信</h3>
290
- <form id="form-new-sms">
291
- <div class="form-group">
292
- <label for="sms-phone">电话号码 <span class="required">*</span></label>
293
- <input type="tel" id="sms-phone" name="phone" placeholder="输入电话号码" required>
294
- </div>
295
- <div class="form-group">
296
- <label for="sms-content">短信内容 <span class="required">*</span></label>
297
- <textarea id="sms-content" name="content" rows="4" placeholder="输入短信内容" required></textarea>
298
- </div>
299
- <div class="form-actions">
300
- <button type="submit" class="btn btn-primary">发送</button>
301
- <button type="button" class="btn btn-secondary" id="btn-cancel-new-sms">取消</button>
302
- </div>
303
- </form>
304
- </div>
305
-
306
- <!-- SMS List -->
307
- <div class="panel">
308
- <div class="table-wrapper">
309
- <table class="data-table" id="sms-table">
310
- <thead>
311
- <tr>
312
- <th>时间</th>
313
- <th>联系人/号码</th>
314
- <th>方向</th>
315
- <th>内容预览</th>
316
- </tr>
317
- </thead>
318
- <tbody>
319
- <!-- Populated by JS -->
320
- </tbody>
321
- </table>
322
- </div>
323
- <!-- Pagination -->
324
- <div class="pagination" id="sms-pagination">
325
- <button class="btn btn-sm" id="sms-prev" disabled>上一页</button>
326
- <span class="pagination-info" id="sms-page-info">第 1 页</span>
327
- <button class="btn btn-sm" id="sms-next">下一页</button>
328
- </div>
329
- </div>
330
- </section>
331
-
332
- <!-- ==================== Contacts ==================== -->
333
- <section id="page-contacts" class="page">
334
- <h2 class="page-title">联系人</h2>
335
-
336
- <div class="page-actions">
337
- <button class="btn btn-primary" id="btn-add-contact">添加联系人</button>
338
- <button class="btn btn-secondary" id="btn-sync-contacts">从手机同步</button>
339
- <div class="search-box">
340
- <input type="text" id="contacts-search" placeholder="搜索联系人...">
341
- </div>
342
- </div>
343
-
344
- <!-- Add / Edit Contact Form (hidden by default) -->
345
- <div id="contact-form-section" class="form-section hidden">
346
- <h3 class="form-title" id="contact-form-title">添加联系人</h3>
347
- <form id="form-contact">
348
- <input type="hidden" id="contact-id" name="id" value="">
349
- <div class="form-row">
350
- <div class="form-group">
351
- <label for="contact-name">姓名 <span class="required">*</span></label>
352
- <input type="text" id="contact-name" name="name" placeholder="输入姓名" required>
353
- </div>
354
- <div class="form-group">
355
- <label for="contact-phone">电话号码 <span class="required">*</span></label>
356
- <input type="tel" id="contact-phone" name="phone" placeholder="输入电话号码" required>
357
- </div>
358
- </div>
359
- <div class="form-row">
360
- <div class="form-group">
361
- <label for="contact-company">公司</label>
362
- <input type="text" id="contact-company" name="company" placeholder="输入公司名称">
363
- </div>
364
- <div class="form-group">
365
- <label for="contact-title">职务</label>
366
- <input type="text" id="contact-title" name="title" placeholder="输入职务">
367
- </div>
368
- </div>
369
- <div class="form-group">
370
- <label for="contact-notes">备注</label>
371
- <textarea id="contact-notes" name="notes" rows="3" placeholder="输入备注信息"></textarea>
372
- </div>
373
- <div class="form-group">
374
- <label for="contact-tags">标签 (逗号分隔)</label>
375
- <input type="text" id="contact-tags" name="tags" placeholder="例如: 客户, VIP, 供应商">
376
- </div>
377
- <div class="form-actions">
378
- <button type="submit" class="btn btn-primary" id="contact-submit-btn">保存</button>
379
- <button type="button" class="btn btn-secondary" id="btn-cancel-contact">取消</button>
380
- </div>
381
- </form>
382
- </div>
383
-
384
- <!-- Contacts Table -->
385
- <div class="panel">
386
- <div class="table-wrapper">
387
- <table class="data-table" id="contacts-table">
388
- <thead>
389
- <tr>
390
- <th>姓名</th>
391
- <th>电话</th>
392
- <th>公司</th>
393
- <th>标签</th>
394
- <th>操作</th>
395
- </tr>
396
- </thead>
397
- <tbody>
398
- <!-- Populated by JS -->
399
- </tbody>
400
- </table>
401
- </div>
402
- </div>
403
- </section>
404
-
405
- <!-- ==================== Config ==================== -->
406
- <section id="page-config" class="page">
407
- <h2 class="page-title">配置 <span id="config-save-status" class="config-save-status"></span></h2>
408
-
409
- <form id="form-config">
410
- <!-- Basic Info -->
411
- <div class="panel">
412
- <h3 class="panel-title">基础信息</h3>
413
-
414
- <!-- AI Phone Number -->
415
- <div class="form-group">
416
- <label>AI 电话号码</label>
417
- <div class="tag-list" id="ai-phone-list"></div>
418
- <div class="tag-input-row">
419
- <input type="text" id="ai-phone-input" placeholder="输入号码后回车添加" class="tag-input">
420
- <button type="button" class="btn btn-sm" id="btn-add-ai-phone">添加</button>
421
- </div>
422
- <p class="form-hint">标记 <span class="badge badge-primary">当前</span> 的号码为 AI 正在使用的号码,点击其他号码可切换</p>
423
- </div>
424
-
425
- <!-- Owners -->
426
- <div class="form-group">
427
- <label>主人号码</label>
428
- <div class="owner-list" id="owner-list"></div>
429
- <div class="owner-add-row">
430
- <input type="text" id="owner-phone-input" placeholder="号码" class="owner-input owner-input-phone">
431
- <input type="text" id="owner-name-input" placeholder="姓名" class="owner-input owner-input-name">
432
- <input type="text" id="owner-note-input" placeholder="备注(可选)" class="owner-input owner-input-note">
433
- <button type="button" class="btn btn-sm" id="btn-add-owner">添加</button>
434
- </div>
435
- </div>
436
- </div>
437
-
438
- <!-- LLM Configuration -->
439
- <div class="panel">
440
- <h3 class="panel-title">LLM 配置</h3>
441
-
442
- <!-- Provider Tabs -->
443
- <div class="provider-tabs" id="llm-provider-tabs">
444
- <button type="button" class="provider-tab active" data-provider="openai">OpenAI</button>
445
- <button type="button" class="provider-tab" data-provider="claude">Claude</button>
446
- <button type="button" class="provider-tab" data-provider="gemini">Gemini</button>
447
- </div>
448
-
449
- <!-- OpenAI Config -->
450
- <div class="provider-config active" id="provider-openai">
451
- <div class="form-group">
452
- <label for="openai-base-url">Base URL</label>
453
- <input type="url" id="openai-base-url" name="openai_base_url" placeholder="https://api.openai.com/v1" value="https://api.openai.com/v1">
454
- </div>
455
- <div class="form-group">
456
- <label for="openai-api-key">API Key</label>
457
- <input type="text" id="openai-api-key" name="openai_api_key" placeholder="sk-...">
458
- </div>
459
- <div class="form-group">
460
- <label for="openai-model">模型</label>
461
- <div class="input-with-btn">
462
- <select id="openai-model" name="openai_model">
463
- <option value="gpt-4o">gpt-4o</option>
464
- <option value="gpt-4o-mini">gpt-4o-mini</option>
465
- <option value="gpt-4-turbo">gpt-4-turbo</option>
466
- <option value="gpt-3.5-turbo">gpt-3.5-turbo</option>
467
- </select>
468
- <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="openai">刷新模型</button>
469
- </div>
470
- </div>
471
- </div>
472
-
473
- <!-- Claude Config -->
474
- <div class="provider-config" id="provider-claude">
475
- <div class="form-group">
476
- <label for="claude-base-url">Base URL</label>
477
- <input type="url" id="claude-base-url" name="claude_base_url" placeholder="https://api.anthropic.com" value="https://api.anthropic.com">
478
- </div>
479
- <div class="form-group">
480
- <label for="claude-api-key">API Key</label>
481
- <input type="text" id="claude-api-key" name="claude_api_key" placeholder="sk-ant-...">
482
- </div>
483
- <div class="form-group">
484
- <label for="claude-model">模型</label>
485
- <div class="input-with-btn">
486
- <select id="claude-model" name="claude_model">
487
- <option value="claude-opus-4-6">claude-opus-4-6</option>
488
- <option value="claude-sonnet-4-20250514">claude-sonnet-4-20250514</option>
489
- <option value="claude-3-5-haiku-20241022">claude-3-5-haiku-20241022</option>
490
- </select>
491
- <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="claude">刷新模型</button>
492
- </div>
493
- </div>
494
- </div>
495
-
496
- <!-- Gemini Config -->
497
- <div class="provider-config" id="provider-gemini">
498
- <div class="form-group">
499
- <label for="gemini-base-url">Base URL</label>
500
- <input type="url" id="gemini-base-url" name="gemini_base_url" placeholder="https://generativelanguage.googleapis.com/v1beta" value="https://generativelanguage.googleapis.com/v1beta">
501
- </div>
502
- <div class="form-group">
503
- <label for="gemini-api-key">API Key</label>
504
- <input type="text" id="gemini-api-key" name="gemini_api_key" placeholder="AIza...">
505
- </div>
506
- <div class="form-group">
507
- <label for="gemini-model">模型</label>
508
- <div class="input-with-btn">
509
- <select id="gemini-model" name="gemini_model">
510
- <option value="gemini-2.0-flash">gemini-2.0-flash</option>
511
- <option value="gemini-2.0-pro">gemini-2.0-pro</option>
512
- <option value="gemini-1.5-pro">gemini-1.5-pro</option>
513
- <option value="gemini-1.5-flash">gemini-1.5-flash</option>
514
- </select>
515
- <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="gemini">刷新模型</button>
516
- </div>
517
- </div>
518
- </div>
519
-
520
- <!-- Common LLM Settings -->
521
- <div class="form-row">
522
- <div class="form-group">
523
- <label for="llm-temperature">Temperature: <span id="llm-temperature-value">0.7</span></label>
524
- <input type="range" id="llm-temperature" name="temperature" min="0" max="2" value="0.7" step="0.1">
525
- </div>
526
- <div class="form-group">
527
- <label for="llm-max-tokens">Max Tokens</label>
528
- <input type="number" id="llm-max-tokens" name="max_tokens" value="4096" min="256" max="128000" step="256">
529
- </div>
530
- </div>
531
-
532
- <div class="form-actions" style="margin-top:8px;">
533
- <button type="button" class="btn btn-secondary" id="btn-test-model">测试模型</button>
534
- </div>
535
- </div>
536
-
537
- <!-- ASR Configuration -->
538
- <div class="panel">
539
- <h3 class="panel-title">ASR 语音识别配置</h3>
540
- <div class="form-group">
541
- <label for="asr-provider">识别引擎</label>
542
- <select id="asr-provider" name="asr_provider">
543
- <option value="whisper">Whisper (OpenAI 兼容)</option>
544
- <option value="volcengine">火山引擎 (豆包大模型)</option>
545
- <option value="tencent">腾讯云 (实时语音识别)</option>
546
- <option value="xunfei">讯飞 (流式)</option>
547
- </select>
548
- </div>
549
- <div class="form-group">
550
- <label for="asr-language">语言</label>
551
- <select id="asr-language" name="asr_language">
552
- <option value="zh">中文</option>
553
- <option value="en">English</option>
554
- <option value="auto">自动检测</option>
555
- </select>
556
- </div>
557
-
558
- <!-- Whisper config -->
559
- <div class="asr-config" id="asr-config-whisper">
560
- <div class="form-group">
561
- <label for="asr-whisper-base-url">Base URL</label>
562
- <input type="url" id="asr-whisper-base-url" placeholder="https://api.openai.com/v1">
563
- </div>
564
- <div class="form-group">
565
- <label for="asr-whisper-api-key">API Key</label>
566
- <input type="text" id="asr-whisper-api-key" placeholder="sk-...">
567
- </div>
568
- <div class="form-group">
569
- <label for="asr-whisper-model">模型</label>
570
- <input type="text" id="asr-whisper-model" value="whisper-1" placeholder="whisper-1">
571
- </div>
572
- </div>
573
-
574
- <!-- Volcengine config -->
575
- <div class="asr-config hidden" id="asr-config-volcengine">
576
- <div class="form-group">
577
- <label for="asr-volc-app-id">App ID</label>
578
- <input type="text" id="asr-volc-app-id" placeholder="从火山引擎控制台获取">
579
- </div>
580
- <div class="form-group">
581
- <label for="asr-volc-access-token">Access Token</label>
582
- <input type="text" id="asr-volc-access-token" placeholder="从火山引擎控制台获取">
583
- </div>
584
- <div class="form-group">
585
- <label for="asr-volc-resource-id">Resource ID</label>
586
- <select id="asr-volc-resource-id">
587
- <option value="volc.bigasr.sauc.duration">模型1.0 小时版 (volc.bigasr.sauc.duration)</option>
588
- <option value="volc.bigasr.sauc.concurrent">模型1.0 并发版 (volc.bigasr.sauc.concurrent)</option>
589
- <option value="volc.seedasr.sauc.duration">模型2.0 小时版 (volc.seedasr.sauc.duration)</option>
590
- <option value="volc.seedasr.sauc.concurrent">模型2.0 并发版 (volc.seedasr.sauc.concurrent)</option>
591
- </select>
592
- </div>
593
- </div>
594
-
595
- <!-- Tencent config -->
596
- <div class="asr-config hidden" id="asr-config-tencent">
597
- <div class="form-group">
598
- <label for="asr-tencent-app-id">App ID</label>
599
- <input type="text" id="asr-tencent-app-id" placeholder="腾讯云 AppId (数字)">
600
- </div>
601
- <div class="form-group">
602
- <label for="asr-tencent-secret-id">Secret ID</label>
603
- <input type="text" id="asr-tencent-secret-id" placeholder="腾讯云 API 密钥 ID">
604
- </div>
605
- <div class="form-group">
606
- <label for="asr-tencent-secret-key">Secret Key</label>
607
- <input type="text" id="asr-tencent-secret-key" placeholder="腾讯云 API 密钥 Key">
608
- </div>
609
- <div class="form-group">
610
- <label for="asr-tencent-engine">引擎模型</label>
611
- <select id="asr-tencent-engine">
612
- <option value="16k_zh_large">普方英大模型 (16k_zh_large)</option>
613
- <option value="16k_zh_en">中英粤+方言大模型 (16k_zh_en)</option>
614
- <option value="16k_zh">中文通用 (16k_zh)</option>
615
- <option value="16k_en">英文通用 (16k_en)</option>
616
- <option value="8k_zh_large">电话大模型 (8k_zh_large)</option>
617
- <option value="16k_multi_lang">多语种大模型 (16k_multi_lang)</option>
618
- </select>
619
- </div>
620
- </div>
621
-
622
- <!-- Xunfei config -->
623
- <div class="asr-config hidden" id="asr-config-xunfei">
624
- <div class="form-group">
625
- <label for="asr-xunfei-app-id">App ID</label>
626
- <input type="text" id="asr-xunfei-app-id" placeholder="讯飞 App ID">
627
- </div>
628
- <div class="form-group">
629
- <label for="asr-xunfei-api-key">API Key</label>
630
- <input type="text" id="asr-xunfei-api-key" placeholder="讯飞 API Key">
631
- </div>
632
- <div class="form-group">
633
- <label for="asr-xunfei-api-secret">API Secret</label>
634
- <input type="text" id="asr-xunfei-api-secret" placeholder="讯飞 API Secret">
635
- </div>
636
- </div>
637
- <div class="form-actions" style="margin-top:8px;">
638
- <button type="button" class="btn btn-secondary" id="btn-test-asr">测试 ASR</button>
639
- <button type="button" class="btn btn-secondary" id="btn-audio-diag" style="margin-left:8px">音频诊断</button>
640
- </div>
641
-
642
- <!-- VAD 语音活动检测 (ASR 子配置) -->
643
- <h4 class="panel-subtitle" style="margin-top:16px; margin-bottom:8px; font-size:0.95em; color:var(--text-secondary,#888);">VAD 语音活动检测</h4>
644
- <div class="form-row">
645
- <div class="form-group">
646
- <label for="vad-energy-threshold">能量阈值</label>
647
- <input type="number" id="vad-energy-threshold" name="vad_energy_threshold" value="300" min="50" max="2000" step="50">
648
- <small class="form-hint">RMS 能量阈值,越低越灵敏 (默认 300)</small>
649
- </div>
650
- <div class="form-group">
651
- <label for="vad-silence-ms">静音判定 (ms)</label>
652
- <input type="number" id="vad-silence-ms" name="vad_silence_ms" value="800" min="200" max="3000" step="100">
653
- <small class="form-hint">连续静音多久判定说话结束 (默认 800ms)</small>
654
- </div>
655
- <div class="form-group">
656
- <label for="vad-min-speech-ms">最短语音 (ms)</label>
657
- <input type="number" id="vad-min-speech-ms" name="vad_min_speech_ms" value="250" min="50" max="1000" step="50">
658
- <small class="form-hint">最短语音时长才触发识别 (默认 250ms)</small>
659
- </div>
660
- </div>
661
- </div>
662
-
663
- <!-- TTS Configuration -->
664
- <div class="panel">
665
- <h3 class="panel-title">TTS 语音合成配置</h3>
666
- <div class="form-group">
667
- <label for="tts-provider">合成引擎</label>
668
- <select id="tts-provider" name="tts_provider">
669
- <option value="edge-tts">Edge TTS (免费)</option>
670
- <option value="volcengine">火山引擎</option>
671
- <option value="tencent">腾讯云</option>
672
- <option value="azure">Azure TTS</option>
673
- <option value="openai">OpenAI TTS</option>
674
- <option value="aliyun">阿里云</option>
675
- <option value="local">本地部署</option>
676
- </select>
677
- </div>
678
-
679
- <!-- Edge TTS config -->
680
- <div id="tts-cfg-edge-tts" class="tts-provider-cfg">
681
- <div class="form-group">
682
- <label for="tts-edge-voice">语音</label>
683
- <select id="tts-edge-voice">
684
- <option value="zh-CN-XiaoxiaoNeural">晓晓 (女声)</option>
685
- <option value="zh-CN-YunxiNeural">云希 (男声)</option>
686
- <option value="zh-CN-XiaoyiNeural">晓伊 (女声)</option>
687
- <option value="zh-CN-YunjianNeural">云健 (男声)</option>
688
- </select>
689
- </div>
690
- </div>
691
-
692
- <!-- Volcengine TTS config -->
693
- <div id="tts-cfg-volcengine" class="tts-provider-cfg" style="display:none">
694
- <div class="form-group">
695
- <label for="tts-volc-voice">音色</label>
696
- <select id="tts-volc-voice">
697
- <option value="BV001_streaming">通用女声</option>
698
- <option value="BV002_streaming">通用男声</option>
699
- <option value="BV007_streaming">亲切女声</option>
700
- <option value="BV700_streaming">灿灿</option>
701
- <option value="BV701_streaming">擎苍</option>
702
- <option value="BV705_streaming">炀炀</option>
703
- <option value="BV113_streaming">甜宠少御</option>
704
- <option value="BV056_streaming">阳光男声</option>
705
- <option value="BV033_streaming">温柔小哥</option>
706
- </select>
707
- </div>
708
- <div class="form-row">
709
- <div class="form-group">
710
- <label for="tts-volc-speed">语速: <span id="tts-volc-speed-val">1.0</span>x</label>
711
- <input type="range" id="tts-volc-speed" min="0.5" max="2.0" value="1.0" step="0.1">
712
- </div>
713
- <div class="form-group">
714
- <label for="tts-volc-volume">音量: <span id="tts-volc-volume-val">1.0</span>x</label>
715
- <input type="range" id="tts-volc-volume" min="0.5" max="2.0" value="1.0" step="0.1">
716
- </div>
717
- </div>
718
- <div class="form-group">
719
- <label>认证 (复用ASR配置的 app_id / access_token)</label>
720
- <small class="form-hint">如需单独配置,请在 config.yaml 中修改 tts.volcengine 节</small>
721
- </div>
722
- </div>
723
-
724
- <!-- Tencent TTS config -->
725
- <div id="tts-cfg-tencent" class="tts-provider-cfg" style="display:none">
726
- <div class="form-group">
727
- <label for="tts-tc-voice">音色</label>
728
- <select id="tts-tc-voice">
729
- <option value="101001">智瑜 (情感女声)</option>
730
- <option value="101002">智聆 (通用女声)</option>
731
- <option value="101004">智云 (通用男声)</option>
732
- <option value="101005">智莉 (通用女声)</option>
733
- <option value="101010">智华 (通用男声)</option>
734
- <option value="101018">智靖 (情感男声)</option>
735
- <option value="501001">智兰 (新闻女声)</option>
736
- <option value="501004">月华 (聊天女声)</option>
737
- <option value="501005">飞镜 (聊天男声)</option>
738
- </select>
739
- </div>
740
- <div class="form-row">
741
- <div class="form-group">
742
- <label for="tts-tc-speed">语速: <span id="tts-tc-speed-val">0</span></label>
743
- <input type="range" id="tts-tc-speed" min="-2" max="6" value="0" step="0.5">
744
- </div>
745
- <div class="form-group">
746
- <label for="tts-tc-volume">音量: <span id="tts-tc-volume-val">0</span></label>
747
- <input type="range" id="tts-tc-volume" min="-10" max="10" value="0" step="1">
748
- </div>
749
- </div>
750
- <div class="form-group">
751
- <label>认证 (复用ASR配置的 app_id / secret_id / secret_key)</label>
752
- <small class="form-hint">如需单独配置,请在 config.yaml 中修改 tts.tencent 节</small>
753
- </div>
754
- </div>
755
-
756
- <!-- Azure TTS config (placeholder) -->
757
- <div id="tts-cfg-azure" class="tts-provider-cfg" style="display:none">
758
- <div class="form-group">
759
- <label for="tts-azure-key">API Key</label>
760
- <input type="password" id="tts-azure-key" placeholder="Azure Speech API Key">
761
- </div>
762
- <div class="form-group">
763
- <label for="tts-azure-region">区域</label>
764
- <input type="text" id="tts-azure-region" placeholder="eastasia" value="eastasia">
765
- </div>
766
- <div class="form-group">
767
- <label for="tts-azure-voice">语音</label>
768
- <input type="text" id="tts-azure-voice" value="zh-CN-XiaoxiaoNeural">
769
- </div>
770
- </div>
771
-
772
- <!-- OpenAI TTS config (placeholder) -->
773
- <div id="tts-cfg-openai" class="tts-provider-cfg" style="display:none">
774
- <div class="form-group">
775
- <label for="tts-openai-key">API Key</label>
776
- <input type="password" id="tts-openai-key" placeholder="sk-...">
777
- </div>
778
- <div class="form-group">
779
- <label for="tts-openai-voice">语音</label>
780
- <select id="tts-openai-voice">
781
- <option value="alloy">Alloy</option>
782
- <option value="echo">Echo</option>
783
- <option value="fable">Fable</option>
784
- <option value="onyx">Onyx</option>
785
- <option value="nova">Nova</option>
786
- <option value="shimmer">Shimmer</option>
787
- </select>
788
- </div>
789
- </div>
790
-
791
- <!-- Aliyun TTS config (placeholder) -->
792
- <div id="tts-cfg-aliyun" class="tts-provider-cfg" style="display:none">
793
- <div class="form-group">
794
- <label for="tts-ali-akid">Access Key ID</label>
795
- <input type="password" id="tts-ali-akid" placeholder="Access Key ID">
796
- </div>
797
- <div class="form-group">
798
- <label for="tts-ali-aksecret">Access Key Secret</label>
799
- <input type="password" id="tts-ali-aksecret" placeholder="Access Key Secret">
800
- </div>
801
- <div class="form-group">
802
- <label for="tts-ali-appkey">App Key</label>
803
- <input type="text" id="tts-ali-appkey" placeholder="App Key">
804
- </div>
805
- </div>
806
-
807
- <!-- Local TTS config (placeholder) -->
808
- <div id="tts-cfg-local" class="tts-provider-cfg" style="display:none">
809
- <div class="form-group">
810
- <label for="tts-local-engine">引擎</label>
811
- <select id="tts-local-engine">
812
- <option value="sherpa-onnx">Sherpa-ONNX</option>
813
- <option value="chattts">ChatTTS</option>
814
- <option value="vits">VITS</option>
815
- </select>
816
- </div>
817
- <div class="form-group">
818
- <label for="tts-local-model">模型路径</label>
819
- <input type="text" id="tts-local-model" placeholder="./models/tts/...">
820
- </div>
821
- </div>
822
-
823
- <!-- Common: rate & volume for edge-tts -->
824
- <div id="tts-common-sliders" class="form-row">
825
- <div class="form-group">
826
- <label for="tts-rate">语速: <span id="tts-rate-value">1.0</span>x</label>
827
- <input type="range" id="tts-rate" name="tts_rate" min="0.5" max="2.0" value="1.0" step="0.1">
828
- </div>
829
- <div class="form-group">
830
- <label for="tts-volume">音量: <span id="tts-volume-value">100</span>%</label>
831
- <input type="range" id="tts-volume" name="tts_volume" min="0" max="100" value="100" step="5">
832
- </div>
833
- </div>
834
- <div class="form-actions" style="margin-top:8px;">
835
- <button type="button" class="btn btn-secondary" id="btn-test-tts">测试 TTS</button>
836
- </div>
837
- </div>
838
-
839
- <!-- Call Defaults -->
840
- <div class="panel">
841
- <h3 class="panel-title">通话默认设置</h3>
842
- <div class="form-row">
843
- <div class="form-group">
844
- <label for="default-max-duration">默认最大时长 (秒)</label>
845
- <input type="number" id="default-max-duration" name="default_max_duration" value="300" min="60" max="3600" step="30">
846
- </div>
847
- <div class="form-group">
848
- <label for="default-timeout">超时时间 (秒)</label>
849
- <input type="number" id="default-timeout" name="default_timeout" value="30" min="5" max="120" step="5">
850
- </div>
851
- </div>
852
- <div class="form-group">
853
- <label for="incoming-action">来电默认处理</label>
854
- <select id="incoming-action" name="incoming_default_action">
855
- <option value="auto_answer">自动接听</option>
856
- <option value="notify">仅通知</option>
857
- <option value="reject">自动拒绝</option>
858
- <option value="voicemail">语音留言</option>
859
- </select>
860
- </div>
861
- </div>
862
-
863
- <!-- Webhook Settings -->
864
- <div class="panel">
865
- <h3 class="panel-title">Webhook 设置</h3>
866
- <div class="form-group">
867
- <label for="webhook-default-url">默认 Webhook URL</label>
868
- <input type="url" id="webhook-default-url" name="webhook_default_url" placeholder="https://example.com/webhook">
869
- </div>
870
- <div class="form-row">
871
- <div class="form-group">
872
- <label for="webhook-retry-count">重试次数</label>
873
- <input type="number" id="webhook-retry-count" name="webhook_retry_count" value="3" min="0" max="10">
874
- </div>
875
- <div class="form-group">
876
- <label for="webhook-retry-interval">重试间隔 (秒)</label>
877
- <input type="number" id="webhook-retry-interval" name="webhook_retry_interval" value="5" min="1" max="60">
878
- </div>
879
- </div>
880
- </div>
881
-
882
- <!-- Save button removed: auto-save on field change -->
883
- </form>
884
- </section>
885
-
886
- <!-- ==================== Bluetooth ==================== -->
887
- <section id="page-bluetooth" class="page">
888
- <h2 class="page-title">蓝牙</h2>
889
-
890
- <!-- Current Connection Status -->
891
- <div class="panel">
892
- <h3 class="panel-title">当前连接</h3>
893
- <div class="bt-connection-card" id="bt-connection-card">
894
- <div class="bt-status-row">
895
- <span class="bt-status-indicator" id="bt-status-dot"></span>
896
- <span id="bt-connection-status">未连接</span>
897
- </div>
898
- <div class="bt-device-info" id="bt-device-info">
899
- <div class="bt-info-item">
900
- <span class="info-label">设备名称</span>
901
- <span class="info-value" id="bt-device-name">--</span>
902
- </div>
903
- <div class="bt-info-item">
904
- <span class="info-label">设备地址</span>
905
- <span class="info-value" id="bt-device-address">--</span>
906
- </div>
907
- <div class="bt-info-item">
908
- <span class="info-label">电池电量</span>
909
- <span class="info-value" id="bt-device-battery">--</span>
910
- </div>
911
- <div class="bt-info-item">
912
- <span class="info-label">信号强度</span>
913
- <span class="info-value" id="bt-device-signal">--</span>
914
- </div>
915
- </div>
916
- <div class="bt-actions">
917
- <button class="btn btn-primary" id="btn-bt-connect">连接</button>
918
- <button class="btn btn-danger" id="btn-bt-disconnect" disabled>断开连接</button>
919
- </div>
920
- </div>
921
- </div>
922
-
923
- <!-- Scan for Devices -->
924
- <div class="panel">
925
- <h3 class="panel-title">扫描设备</h3>
926
- <div class="page-actions">
927
- <button class="btn btn-secondary" id="btn-bt-scan">扫描设备</button>
928
- <span id="bt-scan-status" class="text-muted"></span>
929
- </div>
930
- <div class="table-wrapper">
931
- <table class="data-table" id="bt-discovered-table">
932
- <thead>
933
- <tr>
934
- <th>设备名称</th>
935
- <th>地址</th>
936
- <th>信号强度</th>
937
- <th>操作</th>
938
- </tr>
939
- </thead>
940
- <tbody>
941
- <!-- Populated by JS -->
942
- </tbody>
943
- </table>
944
- </div>
945
- </div>
946
-
947
- <!-- Paired Devices -->
948
- <div class="panel">
949
- <h3 class="panel-title">已配对设备</h3>
950
- <div class="table-wrapper">
951
- <table class="data-table" id="bt-paired-table">
952
- <thead>
953
- <tr>
954
- <th>设备名称</th>
955
- <th>地址</th>
956
- <th>状态</th>
957
- <th>操作</th>
958
- </tr>
959
- </thead>
960
- <tbody>
961
- <!-- Populated by JS -->
962
- </tbody>
963
- </table>
964
- </div>
965
- </div>
966
- </section>
967
-
968
- <!-- ==================== Voice Chat ==================== -->
969
-
970
- <!-- ==================== Modules ==================== -->
971
- <section id="page-modules" class="page">
972
- <div id="modules-list-header" style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
973
- <div style="display:flex;align-items:center;gap:12px;">
974
- <h2 class="page-title" style="margin-bottom:0;">模块管理</h2>
975
- <span id="module-save-status" class="config-save-status"></span>
976
- </div>
977
- <div style="display:flex;align-items:center;gap:16px;">
978
- <button class="btn btn-sm btn-secondary" id="btn-toggle-console">
979
- <span id="console-toggle-text">展开控制台</span>
980
- </button>
981
- <button class="btn btn-warning" id="btn-restart-kite" style="display:flex;align-items:center;gap:6px;">
982
- <span>重启 Kite</span>
983
- </button>
984
- </div>
985
- </div>
986
-
987
- <!-- Real-time Console (collapsible) -->
988
- <div id="realtime-console" class="panel" style="display:none;margin-bottom:20px;">
989
- <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
990
- <h3 style="margin:0;font-size:14px;font-weight:600;">实时事件日志</h3>
991
- <button class="btn btn-sm btn-secondary" id="btn-clear-console">清空</button>
992
- </div>
993
- <div id="console-output" style="background:#1e1e1e;color:#d4d4d4;padding:12px;border-radius:4px;font-family:monospace;font-size:12px;max-height:300px;overflow-y:auto;white-space:pre-wrap;line-height:1.4;"></div>
994
- </div>
995
-
996
- <!-- Statistics Panel -->
997
- <div class="panel" style="margin-bottom:20px;" id="statistics-panel">
998
- <div class="stats-grid">
999
- <div class="stat-item" data-stat-type="uptime">
1000
- <div class="stat-label">运行时长</div>
1001
- <div class="stat-value" id="stat-uptime">--</div>
1002
- </div>
1003
- <div class="stat-item" data-stat-type="modules">
1004
- <div class="stat-label">模块数量</div>
1005
- <div class="stat-value" id="stat-modules">--</div>
1006
- </div>
1007
- <div class="stat-item" data-stat-type="registry">
1008
- <div class="stat-label">注册记录</div>
1009
- <div class="stat-value" id="stat-registry">--</div>
1010
- </div>
1011
- <div class="stat-item" data-stat-type="rpc">
1012
- <div class="stat-label">RPC 方法</div>
1013
- <div class="stat-value" id="stat-rpc">--</div>
1014
- </div>
1015
- <div class="stat-item" data-stat-type="hooks">
1016
- <div class="stat-label">Hook 数量</div>
1017
- <div class="stat-value" id="stat-hooks">--</div>
1018
- </div>
1019
- <div class="stat-item" data-stat-type="api">
1020
- <div class="stat-label">API 端点</div>
1021
- <div class="stat-value" id="stat-api">--</div>
1022
- </div>
1023
- <div class="stat-item" data-stat-type="events">
1024
- <div class="stat-label">事件处理</div>
1025
- <div class="stat-value" id="stat-events">--</div>
1026
- </div>
1027
- <div class="stat-item" data-stat-type="rpc-calls">
1028
- <div class="stat-label">RPC 调用</div>
1029
- <div class="stat-value" id="stat-rpc-calls">--</div>
1030
- </div>
1031
- </div>
1032
- </div>
1033
-
1034
- <!-- Tooltip for statistics -->
1035
- <div id="stat-tooltip" class="stat-tooltip"></div>
1036
-
1037
- <!-- Module List Table -->
1038
- <div class="panel">
1039
- <div class="table-wrapper">
1040
- <table class="data-table" id="modules-table">
1041
- <thead>
1042
- <tr>
1043
- <th style="width:40px;"></th>
1044
- <th>模块名称</th>
1045
- <th>显示名称</th>
1046
- <th>类型</th>
1047
- <th>版本</th>
1048
- <th>端口</th>
1049
- <th>运行状态</th>
1050
- <th>默认状态</th>
1051
- <th style="width:180px;">操作</th>
1052
- </tr>
1053
- </thead>
1054
- <tbody id="modules-tbody">
1055
- <tr><td colspan="9" class="text-muted" style="text-align:center;padding:40px;">加载中...</td></tr>
1056
- </tbody>
1057
- </table>
1058
- </div>
1059
- </div>
1060
-
1061
- <!-- Token Management Section -->
1062
- <div id="token-management-section">
1063
- <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;margin-top:40px;">
1064
- <div style="display:flex;align-items:center;gap:12px;">
1065
- <h2 class="page-title" style="margin-bottom:0;">Token 管理</h2>
1066
- </div>
1067
- <div style="display:flex;align-items:center;gap:16px;">
1068
- <button class="btn btn-sm btn-secondary" onclick="refreshTokens()">刷新</button>
1069
- </div>
1070
- </div>
1071
-
1072
- <div class="panel">
1073
- <div class="table-wrapper">
1074
- <table class="data-table" id="tokens-table">
1075
- <thead>
1076
- <tr>
1077
- <th style="width:200px;">Token</th>
1078
- <th>角色</th>
1079
- <th>创建时间</th>
1080
- <th>过期时间</th>
1081
- <th>状态</th>
1082
- <th style="width:100px;">操作</th>
1083
- </tr>
1084
- </thead>
1085
- <tbody id="tokens-tbody">
1086
- <tr><td colspan="6" class="text-muted" style="text-align:center;padding:40px;">加载中...</td></tr>
1087
- </tbody>
1088
- </table>
1089
- </div>
1090
- </div>
1091
- </div>
1092
-
1093
- <!-- Registry Test Section -->
1094
- <div id="registry-test-section" style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;margin-top:40px;">
1095
- <div style="display:flex;align-items:center;gap:12px;">
1096
- <h2 class="page-title" style="margin-bottom:0;">注册中心测试</h2>
1097
- </div>
1098
- <div style="display:flex;align-items:center;gap:16px;">
1099
- <button class="btn btn-sm btn-primary" id="btn-test-registry">运行测试</button>
1100
- <button class="btn btn-sm btn-secondary" id="btn-clear-test-output">清空输出</button>
1101
- </div>
1102
- </div>
1103
-
1104
- <div class="panel" id="registry-test-output">
1105
- <div id="test-output" style="background:#1e1e1e;color:#d4d4d4;padding:15px;border-radius:4px;font-family:monospace;font-size:13px;max-height:400px;overflow-y:auto;white-space:pre-wrap;"></div>
1106
- </div>
1107
-
1108
- <!-- Module Detail Panel (hidden by default) -->
1109
- <div id="module-detail" class="hidden">
1110
- <!-- 第一排:模块名和返回按钮 -->
1111
- <div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;">
1112
- <h3 id="module-detail-name" style="font-size:18px;font-weight:600;color:var(--gray-900);margin:0;"></h3>
1113
- <button class="btn btn-primary btn-sm" id="btn-module-back">返回</button>
1114
- </div>
1115
-
1116
- <!-- 第二排:类型状态和操作按钮 -->
1117
- <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;">
1118
- <div style="display:flex;align-items:center;gap:12px;">
1119
- <span id="module-detail-type-badge" class="module-type-badge"></span>
1120
- <span id="module-detail-run-status" style="font-size:13px;"></span>
1121
- </div>
1122
- <div style="display:flex;align-items:center;gap:8px;">
1123
- <button class="btn btn-sm btn-secondary" id="btn-reset-defaults" onclick="resetModuleDefaults()">恢复默认值</button>
1124
- <button class="btn btn-sm btn-success" id="btn-detail-start" onclick="startModuleFromDetail()">启动</button>
1125
- <button class="btn btn-sm btn-danger" id="btn-detail-stop" onclick="stopModuleFromDetail()">停止</button>
1126
- </div>
1127
- </div>
1128
-
1129
- <!-- 【区块1:模块标识】 -->
1130
- <div class="form-section">
1131
- <h4 class="form-title">模块标识</h4>
1132
-
1133
- <!-- 模块路径 -->
1134
- <div class="form-row">
1135
- <div class="form-group" style="grid-column: 1 / -1;">
1136
- <label>模块路径 <span style="font-size:11px;color:var(--gray-400);">(source_path)</span></label>
1137
- <input type="text" id="mod-source-path" disabled style="background:var(--gray-100);cursor:not-allowed;font-size:12px;font-family:monospace;">
1138
- </div>
1139
- </div>
1140
-
1141
- <div class="form-row">
1142
- <div class="form-group">
1143
- <label>模块名 <span style="font-size:11px;color:var(--gray-400);">(name)</span></label>
1144
- <input type="text" id="mod-meta-name" disabled style="background:var(--gray-100);cursor:not-allowed;">
1145
- </div>
1146
- <div class="form-group">
1147
- <label>模块类型 <span style="font-size:11px;color:var(--gray-400);">(type)</span></label>
1148
- <input type="text" id="mod-meta-type" disabled style="background:var(--gray-100);cursor:not-allowed;">
1149
- </div>
1150
- </div>
1151
- <div class="form-row">
1152
- <div class="form-group">
1153
- <label>运行时 <span style="font-size:11px;color:var(--gray-400);">(runtime)</span></label>
1154
- <input type="text" id="mod-meta-runtime" disabled style="background:var(--gray-100);cursor:not-allowed;">
1155
- </div>
1156
- <div class="form-group">
1157
- <label>入口文件 <span style="font-size:11px;color:var(--gray-400);">(entry)</span></label>
1158
- <input type="text" id="mod-meta-entry" disabled style="background:var(--gray-100);cursor:not-allowed;">
1159
- </div>
1160
- </div>
1161
- <div class="form-row">
1162
- <div class="form-group">
1163
- <label>版本 <span style="font-size:11px;color:var(--gray-400);">(version)</span></label>
1164
- <input type="text" id="mod-meta-version" disabled style="background:var(--gray-100);cursor:not-allowed;">
1165
- </div>
1166
- <div class="form-group">
1167
- <label>显示名称 <span style="font-size:11px;color:var(--gray-400);">(display_name)</span></label>
1168
- <input type="text" id="mod-meta-display-name" data-field="display_name">
1169
- </div>
1170
- </div>
1171
- </div>
1172
-
1173
- <!-- 【区块2:启动配置】 -->
1174
- <div class="form-section">
1175
- <h4 class="form-title">启动配置</h4>
1176
-
1177
- <div class="form-row">
1178
- <div class="form-group">
1179
- <label>默认状态 <span style="font-size:11px;color:var(--gray-400);">(state - 需重启生效)</span></label>
1180
- <select id="mod-meta-state" data-field="state">
1181
- <option value="enabled">enabled - 自动启动</option>
1182
- <option value="manual">manual - 手动启动</option>
1183
- <option value="disabled">disabled - 禁用</option>
1184
- </select>
1185
- </div>
1186
- <div class="form-group">
1187
- <label>监控 <span style="font-size:11px;color:var(--gray-400);">(monitor - Watchdog是否监控此模块)</span></label>
1188
- <select id="mod-meta-monitor" data-field="monitor">
1189
- <option value="true">启用监控 (默认)</option>
1190
- <option value="false">禁用监控</option>
1191
- </select>
1192
- </div>
1193
- </div>
1194
- </div>
1195
-
1196
- <!-- 【区块3:网络配置】 -->
1197
- <div class="form-section">
1198
- <h4 class="form-title">网络配置</h4>
1199
-
1200
- <div class="form-row">
1201
- <div class="form-group">
1202
- <label>首选端口 <span style="font-size:11px;color:var(--gray-400);">(preferred_port)</span></label>
1203
- <input type="number" id="mod-meta-port" data-field="preferred_port" placeholder="()">
1204
- </div>
1205
- <div class="form-group">
1206
- <label>监听地址 <span style="font-size:11px;color:var(--gray-400);">(advertise_ip)</span></label>
1207
- <select id="mod-meta-ip" data-field="advertise_ip">
1208
- <option value="127.0.0.1">127.0.0.1 - 仅本地</option>
1209
- <option value="0.0.0.0">0.0.0.0 - 允许远程</option>
1210
- </select>
1211
- </div>
1212
- </div>
1213
- </div>
1214
-
1215
- <!-- 【区块5:模块配置文件】 -->
1216
- <div class="form-section hidden" id="module-config-section">
1217
- <h4 class="form-title">模块配置文件 (config.yaml)</h4>
1218
- <div id="module-config-tree"></div>
1219
- </div>
1220
- </div>
1221
- </section>
1222
-
1223
- <!-- ==================== Voice Chat ==================== -->
1224
- <section id="page-voicechat" class="page">
1225
- <div class="vc-layout">
1226
-
1227
- <!-- Left: main chat area -->
1228
- <div class="vc-main">
1229
- <!-- Status Bar -->
1230
- <div class="vc-status-bar">
1231
- <div class="vc-status-indicator" id="vc-status-indicator">
1232
- <span class="vc-pulse-dot"></span>
1233
- <span class="vc-status-text" id="vc-status-text">等待开始</span>
1234
- </div>
1235
- <span class="vc-call-timer" id="vc-call-timer"></span>
1236
- </div>
1237
-
1238
- <!-- Config Info Panel -->
1239
- <div class="vc-config-panel" id="vc-config-panel">
1240
- <div class="vc-config-row">
1241
- <span class="vc-config-label">LLM</span>
1242
- <span class="vc-config-value" id="vc-cfg-llm">--</span>
1243
- </div>
1244
- <div class="vc-config-row">
1245
- <span class="vc-config-label">ASR</span>
1246
- <span class="vc-config-value" id="vc-cfg-asr">--</span>
1247
- </div>
1248
- <div class="vc-config-row">
1249
- <span class="vc-config-label">TTS</span>
1250
- <span class="vc-config-value" id="vc-cfg-tts">--</span>
1251
- </div>
1252
- </div>
1253
-
1254
- <!-- VAD Inline Controls -->
1255
- <div class="vc-vad-bar">
1256
- <div class="vc-vad-group">
1257
- <label class="vc-vad-label" for="vc-vad-threshold">能量阈值</label>
1258
- <input type="number" id="vc-vad-threshold" class="vc-vad-input" value="300" min="50" max="2000" step="50">
1259
- </div>
1260
- <div class="vc-vad-group">
1261
- <label class="vc-vad-label" for="vc-vad-silence">静音判定(ms)</label>
1262
- <input type="number" id="vc-vad-silence" class="vc-vad-input" value="800" min="200" max="3000" step="100">
1263
- </div>
1264
- <div class="vc-vad-group">
1265
- <label class="vc-vad-label" for="vc-vad-min-speech">最短语音(ms)</label>
1266
- <input type="number" id="vc-vad-min-speech" class="vc-vad-input" value="250" min="50" max="1000" step="50">
1267
- </div>
1268
- </div>
1269
-
1270
- <!-- Phone Simulation -->
1271
- <div class="vc-phone-bar">
1272
- <div class="vc-phone-group">
1273
- <label class="vc-phone-label" for="vc-phone-direction">方向</label>
1274
- <select id="vc-phone-direction" class="vc-phone-select">
1275
- <option value="incoming">来电 (接入)</option>
1276
- <option value="outgoing">拨出</option>
1277
- </select>
1278
- </div>
1279
- <div class="vc-phone-group vc-phone-group-num">
1280
- <label class="vc-phone-label" for="vc-phone-number">号码</label>
1281
- <input type="text" id="vc-phone-number" class="vc-phone-input" placeholder="13800138000" value="">
1282
- </div>
1283
- <div class="vc-phone-group vc-phone-group-name">
1284
- <label class="vc-phone-label" for="vc-phone-name">姓名</label>
1285
- <input type="text" id="vc-phone-name" class="vc-phone-input" placeholder="(可选)" value="">
1286
- </div>
1287
- </div>
1288
-
1289
- <!-- System Prompt -->
1290
- <div class="vc-prompt-bar">
1291
- <label class="vc-prompt-label" for="vc-system-prompt">系统提示词</label>
1292
- <textarea id="vc-system-prompt" class="vc-prompt-input" rows="2" placeholder="输入系统提示词... 设定任务目标后 AI 会主动发起对话"></textarea>
1293
- </div>
1294
-
1295
- <!-- Waveform Visualization -->
1296
- <div class="vc-viz" id="vc-viz" style="display:none">
1297
- <canvas id="vc-canvas" width="600" height="64"></canvas>
1298
- <div class="vc-vol-row">
1299
- <span class="vc-vol-label">音量</span>
1300
- <div class="vc-vol-track"><div id="vc-vol-bar" class="vc-vol-bar"></div></div>
1301
- <span id="vc-vol-db" class="vc-vol-db">-- dB</span>
1302
- </div>
1303
- </div>
1304
-
1305
- <!-- Chat Messages Area -->
1306
- <div class="vc-messages" id="vc-messages">
1307
- <div class="vc-empty-hint" id="vc-empty-hint">点击"开始通话"后对麦克风说话</div>
1308
- </div>
1309
-
1310
- <!-- Control Bar -->
1311
- <div class="vc-controls">
1312
- <button class="btn btn-lg vc-btn-call" id="vc-btn-start">开始通话</button>
1313
- <button class="btn btn-lg btn-danger vc-btn-hangup" id="vc-btn-stop" style="display:none">结束通话</button>
1314
- </div>
1315
- </div>
1316
-
1317
- <!-- Right: status log + debug panel -->
1318
- <div class="vc-sidebar">
1319
- <div class="vc-sidebar-title">状态日志</div>
1320
- <div class="vc-log" id="vc-log"></div>
1321
- <div class="vc-sidebar-title vc-debug-title">调试记录 <span id="vc-debug-count" class="vc-debug-count"></span></div>
1322
- <div class="vc-debug" id="vc-debug"></div>
1323
- </div>
1324
-
1325
- </div>
1326
- </section>
1327
-
1328
- <!-- ==================== Dev Log ==================== -->
1329
- <section id="page-devlog" class="page">
1330
- <h2 class="page-title">开发记录</h2>
1331
-
1332
- <!-- New Dev Log Form -->
1333
- <div class="form-section">
1334
- <h3 class="form-title">新建开发需求</h3>
1335
- <form id="form-new-devlog">
1336
- <div class="form-group">
1337
- <label for="devlog-content">开发需求 <span class="required">*</span></label>
1338
- <textarea id="devlog-content" name="content" rows="5" placeholder="描述开发需求..." required></textarea>
1339
- </div>
1340
- <div class="form-actions">
1341
- <button type="submit" class="btn btn-primary">提交</button>
1342
- <select id="devlog-type" style="padding:4px 8px;border:1px solid var(--gray-300);border-radius:4px;font-size:13px;">
1343
- <option value="需求">需求</option>
1344
- <option value="BUG">BUG</option>
1345
- <option value="优化">优化</option>
1346
- <option value="重构">重构</option>
1347
- <option value="澄清">澄清</option>
1348
- <option value="文档">文档</option>
1349
- </select>
1350
- <label class="toggle-switch-label">
1351
- <input type="checkbox" id="devlog-important">
1352
- <span class="toggle-switch"></span>
1353
- <span>重要</span>
1354
- </label>
1355
- <label class="toggle-switch-label">
1356
- <input type="checkbox" id="devlog-urgent">
1357
- <span class="toggle-switch"></span>
1358
- <span>优先</span>
1359
- </label>
1360
- </div>
1361
- </form>
1362
- </div>
1363
-
1364
- <!-- Dev Log List -->
1365
- <div class="panel">
1366
- <h3 class="panel-title">需求记录</h3>
1367
- <div class="page-actions">
1368
- <select id="devlog-filter-status" class="btn btn-secondary">
1369
- <option value="">全部状态</option>
1370
- <option value="pending">待处理</option>
1371
- <option value="in_progress">进行中</option>
1372
- <option value="done">已完成</option>
1373
- </select>
1374
- <button class="btn btn-secondary" id="devlog-btn-archive" title="归档指定时间之前的已完成需求">归档</button>
1375
- <button class="btn btn-secondary" id="devlog-btn-view-archives" title="查看归档记录">查看归档</button>
1376
- </div>
1377
- <div class="table-wrapper">
1378
- <table class="data-table" id="devlog-table">
1379
- <thead>
1380
- <tr>
1381
- <th>内容</th>
1382
- <th>标记</th>
1383
- <th>状态</th>
1384
- <th>创建时间</th>
1385
- <th>操作</th>
1386
- </tr>
1387
- </thead>
1388
- <tbody id="devlog-tbody">
1389
- <!-- Populated by JS -->
1390
- </tbody>
1391
- </table>
1392
- </div>
1393
- <div class="pagination" id="devlog-pagination"></div>
1394
- </div>
1395
-
1396
- <!-- Dev Log Detail Modal -->
1397
- <div class="modal-overlay hidden" id="devlog-detail-modal">
1398
- <div class="modal">
1399
- <div class="modal-header">
1400
- <h3 class="modal-title">需求详情</h3>
1401
- <button class="modal-close" id="devlog-detail-close">&times;</button>
1402
- </div>
1403
- <div class="modal-body">
1404
- <div class="form-group">
1405
- <label>需求内容</label>
1406
- <div id="devlog-detail-content" style="white-space:pre-wrap;line-height:1.6;color:var(--gray-700);"></div>
1407
- </div>
1408
- <div class="form-group">
1409
- <label>类型</label>
1410
- <select id="devlog-detail-type" style="padding:4px 8px;border:1px solid var(--gray-300);border-radius:4px;font-size:13px;width:auto;">
1411
- <option value="需求">需求</option>
1412
- <option value="BUG">BUG</option>
1413
- <option value="优化">优化</option>
1414
- <option value="重构">重构</option>
1415
- <option value="澄清">澄清</option>
1416
- <option value="文档">文档</option>
1417
- </select>
1418
- </div>
1419
- <div class="form-group">
1420
- <label>标记</label>
1421
- <div style="display:flex;gap:12px;align-items:center;">
1422
- <label class="toggle-switch-label">
1423
- <input type="checkbox" id="devlog-detail-important">
1424
- <span class="toggle-switch"></span>
1425
- <span>重要</span>
1426
- </label>
1427
- <label class="toggle-switch-label">
1428
- <input type="checkbox" id="devlog-detail-urgent">
1429
- <span class="toggle-switch"></span>
1430
- <span>优先</span>
1431
- </label>
1432
- </div>
1433
- </div>
1434
- <div class="form-group">
1435
- <label>状态</label>
1436
- <select id="devlog-detail-status">
1437
- <option value="pending">待处理</option>
1438
- <option value="in_progress">进行中</option>
1439
- <option value="done">已完成</option>
1440
- </select>
1441
- </div>
1442
- <div class="form-group">
1443
- <label>创建时间</label>
1444
- <span id="devlog-detail-created" class="text-muted"></span>
1445
- </div>
1446
- <div class="form-group" id="devlog-detail-completed-group" style="display:none;">
1447
- <label>完成时间</label>
1448
- <span id="devlog-detail-completed" class="text-muted"></span>
1449
- </div>
1450
- </div>
1451
- <div class="modal-footer">
1452
- <button class="btn btn-danger btn-sm" id="devlog-detail-delete">删除</button>
1453
- <button class="btn btn-primary btn-sm" id="devlog-detail-save">保存</button>
1454
- </div>
1455
- </div>
1456
- </div>
1457
-
1458
- <!-- Dev Log Archive Cutoff Modal -->
1459
- <div class="modal-overlay hidden" id="devlog-archive-cutoff-modal">
1460
- <div class="modal" style="max-width:400px;">
1461
- <div class="modal-header">
1462
- <h3 class="modal-title">归档设置</h3>
1463
- <button class="modal-close" id="devlog-archive-cutoff-close">&times;</button>
1464
- </div>
1465
- <div class="modal-body">
1466
- <p style="font-size:13px;color:var(--gray-500);margin-bottom:12px;">归档此时间之前完成的需求(状态为"已完成"的记录)</p>
1467
- <div class="form-group">
1468
- <label for="devlog-archive-cutoff-input">截止时间</label>
1469
- <input type="datetime-local" id="devlog-archive-cutoff-input" class="form-control" style="width:100%;">
1470
- <span id="devlog-archive-cutoff-hint" style="font-size:12px;color:var(--gray-400);margin-top:4px;display:block;"></span>
1471
- </div>
1472
- </div>
1473
- <div class="modal-footer">
1474
- <button class="btn btn-secondary btn-sm" id="devlog-archive-cutoff-cancel">取消</button>
1475
- <button class="btn btn-primary btn-sm" id="devlog-archive-cutoff-confirm">确认归档</button>
1476
- </div>
1477
- </div>
1478
- </div>
1479
-
1480
- <!-- Dev Log Archive List Modal -->
1481
- <div class="modal-overlay hidden" id="devlog-archive-modal">
1482
- <div class="modal" style="max-width:640px;">
1483
- <div class="modal-header">
1484
- <h3 class="modal-title">归档记录</h3>
1485
- <button class="modal-close" id="devlog-archive-close">&times;</button>
1486
- </div>
1487
- <div class="modal-body" id="devlog-archive-body">
1488
- <p class="text-muted" style="text-align:center;padding:24px;">加载中...</p>
1489
- </div>
1490
- </div>
1491
- </div>
1492
- </section>
1493
-
1494
- </main>
1495
- </div>
1496
-
1497
- <!-- ===== Bottom Status Bar ===== -->
1498
- <footer id="status-bar">
1499
- <div class="status-item">
1500
- <span class="status-label">蓝牙:</span>
1501
- <span class="status-value" id="statusbar-bt">未连接</span>
1502
- </div>
1503
- <div class="status-item">
1504
- <span class="status-label">电池:</span>
1505
- <span class="status-value" id="statusbar-battery">--</span>
1506
- </div>
1507
- <div class="status-item">
1508
- <span class="status-label">信号:</span>
1509
- <span class="status-value" id="statusbar-signal">--</span>
1510
- </div>
1511
- </footer>
1512
-
1513
- <!-- ===== Modal Component ===== -->
1514
- <div id="modal-overlay" class="modal-overlay hidden">
1515
- <div class="modal" id="modal-container">
1516
- <div class="modal-header">
1517
- <h3 class="modal-title" id="modal-title">标题</h3>
1518
- <button class="modal-close" id="modal-close">&times;</button>
1519
- </div>
1520
- <div class="modal-body" id="modal-body">
1521
- <!-- Dynamic modal content -->
1522
- </div>
1523
- <div class="modal-footer" id="modal-footer">
1524
- <!-- Dynamic modal actions -->
1525
- </div>
1526
- </div>
1527
- </div>
1528
-
1529
- <!-- ===== Reset Module Defaults Dialog ===== -->
1530
- <div id="reset-defaults-modal" class="modal-overlay hidden">
1531
- <div class="modal" style="max-width:600px;">
1532
- <div class="modal-header">
1533
- <h3 class="modal-title">恢复默认值</h3>
1534
- <button class="modal-close" id="reset-defaults-close">&times;</button>
1535
- </div>
1536
- <div class="modal-body">
1537
- <p style="margin-bottom:16px;color:var(--gray-600);">以下配置将被恢复为默认值:</p>
1538
- <table style="width:100%;border-collapse:collapse;">
1539
- <thead>
1540
- <tr style="background:var(--gray-100);border-bottom:1px solid var(--gray-300);">
1541
- <th style="padding:8px;text-align:left;font-weight:600;">字段</th>
1542
- <th style="padding:8px;text-align:left;font-weight:600;">当前值</th>
1543
- <th style="padding:8px;text-align:left;font-weight:600;">默认值</th>
1544
- </tr>
1545
- </thead>
1546
- <tbody id="reset-defaults-comparison">
1547
- <!-- Dynamic content -->
1548
- </tbody>
1549
- </table>
1550
- </div>
1551
- <div class="modal-footer">
1552
- <button class="btn btn-secondary" id="reset-defaults-cancel">取消</button>
1553
- <button class="btn btn-primary" id="reset-defaults-confirm">确认恢复</button>
1554
- </div>
1555
- </div>
1556
- </div>
1557
-
1558
- <!-- ===== TTS Test Dialog ===== -->
1559
- <div id="tts-test-overlay" class="asr-test-overlay hidden">
1560
- <div class="asr-test-dialog" style="width:560px">
1561
- <div class="asr-test-header">
1562
- <h3>TTS 语音合成测试</h3>
1563
- <button type="button" class="asr-test-close" id="tts-test-close">&times;</button>
1564
- </div>
1565
- <div class="asr-test-body">
1566
- <div class="asr-ctrl-bar">
1567
- <div class="asr-ctrl-row">
1568
- <label class="asr-ctrl-label">引擎</label>
1569
- <select id="tts-test-provider" class="asr-ctrl-select" style="flex:1">
1570
- <option value="edge-tts">Edge TTS</option>
1571
- <option value="volcengine">火山引擎</option>
1572
- <option value="tencent">腾讯云</option>
1573
- <option value="azure">Azure</option>
1574
- <option value="openai">OpenAI</option>
1575
- <option value="aliyun">阿里云</option>
1576
- <option value="local">本地</option>
1577
- </select>
1578
- </div>
1579
- <div class="asr-ctrl-row">
1580
- <label class="asr-ctrl-label">音色</label>
1581
- <select id="tts-test-voice" class="asr-ctrl-select" style="flex:1">
1582
- </select>
1583
- </div>
1584
- <div class="asr-ctrl-row">
1585
- <label class="asr-ctrl-label">语速</label>
1586
- <input type="range" id="tts-test-speed" class="asr-mic-gain" min="0.5" max="2.0" value="1.0" step="0.1" style="flex:1">
1587
- <span id="tts-test-speed-val" class="asr-gain-val">1.0x</span>
1588
- </div>
1589
- </div>
1590
- <div class="form-group" style="margin-top:10px">
1591
- <textarea id="tts-test-text" rows="3" style="width:100%;resize:vertical;font-size:13px" placeholder="输入要合成的文本...">你好,我是AI语音助手,很高兴为你服务。今天天气不错,有什么可以帮你的吗?</textarea>
1592
- </div>
1593
- <div id="tts-test-status" class="asr-test-status-text" style="text-align:center;margin:8px 0">点击"合成并播放"开始测试</div>
1594
- <div id="tts-test-log" class="asr-test-log" style="display:none"></div>
1595
- </div>
1596
- <div class="asr-test-footer">
1597
- <button type="button" class="btn btn-primary" id="tts-test-play">合成并播放</button>
1598
- <button type="button" class="btn btn-danger" id="tts-test-stop" style="display:none">停止</button>
1599
- </div>
1600
- </div>
1601
- </div>
1602
-
1603
- <!-- ===== Chat Test Dialog ===== -->
1604
- <div id="chat-test-overlay" class="chat-test-overlay hidden">
1605
- <div class="chat-test-dialog">
1606
- <div class="chat-test-header">
1607
- <h3>模型测试</h3>
1608
- <div class="chat-test-controls">
1609
- <select id="chat-test-provider" class="chat-test-select">
1610
- <option value="openai">OpenAI</option>
1611
- <option value="claude">Claude</option>
1612
- <option value="gemini">Gemini</option>
1613
- </select>
1614
- <select id="chat-test-model" class="chat-test-select chat-test-model-select"></select>
1615
- <button type="button" class="btn btn-sm" id="chat-test-refresh" title="刷新模型列表">刷新</button>
1616
- <button type="button" class="btn btn-sm" id="chat-test-clear" title="清空对话">清空</button>
1617
- <button type="button" class="chat-test-close" id="chat-test-close">&times;</button>
1618
- </div>
1619
- </div>
1620
- <div class="chat-test-messages" id="chat-test-messages">
1621
- <div class="chat-test-empty">选择模型后开始对话</div>
1622
- </div>
1623
- <div class="chat-test-footer">
1624
- <textarea id="chat-test-input" class="chat-test-input" placeholder="输入消息... (Enter 发送, Shift+Enter 换行)" rows="1"></textarea>
1625
- <button type="button" class="btn btn-primary" id="chat-test-send">发送</button>
1626
- </div>
1627
- </div>
1628
- </div>
1629
-
1630
- <!-- ===== ASR Test Dialog ===== -->
1631
- <div id="asr-test-overlay" class="asr-test-overlay hidden">
1632
- <div class="asr-test-dialog">
1633
- <div class="asr-test-header">
1634
- <h3>ASR 语音识别测试</h3>
1635
- <button type="button" class="asr-test-close" id="asr-test-close">&times;</button>
1636
- </div>
1637
- <div class="asr-test-body">
1638
- <!-- Controls bar: mic select + gain + ASR params -->
1639
- <div class="asr-ctrl-bar">
1640
- <div class="asr-ctrl-row">
1641
- <button type="button" id="asr-mute-btn" class="asr-mute-btn" title="静音/取消静音"><svg class="mic-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="9" y1="22" x2="15" y2="22"/><line class="mic-slash" x1="3" y1="3" x2="21" y2="21"/></svg></button>
1642
- <select id="asr-test-mic" class="asr-ctrl-select" style="flex:1;min-width:0">
1643
- <option value="">加载中...</option>
1644
- </select>
1645
- <input type="range" id="asr-mic-gain" class="asr-mic-gain" min="0" max="200" value="100" title="麦克风增益">
1646
- <span id="asr-mic-gain-val" class="asr-gain-val">100%</span>
1647
- <label class="asr-agc-label" title="自动增益控制"><input type="checkbox" id="asr-agc-toggle" checked> AGC</label>
1648
- </div>
1649
- <div class="asr-ctrl-row">
1650
- <label class="asr-ctrl-label">识别引擎</label>
1651
- <select id="asr-test-provider" class="asr-ctrl-select" style="width:110px">
1652
- <option value="volcengine">火山引擎</option>
1653
- <option value="tencent">腾讯云</option>
1654
- <option value="xunfei">讯飞</option>
1655
- <option value="whisper">Whisper</option>
1656
- </select>
1657
- <select id="asr-test-resid" class="asr-ctrl-select" style="flex:1;min-width:0">
1658
- <option value="">加载中...</option>
1659
- </select>
1660
- <label class="asr-ctrl-label" style="margin-left:10px">采样率</label>
1661
- <select id="asr-test-samplerate" class="asr-ctrl-select" style="width:90px">
1662
- <option value="16000" selected>16 kHz</option>
1663
- <option value="8000">8 kHz</option>
1664
- </select>
1665
- </div>
1666
- </div>
1667
- <!-- Status + Timer row -->
1668
- <div class="asr-test-status-row">
1669
- <span id="asr-test-status" class="asr-test-status-text">点击"开始录音"后对麦克风说话</span>
1670
- <span id="asr-test-timer" class="asr-test-timer"></span>
1671
- </div>
1672
- <!-- Real-time waveform canvas -->
1673
- <div class="asr-test-viz">
1674
- <canvas id="asr-test-canvas" width="660" height="100"></canvas>
1675
- <div class="asr-test-vol-row">
1676
- <span class="asr-test-vol-label">音量</span>
1677
- <div class="asr-test-vol-track">
1678
- <div id="asr-test-vol-bar" class="asr-test-vol-bar"></div>
1679
- </div>
1680
- <span id="asr-test-vol-db" class="asr-test-vol-db">-- dB</span>
1681
- </div>
1682
- </div>
1683
- <!-- Stats -->
1684
- <div id="asr-test-stats" class="asr-test-stats" style="display:none">
1685
- <span id="asr-stat-duration">0.0s</span>
1686
- <span id="asr-stat-bytes">0 KB</span>
1687
- <span id="asr-stat-packets">0 包</span>
1688
- <span id="asr-stat-bw">0 kbps</span>
1689
- </div>
1690
- <!-- Result -->
1691
- <div class="asr-test-result-area">
1692
- <div class="asr-test-result-label">识别结果:</div>
1693
- <div id="asr-test-result" class="asr-test-result-text"></div>
1694
- </div>
1695
- <!-- Playback -->
1696
- <div id="asr-test-playback" class="asr-test-playback" style="display:none">
1697
- <button type="button" class="btn btn-sm btn-secondary" id="asr-test-play">回放录音</button>
1698
- <span id="asr-test-play-dur" class="asr-test-play-dur"></span>
1699
- </div>
1700
- <!-- Log -->
1701
- <div id="asr-test-log" class="asr-test-log" style="display:none"></div>
1702
- </div>
1703
- <div class="asr-test-footer">
1704
- <button type="button" class="btn btn-primary" id="asr-test-start">开始录音</button>
1705
- <button type="button" class="btn btn-danger" id="asr-test-stop" style="display:none">停止</button>
1706
- </div>
1707
- </div>
1708
- </div>
1709
-
1710
- <!-- ===== Audio Diagnostic Dialog ===== -->
1711
- <div id="audio-diag-overlay" class="chat-test-overlay hidden">
1712
- <div class="chat-test-dialog" style="width:680px;height:auto;max-height:90vh">
1713
- <div class="chat-test-header">
1714
- <h3>音频采集诊断</h3>
1715
- <button type="button" class="chat-test-close" id="audio-diag-close">&times;</button>
1716
- </div>
1717
- <div style="padding:20px;overflow-y:auto;flex:1">
1718
- <div id="audio-diag-log" style="font-family:monospace;font-size:12px;line-height:1.7;background:#0f172a;color:#e2e8f0;border-radius:8px;padding:16px;max-height:60vh;overflow-y:auto;white-space:pre-wrap;word-break:break-all"></div>
1719
- </div>
1720
- <div style="padding:14px 20px;border-top:1px solid var(--gray-200);display:flex;gap:10px;flex-wrap:wrap">
1721
- <button type="button" class="btn btn-primary btn-sm" id="audio-diag-run">开始诊断</button>
1722
- <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-stop" style="display:none">停止</button>
1723
- <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-play-sp" style="display:none">回放 ScriptProcessor</button>
1724
- <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-play-mr" style="display:none">回放 MediaRecorder</button>
1725
- </div>
1726
- </div>
1727
- </div>
1728
-
1729
- <!-- ===== Toast / Notification Area ===== -->
1730
- <div id="toast-container"></div>
1731
-
1732
- <script src="js/kernel-client.js"></script>
1733
- <script src="js/kernel-client-example.js"></script>
1734
- <script src="js/registry-tests.js"></script>
1735
- <script src="js/token-manager.js"></script>
1736
- <script src="js/app.js?v=65"></script>
1737
- </body>
1738
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Phone Agent</title>
7
+ <link rel="stylesheet" href="css/style.css?v=41">
8
+ </head>
9
+ <body>
10
+
11
+ <!-- ===== Top Header Bar ===== -->
12
+ <header id="app-header">
13
+ <div class="header-left">
14
+ <button id="sidebar-toggle" class="icon-btn" title="Toggle Sidebar">&#9776;</button>
15
+ <h1 class="header-title">AI Phone Agent</h1>
16
+ </div>
17
+ <div class="header-right">
18
+ <span id="ws-indicator" style="font-size:13px;color:var(--gray-400);margin-right:16px;" title="Kite 连接状态">○ 未连线</span>
19
+ <span id="header-bt-status" class="bt-indicator" title="Bluetooth Status">
20
+ <span class="bt-icon">BT</span>
21
+ <span class="bt-label">未连接</span>
22
+ </span>
23
+ </div>
24
+ </header>
25
+
26
+ <!-- ===== Layout Container ===== -->
27
+ <div id="app-layout">
28
+
29
+ <!-- ===== Left Sidebar Navigation ===== -->
30
+ <nav id="sidebar">
31
+ <ul class="nav-list">
32
+ <li class="nav-item active" data-page="dashboard">
33
+ <span class="nav-label">仪表盘</span>
34
+ <span class="nav-sublabel">Dashboard</span>
35
+ </li>
36
+ <li class="nav-item" data-page="calls">
37
+ <span class="nav-label">通话</span>
38
+ <span class="nav-sublabel">Calls</span>
39
+ </li>
40
+ <li class="nav-item" data-page="sms">
41
+ <span class="nav-label">短信</span>
42
+ <span class="nav-sublabel">SMS</span>
43
+ </li>
44
+ <li class="nav-item" data-page="contacts">
45
+ <span class="nav-label">联系人</span>
46
+ <span class="nav-sublabel">Contacts</span>
47
+ </li>
48
+ <li class="nav-item" data-page="config">
49
+ <span class="nav-label">配置</span>
50
+ <span class="nav-sublabel">Config</span>
51
+ </li>
52
+ <li class="nav-item" data-page="bluetooth">
53
+ <span class="nav-label">蓝牙</span>
54
+ <span class="nav-sublabel">Bluetooth</span>
55
+ </li>
56
+ <li class="nav-item" data-page="modules">
57
+ <span class="nav-label">模块</span>
58
+ <span class="nav-sublabel">Modules</span>
59
+ </li>
60
+ <li class="nav-item" data-page="voicechat">
61
+ <span class="nav-label">语音测试</span>
62
+ <span class="nav-sublabel">Voice Chat</span>
63
+ </li>
64
+ <li class="nav-item" data-page="devlog">
65
+ <span class="nav-label">开发记录</span>
66
+ <span class="nav-sublabel">Dev Log</span>
67
+ </li>
68
+ </ul>
69
+ </nav>
70
+
71
+ <!-- ===== Main Content Area ===== -->
72
+ <main id="main-content">
73
+
74
+ <!-- Statistics Update Info (Global - Always Visible) -->
75
+ <div id="stats-update-info" style="margin:0 0 20px 0;padding:12px;background:#f8f9fa;border-left:4px solid #007bff;border-radius:4px;font-size:13px;color:#495057;">
76
+ <div style="display:flex;align-items:center;gap:8px;">
77
+ <span style="font-weight:600;">统计数据更新:</span>
78
+ <span id="stats-update-status">正在加载...</span>
79
+ <span style="margin-left:auto;color:#6c757d;font-size:12px;" id="stats-last-update">--</span>
80
+ </div>
81
+ <div style="margin-top:8px;font-size:12px;color:#6c757d;" id="stats-update-details">
82
+ 事件: <span id="stats-events-count">0</span> |
83
+ RPC: <span id="stats-rpc-count">0</span> |
84
+ 更新频率: 每秒
85
+ </div>
86
+ </div>
87
+
88
+ <!-- ==================== Dashboard ==================== -->
89
+ <section id="page-dashboard" class="page active">
90
+ <h2 class="page-title">仪表盘</h2>
91
+
92
+ <!-- Stats Cards -->
93
+ <div class="stats-row">
94
+ <div class="stat-card">
95
+ <div class="stat-value" id="stat-total-calls">0</div>
96
+ <div class="stat-label">总通话数</div>
97
+ </div>
98
+ <div class="stat-card">
99
+ <div class="stat-value" id="stat-today-calls">0</div>
100
+ <div class="stat-label">今日通话</div>
101
+ </div>
102
+ <div class="stat-card">
103
+ <div class="stat-value" id="stat-avg-duration">0s</div>
104
+ <div class="stat-label">平均时长</div>
105
+ </div>
106
+ <div class="stat-card">
107
+ <div class="stat-value" id="stat-total-contacts">0</div>
108
+ <div class="stat-label">联系人数</div>
109
+ </div>
110
+ </div>
111
+
112
+ <!-- Calls by Result Breakdown -->
113
+ <div class="panel">
114
+ <h3 class="panel-title">通话结果分布</h3>
115
+ <ul id="calls-result-breakdown" class="breakdown-list">
116
+ <li><span class="breakdown-label">已完成</span><span class="breakdown-value" id="breakdown-completed">0</span></li>
117
+ <li><span class="breakdown-label">未接听</span><span class="breakdown-value" id="breakdown-no-answer">0</span></li>
118
+ <li><span class="breakdown-label">占线</span><span class="breakdown-value" id="breakdown-busy">0</span></li>
119
+ <li><span class="breakdown-label">失败</span><span class="breakdown-value" id="breakdown-failed">0</span></li>
120
+ <li><span class="breakdown-label">进行中</span><span class="breakdown-value" id="breakdown-in-progress">0</span></li>
121
+ </ul>
122
+ </div>
123
+
124
+ <!-- Recent Calls Table -->
125
+ <div class="panel">
126
+ <h3 class="panel-title">最近通话</h3>
127
+ <div class="table-wrapper">
128
+ <table class="data-table" id="dashboard-recent-calls">
129
+ <thead>
130
+ <tr>
131
+ <th>时间</th>
132
+ <th>联系人/号码</th>
133
+ <th>方向</th>
134
+ <th>时长</th>
135
+ <th>结果</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody>
139
+ <!-- Populated by JS -->
140
+ </tbody>
141
+ </table>
142
+ </div>
143
+ </div>
144
+ </section>
145
+
146
+ <!-- ==================== Calls ==================== -->
147
+ <section id="page-calls" class="page">
148
+ <h2 class="page-title">通话</h2>
149
+
150
+ <!-- Calls List View -->
151
+ <div id="calls-list-view">
152
+ <div class="page-actions">
153
+ <button class="btn btn-primary" id="btn-new-call">新建通话</button>
154
+ </div>
155
+
156
+ <!-- New Call Form (inline, hidden by default) -->
157
+ <div id="new-call-form" class="form-section hidden">
158
+ <h3 class="form-title">新建通话</h3>
159
+ <form id="form-new-call">
160
+ <div class="form-group">
161
+ <label for="call-phone">电话号码 (可选)</label>
162
+ <input type="tel" id="call-phone" name="phone" placeholder="输入电话号码">
163
+ </div>
164
+ <div class="form-group">
165
+ <label for="call-purpose">通话目的 <span class="required">*</span></label>
166
+ <textarea id="call-purpose" name="purpose" rows="3" placeholder="描述通话目的" required></textarea>
167
+ </div>
168
+ <div class="form-group">
169
+ <label for="call-system-prompt">系统提示词 (可选)</label>
170
+ <textarea id="call-system-prompt" name="system_prompt" rows="4" placeholder="自定义系统提示词"></textarea>
171
+ </div>
172
+ <div class="form-group">
173
+ <label for="call-play-text">播放文本 (可选)</label>
174
+ <textarea id="call-play-text" name="play_text" rows="3" placeholder="通话开始时播放的文本"></textarea>
175
+ </div>
176
+ <div class="form-group">
177
+ <label for="call-webhook">Webhook URL (可选)</label>
178
+ <input type="url" id="call-webhook" name="webhook_url" placeholder="https://example.com/webhook">
179
+ </div>
180
+ <div class="form-group">
181
+ <label for="call-max-duration">最大时长: <span id="call-max-duration-value">300</span>秒</label>
182
+ <input type="range" id="call-max-duration" name="max_duration" min="60" max="600" value="300" step="10">
183
+ </div>
184
+ <div class="form-actions">
185
+ <button type="submit" class="btn btn-primary">发起通话</button>
186
+ <button type="button" class="btn btn-secondary" id="btn-cancel-new-call">取消</button>
187
+ </div>
188
+ </form>
189
+ </div>
190
+
191
+ <!-- Calls History Table -->
192
+ <div class="panel">
193
+ <div class="table-wrapper">
194
+ <table class="data-table" id="calls-history-table">
195
+ <thead>
196
+ <tr>
197
+ <th>时间</th>
198
+ <th>联系人/号码</th>
199
+ <th>方向</th>
200
+ <th>时长</th>
201
+ <th>结果</th>
202
+ <th>操作</th>
203
+ </tr>
204
+ </thead>
205
+ <tbody>
206
+ <!-- Populated by JS -->
207
+ </tbody>
208
+ </table>
209
+ </div>
210
+ <!-- Pagination -->
211
+ <div class="pagination" id="calls-pagination">
212
+ <button class="btn btn-sm" id="calls-prev" disabled>上一页</button>
213
+ <span class="pagination-info" id="calls-page-info">第 1 页</span>
214
+ <button class="btn btn-sm" id="calls-next">下一页</button>
215
+ </div>
216
+ </div>
217
+ </div>
218
+
219
+ <!-- Call Detail View (hidden by default) -->
220
+ <div id="call-detail-view" class="hidden">
221
+ <div class="page-actions">
222
+ <button class="btn btn-secondary" id="btn-back-to-calls">&larr; 返回列表</button>
223
+ </div>
224
+
225
+ <!-- Call Info Header -->
226
+ <div class="panel" id="call-detail-header">
227
+ <div class="call-info-grid">
228
+ <div class="call-info-item">
229
+ <span class="info-label">电话号码</span>
230
+ <span class="info-value" id="detail-phone">--</span>
231
+ </div>
232
+ <div class="call-info-item">
233
+ <span class="info-label">联系人</span>
234
+ <span class="info-value" id="detail-contact">--</span>
235
+ </div>
236
+ <div class="call-info-item">
237
+ <span class="info-label">方向</span>
238
+ <span class="info-value" id="detail-direction">--</span>
239
+ </div>
240
+ <div class="call-info-item">
241
+ <span class="info-label">时间</span>
242
+ <span class="info-value" id="detail-time">--</span>
243
+ </div>
244
+ <div class="call-info-item">
245
+ <span class="info-label">时长</span>
246
+ <span class="info-value" id="detail-duration">--</span>
247
+ </div>
248
+ <div class="call-info-item">
249
+ <span class="info-label">结果</span>
250
+ <span class="info-value" id="detail-result">--</span>
251
+ </div>
252
+ </div>
253
+ </div>
254
+
255
+ <!-- Summary -->
256
+ <div class="panel">
257
+ <h3 class="panel-title">通话摘要</h3>
258
+ <div id="detail-summary" class="summary-content">
259
+ <p class="text-muted">暂无摘要</p>
260
+ </div>
261
+ </div>
262
+
263
+ <!-- Transcript -->
264
+ <div class="panel">
265
+ <h3 class="panel-title">通话记录</h3>
266
+ <div id="detail-transcript" class="transcript-container">
267
+ <!-- Chat-style transcript: AI messages right, human messages left -->
268
+ </div>
269
+ </div>
270
+
271
+ <!-- Audio Player -->
272
+ <div class="panel">
273
+ <h3 class="panel-title">通话录音</h3>
274
+ <div id="detail-audio-container">
275
+ <audio id="detail-audio" controls>
276
+ <source src="" type="audio/wav">
277
+ 您的浏览器不支持音频播放
278
+ </audio>
279
+ <p class="text-muted" id="detail-no-audio">暂无录音</p>
280
+ </div>
281
+ </div>
282
+
283
+ <!-- MCP Tool Calls -->
284
+ <div class="panel">
285
+ <h3 class="panel-title">MCP 工具调用</h3>
286
+ <div id="detail-tool-calls" class="tool-calls-container">
287
+ <p class="text-muted">暂无工具调用记录</p>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ </section>
292
+
293
+ <!-- ==================== SMS ==================== -->
294
+ <section id="page-sms" class="page">
295
+ <h2 class="page-title">短信</h2>
296
+
297
+ <div class="page-actions">
298
+ <button class="btn btn-primary" id="btn-new-sms">新建短信</button>
299
+ </div>
300
+
301
+ <!-- New SMS Form (hidden by default) -->
302
+ <div id="new-sms-form" class="form-section hidden">
303
+ <h3 class="form-title">发送短信</h3>
304
+ <form id="form-new-sms">
305
+ <div class="form-group">
306
+ <label for="sms-phone">电话号码 <span class="required">*</span></label>
307
+ <input type="tel" id="sms-phone" name="phone" placeholder="输入电话号码" required>
308
+ </div>
309
+ <div class="form-group">
310
+ <label for="sms-content">短信内容 <span class="required">*</span></label>
311
+ <textarea id="sms-content" name="content" rows="4" placeholder="输入短信内容" required></textarea>
312
+ </div>
313
+ <div class="form-actions">
314
+ <button type="submit" class="btn btn-primary">发送</button>
315
+ <button type="button" class="btn btn-secondary" id="btn-cancel-new-sms">取消</button>
316
+ </div>
317
+ </form>
318
+ </div>
319
+
320
+ <!-- SMS List -->
321
+ <div class="panel">
322
+ <div class="table-wrapper">
323
+ <table class="data-table" id="sms-table">
324
+ <thead>
325
+ <tr>
326
+ <th>时间</th>
327
+ <th>联系人/号码</th>
328
+ <th>方向</th>
329
+ <th>内容预览</th>
330
+ </tr>
331
+ </thead>
332
+ <tbody>
333
+ <!-- Populated by JS -->
334
+ </tbody>
335
+ </table>
336
+ </div>
337
+ <!-- Pagination -->
338
+ <div class="pagination" id="sms-pagination">
339
+ <button class="btn btn-sm" id="sms-prev" disabled>上一页</button>
340
+ <span class="pagination-info" id="sms-page-info">第 1 页</span>
341
+ <button class="btn btn-sm" id="sms-next">下一页</button>
342
+ </div>
343
+ </div>
344
+ </section>
345
+
346
+ <!-- ==================== Contacts ==================== -->
347
+ <section id="page-contacts" class="page">
348
+ <h2 class="page-title">联系人</h2>
349
+
350
+ <div class="page-actions">
351
+ <button class="btn btn-primary" id="btn-add-contact">添加联系人</button>
352
+ <button class="btn btn-secondary" id="btn-sync-contacts">从手机同步</button>
353
+ <div class="search-box">
354
+ <input type="text" id="contacts-search" placeholder="搜索联系人...">
355
+ </div>
356
+ </div>
357
+
358
+ <!-- Add / Edit Contact Form (hidden by default) -->
359
+ <div id="contact-form-section" class="form-section hidden">
360
+ <h3 class="form-title" id="contact-form-title">添加联系人</h3>
361
+ <form id="form-contact">
362
+ <input type="hidden" id="contact-id" name="id" value="">
363
+ <div class="form-row">
364
+ <div class="form-group">
365
+ <label for="contact-name">姓名 <span class="required">*</span></label>
366
+ <input type="text" id="contact-name" name="name" placeholder="输入姓名" required>
367
+ </div>
368
+ <div class="form-group">
369
+ <label for="contact-phone">电话号码 <span class="required">*</span></label>
370
+ <input type="tel" id="contact-phone" name="phone" placeholder="输入电话号码" required>
371
+ </div>
372
+ </div>
373
+ <div class="form-row">
374
+ <div class="form-group">
375
+ <label for="contact-company">公司</label>
376
+ <input type="text" id="contact-company" name="company" placeholder="输入公司名称">
377
+ </div>
378
+ <div class="form-group">
379
+ <label for="contact-title">职务</label>
380
+ <input type="text" id="contact-title" name="title" placeholder="输入职务">
381
+ </div>
382
+ </div>
383
+ <div class="form-group">
384
+ <label for="contact-notes">备注</label>
385
+ <textarea id="contact-notes" name="notes" rows="3" placeholder="输入备注信息"></textarea>
386
+ </div>
387
+ <div class="form-group">
388
+ <label for="contact-tags">标签 (逗号分隔)</label>
389
+ <input type="text" id="contact-tags" name="tags" placeholder="例如: 客户, VIP, 供应商">
390
+ </div>
391
+ <div class="form-actions">
392
+ <button type="submit" class="btn btn-primary" id="contact-submit-btn">保存</button>
393
+ <button type="button" class="btn btn-secondary" id="btn-cancel-contact">取消</button>
394
+ </div>
395
+ </form>
396
+ </div>
397
+
398
+ <!-- Contacts Table -->
399
+ <div class="panel">
400
+ <div class="table-wrapper">
401
+ <table class="data-table" id="contacts-table">
402
+ <thead>
403
+ <tr>
404
+ <th>姓名</th>
405
+ <th>电话</th>
406
+ <th>公司</th>
407
+ <th>标签</th>
408
+ <th>操作</th>
409
+ </tr>
410
+ </thead>
411
+ <tbody>
412
+ <!-- Populated by JS -->
413
+ </tbody>
414
+ </table>
415
+ </div>
416
+ </div>
417
+ </section>
418
+
419
+ <!-- ==================== Config ==================== -->
420
+ <section id="page-config" class="page">
421
+ <h2 class="page-title">配置 <span id="config-save-status" class="config-save-status"></span></h2>
422
+
423
+ <form id="form-config">
424
+ <!-- Basic Info -->
425
+ <div class="panel">
426
+ <h3 class="panel-title">基础信息</h3>
427
+
428
+ <!-- AI Phone Number -->
429
+ <div class="form-group">
430
+ <label>AI 电话号码</label>
431
+ <div class="tag-list" id="ai-phone-list"></div>
432
+ <div class="tag-input-row">
433
+ <input type="text" id="ai-phone-input" placeholder="输入号码后回车添加" class="tag-input">
434
+ <button type="button" class="btn btn-sm" id="btn-add-ai-phone">添加</button>
435
+ </div>
436
+ <p class="form-hint">标记 <span class="badge badge-primary">当前</span> 的号码为 AI 正在使用的号码,点击其他号码可切换</p>
437
+ </div>
438
+
439
+ <!-- Owners -->
440
+ <div class="form-group">
441
+ <label>主人号码</label>
442
+ <div class="owner-list" id="owner-list"></div>
443
+ <div class="owner-add-row">
444
+ <input type="text" id="owner-phone-input" placeholder="号码" class="owner-input owner-input-phone">
445
+ <input type="text" id="owner-name-input" placeholder="姓名" class="owner-input owner-input-name">
446
+ <input type="text" id="owner-note-input" placeholder="备注(可选)" class="owner-input owner-input-note">
447
+ <button type="button" class="btn btn-sm" id="btn-add-owner">添加</button>
448
+ </div>
449
+ </div>
450
+ </div>
451
+
452
+ <!-- LLM Configuration -->
453
+ <div class="panel">
454
+ <h3 class="panel-title">LLM 配置</h3>
455
+
456
+ <!-- Provider Tabs -->
457
+ <div class="provider-tabs" id="llm-provider-tabs">
458
+ <button type="button" class="provider-tab active" data-provider="openai">OpenAI</button>
459
+ <button type="button" class="provider-tab" data-provider="claude">Claude</button>
460
+ <button type="button" class="provider-tab" data-provider="gemini">Gemini</button>
461
+ </div>
462
+
463
+ <!-- OpenAI Config -->
464
+ <div class="provider-config active" id="provider-openai">
465
+ <div class="form-group">
466
+ <label for="openai-base-url">Base URL</label>
467
+ <input type="url" id="openai-base-url" name="openai_base_url" placeholder="https://api.openai.com/v1" value="https://api.openai.com/v1">
468
+ </div>
469
+ <div class="form-group">
470
+ <label for="openai-api-key">API Key</label>
471
+ <input type="text" id="openai-api-key" name="openai_api_key" placeholder="sk-...">
472
+ </div>
473
+ <div class="form-group">
474
+ <label for="openai-model">模型</label>
475
+ <div class="input-with-btn">
476
+ <select id="openai-model" name="openai_model">
477
+ <option value="gpt-4o">gpt-4o</option>
478
+ <option value="gpt-4o-mini">gpt-4o-mini</option>
479
+ <option value="gpt-4-turbo">gpt-4-turbo</option>
480
+ <option value="gpt-3.5-turbo">gpt-3.5-turbo</option>
481
+ </select>
482
+ <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="openai">刷新模型</button>
483
+ </div>
484
+ </div>
485
+ </div>
486
+
487
+ <!-- Claude Config -->
488
+ <div class="provider-config" id="provider-claude">
489
+ <div class="form-group">
490
+ <label for="claude-base-url">Base URL</label>
491
+ <input type="url" id="claude-base-url" name="claude_base_url" placeholder="https://api.anthropic.com" value="https://api.anthropic.com">
492
+ </div>
493
+ <div class="form-group">
494
+ <label for="claude-api-key">API Key</label>
495
+ <input type="text" id="claude-api-key" name="claude_api_key" placeholder="sk-ant-...">
496
+ </div>
497
+ <div class="form-group">
498
+ <label for="claude-model">模型</label>
499
+ <div class="input-with-btn">
500
+ <select id="claude-model" name="claude_model">
501
+ <option value="claude-opus-4-6">claude-opus-4-6</option>
502
+ <option value="claude-sonnet-4-20250514">claude-sonnet-4-20250514</option>
503
+ <option value="claude-3-5-haiku-20241022">claude-3-5-haiku-20241022</option>
504
+ </select>
505
+ <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="claude">刷新模型</button>
506
+ </div>
507
+ </div>
508
+ </div>
509
+
510
+ <!-- Gemini Config -->
511
+ <div class="provider-config" id="provider-gemini">
512
+ <div class="form-group">
513
+ <label for="gemini-base-url">Base URL</label>
514
+ <input type="url" id="gemini-base-url" name="gemini_base_url" placeholder="https://generativelanguage.googleapis.com/v1beta" value="https://generativelanguage.googleapis.com/v1beta">
515
+ </div>
516
+ <div class="form-group">
517
+ <label for="gemini-api-key">API Key</label>
518
+ <input type="text" id="gemini-api-key" name="gemini_api_key" placeholder="AIza...">
519
+ </div>
520
+ <div class="form-group">
521
+ <label for="gemini-model">模型</label>
522
+ <div class="input-with-btn">
523
+ <select id="gemini-model" name="gemini_model">
524
+ <option value="gemini-2.0-flash">gemini-2.0-flash</option>
525
+ <option value="gemini-2.0-pro">gemini-2.0-pro</option>
526
+ <option value="gemini-1.5-pro">gemini-1.5-pro</option>
527
+ <option value="gemini-1.5-flash">gemini-1.5-flash</option>
528
+ </select>
529
+ <button type="button" class="btn btn-sm" data-action="refresh-models" data-provider="gemini">刷新模型</button>
530
+ </div>
531
+ </div>
532
+ </div>
533
+
534
+ <!-- Common LLM Settings -->
535
+ <div class="form-row">
536
+ <div class="form-group">
537
+ <label for="llm-temperature">Temperature: <span id="llm-temperature-value">0.7</span></label>
538
+ <input type="range" id="llm-temperature" name="temperature" min="0" max="2" value="0.7" step="0.1">
539
+ </div>
540
+ <div class="form-group">
541
+ <label for="llm-max-tokens">Max Tokens</label>
542
+ <input type="number" id="llm-max-tokens" name="max_tokens" value="4096" min="256" max="128000" step="256">
543
+ </div>
544
+ </div>
545
+
546
+ <div class="form-actions" style="margin-top:8px;">
547
+ <button type="button" class="btn btn-secondary" id="btn-test-model">测试模型</button>
548
+ </div>
549
+ </div>
550
+
551
+ <!-- ASR Configuration -->
552
+ <div class="panel">
553
+ <h3 class="panel-title">ASR 语音识别配置</h3>
554
+ <div class="form-group">
555
+ <label for="asr-provider">识别引擎</label>
556
+ <select id="asr-provider" name="asr_provider">
557
+ <option value="whisper">Whisper (OpenAI 兼容)</option>
558
+ <option value="volcengine">火山引擎 (豆包大模型)</option>
559
+ <option value="tencent">腾讯云 (实时语音识别)</option>
560
+ <option value="xunfei">讯飞 (流式)</option>
561
+ </select>
562
+ </div>
563
+ <div class="form-group">
564
+ <label for="asr-language">语言</label>
565
+ <select id="asr-language" name="asr_language">
566
+ <option value="zh">中文</option>
567
+ <option value="en">English</option>
568
+ <option value="auto">自动检测</option>
569
+ </select>
570
+ </div>
571
+
572
+ <!-- Whisper config -->
573
+ <div class="asr-config" id="asr-config-whisper">
574
+ <div class="form-group">
575
+ <label for="asr-whisper-base-url">Base URL</label>
576
+ <input type="url" id="asr-whisper-base-url" placeholder="https://api.openai.com/v1">
577
+ </div>
578
+ <div class="form-group">
579
+ <label for="asr-whisper-api-key">API Key</label>
580
+ <input type="text" id="asr-whisper-api-key" placeholder="sk-...">
581
+ </div>
582
+ <div class="form-group">
583
+ <label for="asr-whisper-model">模型</label>
584
+ <input type="text" id="asr-whisper-model" value="whisper-1" placeholder="whisper-1">
585
+ </div>
586
+ </div>
587
+
588
+ <!-- Volcengine config -->
589
+ <div class="asr-config hidden" id="asr-config-volcengine">
590
+ <div class="form-group">
591
+ <label for="asr-volc-app-id">App ID</label>
592
+ <input type="text" id="asr-volc-app-id" placeholder="从火山引擎控制台获取">
593
+ </div>
594
+ <div class="form-group">
595
+ <label for="asr-volc-access-token">Access Token</label>
596
+ <input type="text" id="asr-volc-access-token" placeholder="从火山引擎控制台获取">
597
+ </div>
598
+ <div class="form-group">
599
+ <label for="asr-volc-resource-id">Resource ID</label>
600
+ <select id="asr-volc-resource-id">
601
+ <option value="volc.bigasr.sauc.duration">模型1.0 小时版 (volc.bigasr.sauc.duration)</option>
602
+ <option value="volc.bigasr.sauc.concurrent">模型1.0 并发版 (volc.bigasr.sauc.concurrent)</option>
603
+ <option value="volc.seedasr.sauc.duration">模型2.0 小时版 (volc.seedasr.sauc.duration)</option>
604
+ <option value="volc.seedasr.sauc.concurrent">模型2.0 并发版 (volc.seedasr.sauc.concurrent)</option>
605
+ </select>
606
+ </div>
607
+ </div>
608
+
609
+ <!-- Tencent config -->
610
+ <div class="asr-config hidden" id="asr-config-tencent">
611
+ <div class="form-group">
612
+ <label for="asr-tencent-app-id">App ID</label>
613
+ <input type="text" id="asr-tencent-app-id" placeholder="腾讯云 AppId (数字)">
614
+ </div>
615
+ <div class="form-group">
616
+ <label for="asr-tencent-secret-id">Secret ID</label>
617
+ <input type="text" id="asr-tencent-secret-id" placeholder="腾讯云 API 密钥 ID">
618
+ </div>
619
+ <div class="form-group">
620
+ <label for="asr-tencent-secret-key">Secret Key</label>
621
+ <input type="text" id="asr-tencent-secret-key" placeholder="腾讯云 API 密钥 Key">
622
+ </div>
623
+ <div class="form-group">
624
+ <label for="asr-tencent-engine">引擎模型</label>
625
+ <select id="asr-tencent-engine">
626
+ <option value="16k_zh_large">普方英大模型 (16k_zh_large)</option>
627
+ <option value="16k_zh_en">中英粤+方言大模型 (16k_zh_en)</option>
628
+ <option value="16k_zh">中文通用 (16k_zh)</option>
629
+ <option value="16k_en">英文通用 (16k_en)</option>
630
+ <option value="8k_zh_large">电话大模型 (8k_zh_large)</option>
631
+ <option value="16k_multi_lang">多语种大模型 (16k_multi_lang)</option>
632
+ </select>
633
+ </div>
634
+ </div>
635
+
636
+ <!-- Xunfei config -->
637
+ <div class="asr-config hidden" id="asr-config-xunfei">
638
+ <div class="form-group">
639
+ <label for="asr-xunfei-app-id">App ID</label>
640
+ <input type="text" id="asr-xunfei-app-id" placeholder="讯飞 App ID">
641
+ </div>
642
+ <div class="form-group">
643
+ <label for="asr-xunfei-api-key">API Key</label>
644
+ <input type="text" id="asr-xunfei-api-key" placeholder="讯飞 API Key">
645
+ </div>
646
+ <div class="form-group">
647
+ <label for="asr-xunfei-api-secret">API Secret</label>
648
+ <input type="text" id="asr-xunfei-api-secret" placeholder="讯飞 API Secret">
649
+ </div>
650
+ </div>
651
+ <div class="form-actions" style="margin-top:8px;">
652
+ <button type="button" class="btn btn-secondary" id="btn-test-asr">测试 ASR</button>
653
+ <button type="button" class="btn btn-secondary" id="btn-audio-diag" style="margin-left:8px">音频诊断</button>
654
+ </div>
655
+
656
+ <!-- VAD 语音活动检测 (ASR 子配置) -->
657
+ <h4 class="panel-subtitle" style="margin-top:16px; margin-bottom:8px; font-size:0.95em; color:var(--text-secondary,#888);">VAD 语音活动检测</h4>
658
+ <div class="form-row">
659
+ <div class="form-group">
660
+ <label for="vad-energy-threshold">能量阈值</label>
661
+ <input type="number" id="vad-energy-threshold" name="vad_energy_threshold" value="300" min="50" max="2000" step="50">
662
+ <small class="form-hint">RMS 能量阈值,越低越灵敏 (默认 300)</small>
663
+ </div>
664
+ <div class="form-group">
665
+ <label for="vad-silence-ms">静音判定 (ms)</label>
666
+ <input type="number" id="vad-silence-ms" name="vad_silence_ms" value="800" min="200" max="3000" step="100">
667
+ <small class="form-hint">连续静音多久判定说话结束 (默认 800ms)</small>
668
+ </div>
669
+ <div class="form-group">
670
+ <label for="vad-min-speech-ms">最短语音 (ms)</label>
671
+ <input type="number" id="vad-min-speech-ms" name="vad_min_speech_ms" value="250" min="50" max="1000" step="50">
672
+ <small class="form-hint">最短语音时长才触发识别 (默认 250ms)</small>
673
+ </div>
674
+ </div>
675
+ </div>
676
+
677
+ <!-- TTS Configuration -->
678
+ <div class="panel">
679
+ <h3 class="panel-title">TTS 语音合成配置</h3>
680
+ <div class="form-group">
681
+ <label for="tts-provider">合成引擎</label>
682
+ <select id="tts-provider" name="tts_provider">
683
+ <option value="edge-tts">Edge TTS (免费)</option>
684
+ <option value="volcengine">火山引擎</option>
685
+ <option value="tencent">腾讯云</option>
686
+ <option value="azure">Azure TTS</option>
687
+ <option value="openai">OpenAI TTS</option>
688
+ <option value="aliyun">阿里云</option>
689
+ <option value="local">本地部署</option>
690
+ </select>
691
+ </div>
692
+
693
+ <!-- Edge TTS config -->
694
+ <div id="tts-cfg-edge-tts" class="tts-provider-cfg">
695
+ <div class="form-group">
696
+ <label for="tts-edge-voice">语音</label>
697
+ <select id="tts-edge-voice">
698
+ <option value="zh-CN-XiaoxiaoNeural">晓晓 (女声)</option>
699
+ <option value="zh-CN-YunxiNeural">云希 (男声)</option>
700
+ <option value="zh-CN-XiaoyiNeural">晓伊 (女声)</option>
701
+ <option value="zh-CN-YunjianNeural">云健 (男声)</option>
702
+ </select>
703
+ </div>
704
+ </div>
705
+
706
+ <!-- Volcengine TTS config -->
707
+ <div id="tts-cfg-volcengine" class="tts-provider-cfg" style="display:none">
708
+ <div class="form-group">
709
+ <label for="tts-volc-voice">音色</label>
710
+ <select id="tts-volc-voice">
711
+ <option value="BV001_streaming">通用女声</option>
712
+ <option value="BV002_streaming">通用男声</option>
713
+ <option value="BV007_streaming">亲切女声</option>
714
+ <option value="BV700_streaming">灿灿</option>
715
+ <option value="BV701_streaming">擎苍</option>
716
+ <option value="BV705_streaming">炀炀</option>
717
+ <option value="BV113_streaming">甜宠少御</option>
718
+ <option value="BV056_streaming">阳光男声</option>
719
+ <option value="BV033_streaming">温柔小哥</option>
720
+ </select>
721
+ </div>
722
+ <div class="form-row">
723
+ <div class="form-group">
724
+ <label for="tts-volc-speed">语速: <span id="tts-volc-speed-val">1.0</span>x</label>
725
+ <input type="range" id="tts-volc-speed" min="0.5" max="2.0" value="1.0" step="0.1">
726
+ </div>
727
+ <div class="form-group">
728
+ <label for="tts-volc-volume">音量: <span id="tts-volc-volume-val">1.0</span>x</label>
729
+ <input type="range" id="tts-volc-volume" min="0.5" max="2.0" value="1.0" step="0.1">
730
+ </div>
731
+ </div>
732
+ <div class="form-group">
733
+ <label>认证 (复用ASR配置的 app_id / access_token)</label>
734
+ <small class="form-hint">如需单独配置,请在 config.json5 中修改 tts.volcengine 节</small>
735
+ </div>
736
+ </div>
737
+
738
+ <!-- Tencent TTS config -->
739
+ <div id="tts-cfg-tencent" class="tts-provider-cfg" style="display:none">
740
+ <div class="form-group">
741
+ <label for="tts-tc-voice">音色</label>
742
+ <select id="tts-tc-voice">
743
+ <option value="101001">智瑜 (情感女声)</option>
744
+ <option value="101002">智聆 (通用女声)</option>
745
+ <option value="101004">智云 (通用男声)</option>
746
+ <option value="101005">智莉 (通用女声)</option>
747
+ <option value="101010">智华 (通用男声)</option>
748
+ <option value="101018">智靖 (情感男声)</option>
749
+ <option value="501001">智兰 (新闻女声)</option>
750
+ <option value="501004">月华 (聊天女声)</option>
751
+ <option value="501005">飞镜 (聊天男声)</option>
752
+ </select>
753
+ </div>
754
+ <div class="form-row">
755
+ <div class="form-group">
756
+ <label for="tts-tc-speed">语速: <span id="tts-tc-speed-val">0</span></label>
757
+ <input type="range" id="tts-tc-speed" min="-2" max="6" value="0" step="0.5">
758
+ </div>
759
+ <div class="form-group">
760
+ <label for="tts-tc-volume">音量: <span id="tts-tc-volume-val">0</span></label>
761
+ <input type="range" id="tts-tc-volume" min="-10" max="10" value="0" step="1">
762
+ </div>
763
+ </div>
764
+ <div class="form-group">
765
+ <label>认证 (复用ASR配置的 app_id / secret_id / secret_key)</label>
766
+ <small class="form-hint">如需单独配置,请在 config.json5 中修改 tts.tencent 节</small>
767
+ </div>
768
+ </div>
769
+
770
+ <!-- Azure TTS config (placeholder) -->
771
+ <div id="tts-cfg-azure" class="tts-provider-cfg" style="display:none">
772
+ <div class="form-group">
773
+ <label for="tts-azure-key">API Key</label>
774
+ <input type="password" id="tts-azure-key" placeholder="Azure Speech API Key">
775
+ </div>
776
+ <div class="form-group">
777
+ <label for="tts-azure-region">区域</label>
778
+ <input type="text" id="tts-azure-region" placeholder="eastasia" value="eastasia">
779
+ </div>
780
+ <div class="form-group">
781
+ <label for="tts-azure-voice">语音</label>
782
+ <input type="text" id="tts-azure-voice" value="zh-CN-XiaoxiaoNeural">
783
+ </div>
784
+ </div>
785
+
786
+ <!-- OpenAI TTS config (placeholder) -->
787
+ <div id="tts-cfg-openai" class="tts-provider-cfg" style="display:none">
788
+ <div class="form-group">
789
+ <label for="tts-openai-key">API Key</label>
790
+ <input type="password" id="tts-openai-key" placeholder="sk-...">
791
+ </div>
792
+ <div class="form-group">
793
+ <label for="tts-openai-voice">语音</label>
794
+ <select id="tts-openai-voice">
795
+ <option value="alloy">Alloy</option>
796
+ <option value="echo">Echo</option>
797
+ <option value="fable">Fable</option>
798
+ <option value="onyx">Onyx</option>
799
+ <option value="nova">Nova</option>
800
+ <option value="shimmer">Shimmer</option>
801
+ </select>
802
+ </div>
803
+ </div>
804
+
805
+ <!-- Aliyun TTS config (placeholder) -->
806
+ <div id="tts-cfg-aliyun" class="tts-provider-cfg" style="display:none">
807
+ <div class="form-group">
808
+ <label for="tts-ali-akid">Access Key ID</label>
809
+ <input type="password" id="tts-ali-akid" placeholder="Access Key ID">
810
+ </div>
811
+ <div class="form-group">
812
+ <label for="tts-ali-aksecret">Access Key Secret</label>
813
+ <input type="password" id="tts-ali-aksecret" placeholder="Access Key Secret">
814
+ </div>
815
+ <div class="form-group">
816
+ <label for="tts-ali-appkey">App Key</label>
817
+ <input type="text" id="tts-ali-appkey" placeholder="App Key">
818
+ </div>
819
+ </div>
820
+
821
+ <!-- Local TTS config (placeholder) -->
822
+ <div id="tts-cfg-local" class="tts-provider-cfg" style="display:none">
823
+ <div class="form-group">
824
+ <label for="tts-local-engine">引擎</label>
825
+ <select id="tts-local-engine">
826
+ <option value="sherpa-onnx">Sherpa-ONNX</option>
827
+ <option value="chattts">ChatTTS</option>
828
+ <option value="vits">VITS</option>
829
+ </select>
830
+ </div>
831
+ <div class="form-group">
832
+ <label for="tts-local-model">模型路径</label>
833
+ <input type="text" id="tts-local-model" placeholder="./models/tts/...">
834
+ </div>
835
+ </div>
836
+
837
+ <!-- Common: rate & volume for edge-tts -->
838
+ <div id="tts-common-sliders" class="form-row">
839
+ <div class="form-group">
840
+ <label for="tts-rate">语速: <span id="tts-rate-value">1.0</span>x</label>
841
+ <input type="range" id="tts-rate" name="tts_rate" min="0.5" max="2.0" value="1.0" step="0.1">
842
+ </div>
843
+ <div class="form-group">
844
+ <label for="tts-volume">音量: <span id="tts-volume-value">100</span>%</label>
845
+ <input type="range" id="tts-volume" name="tts_volume" min="0" max="100" value="100" step="5">
846
+ </div>
847
+ </div>
848
+ <div class="form-actions" style="margin-top:8px;">
849
+ <button type="button" class="btn btn-secondary" id="btn-test-tts">测试 TTS</button>
850
+ </div>
851
+ </div>
852
+
853
+ <!-- Call Defaults -->
854
+ <div class="panel">
855
+ <h3 class="panel-title">通话默认设置</h3>
856
+ <div class="form-row">
857
+ <div class="form-group">
858
+ <label for="default-max-duration">默认最大时长 (秒)</label>
859
+ <input type="number" id="default-max-duration" name="default_max_duration" value="300" min="60" max="3600" step="30">
860
+ </div>
861
+ <div class="form-group">
862
+ <label for="default-timeout">超时时间 (秒)</label>
863
+ <input type="number" id="default-timeout" name="default_timeout" value="30" min="5" max="120" step="5">
864
+ </div>
865
+ </div>
866
+ <div class="form-group">
867
+ <label for="incoming-action">来电默认处理</label>
868
+ <select id="incoming-action" name="incoming_default_action">
869
+ <option value="auto_answer">自动接听</option>
870
+ <option value="notify">仅通知</option>
871
+ <option value="reject">自动拒绝</option>
872
+ <option value="voicemail">语音留言</option>
873
+ </select>
874
+ </div>
875
+ </div>
876
+
877
+ <!-- Webhook Settings -->
878
+ <div class="panel">
879
+ <h3 class="panel-title">Webhook 设置</h3>
880
+ <div class="form-group">
881
+ <label for="webhook-default-url">默认 Webhook URL</label>
882
+ <input type="url" id="webhook-default-url" name="webhook_default_url" placeholder="https://example.com/webhook">
883
+ </div>
884
+ <div class="form-row">
885
+ <div class="form-group">
886
+ <label for="webhook-retry-count">重试次数</label>
887
+ <input type="number" id="webhook-retry-count" name="webhook_retry_count" value="3" min="0" max="10">
888
+ </div>
889
+ <div class="form-group">
890
+ <label for="webhook-retry-interval">重试间隔 (秒)</label>
891
+ <input type="number" id="webhook-retry-interval" name="webhook_retry_interval" value="5" min="1" max="60">
892
+ </div>
893
+ </div>
894
+ </div>
895
+
896
+ <!-- Save button removed: auto-save on field change -->
897
+ </form>
898
+ </section>
899
+
900
+ <!-- ==================== Bluetooth ==================== -->
901
+ <section id="page-bluetooth" class="page">
902
+ <h2 class="page-title">蓝牙</h2>
903
+
904
+ <!-- Current Connection Status -->
905
+ <div class="panel">
906
+ <h3 class="panel-title">当前连接</h3>
907
+ <div class="bt-connection-card" id="bt-connection-card">
908
+ <div class="bt-status-row">
909
+ <span class="bt-status-indicator" id="bt-status-dot"></span>
910
+ <span id="bt-connection-status">未连接</span>
911
+ </div>
912
+ <div class="bt-device-info" id="bt-device-info">
913
+ <div class="bt-info-item">
914
+ <span class="info-label">设备名称</span>
915
+ <span class="info-value" id="bt-device-name">--</span>
916
+ </div>
917
+ <div class="bt-info-item">
918
+ <span class="info-label">设备地址</span>
919
+ <span class="info-value" id="bt-device-address">--</span>
920
+ </div>
921
+ <div class="bt-info-item">
922
+ <span class="info-label">电池电量</span>
923
+ <span class="info-value" id="bt-device-battery">--</span>
924
+ </div>
925
+ <div class="bt-info-item">
926
+ <span class="info-label">信号强度</span>
927
+ <span class="info-value" id="bt-device-signal">--</span>
928
+ </div>
929
+ </div>
930
+ <div class="bt-actions">
931
+ <button class="btn btn-primary" id="btn-bt-connect">连接</button>
932
+ <button class="btn btn-danger" id="btn-bt-disconnect" disabled>断开连接</button>
933
+ </div>
934
+ </div>
935
+ </div>
936
+
937
+ <!-- Scan for Devices -->
938
+ <div class="panel">
939
+ <h3 class="panel-title">扫描设备</h3>
940
+ <div class="page-actions">
941
+ <button class="btn btn-secondary" id="btn-bt-scan">扫描设备</button>
942
+ <span id="bt-scan-status" class="text-muted"></span>
943
+ </div>
944
+ <div class="table-wrapper">
945
+ <table class="data-table" id="bt-discovered-table">
946
+ <thead>
947
+ <tr>
948
+ <th>设备名称</th>
949
+ <th>地址</th>
950
+ <th>信号强度</th>
951
+ <th>操作</th>
952
+ </tr>
953
+ </thead>
954
+ <tbody>
955
+ <!-- Populated by JS -->
956
+ </tbody>
957
+ </table>
958
+ </div>
959
+ </div>
960
+
961
+ <!-- Paired Devices -->
962
+ <div class="panel">
963
+ <h3 class="panel-title">已配对设备</h3>
964
+ <div class="table-wrapper">
965
+ <table class="data-table" id="bt-paired-table">
966
+ <thead>
967
+ <tr>
968
+ <th>设备名称</th>
969
+ <th>地址</th>
970
+ <th>状态</th>
971
+ <th>操作</th>
972
+ </tr>
973
+ </thead>
974
+ <tbody>
975
+ <!-- Populated by JS -->
976
+ </tbody>
977
+ </table>
978
+ </div>
979
+ </div>
980
+ </section>
981
+
982
+ <!-- ==================== Voice Chat ==================== -->
983
+
984
+ <!-- ==================== Modules ==================== -->
985
+ <section id="page-modules" class="page">
986
+ <div id="modules-list-header" style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;">
987
+ <div style="display:flex;align-items:center;gap:12px;">
988
+ <h2 class="page-title" style="margin-bottom:0;">模块管理</h2>
989
+ <span id="module-save-status" class="config-save-status"></span>
990
+ </div>
991
+ <div style="display:flex;align-items:center;gap:16px;">
992
+ <button class="btn btn-sm btn-secondary" id="btn-toggle-console">
993
+ <span id="console-toggle-text">展开控制台</span>
994
+ </button>
995
+ <button class="btn btn-warning" id="btn-restart-kite" style="display:flex;align-items:center;gap:6px;">
996
+ <span>重启 Kite</span>
997
+ </button>
998
+ </div>
999
+ </div>
1000
+
1001
+ <!-- Real-time Console (collapsible) -->
1002
+ <div id="realtime-console" class="panel" style="display:none;margin-bottom:20px;">
1003
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
1004
+ <h3 style="margin:0;font-size:14px;font-weight:600;">实时事件日志</h3>
1005
+ <button class="btn btn-sm btn-secondary" id="btn-clear-console">清空</button>
1006
+ </div>
1007
+ <div id="console-output" style="background:#1e1e1e;color:#d4d4d4;padding:12px;border-radius:4px;font-family:monospace;font-size:12px;max-height:300px;overflow-y:auto;white-space:pre-wrap;line-height:1.4;"></div>
1008
+ </div>
1009
+
1010
+ <!-- Statistics Panel -->
1011
+ <div class="panel" style="margin-bottom:20px;" id="statistics-panel">
1012
+ <div class="stats-grid">
1013
+ <div class="stat-item" data-stat-type="uptime">
1014
+ <div class="stat-label">运行时长</div>
1015
+ <div class="stat-value" id="stat-uptime">--</div>
1016
+ </div>
1017
+ <div class="stat-item" data-stat-type="modules">
1018
+ <div class="stat-label">模块数量</div>
1019
+ <div class="stat-value" id="stat-modules">--</div>
1020
+ </div>
1021
+ <div class="stat-item" data-stat-type="registry">
1022
+ <div class="stat-label">注册记录</div>
1023
+ <div class="stat-value" id="stat-registry">--</div>
1024
+ </div>
1025
+ <div class="stat-item" data-stat-type="rpc">
1026
+ <div class="stat-label">RPC 方法</div>
1027
+ <div class="stat-value" id="stat-rpc">--</div>
1028
+ </div>
1029
+ <div class="stat-item" data-stat-type="hooks">
1030
+ <div class="stat-label">Hook 数量</div>
1031
+ <div class="stat-value" id="stat-hooks">--</div>
1032
+ </div>
1033
+ <div class="stat-item" data-stat-type="api">
1034
+ <div class="stat-label">API 端点</div>
1035
+ <div class="stat-value" id="stat-api">--</div>
1036
+ </div>
1037
+ <div class="stat-item" data-stat-type="events">
1038
+ <div class="stat-label">事件处理</div>
1039
+ <div class="stat-value" id="stat-events">--</div>
1040
+ </div>
1041
+ <div class="stat-item" data-stat-type="rpc-calls">
1042
+ <div class="stat-label">RPC 调用</div>
1043
+ <div class="stat-value" id="stat-rpc-calls">--</div>
1044
+ </div>
1045
+ </div>
1046
+ </div>
1047
+
1048
+ <!-- Tooltip for statistics -->
1049
+ <div id="stat-tooltip" class="stat-tooltip"></div>
1050
+
1051
+ <!-- Module List Table -->
1052
+ <div class="panel">
1053
+ <div class="table-wrapper">
1054
+ <table class="data-table" id="modules-table">
1055
+ <thead>
1056
+ <tr>
1057
+ <th style="width:40px;"></th>
1058
+ <th style="max-width:150px;">模块名称</th>
1059
+ <th>显示名称</th>
1060
+ <th>类型</th>
1061
+ <th>版本</th>
1062
+ <th>端口</th>
1063
+ <th>运行状态</th>
1064
+ <th>默认状态</th>
1065
+ <th style="width:180px;">操作</th>
1066
+ </tr>
1067
+ </thead>
1068
+ <tbody id="modules-tbody">
1069
+ <tr><td colspan="9" class="text-muted" style="text-align:center;padding:40px;">加载中...</td></tr>
1070
+ </tbody>
1071
+ </table>
1072
+ </div>
1073
+ </div>
1074
+
1075
+ <!-- Token Management Section -->
1076
+ <div id="token-management-section">
1077
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;margin-top:40px;">
1078
+ <div style="display:flex;align-items:center;gap:12px;">
1079
+ <h2 class="page-title" style="margin-bottom:0;">Token 管理</h2>
1080
+ </div>
1081
+ <div style="display:flex;align-items:center;gap:16px;">
1082
+ <button class="btn btn-sm btn-secondary" onclick="refreshTokens()">刷新</button>
1083
+ </div>
1084
+ </div>
1085
+
1086
+ <div class="panel">
1087
+ <div class="table-wrapper">
1088
+ <table class="data-table" id="tokens-table">
1089
+ <thead>
1090
+ <tr>
1091
+ <th style="width:200px;">Token</th>
1092
+ <th>角色</th>
1093
+ <th>创建时间</th>
1094
+ <th>过期时间</th>
1095
+ <th>状态</th>
1096
+ <th style="width:100px;">操作</th>
1097
+ </tr>
1098
+ </thead>
1099
+ <tbody id="tokens-tbody">
1100
+ <tr><td colspan="6" class="text-muted" style="text-align:center;padding:40px;">加载中...</td></tr>
1101
+ </tbody>
1102
+ </table>
1103
+ </div>
1104
+ </div>
1105
+ </div>
1106
+
1107
+ <!-- Registry Test Section -->
1108
+ <div id="registry-test-section" style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;margin-top:40px;">
1109
+ <div style="display:flex;align-items:center;gap:12px;">
1110
+ <h2 class="page-title" style="margin-bottom:0;">注册中心测试</h2>
1111
+ </div>
1112
+ <div style="display:flex;align-items:center;gap:16px;">
1113
+ <button class="btn btn-sm btn-primary" id="btn-test-registry">运行测试</button>
1114
+ <button class="btn btn-sm btn-secondary" id="btn-clear-test-output">清空输出</button>
1115
+ </div>
1116
+ </div>
1117
+
1118
+ <div class="panel" id="registry-test-output">
1119
+ <div id="test-output" style="background:#1e1e1e;color:#d4d4d4;padding:15px;border-radius:4px;font-family:monospace;font-size:13px;max-height:400px;overflow-y:auto;white-space:pre-wrap;"></div>
1120
+ </div>
1121
+
1122
+ <!-- Module Detail Panel (hidden by default) -->
1123
+ <div id="module-detail" class="hidden">
1124
+ <!-- 第一排:模块名和返回按钮 -->
1125
+ <div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;">
1126
+ <h3 id="module-detail-name" style="font-size:18px;font-weight:600;color:var(--gray-900);margin:0;"></h3>
1127
+ <button class="btn btn-primary btn-sm" id="btn-module-back">返回</button>
1128
+ </div>
1129
+
1130
+ <!-- 第二排:类型状态和操作按钮 -->
1131
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;">
1132
+ <div style="display:flex;align-items:center;gap:12px;">
1133
+ <span id="module-detail-type-badge" class="module-type-badge"></span>
1134
+ <span id="module-detail-run-status" style="font-size:13px;"></span>
1135
+ </div>
1136
+ <div style="display:flex;align-items:center;gap:8px;">
1137
+ <button class="btn btn-sm btn-secondary" id="btn-reset-defaults" onclick="resetModuleDefaults()">恢复默认值</button>
1138
+ <button class="btn btn-sm btn-success" id="btn-detail-start" onclick="startModuleFromDetail()">启动</button>
1139
+ <button class="btn btn-sm btn-danger" id="btn-detail-stop" onclick="stopModuleFromDetail()">停止</button>
1140
+ </div>
1141
+ </div>
1142
+
1143
+ <!-- 【区块1:模块标识】 -->
1144
+ <div class="form-section">
1145
+ <h4 class="form-title">模块标识</h4>
1146
+
1147
+ <!-- 模块路径 -->
1148
+ <div class="form-row">
1149
+ <div class="form-group" style="grid-column: 1 / -1;">
1150
+ <label>模块路径 <span style="font-size:11px;color:var(--gray-400);">(source_path)</span></label>
1151
+ <input type="text" id="mod-source-path" disabled style="background:var(--gray-100);cursor:not-allowed;font-size:12px;font-family:monospace;">
1152
+ </div>
1153
+ </div>
1154
+
1155
+ <div class="form-row">
1156
+ <div class="form-group">
1157
+ <label>模块名 <span style="font-size:11px;color:var(--gray-400);">(name)</span></label>
1158
+ <input type="text" id="mod-meta-name" disabled style="background:var(--gray-100);cursor:not-allowed;">
1159
+ </div>
1160
+ <div class="form-group">
1161
+ <label>模块类型 <span style="font-size:11px;color:var(--gray-400);">(type)</span></label>
1162
+ <input type="text" id="mod-meta-type" disabled style="background:var(--gray-100);cursor:not-allowed;">
1163
+ </div>
1164
+ </div>
1165
+ <div class="form-row">
1166
+ <div class="form-group">
1167
+ <label>运行时 <span style="font-size:11px;color:var(--gray-400);">(runtime)</span></label>
1168
+ <input type="text" id="mod-meta-runtime" disabled style="background:var(--gray-100);cursor:not-allowed;">
1169
+ </div>
1170
+ <div class="form-group">
1171
+ <label>入口文件 <span style="font-size:11px;color:var(--gray-400);">(entry)</span></label>
1172
+ <input type="text" id="mod-meta-entry" disabled style="background:var(--gray-100);cursor:not-allowed;">
1173
+ </div>
1174
+ </div>
1175
+ <div class="form-row">
1176
+ <div class="form-group">
1177
+ <label>版本 <span style="font-size:11px;color:var(--gray-400);">(version)</span></label>
1178
+ <input type="text" id="mod-meta-version" disabled style="background:var(--gray-100);cursor:not-allowed;">
1179
+ </div>
1180
+ <div class="form-group">
1181
+ <label>显示名称 <span style="font-size:11px;color:var(--gray-400);">(display_name)</span></label>
1182
+ <input type="text" id="mod-meta-display-name" data-field="display_name">
1183
+ </div>
1184
+ </div>
1185
+ </div>
1186
+
1187
+ <!-- 【区块2:启动配置】 -->
1188
+ <div class="form-section">
1189
+ <h4 class="form-title">启动配置</h4>
1190
+
1191
+ <div class="form-row">
1192
+ <div class="form-group">
1193
+ <label>默认状态 <span style="font-size:11px;color:var(--gray-400);">(state - 需重启生效)</span></label>
1194
+ <select id="mod-meta-state" data-field="state">
1195
+ <option value="enabled">enabled - 自动启动</option>
1196
+ <option value="manual">manual - 手动启动</option>
1197
+ <option value="disabled">disabled - 禁用</option>
1198
+ </select>
1199
+ </div>
1200
+ <div class="form-group">
1201
+ <label>监控 <span style="font-size:11px;color:var(--gray-400);">(monitor - Watchdog是否监控此模块)</span></label>
1202
+ <select id="mod-meta-monitor" data-field="monitor">
1203
+ <option value="true">启用监控 (默认)</option>
1204
+ <option value="false">禁用监控</option>
1205
+ </select>
1206
+ </div>
1207
+ </div>
1208
+ </div>
1209
+
1210
+ <!-- 【区块3:网络配置】 -->
1211
+ <div class="form-section">
1212
+ <h4 class="form-title">网络配置</h4>
1213
+
1214
+ <div class="form-row">
1215
+ <div class="form-group">
1216
+ <label>首选端口 <span style="font-size:11px;color:var(--gray-400);">(preferred_port)</span></label>
1217
+ <input type="number" id="mod-meta-port" data-field="preferred_port" placeholder="()">
1218
+ </div>
1219
+ <div class="form-group">
1220
+ <label>监听地址 <span style="font-size:11px;color:var(--gray-400);">(advertise_ip)</span></label>
1221
+ <select id="mod-meta-ip" data-field="advertise_ip">
1222
+ <option value="127.0.0.1">127.0.0.1 - 仅本地</option>
1223
+ <option value="0.0.0.0">0.0.0.0 - 允许远程</option>
1224
+ </select>
1225
+ </div>
1226
+ </div>
1227
+ </div>
1228
+
1229
+ <!-- 【区块5:模块配置文件】 -->
1230
+ <div class="form-section hidden" id="module-config-section">
1231
+ <h4 class="form-title">模块配置文件 (config.json5)</h4>
1232
+ <div id="module-config-tree"></div>
1233
+ </div>
1234
+ </div>
1235
+ </section>
1236
+
1237
+ <!-- ==================== Voice Chat ==================== -->
1238
+ <section id="page-voicechat" class="page">
1239
+ <div class="vc-layout">
1240
+
1241
+ <!-- Left: main chat area -->
1242
+ <div class="vc-main">
1243
+ <!-- Status Bar -->
1244
+ <div class="vc-status-bar">
1245
+ <div class="vc-status-indicator" id="vc-status-indicator">
1246
+ <span class="vc-pulse-dot"></span>
1247
+ <span class="vc-status-text" id="vc-status-text">等待开始</span>
1248
+ </div>
1249
+ <span class="vc-call-timer" id="vc-call-timer"></span>
1250
+ </div>
1251
+
1252
+ <!-- Config Info Panel -->
1253
+ <div class="vc-config-panel" id="vc-config-panel">
1254
+ <div class="vc-config-row">
1255
+ <span class="vc-config-label">LLM</span>
1256
+ <span class="vc-config-value" id="vc-cfg-llm">--</span>
1257
+ </div>
1258
+ <div class="vc-config-row">
1259
+ <span class="vc-config-label">ASR</span>
1260
+ <span class="vc-config-value" id="vc-cfg-asr">--</span>
1261
+ </div>
1262
+ <div class="vc-config-row">
1263
+ <span class="vc-config-label">TTS</span>
1264
+ <span class="vc-config-value" id="vc-cfg-tts">--</span>
1265
+ </div>
1266
+ </div>
1267
+
1268
+ <!-- VAD Inline Controls -->
1269
+ <div class="vc-vad-bar">
1270
+ <div class="vc-vad-group">
1271
+ <label class="vc-vad-label" for="vc-vad-threshold">能量阈值</label>
1272
+ <input type="number" id="vc-vad-threshold" class="vc-vad-input" value="300" min="50" max="2000" step="50">
1273
+ </div>
1274
+ <div class="vc-vad-group">
1275
+ <label class="vc-vad-label" for="vc-vad-silence">静音判定(ms)</label>
1276
+ <input type="number" id="vc-vad-silence" class="vc-vad-input" value="800" min="200" max="3000" step="100">
1277
+ </div>
1278
+ <div class="vc-vad-group">
1279
+ <label class="vc-vad-label" for="vc-vad-min-speech">最短语音(ms)</label>
1280
+ <input type="number" id="vc-vad-min-speech" class="vc-vad-input" value="250" min="50" max="1000" step="50">
1281
+ </div>
1282
+ </div>
1283
+
1284
+ <!-- Phone Simulation -->
1285
+ <div class="vc-phone-bar">
1286
+ <div class="vc-phone-group">
1287
+ <label class="vc-phone-label" for="vc-phone-direction">方向</label>
1288
+ <select id="vc-phone-direction" class="vc-phone-select">
1289
+ <option value="incoming">来电 (接入)</option>
1290
+ <option value="outgoing">拨出</option>
1291
+ </select>
1292
+ </div>
1293
+ <div class="vc-phone-group vc-phone-group-num">
1294
+ <label class="vc-phone-label" for="vc-phone-number">号码</label>
1295
+ <input type="text" id="vc-phone-number" class="vc-phone-input" placeholder="13800138000" value="">
1296
+ </div>
1297
+ <div class="vc-phone-group vc-phone-group-name">
1298
+ <label class="vc-phone-label" for="vc-phone-name">姓名</label>
1299
+ <input type="text" id="vc-phone-name" class="vc-phone-input" placeholder="(可选)" value="">
1300
+ </div>
1301
+ </div>
1302
+
1303
+ <!-- System Prompt -->
1304
+ <div class="vc-prompt-bar">
1305
+ <label class="vc-prompt-label" for="vc-system-prompt">系统提示词</label>
1306
+ <textarea id="vc-system-prompt" class="vc-prompt-input" rows="2" placeholder="输入系统提示词... 设定任务目标后 AI 会主动发起对话"></textarea>
1307
+ </div>
1308
+
1309
+ <!-- Waveform Visualization -->
1310
+ <div class="vc-viz" id="vc-viz" style="display:none">
1311
+ <canvas id="vc-canvas" width="600" height="64"></canvas>
1312
+ <div class="vc-vol-row">
1313
+ <span class="vc-vol-label">音量</span>
1314
+ <div class="vc-vol-track"><div id="vc-vol-bar" class="vc-vol-bar"></div></div>
1315
+ <span id="vc-vol-db" class="vc-vol-db">-- dB</span>
1316
+ </div>
1317
+ </div>
1318
+
1319
+ <!-- Chat Messages Area -->
1320
+ <div class="vc-messages" id="vc-messages">
1321
+ <div class="vc-empty-hint" id="vc-empty-hint">点击"开始通话"后对麦克风说话</div>
1322
+ </div>
1323
+
1324
+ <!-- Control Bar -->
1325
+ <div class="vc-controls">
1326
+ <button class="btn btn-lg vc-btn-call" id="vc-btn-start">开始通话</button>
1327
+ <button class="btn btn-lg btn-danger vc-btn-hangup" id="vc-btn-stop" style="display:none">结束通话</button>
1328
+ </div>
1329
+ </div>
1330
+
1331
+ <!-- Right: status log + debug panel -->
1332
+ <div class="vc-sidebar">
1333
+ <div class="vc-sidebar-title">状态日志</div>
1334
+ <div class="vc-log" id="vc-log"></div>
1335
+ <div class="vc-sidebar-title vc-debug-title">调试记录 <span id="vc-debug-count" class="vc-debug-count"></span></div>
1336
+ <div class="vc-debug" id="vc-debug"></div>
1337
+ </div>
1338
+
1339
+ </div>
1340
+ </section>
1341
+
1342
+ <!-- ==================== Dev Log ==================== -->
1343
+ <section id="page-devlog" class="page">
1344
+ <h2 class="page-title">开发记录</h2>
1345
+
1346
+ <!-- New Dev Log Form -->
1347
+ <div class="form-section">
1348
+ <h3 class="form-title">新建开发需求</h3>
1349
+ <form id="form-new-devlog">
1350
+ <div class="form-group">
1351
+ <label for="devlog-content">开发需求 <span class="required">*</span></label>
1352
+ <textarea id="devlog-content" name="content" rows="5" placeholder="描述开发需求..." required></textarea>
1353
+ </div>
1354
+ <div class="form-actions">
1355
+ <button type="submit" class="btn btn-primary">提交</button>
1356
+ <select id="devlog-type" style="padding:4px 8px;border:1px solid var(--gray-300);border-radius:4px;font-size:13px;">
1357
+ <option value="需求">需求</option>
1358
+ <option value="BUG">BUG</option>
1359
+ <option value="优化">优化</option>
1360
+ <option value="重构">重构</option>
1361
+ <option value="澄清">澄清</option>
1362
+ <option value="文档">文档</option>
1363
+ </select>
1364
+ <label class="toggle-switch-label">
1365
+ <input type="checkbox" id="devlog-important">
1366
+ <span class="toggle-switch"></span>
1367
+ <span>重要</span>
1368
+ </label>
1369
+ <label class="toggle-switch-label">
1370
+ <input type="checkbox" id="devlog-urgent">
1371
+ <span class="toggle-switch"></span>
1372
+ <span>优先</span>
1373
+ </label>
1374
+ </div>
1375
+ </form>
1376
+ </div>
1377
+
1378
+ <!-- Dev Log List -->
1379
+ <div class="panel">
1380
+ <h3 class="panel-title">需求记录</h3>
1381
+ <div class="page-actions">
1382
+ <select id="devlog-filter-status" class="btn btn-secondary">
1383
+ <option value="">全部状态</option>
1384
+ <option value="pending">待处理</option>
1385
+ <option value="in_progress">进行中</option>
1386
+ <option value="done">已完成</option>
1387
+ </select>
1388
+ <button class="btn btn-secondary" id="devlog-btn-archive" title="归档指定时间之前的已完成需求">归档</button>
1389
+ <button class="btn btn-secondary" id="devlog-btn-view-archives" title="查看归档记录">查看归档</button>
1390
+ </div>
1391
+ <div class="table-wrapper">
1392
+ <table class="data-table" id="devlog-table">
1393
+ <thead>
1394
+ <tr>
1395
+ <th>内容</th>
1396
+ <th>标记</th>
1397
+ <th>状态</th>
1398
+ <th>创建时间</th>
1399
+ <th>操作</th>
1400
+ </tr>
1401
+ </thead>
1402
+ <tbody id="devlog-tbody">
1403
+ <!-- Populated by JS -->
1404
+ </tbody>
1405
+ </table>
1406
+ </div>
1407
+ <div class="pagination" id="devlog-pagination"></div>
1408
+ </div>
1409
+
1410
+ <!-- Dev Log Detail Modal -->
1411
+ <div class="modal-overlay hidden" id="devlog-detail-modal">
1412
+ <div class="modal">
1413
+ <div class="modal-header">
1414
+ <h3 class="modal-title">需求详情</h3>
1415
+ <button class="modal-close" id="devlog-detail-close">&times;</button>
1416
+ </div>
1417
+ <div class="modal-body">
1418
+ <div class="form-group">
1419
+ <label>需求内容</label>
1420
+ <div id="devlog-detail-content" style="white-space:pre-wrap;line-height:1.6;color:var(--gray-700);"></div>
1421
+ </div>
1422
+ <div class="form-group">
1423
+ <label>类型</label>
1424
+ <select id="devlog-detail-type" style="padding:4px 8px;border:1px solid var(--gray-300);border-radius:4px;font-size:13px;width:auto;">
1425
+ <option value="需求">需求</option>
1426
+ <option value="BUG">BUG</option>
1427
+ <option value="优化">优化</option>
1428
+ <option value="重构">重构</option>
1429
+ <option value="澄清">澄清</option>
1430
+ <option value="文档">文档</option>
1431
+ </select>
1432
+ </div>
1433
+ <div class="form-group">
1434
+ <label>标记</label>
1435
+ <div style="display:flex;gap:12px;align-items:center;">
1436
+ <label class="toggle-switch-label">
1437
+ <input type="checkbox" id="devlog-detail-important">
1438
+ <span class="toggle-switch"></span>
1439
+ <span>重要</span>
1440
+ </label>
1441
+ <label class="toggle-switch-label">
1442
+ <input type="checkbox" id="devlog-detail-urgent">
1443
+ <span class="toggle-switch"></span>
1444
+ <span>优先</span>
1445
+ </label>
1446
+ </div>
1447
+ </div>
1448
+ <div class="form-group">
1449
+ <label>状态</label>
1450
+ <select id="devlog-detail-status">
1451
+ <option value="pending">待处理</option>
1452
+ <option value="in_progress">进行中</option>
1453
+ <option value="done">已完成</option>
1454
+ </select>
1455
+ </div>
1456
+ <div class="form-group">
1457
+ <label>创建时间</label>
1458
+ <span id="devlog-detail-created" class="text-muted"></span>
1459
+ </div>
1460
+ <div class="form-group" id="devlog-detail-completed-group" style="display:none;">
1461
+ <label>完成时间</label>
1462
+ <span id="devlog-detail-completed" class="text-muted"></span>
1463
+ </div>
1464
+ </div>
1465
+ <div class="modal-footer">
1466
+ <button class="btn btn-danger btn-sm" id="devlog-detail-delete">删除</button>
1467
+ <button class="btn btn-primary btn-sm" id="devlog-detail-save">保存</button>
1468
+ </div>
1469
+ </div>
1470
+ </div>
1471
+
1472
+ <!-- Dev Log Archive Cutoff Modal -->
1473
+ <div class="modal-overlay hidden" id="devlog-archive-cutoff-modal">
1474
+ <div class="modal" style="max-width:400px;">
1475
+ <div class="modal-header">
1476
+ <h3 class="modal-title">归档设置</h3>
1477
+ <button class="modal-close" id="devlog-archive-cutoff-close">&times;</button>
1478
+ </div>
1479
+ <div class="modal-body">
1480
+ <p style="font-size:13px;color:var(--gray-500);margin-bottom:12px;">归档此时间之前完成的需求(状态为"已完成"的记录)</p>
1481
+ <div class="form-group">
1482
+ <label for="devlog-archive-cutoff-input">截止时间</label>
1483
+ <input type="datetime-local" id="devlog-archive-cutoff-input" class="form-control" style="width:100%;">
1484
+ <span id="devlog-archive-cutoff-hint" style="font-size:12px;color:var(--gray-400);margin-top:4px;display:block;"></span>
1485
+ </div>
1486
+ </div>
1487
+ <div class="modal-footer">
1488
+ <button class="btn btn-secondary btn-sm" id="devlog-archive-cutoff-cancel">取消</button>
1489
+ <button class="btn btn-primary btn-sm" id="devlog-archive-cutoff-confirm">确认归档</button>
1490
+ </div>
1491
+ </div>
1492
+ </div>
1493
+
1494
+ <!-- Dev Log Archive List Modal -->
1495
+ <div class="modal-overlay hidden" id="devlog-archive-modal">
1496
+ <div class="modal" style="max-width:640px;">
1497
+ <div class="modal-header">
1498
+ <h3 class="modal-title">归档记录</h3>
1499
+ <button class="modal-close" id="devlog-archive-close">&times;</button>
1500
+ </div>
1501
+ <div class="modal-body" id="devlog-archive-body">
1502
+ <p class="text-muted" style="text-align:center;padding:24px;">加载中...</p>
1503
+ </div>
1504
+ </div>
1505
+ </div>
1506
+ </section>
1507
+
1508
+ </main>
1509
+ </div>
1510
+
1511
+ <!-- ===== Bottom Status Bar ===== -->
1512
+ <footer id="status-bar">
1513
+ <div class="status-item">
1514
+ <span class="status-label">蓝牙:</span>
1515
+ <span class="status-value" id="statusbar-bt">未连接</span>
1516
+ </div>
1517
+ <div class="status-item">
1518
+ <span class="status-label">电池:</span>
1519
+ <span class="status-value" id="statusbar-battery">--</span>
1520
+ </div>
1521
+ <div class="status-item">
1522
+ <span class="status-label">信号:</span>
1523
+ <span class="status-value" id="statusbar-signal">--</span>
1524
+ </div>
1525
+ </footer>
1526
+
1527
+ <!-- ===== Modal Component ===== -->
1528
+ <div id="modal-overlay" class="modal-overlay hidden">
1529
+ <div class="modal" id="modal-container">
1530
+ <div class="modal-header">
1531
+ <h3 class="modal-title" id="modal-title">标题</h3>
1532
+ <button class="modal-close" id="modal-close">&times;</button>
1533
+ </div>
1534
+ <div class="modal-body" id="modal-body">
1535
+ <!-- Dynamic modal content -->
1536
+ </div>
1537
+ <div class="modal-footer" id="modal-footer">
1538
+ <!-- Dynamic modal actions -->
1539
+ </div>
1540
+ </div>
1541
+ </div>
1542
+
1543
+ <!-- ===== Reset Module Defaults Dialog ===== -->
1544
+ <div id="reset-defaults-modal" class="modal-overlay hidden">
1545
+ <div class="modal" style="max-width:600px;">
1546
+ <div class="modal-header">
1547
+ <h3 class="modal-title">恢复默认值</h3>
1548
+ <button class="modal-close" id="reset-defaults-close">&times;</button>
1549
+ </div>
1550
+ <div class="modal-body">
1551
+ <p style="margin-bottom:16px;color:var(--gray-600);">以下配置将被恢复为默认值:</p>
1552
+ <table style="width:100%;border-collapse:collapse;">
1553
+ <thead>
1554
+ <tr style="background:var(--gray-100);border-bottom:1px solid var(--gray-300);">
1555
+ <th style="padding:8px;text-align:left;font-weight:600;">字段</th>
1556
+ <th style="padding:8px;text-align:left;font-weight:600;">当前值</th>
1557
+ <th style="padding:8px;text-align:left;font-weight:600;">默认值</th>
1558
+ </tr>
1559
+ </thead>
1560
+ <tbody id="reset-defaults-comparison">
1561
+ <!-- Dynamic content -->
1562
+ </tbody>
1563
+ </table>
1564
+ </div>
1565
+ <div class="modal-footer">
1566
+ <button class="btn btn-secondary" id="reset-defaults-cancel">取消</button>
1567
+ <button class="btn btn-primary" id="reset-defaults-confirm">确认恢复</button>
1568
+ </div>
1569
+ </div>
1570
+ </div>
1571
+
1572
+ <!-- ===== TTS Test Dialog ===== -->
1573
+ <div id="tts-test-overlay" class="asr-test-overlay hidden">
1574
+ <div class="asr-test-dialog" style="width:560px">
1575
+ <div class="asr-test-header">
1576
+ <h3>TTS 语音合成测试</h3>
1577
+ <button type="button" class="asr-test-close" id="tts-test-close">&times;</button>
1578
+ </div>
1579
+ <div class="asr-test-body">
1580
+ <div class="asr-ctrl-bar">
1581
+ <div class="asr-ctrl-row">
1582
+ <label class="asr-ctrl-label">引擎</label>
1583
+ <select id="tts-test-provider" class="asr-ctrl-select" style="flex:1">
1584
+ <option value="edge-tts">Edge TTS</option>
1585
+ <option value="volcengine">火山引擎</option>
1586
+ <option value="tencent">腾讯云</option>
1587
+ <option value="azure">Azure</option>
1588
+ <option value="openai">OpenAI</option>
1589
+ <option value="aliyun">阿里云</option>
1590
+ <option value="local">本地</option>
1591
+ </select>
1592
+ </div>
1593
+ <div class="asr-ctrl-row">
1594
+ <label class="asr-ctrl-label">音色</label>
1595
+ <select id="tts-test-voice" class="asr-ctrl-select" style="flex:1">
1596
+ </select>
1597
+ </div>
1598
+ <div class="asr-ctrl-row">
1599
+ <label class="asr-ctrl-label">语速</label>
1600
+ <input type="range" id="tts-test-speed" class="asr-mic-gain" min="0.5" max="2.0" value="1.0" step="0.1" style="flex:1">
1601
+ <span id="tts-test-speed-val" class="asr-gain-val">1.0x</span>
1602
+ </div>
1603
+ </div>
1604
+ <div class="form-group" style="margin-top:10px">
1605
+ <textarea id="tts-test-text" rows="3" style="width:100%;resize:vertical;font-size:13px" placeholder="输入要合成的文本...">你好,我是AI语音助手,很高兴为你服务。今天天气不错,有什么可以帮你的吗?</textarea>
1606
+ </div>
1607
+ <div id="tts-test-status" class="asr-test-status-text" style="text-align:center;margin:8px 0">点击"合成并播放"开始测试</div>
1608
+ <div id="tts-test-log" class="asr-test-log" style="display:none"></div>
1609
+ </div>
1610
+ <div class="asr-test-footer">
1611
+ <button type="button" class="btn btn-primary" id="tts-test-play">合成并播放</button>
1612
+ <button type="button" class="btn btn-danger" id="tts-test-stop" style="display:none">停止</button>
1613
+ </div>
1614
+ </div>
1615
+ </div>
1616
+
1617
+ <!-- ===== Chat Test Dialog ===== -->
1618
+ <div id="chat-test-overlay" class="chat-test-overlay hidden">
1619
+ <div class="chat-test-dialog">
1620
+ <div class="chat-test-header">
1621
+ <h3>模型测试</h3>
1622
+ <div class="chat-test-controls">
1623
+ <select id="chat-test-provider" class="chat-test-select">
1624
+ <option value="openai">OpenAI</option>
1625
+ <option value="claude">Claude</option>
1626
+ <option value="gemini">Gemini</option>
1627
+ </select>
1628
+ <select id="chat-test-model" class="chat-test-select chat-test-model-select"></select>
1629
+ <button type="button" class="btn btn-sm" id="chat-test-refresh" title="刷新模型列表">刷新</button>
1630
+ <button type="button" class="btn btn-sm" id="chat-test-clear" title="清空对话">清空</button>
1631
+ <button type="button" class="chat-test-close" id="chat-test-close">&times;</button>
1632
+ </div>
1633
+ </div>
1634
+ <div class="chat-test-messages" id="chat-test-messages">
1635
+ <div class="chat-test-empty">选择模型后开始对话</div>
1636
+ </div>
1637
+ <div class="chat-test-footer">
1638
+ <textarea id="chat-test-input" class="chat-test-input" placeholder="输入消息... (Enter 发送, Shift+Enter 换行)" rows="1"></textarea>
1639
+ <button type="button" class="btn btn-primary" id="chat-test-send">发送</button>
1640
+ </div>
1641
+ </div>
1642
+ </div>
1643
+
1644
+ <!-- ===== ASR Test Dialog ===== -->
1645
+ <div id="asr-test-overlay" class="asr-test-overlay hidden">
1646
+ <div class="asr-test-dialog">
1647
+ <div class="asr-test-header">
1648
+ <h3>ASR 语音识别测试</h3>
1649
+ <button type="button" class="asr-test-close" id="asr-test-close">&times;</button>
1650
+ </div>
1651
+ <div class="asr-test-body">
1652
+ <!-- Controls bar: mic select + gain + ASR params -->
1653
+ <div class="asr-ctrl-bar">
1654
+ <div class="asr-ctrl-row">
1655
+ <button type="button" id="asr-mute-btn" class="asr-mute-btn" title="静音/取消静音"><svg class="mic-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="9" y1="22" x2="15" y2="22"/><line class="mic-slash" x1="3" y1="3" x2="21" y2="21"/></svg></button>
1656
+ <select id="asr-test-mic" class="asr-ctrl-select" style="flex:1;min-width:0">
1657
+ <option value="">加载中...</option>
1658
+ </select>
1659
+ <input type="range" id="asr-mic-gain" class="asr-mic-gain" min="0" max="200" value="100" title="麦克风增益">
1660
+ <span id="asr-mic-gain-val" class="asr-gain-val">100%</span>
1661
+ <label class="asr-agc-label" title="自动增益控制"><input type="checkbox" id="asr-agc-toggle" checked> AGC</label>
1662
+ </div>
1663
+ <div class="asr-ctrl-row">
1664
+ <label class="asr-ctrl-label">识别引擎</label>
1665
+ <select id="asr-test-provider" class="asr-ctrl-select" style="width:110px">
1666
+ <option value="volcengine">火山引擎</option>
1667
+ <option value="tencent">腾讯云</option>
1668
+ <option value="xunfei">讯飞</option>
1669
+ <option value="whisper">Whisper</option>
1670
+ </select>
1671
+ <select id="asr-test-resid" class="asr-ctrl-select" style="flex:1;min-width:0">
1672
+ <option value="">加载中...</option>
1673
+ </select>
1674
+ <label class="asr-ctrl-label" style="margin-left:10px">采样率</label>
1675
+ <select id="asr-test-samplerate" class="asr-ctrl-select" style="width:90px">
1676
+ <option value="16000" selected>16 kHz</option>
1677
+ <option value="8000">8 kHz</option>
1678
+ </select>
1679
+ </div>
1680
+ </div>
1681
+ <!-- Status + Timer row -->
1682
+ <div class="asr-test-status-row">
1683
+ <span id="asr-test-status" class="asr-test-status-text">点击"开始录音"后对麦克风说话</span>
1684
+ <span id="asr-test-timer" class="asr-test-timer"></span>
1685
+ </div>
1686
+ <!-- Real-time waveform canvas -->
1687
+ <div class="asr-test-viz">
1688
+ <canvas id="asr-test-canvas" width="660" height="100"></canvas>
1689
+ <div class="asr-test-vol-row">
1690
+ <span class="asr-test-vol-label">音量</span>
1691
+ <div class="asr-test-vol-track">
1692
+ <div id="asr-test-vol-bar" class="asr-test-vol-bar"></div>
1693
+ </div>
1694
+ <span id="asr-test-vol-db" class="asr-test-vol-db">-- dB</span>
1695
+ </div>
1696
+ </div>
1697
+ <!-- Stats -->
1698
+ <div id="asr-test-stats" class="asr-test-stats" style="display:none">
1699
+ <span id="asr-stat-duration">0.0s</span>
1700
+ <span id="asr-stat-bytes">0 KB</span>
1701
+ <span id="asr-stat-packets">0 包</span>
1702
+ <span id="asr-stat-bw">0 kbps</span>
1703
+ </div>
1704
+ <!-- Result -->
1705
+ <div class="asr-test-result-area">
1706
+ <div class="asr-test-result-label">识别结果:</div>
1707
+ <div id="asr-test-result" class="asr-test-result-text"></div>
1708
+ </div>
1709
+ <!-- Playback -->
1710
+ <div id="asr-test-playback" class="asr-test-playback" style="display:none">
1711
+ <button type="button" class="btn btn-sm btn-secondary" id="asr-test-play">回放录音</button>
1712
+ <span id="asr-test-play-dur" class="asr-test-play-dur"></span>
1713
+ </div>
1714
+ <!-- Log -->
1715
+ <div id="asr-test-log" class="asr-test-log" style="display:none"></div>
1716
+ </div>
1717
+ <div class="asr-test-footer">
1718
+ <button type="button" class="btn btn-primary" id="asr-test-start">开始录音</button>
1719
+ <button type="button" class="btn btn-danger" id="asr-test-stop" style="display:none">停止</button>
1720
+ </div>
1721
+ </div>
1722
+ </div>
1723
+
1724
+ <!-- ===== Audio Diagnostic Dialog ===== -->
1725
+ <div id="audio-diag-overlay" class="chat-test-overlay hidden">
1726
+ <div class="chat-test-dialog" style="width:680px;height:auto;max-height:90vh">
1727
+ <div class="chat-test-header">
1728
+ <h3>音频采集诊断</h3>
1729
+ <button type="button" class="chat-test-close" id="audio-diag-close">&times;</button>
1730
+ </div>
1731
+ <div style="padding:20px;overflow-y:auto;flex:1">
1732
+ <div id="audio-diag-log" style="font-family:monospace;font-size:12px;line-height:1.7;background:#0f172a;color:#e2e8f0;border-radius:8px;padding:16px;max-height:60vh;overflow-y:auto;white-space:pre-wrap;word-break:break-all"></div>
1733
+ </div>
1734
+ <div style="padding:14px 20px;border-top:1px solid var(--gray-200);display:flex;gap:10px;flex-wrap:wrap">
1735
+ <button type="button" class="btn btn-primary btn-sm" id="audio-diag-run">开始诊断</button>
1736
+ <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-stop" style="display:none">停止</button>
1737
+ <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-play-sp" style="display:none">回放 ScriptProcessor</button>
1738
+ <button type="button" class="btn btn-secondary btn-sm" id="audio-diag-play-mr" style="display:none">回放 MediaRecorder</button>
1739
+ </div>
1740
+ </div>
1741
+ </div>
1742
+
1743
+ <!-- ===== Toast / Notification Area ===== -->
1744
+ <div id="toast-container"></div>
1745
+
1746
+ <script src="js/kernel-client.js"></script>
1747
+ <script src="js/kernel-client-example.js"></script>
1748
+ <script src="js/registry-tests.js"></script>
1749
+ <script src="js/token-manager.js"></script>
1750
+ <script src="js/app.js?v=65"></script>
1751
+ </body>
1752
+ </html>