@agentunion/kite 1.5.0 → 1.6.1

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 (574) 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/__init__.py +9 -1
  492. package/kite_cli/builders/__init__.py +4 -0
  493. package/kite_cli/builders/base.py +67 -0
  494. package/kite_cli/builders/custom.py +31 -0
  495. package/kite_cli/builders/detector.py +56 -0
  496. package/kite_cli/builders/go.py +34 -0
  497. package/kite_cli/builders/gradle.py +41 -0
  498. package/kite_cli/builders/maven.py +36 -0
  499. package/kite_cli/builders/npm.py +44 -0
  500. package/kite_cli/builders/python.py +37 -0
  501. package/kite_cli/commands/BUILD_GUIDE.md +109 -0
  502. package/kite_cli/commands/build.py +142 -0
  503. package/kite_cli/commands/check.py +60 -0
  504. package/kite_cli/commands/config.py +156 -0
  505. package/kite_cli/commands/deps.py +58 -0
  506. package/kite_cli/commands/deps_install.py +7 -7
  507. package/kite_cli/commands/disable.py +162 -0
  508. package/kite_cli/commands/enable.py +162 -0
  509. package/kite_cli/commands/export.py +96 -0
  510. package/kite_cli/commands/import_cmd.py +110 -0
  511. package/kite_cli/commands/install.py +50 -23
  512. package/kite_cli/commands/install_skill.py +107 -0
  513. package/kite_cli/commands/list.py +128 -31
  514. package/kite_cli/commands/outdated.py +202 -0
  515. package/kite_cli/commands/search.py +33 -17
  516. package/kite_cli/commands/update.py +115 -2
  517. package/kite_cli/commands/venv_setup.py +6 -6
  518. package/kite_cli/commands/why.py +48 -0
  519. package/kite_cli/core/config_manager.py +145 -0
  520. package/kite_cli/core/downloader.py +32 -2
  521. package/kite_cli/main.py +153 -7
  522. package/kite_cli/utils/colors.py +153 -0
  523. package/kite_cli/utils/dependency_graph.py +209 -0
  524. package/kite_cli/utils/process.py +55 -0
  525. package/kite_cli/utils/progress.py +207 -0
  526. package/kite_cli/utils/table.py +101 -0
  527. package/launcher/count_lines.py +192 -43
  528. package/launcher/entry.py +4543 -2802
  529. package/launcher/logging_setup.py +54 -1
  530. package/launcher/module.md +32 -6
  531. package/launcher/module_scanner.py +93 -20
  532. package/launcher/process_manager.py +355 -76
  533. package/main.py +6 -0
  534. package/package.json +4 -1
  535. package/requirements.txt +41 -38
  536. package/scripts/auto-fix-deps.py +128 -0
  537. package/scripts/env-manager.js +25 -2
  538. package/scripts/final-test.js +78 -0
  539. package/scripts/setup-python-env.js +700 -191
  540. package/scripts/test-alluser.js +48 -0
  541. package/scripts/test-different-version.js +86 -0
  542. package/scripts/test-direct.js +63 -0
  543. package/scripts/test-extract-installer.js +28 -0
  544. package/scripts/test-install-log.js +54 -0
  545. package/scripts/test-installer.js +39 -0
  546. package/scripts/test-integration.js +250 -0
  547. package/scripts/test-real-install.js +210 -0
  548. package/scripts/test-targetdir.js +49 -0
  549. package/scripts/test-venv-real.js +47 -0
  550. package/scripts/test-venv-simple.js +57 -0
  551. package/scripts/test-wait.js +49 -0
  552. package/scripts/test-with-log.js +63 -0
  553. package/extensions/services/evol/config.yaml +0 -149
  554. package/extensions/services/evol/routes/routes_management_ws.py +0 -127
  555. package/extensions/services/evol/static/index_evol.html +0 -14
  556. package/extensions/services/evol/static/js/app.js +0 -6304
  557. package/extensions/services/evol/static/js/auth.js +0 -326
  558. package/extensions/services/evol/static/js/evol-app-fixed.js +0 -50
  559. package/extensions/services/evol/static/js/evol-app.js.bak +0 -1800
  560. package/extensions/services/evol/static/js/kernel-client-example.js +0 -228
  561. package/extensions/services/evol/static/js/main.js +0 -141
  562. package/extensions/services/evol/static/js/stats.js +0 -217
  563. package/extensions/services/evol/static/js/token-manager.js +0 -175
  564. package/extensions/services/proxy/CHANGELOG_20260308.md +0 -258
  565. package/extensions/services/proxy/_fix_prints.py +0 -133
  566. package/extensions/services/proxy/_fix_prints2.py +0 -87
  567. package/extensions/services/proxy/console_auth.py +0 -109
  568. package/extensions/services/proxy/logs/websocket.log +0 -260
  569. package/extensions/services/proxy/main.py +0 -240
  570. package/extensions/services/proxy/requirements.txt +0 -13
  571. package/extensions/services/web/config.yaml +0 -149
  572. /package/extensions/services/{evol → kite_console}/static/pairing.html +0 -0
  573. /package/extensions/services/{evol → kite_console}/static/test_registry.html +0 -0
  574. /package/extensions/services/{evol → kite_console}/static/test_relay.html +0 -0
@@ -0,0 +1,1708 @@
1
+ # Evol 控制台插件化架构设计
2
+
3
+ ## 一、概述
4
+
5
+ Evol 控制台采用插件化架构,模块通过注册中心声明控制台面板,前端动态加载并渲染。核心理念:
6
+
7
+ - **数据主权在模块**:模块决定暴露什么数据和操作
8
+ - **权限控制在模块**:模块检查每个 RPC 调用的权限
9
+ - **前端只负责渲染**:根据配置加载数据并渲染 UI
10
+ - **注册中心是发现机制**:前端通过注册中心发现可用面板
11
+
12
+ ---
13
+
14
+ ## 二、架构图
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────────┐
18
+ │ 浏览器 │
19
+ │ ┌───────────────────────────────────────────────┐ │
20
+ │ │ Evol 控制台 (http://127.0.0.1:18766) │ │
21
+ │ │ │ │
22
+ │ │ ┌─────────────────────────────────────────┐ │ │
23
+ │ │ │ 主框架 (evol-app.js) │ │ │
24
+ │ │ │ - 查询 Registry 获取面板列表 │ │ │
25
+ │ │ │ - 动态加载面板 JS │ │ │
26
+ │ │ │ - 提供 KernelClient │ │ │
27
+ │ │ └─────────────────────────────────────────┘ │ │
28
+ │ │ │ │
29
+ │ │ ┌─────────────────────────────────────────┐ │ │
30
+ │ │ │ 面板容器 │ │ │
31
+ │ │ │ - LauncherPanel (panels/launcher.js) │ │ │
32
+ │ │ │ - WatchdogPanel (panels/watchdog.js) │ │ │
33
+ │ │ │ - GenericTablePanel (通用渲染器) │ │ │
34
+ │ │ └─────────────────────────────────────────┘ │ │
35
+ │ │ │ │
36
+ │ │ ┌─────────────────────────────────────────┐ │ │
37
+ │ │ │ KernelClient (kernel-client.js) │ │ │
38
+ │ │ │ - 单一 WebSocket 连接 │ │ │
39
+ │ │ │ - rpc(method, params) │ │ │
40
+ │ │ │ - subscribe(event, handler) │ │ │
41
+ │ │ └─────────────────────────────────────────┘ │ │
42
+ │ └───────────────────────────────────────────────┘ │
43
+ └─────────────────────────────────────────────────────┘
44
+ ↓ WebSocket (单一连接)
45
+ ┌─────────────────────────────────────────────────────┐
46
+ │ Kernel (ws://127.0.0.1:18767/ws) │
47
+ │ ┌───────────────────────────────────────────────┐ │
48
+ │ │ RPC 路由器 │ │
49
+ │ │ - 解析 method: "launcher.list_modules" │ │
50
+ │ │ - 查询 Registry 找到 Launcher WebSocket │ │
51
+ │ │ - 转发 RPC 到 Launcher │ │
52
+ │ │ - 返回结果给前端 │ │
53
+ │ └───────────────────────────────────────────────┘ │
54
+ └─────────────────────────────────────────────────────┘
55
+ ↓ WebSocket ↓ WebSocket ↓ WebSocket
56
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
57
+ │ Launcher │ │ Watchdog │ │ Logs │
58
+ │ (连接到 Kernel) │ │ (连接到 Kernel) │ │ (连接到 Kernel) │
59
+ │ │ │ │ │ │
60
+ │ 注册 RPC: │ │ 注册 RPC: │ │ 注册 RPC: │
61
+ │ - list_modules │ │ - get_stats │ │ - search │
62
+ │ - start_module │ │ - get_history │ │ - get_changes │
63
+ │ - stop_module │ │ │ │ │
64
+ └──────────────────┘ └──────────────────┘ └──────────────────┘
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 三、面板暴露控制
70
+
71
+ ### 3.1 两级控制机制
72
+
73
+ 面板是否暴露由两个参数控制:
74
+
75
+ 1. **`has_console_panel`**(模块级):模块是否提供控制台面板
76
+ 2. **`enabled`**(配置级):面板是否启用(可在配置文件中动态控制)
77
+
78
+ ### 3.2 控制逻辑
79
+
80
+ ```python
81
+ # module.md (模块元数据)
82
+ ---
83
+ name: launcher
84
+ type: core
85
+ has_console_panel: true # 模块提供控制台面板
86
+ ---
87
+ ```
88
+
89
+ ```yaml
90
+ # config.yaml (模块配置文件)
91
+ console_panel:
92
+ enabled: true # 面板是否启用(可动态修改)
93
+ ```
94
+
95
+ ### 3.3 注册逻辑
96
+
97
+ ```python
98
+ # 模块注册时
99
+ def should_register_panel():
100
+ # 1. 检查模块是否提供面板
101
+ if not module_metadata.has_console_panel:
102
+ return False
103
+
104
+ # 2. 检查配置是否启用
105
+ if not config.get('console_panel.enabled', False):
106
+ return False
107
+
108
+ return True
109
+
110
+ # 注册到 Registry
111
+ if should_register_panel():
112
+ registry.register({
113
+ "module_id": "launcher",
114
+ "metadata": {
115
+ "console_panel": {
116
+ "enabled": True, # 最终状态
117
+ "panel_id": "launcher",
118
+ "title": "模块管理",
119
+ # ...
120
+ }
121
+ }
122
+ })
123
+ ```
124
+
125
+ ### 3.4 场景说明
126
+
127
+ | has_console_panel | config.enabled | 结果 | 说明 |
128
+ |-------------------|----------------|------|------|
129
+ | `false` | - | 不注册 | 模块不提供面板 |
130
+ | `true` | `false` | 不注册 | 面板被禁用 |
131
+ | `true` | `true` | 注册 | 面板启用 |
132
+ | `true` | 未配置 | 不注册 | 默认不启用 |
133
+
134
+ ---
135
+
136
+ ## 四、模块注册协议
137
+
138
+ ### 4.1 完整注册示例
139
+
140
+ ```python
141
+ # Launcher 模块注册
142
+ {
143
+ "module_id": "launcher",
144
+ "metadata": {
145
+ "console_panel": {
146
+ # 基础配置
147
+ "enabled": True, # 最终启用状态
148
+ "panel_id": "launcher", # 面板标识符
149
+ "title": "模块管理", # 菜单显示名称
150
+ "icon": "grid", # 图标(可选)
151
+ "order": 1, # 菜单排序权重
152
+ "category": "system", # 分类(system/service/tool)
153
+
154
+ # 数据源配置
155
+ "data_sources": [
156
+ {
157
+ "id": "modules_list",
158
+ "rpc_method": "launcher.list_modules",
159
+ "params": {},
160
+ "refresh": {
161
+ "strategy": "event", # event | polling | manual | hybrid
162
+ "events": [
163
+ "module.started",
164
+ "module.stopped",
165
+ "module.crashed"
166
+ ]
167
+ }
168
+ },
169
+ {
170
+ "id": "module_stats",
171
+ "rpc_method": "launcher.get_stats",
172
+ "params": {},
173
+ "refresh": {
174
+ "strategy": "polling",
175
+ "interval": 5000 # 5秒轮询
176
+ }
177
+ }
178
+ ],
179
+
180
+ # 操作方法
181
+ "actions": [
182
+ {
183
+ "id": "start_module",
184
+ "rpc_method": "launcher.start_module",
185
+ "params_schema": {
186
+ "name": "string"
187
+ }
188
+ },
189
+ {
190
+ "id": "stop_module",
191
+ "rpc_method": "launcher.stop_module",
192
+ "params_schema": {
193
+ "name": "string",
194
+ "reason": "string"
195
+ }
196
+ }
197
+ ],
198
+
199
+ # UI 提示(可选,给通用渲染器使用)
200
+ "ui_hints": {
201
+ "type": "table", # table | form | dashboard
202
+ "columns": [
203
+ {"field": "name", "label": "模块名", "width": "200px"},
204
+ {"field": "type", "label": "类型", "width": "100px"},
205
+ {"field": "state", "label": "状态", "width": "100px"}
206
+ ],
207
+ "row_actions": [
208
+ {
209
+ "action_id": "start_module",
210
+ "label": "启动",
211
+ "style": "success",
212
+ "confirm": null
213
+ },
214
+ {
215
+ "action_id": "stop_module",
216
+ "label": "停止",
217
+ "style": "danger",
218
+ "confirm": "确定要停止该模块吗?"
219
+ }
220
+ ]
221
+ }
222
+ }
223
+ },
224
+
225
+ # 注册 RPC 方法
226
+ "rpc_methods": {
227
+ "list_modules": {
228
+ "description": "列出所有模块",
229
+ "params": {},
230
+ "returns": {"modules": "array"}
231
+ },
232
+ "start_module": {
233
+ "description": "启动模块",
234
+ "params": {"name": "string"},
235
+ "returns": {"success": "boolean"}
236
+ },
237
+ "stop_module": {
238
+ "description": "停止模块",
239
+ "params": {"name": "string", "reason": "string"},
240
+ "returns": {"success": "boolean"}
241
+ },
242
+ "get_stats": {
243
+ "description": "获取统计信息",
244
+ "params": {},
245
+ "returns": {
246
+ "total": "number",
247
+ "running": "number",
248
+ "stopped": "number"
249
+ }
250
+ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### 4.2 配置字段说明
256
+
257
+ #### 基础配置
258
+
259
+ | 字段 | 类型 | 必填 | 说明 |
260
+ |------|------|------|------|
261
+ | `enabled` | boolean | 是 | 面板是否启用 |
262
+ | `panel_id` | string | 是 | 面板标识符,对应前端 JS 文件名 |
263
+ | `title` | string | 是 | 菜单显示名称 |
264
+ | `icon` | string | 否 | 图标名称 |
265
+ | `order` | number | 否 | 菜单排序权重(越小越靠前) |
266
+ | `category` | string | 否 | 分类(system/service/tool) |
267
+
268
+ #### 数据源配置
269
+
270
+ | 字段 | 类型 | 必填 | 说明 |
271
+ |------|------|------|------|
272
+ | `id` | string | 是 | 数据源标识符 |
273
+ | `rpc_method` | string | 是 | RPC 方法名(格式:`module_id.method_name`) |
274
+ | `params` | object | 否 | RPC 调用参数 |
275
+ | `refresh.strategy` | string | 是 | 刷新策略(event/polling/manual/hybrid) |
276
+ | `refresh.events` | array | 否 | 订阅的事件列表(strategy=event 时必填) |
277
+ | `refresh.interval` | number | 否 | 轮询间隔(毫秒,strategy=polling 时必填) |
278
+
279
+ #### 操作配置
280
+
281
+ | 字段 | 类型 | 必填 | 说明 |
282
+ |------|------|------|------|
283
+ | `id` | string | 是 | 操作标识符 |
284
+ | `rpc_method` | string | 是 | RPC 方法名 |
285
+ | `params_schema` | object | 否 | 参数 schema |
286
+
287
+ #### UI 提示(可选)
288
+
289
+ | 字段 | 类型 | 必填 | 说明 |
290
+ |------|------|------|------|
291
+ | `type` | string | 是 | 渲染器类型(table/form/dashboard) |
292
+ | `columns` | array | 否 | 表格列配置(type=table 时使用) |
293
+ | `row_actions` | array | 否 | 行操作配置(type=table 时使用) |
294
+
295
+ ---
296
+
297
+ ## 五、刷新策略
298
+
299
+ ### 5.1 策略类型
300
+
301
+ | 策略 | 说明 | 适用场景 |
302
+ |------|------|---------|
303
+ | `event` | 事件驱动刷新 | 数据变化有事件通知(如模块状态变化) |
304
+ | `polling` | 定时轮询刷新 | 数据需要定期更新(如资源监控) |
305
+ | `manual` | 手动刷新 | 数据不需要自动更新(如历史记录) |
306
+ | `hybrid` | 混合策略 | 同时使用事件和轮询 |
307
+
308
+ ### 5.2 配置示例
309
+
310
+ #### 事件驱动
311
+
312
+ ```python
313
+ "refresh": {
314
+ "strategy": "event",
315
+ "events": [
316
+ "module.started",
317
+ "module.stopped",
318
+ "module.crashed"
319
+ ]
320
+ }
321
+ ```
322
+
323
+ #### 定时轮询
324
+
325
+ ```python
326
+ "refresh": {
327
+ "strategy": "polling",
328
+ "interval": 5000 # 5秒
329
+ }
330
+ ```
331
+
332
+ #### 手动刷新
333
+
334
+ ```python
335
+ "refresh": {
336
+ "strategy": "manual"
337
+ }
338
+ ```
339
+
340
+ #### 混合策略
341
+
342
+ ```python
343
+ "refresh": {
344
+ "strategy": "hybrid",
345
+ "polling": {
346
+ "interval": 10000 # 10秒轮询
347
+ },
348
+ "events": [
349
+ "watchdog.resource.warning",
350
+ "watchdog.resource.critical"
351
+ ]
352
+ }
353
+ ```
354
+
355
+ ---
356
+
357
+ ## 六、前端实现
358
+
359
+ ### 6.1 目录结构
360
+
361
+ ```
362
+ evol/static/
363
+ ├── index.html
364
+ ├── js/
365
+ │ ├── evol-app.js # 主应用
366
+ │ ├── kernel-client.js # Kernel WebSocket 客户端
367
+ │ ├── base-panel.js # 面板基类
368
+ │ ├── panel-loader.js # 面板加载器
369
+ │ ├── event-bus.js # 全局事件总线
370
+ │ └── state-manager.js # 全局状态管理
371
+ ├── panels/ # 面板实现
372
+ │ ├── launcher.js # Launcher 自定义面板
373
+ │ ├── watchdog.js # Watchdog 自定义面板
374
+ │ ├── logs.js # Logs 自定义面板
375
+ │ ├── generic-table.js # 通用表格渲染器
376
+ │ ├── generic-form.js # 通用表单渲染器
377
+ │ └── generic-dashboard.js # 通用仪表盘渲染器
378
+ └── css/
379
+ ├── style.css # 全局样式
380
+ └── panel.css # 面板通用样式
381
+ ```
382
+
383
+ ### 6.2 面板加载流程
384
+
385
+ ```javascript
386
+ // evol/static/js/evol-app.js
387
+ class EvolConsole {
388
+ async init() {
389
+ // 1. 连接 Kernel
390
+ await this.connectKernel();
391
+
392
+ // 2. 查询所有面板
393
+ await this.loadPanels();
394
+
395
+ // 3. 构建菜单
396
+ this.buildMenu();
397
+
398
+ // 4. 订阅系统事件
399
+ this.subscribeSystemEvents();
400
+
401
+ // 5. 加载默认面板
402
+ if (this.panels.length > 0) {
403
+ await this.loadPanel(this.panels[0]);
404
+ }
405
+ }
406
+
407
+ async loadPanels() {
408
+ // 查询 Registry 获取所有声明了 console_panel 的模块
409
+ const modules = await this.kernel.rpc('registry.query', {
410
+ filter: 'metadata.console_panel.enabled == true'
411
+ });
412
+
413
+ this.panels = modules
414
+ .map(m => m.metadata.console_panel)
415
+ .filter(p => p.enabled) // 二次过滤
416
+ .sort((a, b) => (a.order || 999) - (b.order || 999));
417
+
418
+ stateManager.setState({ modules: this.panels });
419
+ }
420
+
421
+ async loadPanel(panelConfig) {
422
+ const container = document.getElementById('panel-container');
423
+ await this.panelLoader.loadPanel(panelConfig, container);
424
+
425
+ stateManager.setState({ activeModule: panelConfig.panel_id });
426
+ eventBus.emit('panel:loaded', panelConfig);
427
+ }
428
+ }
429
+ ```
430
+
431
+ ### 6.3 面板渲染决策
432
+
433
+ ```javascript
434
+ // evol/static/js/panel-loader.js
435
+ class PanelLoader {
436
+ async loadPanel(panelConfig, container) {
437
+ const panelId = panelConfig.panel_id;
438
+
439
+ try {
440
+ // 策略 1:尝试加载自定义面板
441
+ const panel = await this.loadCustomPanel(panelId, panelConfig, container);
442
+ this.currentPanel = panel;
443
+
444
+ } catch (error) {
445
+ console.warn(`Custom panel ${panelId}.js not found:`, error);
446
+
447
+ // 策略 2:使用通用渲染器
448
+ const panel = await this.loadGenericPanel(panelConfig, container);
449
+ this.currentPanel = panel;
450
+ }
451
+ }
452
+
453
+ async loadCustomPanel(panelId, panelConfig, container) {
454
+ // 尝试加载自定义面板 JS
455
+ const panelPath = `/panels/${panelId}.js`;
456
+ const module = await import(panelPath);
457
+ const PanelClass = module.default;
458
+
459
+ // 实例化
460
+ const panel = new PanelClass(container, this.kernel, panelConfig);
461
+ await panel.onMount();
462
+
463
+ return panel;
464
+ }
465
+
466
+ async loadGenericPanel(panelConfig, container) {
467
+ // 根据 ui_hints 选择通用渲染器
468
+ const renderer = this.selectGenericRenderer(panelConfig);
469
+
470
+ const module = await import(`/panels/${renderer}.js`);
471
+ const PanelClass = module.default;
472
+
473
+ const panel = new PanelClass(container, this.kernel, panelConfig);
474
+ await panel.onMount();
475
+
476
+ return panel;
477
+ }
478
+
479
+ selectGenericRenderer(panelConfig) {
480
+ const uiType = panelConfig.ui_hints?.type;
481
+
482
+ if (uiType === 'table') return 'generic-table';
483
+ if (uiType === 'form') return 'generic-form';
484
+ if (uiType === 'dashboard') return 'generic-dashboard';
485
+
486
+ // 默认使用表格渲染器
487
+ return 'generic-table';
488
+ }
489
+ }
490
+ ```
491
+
492
+ ### 6.4 Base Panel(面板基类)
493
+
494
+ ```javascript
495
+ // evol/static/js/base-panel.js
496
+ export class BasePanel {
497
+ constructor(container, kernelClient, panelConfig) {
498
+ this.container = container;
499
+ this.kernel = kernelClient;
500
+ this.config = panelConfig;
501
+ this.subscriptions = [];
502
+ this.state = {};
503
+ this.mounted = false;
504
+
505
+ // 数据源管理
506
+ this.dataSources = new Map(); // id -> { data, loading, error }
507
+ this.refreshTimers = new Map(); // id -> timer
508
+ }
509
+
510
+ async onMount() {
511
+ this.mounted = true;
512
+
513
+ // 自动初始化所有数据源
514
+ if (this.config.data_sources) {
515
+ await this.initDataSources();
516
+ }
517
+ }
518
+
519
+ async onUnmount() {
520
+ this.mounted = false;
521
+
522
+ // 清理所有订阅
523
+ this.subscriptions.forEach(unsub => unsub());
524
+ this.subscriptions = [];
525
+
526
+ // 清理所有定时器
527
+ this.refreshTimers.forEach(timer => clearInterval(timer));
528
+ this.refreshTimers.clear();
529
+ }
530
+
531
+ async initDataSources() {
532
+ for (const source of this.config.data_sources) {
533
+ // 初始化数据源状态
534
+ this.dataSources.set(source.id, {
535
+ data: null,
536
+ loading: false,
537
+ error: null
538
+ });
539
+
540
+ // 加载初始数据
541
+ await this.loadDataSource(source.id);
542
+
543
+ // 设置刷新策略
544
+ this.setupRefreshStrategy(source);
545
+ }
546
+ }
547
+
548
+ async loadDataSource(sourceId, showLoading = true) {
549
+ const source = this.config.data_sources.find(s => s.id === sourceId);
550
+ if (!source) return;
551
+
552
+ const state = this.dataSources.get(sourceId);
553
+
554
+ if (showLoading) {
555
+ state.loading = true;
556
+ this.onDataSourceChange(sourceId, state);
557
+ }
558
+
559
+ try {
560
+ const result = await this.rpc(source.rpc_method, source.params || {});
561
+
562
+ state.data = result;
563
+ state.loading = false;
564
+ state.error = null;
565
+
566
+ this.onDataSourceChange(sourceId, state);
567
+
568
+ } catch (error) {
569
+ state.loading = false;
570
+ state.error = error.message;
571
+
572
+ this.onDataSourceChange(sourceId, state);
573
+ this.showError(`加载 ${sourceId} 失败: ${error.message}`);
574
+ }
575
+ }
576
+
577
+ setupRefreshStrategy(source) {
578
+ const { refresh } = source;
579
+
580
+ if (!refresh) return;
581
+
582
+ // 事件驱动刷新
583
+ if (refresh.strategy === 'event' || refresh.strategy === 'hybrid') {
584
+ refresh.events?.forEach(event => {
585
+ const unsubscribe = this.kernel.subscribe(event, () => {
586
+ this.loadDataSource(source.id, false); // 静默刷新
587
+ });
588
+ this.subscriptions.push(unsubscribe);
589
+ });
590
+ }
591
+
592
+ // 轮询刷新
593
+ if (refresh.strategy === 'polling' || refresh.strategy === 'hybrid') {
594
+ const interval = refresh.polling?.interval || refresh.interval || 5000;
595
+ const timer = setInterval(() => {
596
+ this.loadDataSource(source.id, false); // 静默刷新
597
+ }, interval);
598
+ this.refreshTimers.set(source.id, timer);
599
+ }
600
+
601
+ // 手动刷新(不做任何自动刷新)
602
+ // strategy === 'manual'
603
+ }
604
+
605
+ // 子类重写此方法来响应数据变化
606
+ onDataSourceChange(sourceId, state) {
607
+ // 默认实现:触发重新渲染
608
+ this.render();
609
+ }
610
+
611
+ // 获取数据源数据
612
+ getData(sourceId) {
613
+ return this.dataSources.get(sourceId)?.data;
614
+ }
615
+
616
+ // 检查数据源是否加载中
617
+ isLoading(sourceId) {
618
+ return this.dataSources.get(sourceId)?.loading || false;
619
+ }
620
+
621
+ // 获取数据源错误
622
+ getError(sourceId) {
623
+ return this.dataSources.get(sourceId)?.error;
624
+ }
625
+
626
+ // 手动刷新数据源
627
+ async refreshDataSource(sourceId) {
628
+ await this.loadDataSource(sourceId, true);
629
+ }
630
+
631
+ // 执行操作
632
+ async executeAction(actionId, params) {
633
+ const action = this.config.actions?.find(a => a.id === actionId);
634
+ if (!action) {
635
+ throw new Error(`Action not found: ${actionId}`);
636
+ }
637
+
638
+ try {
639
+ const result = await this.rpc(action.rpc_method, params);
640
+ return result;
641
+ } catch (error) {
642
+ this.showError(`操作失败: ${error.message}`);
643
+ throw error;
644
+ }
645
+ }
646
+
647
+ // RPC 调用
648
+ async rpc(method, params = {}) {
649
+ return await this.kernel.rpc(method, params);
650
+ }
651
+
652
+ // 订阅事件
653
+ subscribe(eventPattern, handler) {
654
+ const unsubscribe = this.kernel.subscribe(eventPattern, handler);
655
+ this.subscriptions.push(unsubscribe);
656
+ return unsubscribe;
657
+ }
658
+
659
+ // 渲染方法(子类实现)
660
+ render() {
661
+ // 子类重写
662
+ }
663
+
664
+ showError(message) {
665
+ console.error(message);
666
+ // 可以集成 toast 通知
667
+ }
668
+ }
669
+ ```
670
+
671
+ ---
672
+
673
+ ## 七、自定义面板开发
674
+
675
+ ### 7.1 Launcher 面板示例
676
+
677
+ ```javascript
678
+ // evol/static/panels/launcher.js
679
+ import { BasePanel } from '../js/base-panel.js';
680
+
681
+ export default class LauncherPanel extends BasePanel {
682
+ async onMount() {
683
+ // 调用父类初始化(自动加载数据源)
684
+ await super.onMount();
685
+
686
+ // 渲染 UI
687
+ this.render();
688
+
689
+ // 绑定事件
690
+ this.bindEvents();
691
+ }
692
+
693
+ // 响应数据变化(自动调用)
694
+ onDataSourceChange(sourceId, state) {
695
+ if (sourceId === 'modules_list') {
696
+ this.renderModuleList();
697
+ } else if (sourceId === 'module_stats') {
698
+ this.renderStats();
699
+ }
700
+ }
701
+
702
+ render() {
703
+ this.container.innerHTML = `
704
+ <div class="launcher-panel">
705
+ <div class="panel-header">
706
+ <h2>模块管理</h2>
707
+ <div class="actions">
708
+ <input type="text" id="module-filter" placeholder="搜索模块...">
709
+ <button id="btn-refresh">刷新</button>
710
+ </div>
711
+ </div>
712
+
713
+ <div class="statistics" id="module-stats"></div>
714
+
715
+ <table class="module-table">
716
+ <thead>
717
+ <tr>
718
+ <th>模块名</th>
719
+ <th>类型</th>
720
+ <th>状态</th>
721
+ <th>运行状态</th>
722
+ <th>操作</th>
723
+ </tr>
724
+ </thead>
725
+ <tbody id="modules-tbody"></tbody>
726
+ </table>
727
+ </div>
728
+ `;
729
+
730
+ // 初始渲染
731
+ this.renderModuleList();
732
+ this.renderStats();
733
+ }
734
+
735
+ renderModuleList() {
736
+ const tbody = this.container.querySelector('#modules-tbody');
737
+
738
+ // 获取数据(自动管理)
739
+ const modules = this.getData('modules_list')?.modules || [];
740
+ const loading = this.isLoading('modules_list');
741
+
742
+ if (loading) {
743
+ tbody.innerHTML = '<tr><td colspan="5">加载中...</td></tr>';
744
+ return;
745
+ }
746
+
747
+ if (modules.length === 0) {
748
+ tbody.innerHTML = '<tr><td colspan="5">暂无模块</td></tr>';
749
+ return;
750
+ }
751
+
752
+ tbody.innerHTML = modules.map(mod => {
753
+ const running = mod.actual_state?.startsWith('running');
754
+
755
+ return `
756
+ <tr>
757
+ <td>${mod.name}</td>
758
+ <td>${mod.type}</td>
759
+ <td>${mod.state}</td>
760
+ <td>${running ? '运行中' : '已停止'}</td>
761
+ <td>
762
+ ${this.renderActionButton(mod, running)}
763
+ </td>
764
+ </tr>
765
+ `;
766
+ }).join('');
767
+ }
768
+
769
+ renderActionButton(mod, running) {
770
+ if (mod.state === 'disabled' || ['kernel', 'launcher'].includes(mod.name)) {
771
+ return '-';
772
+ }
773
+
774
+ if (running) {
775
+ return `<button class="btn-danger" data-action="stop" data-module="${mod.name}">停止</button>`;
776
+ } else {
777
+ return `<button class="btn-success" data-action="start" data-module="${mod.name}">启动</button>`;
778
+ }
779
+ }
780
+
781
+ renderStats() {
782
+ const stats = this.getData('module_stats');
783
+ if (!stats) return;
784
+
785
+ const statsEl = this.container.querySelector('#module-stats');
786
+ statsEl.innerHTML = `
787
+ <div class="stat-item">
788
+ <span>总数</span>
789
+ <span>${stats.total}</span>
790
+ </div>
791
+ <div class="stat-item">
792
+ <span>运行中</span>
793
+ <span>${stats.running}</span>
794
+ </div>
795
+ <div class="stat-item">
796
+ <span>已停止</span>
797
+ <span>${stats.stopped}</span>
798
+ </div>
799
+ `;
800
+ }
801
+
802
+ bindEvents() {
803
+ // 刷新按钮
804
+ this.container.querySelector('#btn-refresh').addEventListener('click', () => {
805
+ this.refreshDataSource('modules_list');
806
+ this.refreshDataSource('module_stats');
807
+ });
808
+
809
+ // 模块操作(事件委托)
810
+ this.container.querySelector('#modules-tbody').addEventListener('click', async (e) => {
811
+ const btn = e.target.closest('[data-action]');
812
+ if (!btn) return;
813
+
814
+ const action = btn.dataset.action;
815
+ const moduleName = btn.dataset.module;
816
+
817
+ btn.disabled = true;
818
+ btn.textContent = '操作中...';
819
+
820
+ try {
821
+ if (action === 'start') {
822
+ await this.executeAction('start_module', { name: moduleName });
823
+ // 等待 module.started 事件自动刷新
824
+ } else if (action === 'stop') {
825
+ await this.executeAction('stop_module', {
826
+ name: moduleName,
827
+ reason: 'user_request'
828
+ });
829
+ // 等待 module.stopped 事件自动刷新
830
+ }
831
+ } catch (error) {
832
+ // 错误已在 executeAction 中处理
833
+ btn.disabled = false;
834
+ this.renderModuleList(); // 恢复按钮状态
835
+ }
836
+ });
837
+ }
838
+ }
839
+ ```
840
+
841
+ ---
842
+
843
+ ## 八、通用渲染器
844
+
845
+ ### 8.1 通用表格渲染器
846
+
847
+ ```javascript
848
+ // evol/static/panels/generic-table.js
849
+ import { BasePanel } from '../js/base-panel.js';
850
+
851
+ export default class GenericTablePanel extends BasePanel {
852
+ async onMount() {
853
+ await super.onMount(); // 自动加载数据源
854
+ this.render();
855
+ this.bindEvents();
856
+ }
857
+
858
+ onDataSourceChange(sourceId, state) {
859
+ this.renderTable();
860
+ }
861
+
862
+ render() {
863
+ const { title, ui_hints } = this.config;
864
+ const columns = ui_hints?.columns || [];
865
+
866
+ this.container.innerHTML = `
867
+ <div class="generic-table-panel">
868
+ <div class="panel-header">
869
+ <h2>${title}</h2>
870
+ <button id="btn-refresh">刷新</button>
871
+ </div>
872
+
873
+ <table class="data-table">
874
+ <thead>
875
+ <tr>
876
+ ${columns.map(col => `
877
+ <th style="width: ${col.width || 'auto'}">
878
+ ${col.label}
879
+ </th>
880
+ `).join('')}
881
+ <th>操作</th>
882
+ </tr>
883
+ </thead>
884
+ <tbody id="table-body"></tbody>
885
+ </table>
886
+ </div>
887
+ `;
888
+
889
+ this.renderTable();
890
+ }
891
+
892
+ renderTable() {
893
+ const tbody = this.container.querySelector('#table-body');
894
+ const { ui_hints, data_sources } = this.config;
895
+ const columns = ui_hints?.columns || [];
896
+ const rowActions = ui_hints?.row_actions || [];
897
+
898
+ // 获取第一个数据源的数据
899
+ const dataSource = data_sources[0];
900
+ const data = this.getData(dataSource.id);
901
+
902
+ if (!data) {
903
+ tbody.innerHTML = '<tr><td colspan="100">加载中...</td></tr>';
904
+ return;
905
+ }
906
+
907
+ // 假设数据格式是 { items: [...] } 或 [...]
908
+ const items = Array.isArray(data) ? data : (data.items || data.list || []);
909
+
910
+ if (items.length === 0) {
911
+ tbody.innerHTML = '<tr><td colspan="100">暂无数据</td></tr>';
912
+ return;
913
+ }
914
+
915
+ tbody.innerHTML = items.map(item => `
916
+ <tr>
917
+ ${columns.map(col => `
918
+ <td>${item[col.field] || '-'}</td>
919
+ `).join('')}
920
+ <td>
921
+ ${rowActions.map(action => `
922
+ <button
923
+ class="btn-${action.style || 'primary'}"
924
+ data-action="${action.action_id}"
925
+ data-item='${JSON.stringify(item)}'>
926
+ ${action.label}
927
+ </button>
928
+ `).join('')}
929
+ </td>
930
+ </tr>
931
+ `).join('');
932
+ }
933
+
934
+ bindEvents() {
935
+ // 刷新按钮
936
+ this.container.querySelector('#btn-refresh').addEventListener('click', () => {
937
+ const dataSource = this.config.data_sources[0];
938
+ this.refreshDataSource(dataSource.id);
939
+ });
940
+
941
+ // 行操作(事件委托)
942
+ this.container.querySelector('#table-body').addEventListener('click', async (e) => {
943
+ const btn = e.target.closest('[data-action]');
944
+ if (!btn) return;
945
+
946
+ const actionId = btn.dataset.action;
947
+ const item = JSON.parse(btn.dataset.item);
948
+
949
+ const action = this.config.ui_hints.row_actions.find(a => a.action_id === actionId);
950
+
951
+ // 确认对话框
952
+ if (action.confirm && !confirm(action.confirm)) {
953
+ return;
954
+ }
955
+
956
+ btn.disabled = true;
957
+ btn.textContent = '处理中...';
958
+
959
+ try {
960
+ // 执行操作(从 item 中提取参数)
961
+ await this.executeAction(actionId, item);
962
+
963
+ // 等待事件自动刷新
964
+
965
+ } catch (error) {
966
+ btn.disabled = false;
967
+ btn.textContent = action.label;
968
+ }
969
+ });
970
+ }
971
+ }
972
+ ```
973
+
974
+ ---
975
+
976
+ ## 九、模块侧实现
977
+
978
+ ### 9.1 模块配置文件
979
+
980
+ ```yaml
981
+ # launcher/config.yaml
982
+ console_panel:
983
+ enabled: true # 是否启用控制台面板
984
+ ```
985
+
986
+ ### 9.2 模块元数据
987
+
988
+ ```markdown
989
+ <!-- launcher/module.md -->
990
+ ---
991
+ name: launcher
992
+ type: core
993
+ has_console_panel: true # 模块提供控制台面板
994
+ ---
995
+
996
+ # Launcher
997
+
998
+ Kite 启动器模块。
999
+ ```
1000
+
1001
+ ### 9.3 模块注册实现
1002
+
1003
+ ```python
1004
+ # launcher/entry.py
1005
+ import asyncio
1006
+ import json
1007
+ from core.kernel_client import KernelClient
1008
+
1009
+ class LauncherModule:
1010
+ def __init__(self, token, kernel_port):
1011
+ self.kernel = KernelClient(token, kernel_port)
1012
+ self.config = self.load_config()
1013
+ self.metadata = self.load_metadata()
1014
+ self.rpc_handlers = {
1015
+ 'list_modules': self.handle_list_modules,
1016
+ 'start_module': self.handle_start_module,
1017
+ 'stop_module': self.handle_stop_module,
1018
+ 'get_stats': self.handle_get_stats,
1019
+ }
1020
+
1021
+ def load_config(self):
1022
+ """加载配置文件"""
1023
+ with open('config.yaml', 'r') as f:
1024
+ return yaml.safe_load(f)
1025
+
1026
+ def load_metadata(self):
1027
+ """加载模块元数据"""
1028
+ with open('module.md', 'r') as f:
1029
+ content = f.read()
1030
+ # 解析 frontmatter
1031
+ return parse_frontmatter(content)
1032
+
1033
+ def should_register_panel(self):
1034
+ """判断是否应该注册控制台面板"""
1035
+ # 1. 检查模块是否提供面板
1036
+ if not self.metadata.get('has_console_panel', False):
1037
+ return False
1038
+
1039
+ # 2. 检查配置是否启用
1040
+ if not self.config.get('console_panel', {}).get('enabled', False):
1041
+ return False
1042
+
1043
+ return True
1044
+
1045
+ async def start(self):
1046
+ # 连接 Kernel
1047
+ await self.kernel.connect()
1048
+
1049
+ # 构建注册 payload
1050
+ payload = {
1051
+ 'module_id': 'launcher',
1052
+ 'rpc_methods': {
1053
+ 'list_modules': {
1054
+ 'description': '列出所有模块',
1055
+ 'params': {},
1056
+ 'returns': {'modules': 'array'}
1057
+ },
1058
+ 'start_module': {
1059
+ 'description': '启动模块',
1060
+ 'params': {'name': 'string'},
1061
+ 'returns': {'success': 'boolean'}
1062
+ },
1063
+ 'stop_module': {
1064
+ 'description': '停止模块',
1065
+ 'params': {'name': 'string', 'reason': 'string'},
1066
+ 'returns': {'success': 'boolean'}
1067
+ },
1068
+ 'get_stats': {
1069
+ 'description': '获取统计信息',
1070
+ 'params': {},
1071
+ 'returns': {
1072
+ 'total': 'number',
1073
+ 'running': 'number',
1074
+ 'stopped': 'number'
1075
+ }
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ # 如果应该注册面板,添加 console_panel 配置
1081
+ if self.should_register_panel():
1082
+ payload['metadata'] = {
1083
+ 'console_panel': {
1084
+ 'enabled': True,
1085
+ 'panel_id': 'launcher',
1086
+ 'title': '模块管理',
1087
+ 'icon': 'grid',
1088
+ 'order': 1,
1089
+ 'category': 'system',
1090
+ 'data_sources': [
1091
+ {
1092
+ 'id': 'modules_list',
1093
+ 'rpc_method': 'launcher.list_modules',
1094
+ 'params': {},
1095
+ 'refresh': {
1096
+ 'strategy': 'event',
1097
+ 'events': [
1098
+ 'module.started',
1099
+ 'module.stopped',
1100
+ 'module.crashed'
1101
+ ]
1102
+ }
1103
+ },
1104
+ {
1105
+ 'id': 'module_stats',
1106
+ 'rpc_method': 'launcher.get_stats',
1107
+ 'params': {},
1108
+ 'refresh': {
1109
+ 'strategy': 'polling',
1110
+ 'interval': 5000
1111
+ }
1112
+ }
1113
+ ],
1114
+ 'actions': [
1115
+ {
1116
+ 'id': 'start_module',
1117
+ 'rpc_method': 'launcher.start_module',
1118
+ 'params_schema': {'name': 'string'}
1119
+ },
1120
+ {
1121
+ 'id': 'stop_module',
1122
+ 'rpc_method': 'launcher.stop_module',
1123
+ 'params_schema': {
1124
+ 'name': 'string',
1125
+ 'reason': 'string'
1126
+ }
1127
+ }
1128
+ ]
1129
+ }
1130
+ }
1131
+
1132
+ # 注册到 Registry
1133
+ await self.kernel.rpc('registry.register', payload)
1134
+
1135
+ # 注册 RPC 处理器
1136
+ self.kernel.register_rpc_handler(self.handle_rpc)
1137
+
1138
+ # 发送 module.ready
1139
+ await self.kernel.publish_event('module.ready', {
1140
+ 'module_id': 'launcher'
1141
+ })
1142
+
1143
+ # 运行主循环
1144
+ await self.run()
1145
+
1146
+ async def handle_rpc(self, method, params, context):
1147
+ """处理 RPC 调用"""
1148
+ # 权限检查
1149
+ if method == 'stop_module':
1150
+ module_name = params.get('name')
1151
+
1152
+ # 核心模块不允许停止
1153
+ if module_name in ['kernel', 'launcher']:
1154
+ raise PermissionError("Cannot stop core modules")
1155
+
1156
+ # 只有管理员可以停止模块
1157
+ caller_role = context.get('caller_role')
1158
+ if caller_role != 'admin':
1159
+ raise PermissionError("Only admin can stop modules")
1160
+
1161
+ # 执行操作
1162
+ handler = self.rpc_handlers.get(method)
1163
+ if not handler:
1164
+ raise ValueError(f"Unknown RPC method: {method}")
1165
+
1166
+ return await handler(params)
1167
+
1168
+ async def handle_list_modules(self, params):
1169
+ """列出所有模块"""
1170
+ modules = self.get_all_modules()
1171
+ return {'modules': modules}
1172
+
1173
+ async def handle_start_module(self, params):
1174
+ """启动模块"""
1175
+ name = params['name']
1176
+ await self.start_module_process(name)
1177
+ return {'success': True}
1178
+
1179
+ async def handle_stop_module(self, params):
1180
+ """停止模块"""
1181
+ name = params['name']
1182
+ reason = params.get('reason', 'user_request')
1183
+ await self.stop_module_process(name, reason)
1184
+ return {'success': True}
1185
+
1186
+ async def handle_get_stats(self, params):
1187
+ """获取统计信息"""
1188
+ modules = self.get_all_modules()
1189
+ running = sum(1 for m in modules if m['actual_state'].startswith('running'))
1190
+ return {
1191
+ 'total': len(modules),
1192
+ 'running': running,
1193
+ 'stopped': len(modules) - running
1194
+ }
1195
+ ```
1196
+
1197
+ ---
1198
+
1199
+ ## 十、职责划分
1200
+
1201
+ ### 10.1 职责边界
1202
+
1203
+ | 层级 | 职责 | 不负责 |
1204
+ |------|------|--------|
1205
+ | **模块** | - 数据主权<br>- 权限控制<br>- 业务逻辑<br>- 决定暴露什么<br>- RPC 实现 | - UI 渲染<br>- 前端交互<br>- 样式设计 |
1206
+ | **注册中心** | - 服务发现<br>- 配置存储<br>- 查询接口 | - 权限判断<br>- 数据处理<br>- 业务逻辑 |
1207
+ | **Kernel** | - RPC 路由<br>- 事件分发<br>- 上下文传递 | - 业务逻辑<br>- 权限判断<br>- 数据存储 |
1208
+ | **前端** | - UI 渲染<br>- 用户交互<br>- 加载状态显示<br>- 错误提示 | - 权限判断<br>- 业务逻辑<br>- 数据过滤 |
1209
+
1210
+ ### 10.2 数据流向
1211
+
1212
+ ```
1213
+ 模块决定暴露 → 注册到 Registry → 前端查询发现 → 前端渲染 UI
1214
+ ↓ ↓
1215
+ 模块提供 RPC ←────── Kernel 路由 ←────── 前端调用 RPC
1216
+ ↓ ↓
1217
+ 模块检查权限 ────────────────────────→ 返回结果/错误
1218
+ ↓ ↓
1219
+ 模块发送事件 ────────────────────────→ 前端自动刷新
1220
+ ```
1221
+
1222
+ ---
1223
+
1224
+ ## 十一、开发流程
1225
+
1226
+ ### 11.1 模块开发者(后端)
1227
+
1228
+ #### 步骤 1:配置模块元数据
1229
+
1230
+ ```markdown
1231
+ <!-- module.md -->
1232
+ ---
1233
+ name: my_module
1234
+ type: service
1235
+ has_console_panel: true # 声明提供控制台面板
1236
+ ---
1237
+
1238
+ # My Module
1239
+
1240
+ 模块说明。
1241
+ ```
1242
+
1243
+ #### 步骤 2:配置面板启用状态
1244
+
1245
+ ```yaml
1246
+ # config.yaml
1247
+ console_panel:
1248
+ enabled: true # 启用控制台面板
1249
+ ```
1250
+
1251
+ #### 步骤 3:实现 RPC 处理器
1252
+
1253
+ ```python
1254
+ # entry.py
1255
+ class MyModule:
1256
+ def __init__(self):
1257
+ self.rpc_handlers = {
1258
+ 'get_data': self.handle_get_data,
1259
+ 'update_config': self.handle_update_config,
1260
+ }
1261
+
1262
+ async def handle_get_data(self, params):
1263
+ """获取数据"""
1264
+ data = self.load_data()
1265
+ return {'items': data}
1266
+
1267
+ async def handle_update_config(self, params):
1268
+ """更新配置"""
1269
+ config_key = params['key']
1270
+ config_value = params['value']
1271
+
1272
+ # 权限检查
1273
+ if not self.check_permission(context, 'update_config'):
1274
+ raise PermissionError("No permission")
1275
+
1276
+ self.update_config(config_key, config_value)
1277
+ return {'success': True}
1278
+ ```
1279
+
1280
+ #### 步骤 4:注册到 Registry
1281
+
1282
+ ```python
1283
+ async def start(self):
1284
+ # 判断是否应该注册面板
1285
+ if self.should_register_panel():
1286
+ payload = {
1287
+ 'module_id': 'my_module',
1288
+ 'metadata': {
1289
+ 'console_panel': {
1290
+ 'enabled': True,
1291
+ 'panel_id': 'my_module',
1292
+ 'title': '我的模块',
1293
+ 'icon': 'star',
1294
+ 'order': 20,
1295
+ 'category': 'service',
1296
+ 'data_sources': [
1297
+ {
1298
+ 'id': 'items_list',
1299
+ 'rpc_method': 'my_module.get_data',
1300
+ 'params': {},
1301
+ 'refresh': {
1302
+ 'strategy': 'event',
1303
+ 'events': ['my_module.data_changed']
1304
+ }
1305
+ }
1306
+ ],
1307
+ 'actions': [
1308
+ {
1309
+ 'id': 'update_config',
1310
+ 'rpc_method': 'my_module.update_config',
1311
+ 'params_schema': {
1312
+ 'key': 'string',
1313
+ 'value': 'string'
1314
+ }
1315
+ }
1316
+ ],
1317
+ # 可选:提供 UI 提示(使用通用渲染器)
1318
+ 'ui_hints': {
1319
+ 'type': 'table',
1320
+ 'columns': [
1321
+ {'field': 'id', 'label': 'ID', 'width': '100px'},
1322
+ {'field': 'name', 'label': '名称', 'width': '200px'}
1323
+ ],
1324
+ 'row_actions': [
1325
+ {
1326
+ 'action_id': 'update_config',
1327
+ 'label': '编辑',
1328
+ 'style': 'primary'
1329
+ }
1330
+ ]
1331
+ }
1332
+ }
1333
+ },
1334
+ 'rpc_methods': {
1335
+ 'get_data': {
1336
+ 'description': '获取数据',
1337
+ 'params': {},
1338
+ 'returns': {'items': 'array'}
1339
+ },
1340
+ 'update_config': {
1341
+ 'description': '更新配置',
1342
+ 'params': {'key': 'string', 'value': 'string'},
1343
+ 'returns': {'success': 'boolean'}
1344
+ }
1345
+ }
1346
+ }
1347
+
1348
+ await self.kernel.rpc('registry.register', payload)
1349
+ ```
1350
+
1351
+ #### 步骤 5:完成
1352
+
1353
+ - 如果提供了 `ui_hints`,前端会使用通用渲染器自动渲染
1354
+ - 如果需要自定义 UI,通知前端开发者创建 `panels/my_module.js`
1355
+
1356
+ ---
1357
+
1358
+ ### 11.2 前端开发者
1359
+
1360
+ #### 选择 1:使用通用渲染器(无需开发)
1361
+
1362
+ 如果模块提供了 `ui_hints`,前端会自动使用通用渲染器,无需任何开发工作。
1363
+
1364
+ #### 选择 2:开发自定义面板
1365
+
1366
+ 如果需要完全自定义的 UI,创建面板 JS 文件:
1367
+
1368
+ ```javascript
1369
+ // evol/static/panels/my_module.js
1370
+ import { BasePanel } from '../js/base-panel.js';
1371
+
1372
+ export default class MyModulePanel extends BasePanel {
1373
+ async onMount() {
1374
+ await super.onMount(); // 自动加载数据源
1375
+ this.render();
1376
+ this.bindEvents();
1377
+ }
1378
+
1379
+ onDataSourceChange(sourceId, state) {
1380
+ if (sourceId === 'items_list') {
1381
+ this.renderItems();
1382
+ }
1383
+ }
1384
+
1385
+ render() {
1386
+ this.container.innerHTML = `
1387
+ <div class="my-module-panel">
1388
+ <h2>我的模块</h2>
1389
+ <div id="items-container"></div>
1390
+ </div>
1391
+ `;
1392
+
1393
+ this.renderItems();
1394
+ }
1395
+
1396
+ renderItems() {
1397
+ const items = this.getData('items_list')?.items || [];
1398
+ const container = this.container.querySelector('#items-container');
1399
+
1400
+ container.innerHTML = items.map(item => `
1401
+ <div class="item">
1402
+ <span>${item.name}</span>
1403
+ <button data-action="update" data-id="${item.id}">
1404
+ 编辑
1405
+ </button>
1406
+ </div>
1407
+ `).join('');
1408
+ }
1409
+
1410
+ bindEvents() {
1411
+ this.container.addEventListener('click', async (e) => {
1412
+ const btn = e.target.closest('[data-action="update"]');
1413
+ if (!btn) return;
1414
+
1415
+ const id = btn.dataset.id;
1416
+ const newValue = prompt('输入新值');
1417
+
1418
+ if (newValue) {
1419
+ await this.executeAction('update_config', {
1420
+ key: id,
1421
+ value: newValue
1422
+ });
1423
+ }
1424
+ });
1425
+ }
1426
+ }
1427
+ ```
1428
+
1429
+ ---
1430
+
1431
+ ## 十二、最佳实践
1432
+
1433
+ ### 12.1 模块侧
1434
+
1435
+ #### ✅ 推荐做法
1436
+
1437
+ ```python
1438
+ # 1. 明确声明面板配置
1439
+ has_console_panel: true # 在 module.md 中声明
1440
+
1441
+ # 2. 提供清晰的 RPC 方法
1442
+ async def handle_get_data(self, params):
1443
+ """获取数据 - 清晰的文档注释"""
1444
+ return {'items': [...]}
1445
+
1446
+ # 3. 严格的权限检查
1447
+ async def handle_delete_item(self, params, context):
1448
+ if not self.check_permission(context, 'delete'):
1449
+ raise PermissionError("No permission to delete")
1450
+ # ...
1451
+
1452
+ # 4. 合理的刷新策略
1453
+ 'refresh': {
1454
+ 'strategy': 'event', # 优先使用事件驱动
1455
+ 'events': ['my_module.data_changed']
1456
+ }
1457
+
1458
+ # 5. 提供 UI 提示(可选)
1459
+ 'ui_hints': {
1460
+ 'type': 'table',
1461
+ 'columns': [...]
1462
+ }
1463
+ ```
1464
+
1465
+ #### ❌ 避免做法
1466
+
1467
+ ```python
1468
+ # 1. 不要在模块中处理前端逻辑
1469
+ # 错误示例:
1470
+ def get_html_for_item(item):
1471
+ return f"<div>{item.name}</div>" # ❌
1472
+
1473
+ # 2. 不要在 RPC 中返回 HTML
1474
+ # 错误示例:
1475
+ return {'html': '<table>...</table>'} # ❌
1476
+
1477
+ # 3. 不要在模块中做前端权限判断
1478
+ # 错误示例:
1479
+ if user_role == 'viewer':
1480
+ return {'items': []} # ❌ 应该返回完整数据,让前端决定显示
1481
+
1482
+ # 4. 不要过度轮询
1483
+ # 错误示例:
1484
+ 'refresh': {
1485
+ 'strategy': 'polling',
1486
+ 'interval': 100 # ❌ 太频繁
1487
+ }
1488
+ ```
1489
+
1490
+ ---
1491
+
1492
+ ### 12.2 前端侧
1493
+
1494
+ #### ✅ 推荐做法
1495
+
1496
+ ```javascript
1497
+ // 1. 继承 BasePanel
1498
+ export default class MyPanel extends BasePanel {
1499
+ // ...
1500
+ }
1501
+
1502
+ // 2. 使用 BasePanel 提供的方法
1503
+ const data = this.getData('items_list'); // ✅
1504
+ await this.executeAction('delete_item', {id: 1}); // ✅
1505
+
1506
+ // 3. 响应数据变化
1507
+ onDataSourceChange(sourceId, state) {
1508
+ this.renderItems(); // ✅
1509
+ }
1510
+
1511
+ // 4. 显示加载状态
1512
+ if (this.isLoading('items_list')) {
1513
+ // 显示加载动画
1514
+ }
1515
+
1516
+ // 5. 处理错误
1517
+ try {
1518
+ await this.executeAction('delete_item', {id: 1});
1519
+ } catch (error) {
1520
+ this.showError(error.message); // ✅
1521
+ }
1522
+ ```
1523
+
1524
+ #### ❌ 避免做法
1525
+
1526
+ ```javascript
1527
+ // 1. 不要做权限判断
1528
+ // 错误示例:
1529
+ if (moduleName === 'kernel') {
1530
+ alert('不能操作核心模块'); // ❌
1531
+ return;
1532
+ }
1533
+ // 正确做法:直接调用,让模块检查权限
1534
+
1535
+ // 2. 不要做业务逻辑判断
1536
+ // 错误示例:
1537
+ const filteredItems = items.filter(item => item.status !== 'deleted'); // ❌
1538
+ // 正确做法:渲染模块返回的所有数据
1539
+
1540
+ // 3. 不要手动管理数据缓存
1541
+ // 错误示例:
1542
+ localStorage.setItem('items', JSON.stringify(items)); // ❌
1543
+ // 正确做法:让 BasePanel 自动管理
1544
+
1545
+ // 4. 不要绕过 BasePanel 的方法
1546
+ // 错误示例:
1547
+ fetch('/api/my_module/get_data').then(...); // ❌
1548
+ // 正确做法:使用 this.rpc('my_module.get_data', {})
1549
+ ```
1550
+
1551
+ ---
1552
+
1553
+ ## 十三、常见问题
1554
+
1555
+ ### Q1:模块如何动态启用/禁用面板?
1556
+
1557
+ **A**:修改 `config.yaml` 中的 `console_panel.enabled`,然后重新注册到 Registry。
1558
+
1559
+ ```python
1560
+ # 动态禁用面板
1561
+ self.config['console_panel']['enabled'] = False
1562
+ await self.kernel.rpc('registry.register', payload)
1563
+ ```
1564
+
1565
+ ---
1566
+
1567
+ ### Q2:如何实现不同用户看到不同的面板?
1568
+
1569
+ **A**:在注册时根据用户上下文决定是否注册面板。
1570
+
1571
+ ```python
1572
+ async def register_to_registry(self, user_context):
1573
+ # 只有管理员才能看到管理面板
1574
+ if user_context.get('role') != 'admin':
1575
+ return # 不注册面板
1576
+
1577
+ # 注册面板
1578
+ await self.kernel.rpc('registry.register', payload)
1579
+ ```
1580
+
1581
+ ---
1582
+
1583
+ ### Q3:如何实现面板的权限控制?
1584
+
1585
+ **A**:权限控制在模块侧的 RPC 处理器中实现。
1586
+
1587
+ ```python
1588
+ async def handle_delete_item(self, params, context):
1589
+ # 检查权限
1590
+ caller_role = context.get('caller_role')
1591
+ if caller_role != 'admin':
1592
+ raise PermissionError("Only admin can delete items")
1593
+
1594
+ # 执行操作
1595
+ self.delete_item(params['id'])
1596
+ return {'success': True}
1597
+ ```
1598
+
1599
+ 前端会收到错误并显示给用户。
1600
+
1601
+ ---
1602
+
1603
+ ### Q4:如何实现复杂的自定义 UI?
1604
+
1605
+ **A**:创建自定义面板 JS 文件,完全控制 UI 渲染。
1606
+
1607
+ ```javascript
1608
+ // evol/static/panels/my_module.js
1609
+ export default class MyModulePanel extends BasePanel {
1610
+ render() {
1611
+ // 完全自定义的 HTML
1612
+ this.container.innerHTML = `
1613
+ <div class="custom-layout">
1614
+ <!-- 任意复杂的 UI -->
1615
+ </div>
1616
+ `;
1617
+ }
1618
+ }
1619
+ ```
1620
+
1621
+ ---
1622
+
1623
+ ### Q5:如何调试面板加载问题?
1624
+
1625
+ **A**:打开浏览器开发者工具,查看 Console 和 Network 面板。
1626
+
1627
+ ```javascript
1628
+ // 常见错误:
1629
+ // 1. 找不到面板 JS 文件
1630
+ // → 检查 panel_id 是否正确
1631
+ // → 检查 panels/xxx.js 文件是否存在
1632
+
1633
+ // 2. RPC 调用失败
1634
+ // → 检查 rpc_method 是否正确
1635
+ // → 检查模块是否已注册该 RPC
1636
+
1637
+ // 3. 数据不刷新
1638
+ // → 检查 refresh.strategy 配置
1639
+ // → 检查事件是否正确订阅
1640
+ ```
1641
+
1642
+ ---
1643
+
1644
+ ## 十四、总结
1645
+
1646
+ ### 14.1 核心原则
1647
+
1648
+ 1. **数据主权在模块**:模块决定暴露什么数据和操作
1649
+ 2. **权限控制在模块**:模块检查每个 RPC 调用的权限
1650
+ 3. **前端只负责渲染**:根据配置加载数据并渲染 UI
1651
+ 4. **注册中心是发现机制**:前端通过注册中心发现可用面板
1652
+
1653
+ ### 14.2 架构优势
1654
+
1655
+ - ✅ **解耦**:模块和前端完全解耦,通过 RPC 通信
1656
+ - ✅ **灵活**:支持自定义面板和通用渲染器
1657
+ - ✅ **安全**:权限控制在模块侧,前端无法绕过
1658
+ - ✅ **可扩展**:新增模块自动接入控制台
1659
+ - ✅ **易维护**:职责清晰,前后端分离
1660
+
1661
+ ### 14.3 开发效率
1662
+
1663
+ - **模块开发者**:只需实现 RPC + 声明配置,无需关心前端
1664
+ - **前端开发者**:可选择通用渲染器(零开发)或自定义面板(完全控制)
1665
+ - **用户**:通过配置文件动态控制面板启用/禁用
1666
+
1667
+ ---
1668
+
1669
+ ## 附录
1670
+
1671
+ ### A. 完整示例项目结构
1672
+
1673
+ ```
1674
+ Kite/
1675
+ ├── extensions/
1676
+ │ └── services/
1677
+ │ ├── launcher/
1678
+ │ │ ├── module.md # has_console_panel: true
1679
+ │ │ ├── config.yaml # console_panel.enabled: true
1680
+ │ │ └── entry.py # 注册面板 + RPC 实现
1681
+ │ ├── watchdog/
1682
+ │ │ ├── module.md
1683
+ │ │ ├── config.yaml
1684
+ │ │ └── entry.py
1685
+ │ └── evol/
1686
+ │ ├── static/
1687
+ │ │ ├── index.html
1688
+ │ │ ├── js/
1689
+ │ │ │ ├── evol-app.js
1690
+ │ │ │ ├── kernel-client.js
1691
+ │ │ │ ├── base-panel.js
1692
+ │ │ │ └── panel-loader.js
1693
+ │ │ └── panels/
1694
+ │ │ ├── launcher.js # 自定义面板
1695
+ │ │ ├── watchdog.js # 自定义面板
1696
+ │ │ └── generic-table.js # 通用渲染器
1697
+ │ └── server.py
1698
+ └── docs/
1699
+ └── Evol控制台插件化架构设计.md # 本文档
1700
+ ```
1701
+
1702
+ ### B. 参考文档
1703
+
1704
+ - [Kite 框架设计](Kite框架设计/)
1705
+ - [注册中心设计](注册中心设计.md)
1706
+ - [事件中心设计](事件中心设计.md)
1707
+ - [模块开发指南](模块开发指南.md)
1708
+