@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
@@ -0,0 +1,1496 @@
1
+ # 虚拟模块中转服务完整设计
2
+
3
+ ## 概述
4
+
5
+ 中转服务(Relay Service)是一个独立的、可复用的组件,允许远程客户端(如浏览器、移动应用)作为标准 Kite 模块接入 Kernel。通过中转服务,远程客户端可以调用任何模块的 RPC、订阅/发布事件,就像一个真正的 Kite 模块一样。
6
+
7
+ ## 核心特性
8
+
9
+ 1. **远程客户端作为标准 Kite 模块** - 可以调用任何模块的 RPC,订阅/发布事件
10
+ 2. **全 WebSocket 协议** - 配对、认证、RPC 通信全部通过 WebSocket
11
+ 3. **平滑重连** - 客户端刷新页面时,Kernel 看到的是模块一直在线
12
+ 4. **优雅退出** - 客户端关闭或超时时,中转服务代为完成优雅退出流程
13
+ 5. **独立可复用** - 可以集成到任何模块中,只需复制 `relay.py` 文件
14
+ 6. **动态 Token 管理** - 通过 Launcher 动态申请和释放 Kernel Token
15
+ 7. **多种配对方式** - 支持配对码配对和手机验证码配对
16
+
17
+ ## 架构设计
18
+
19
+ ### 整体架构
20
+
21
+ ```
22
+ ┌──────────────┐
23
+ │ 远程客户端 │ (浏览器/移动应用)
24
+ │ - 配对/认证 │
25
+ │ - RPC 调用 │
26
+ │ - 事件订阅 │
27
+ └──────┬───────┘
28
+ │ WebSocket
29
+ │ /ws/relay
30
+
31
+ ┌──────────────┐
32
+ │ 中转服务 │ (relay.py)
33
+ │ - 配对管理 │
34
+ │ - Token 申请 │
35
+ │ - 消息转发 │
36
+ │ - 重连管理 │
37
+ └──────┬───────┘
38
+ │ RPC: launcher.request_client_token
39
+
40
+ ┌──────────────┐
41
+ │ Launcher │
42
+ │ - Token 生成 │
43
+ │ - 权限控制 │
44
+ │ - Token 注册 │
45
+ └──────┬───────┘
46
+ │ RPC: kernel.register_tokens
47
+
48
+ ┌──────────────┐
49
+ │ Kernel │
50
+ │ - Token 验证 │
51
+ │ - RPC 路由 │
52
+ │ - 事件分发 │
53
+ └──────────────┘
54
+ ```
55
+
56
+ ### 数据流
57
+
58
+ ```
59
+ 远程客户端 sessionStorage: session_token (如 "sess_a3f9e2")
60
+
61
+ 中转服务映射表: {
62
+ "sess_a3f9e2": {
63
+ module_id: "web-client-a3f9e2",
64
+ kernel_ws: <WebSocket>,
65
+ kernel_token: "abc123...",
66
+ client_ws: <WebSocket>,
67
+ frontend_token: "tok_xxx",
68
+ role: "admin",
69
+ created_at: timestamp,
70
+ last_active: timestamp,
71
+ status: "active" | "waiting_reconnect"
72
+ }
73
+ }
74
+
75
+ Kernel 注册: module_id = "web-client-a3f9e2"
76
+ token_map["abc123..."] = "web-client-a3f9e2"
77
+ ```
78
+
79
+ ### 关键设计
80
+
81
+ 1. **session_token 由客户端生成并持久化** - 存储在 sessionStorage/localStorage
82
+ 2. **module_id 由中转服务管理** - 基于 session_token 生成,客户端无需关心
83
+ 3. **kernel_token 由 Launcher 动态生成** - 通过 RPC 申请,用于连接 Kernel
84
+ 4. **中转服务完全控制模块生命周期** - 包括注册、重连、优雅退出、Token 释放
85
+ 5. **全 WebSocket 通信** - 配对、认证、RPC 全部通过 WebSocket
86
+
87
+ ## Token 管理机制
88
+
89
+ ### Token 类型
90
+
91
+ 1. **frontend_token** - 客户端认证凭证
92
+ - 由中转服务生成(通过 PairingManager)
93
+ - 存储在客户端 localStorage
94
+ - 有效期 30 天,快过期时自动续期
95
+ - 用于客户端连接中转服务时的身份验证
96
+
97
+ 2. **kernel_token** - Kernel 连接凭证
98
+ - 由 Launcher 生成
99
+ - 通过 `launcher.request_client_token` RPC 申请
100
+ - 中转服务保存在 session 映射表中
101
+ - 用于中转服务连接 Kernel
102
+ - 整个虚拟模块生命周期内有效,可多次重连使用
103
+
104
+ 3. **session_token** - 会话标识
105
+ - 由客户端生成(如 `sess_a3f9e2`)
106
+ - 存储在客户端 sessionStorage
107
+ - 用于识别重连(刷新页面时保持会话)
108
+
109
+ ### Token 生命周期
110
+
111
+ ```
112
+ ┌─────────────────────────────────────────────────────────────┐
113
+ │ 阶段 1: 配对/认证 │
114
+ ├─────────────────────────────────────────────────────────────┤
115
+ │ 1. 客户端连接中转服务 │
116
+ │ 2. 客户端发送配对码/验证码 │
117
+ │ 3. 中转服务验证配对码 │
118
+ │ 4. 中转服务生成 frontend_token │
119
+ │ 5. 中转服务生成 session_token │
120
+ │ 6. 中转服务返回 frontend_token + session_token │
121
+ │ 7. 客户端保存到 localStorage + sessionStorage │
122
+ └─────────────────────────────────────────────────────────────┘
123
+
124
+ ┌─────────────────────────────────────────────────────────────┐
125
+ │ 阶段 2: 申请 Kernel Token │
126
+ ├─────────────────────────────────────────────────────────────┤
127
+ │ 1. 中转服务生成 module_id (基于 session_token) │
128
+ │ 2. 中转服务调用 launcher.request_client_token(module_id) │
129
+ │ 3. Launcher 检查权限(中转服务是否在白名单中) │
130
+ │ 4. Launcher 生成 kernel_token │
131
+ │ 5. Launcher 调用 kernel.register_tokens 注册到 Kernel │
132
+ │ 6. Launcher 返回 kernel_token 给中转服务 │
133
+ │ 7. 中转服务保存 kernel_token 到 session 映射表 │
134
+ └─────────────────────────────────────────────────────────────┘
135
+
136
+ ┌─────────────────────────────────────────────────────────────┐
137
+ │ 阶段 3: 连接 Kernel │
138
+ ├─────────────────────────────────────────────────────────────┤
139
+ │ 1. 中转服务使用 kernel_token 连接 Kernel │
140
+ │ ws://kernel/ws?token={kernel_token}&id={module_id} │
141
+ │ 2. Kernel 验证 token,返回 module_id │
142
+ │ 3. 中转服务注册模块到 Kernel │
143
+ │ 4. 中转服务发布 module.ready 事件 │
144
+ │ 5. 连接建立,开始双向转发消息 │
145
+ └─────────────────────────────────────────────────────────────┘
146
+
147
+ ┌─────────────────────────────────────────────────────────────┐
148
+ │ 阶段 4: 重连(客户端刷新页面) │
149
+ ├─────────────────────────────────────────────────────────────┤
150
+ │ 1. 客户端断开 WebSocket │
151
+ │ 2. 中转服务保持 Kernel 连接(6 秒等待) │
152
+ │ 3. 客户端重新连接,发送 frontend_token + session_token │
153
+ │ 4. 中转服务识别重连,恢复 client_ws 引用 │
154
+ │ 5. 复用已有的 kernel_ws 和 kernel_token │
155
+ │ 6. Kernel 看到的是模块一直在线(无感知) │
156
+ └─────────────────────────────────────────────────────────────┘
157
+
158
+ ┌─────────────────────────────────────────────────────────────┐
159
+ │ 阶段 5: 优雅退出 │
160
+ ├─────────────────────────────────────────────────────────────┤
161
+ │ 1. 客户端主动断开 或 超时未重连 │
162
+ │ 2. 中转服务发布 module.exiting 事件 │
163
+ │ data: {module_id, token_revoked: true} │
164
+ │ 3. 中转服务发布 module.shutdown.ready 事件 │
165
+ │ 4. 中转服务关闭 Kernel 连接 │
166
+ │ 5. 中转服务删除 session 映射 │
167
+ │ 6. Launcher 监听 module.exiting 事件,标记 token 失效 │
168
+ │ 7. 客户端再次连接时,必须重新申请 kernel_token │
169
+ └─────────────────────────────────────────────────────────────┘
170
+ ```
171
+
172
+ ## 配对机制
173
+
174
+ ### 方式 1: 配对码配对
175
+
176
+ **适用场景:** 开发环境、内网环境、桌面浏览器
177
+
178
+ **流程:**
179
+
180
+ ```
181
+ 1. 用户请求配对码
182
+ - 通过 Launcher UI 或命令行
183
+ - Launcher 调用 relay 模块的 RPC: relay.generate_pairing_code(role)
184
+ - relay 生成临时配对码(6 位大写字母+数字,5 分钟有效)
185
+ - Launcher 显示配对码给用户
186
+
187
+ 2. 客户端配对
188
+ - 客户端连接 /ws/relay
189
+ - 发送配对消息: {type: "pair", code: "ABC123"}
190
+ - 中转服务验证配对码
191
+ - 验证成功 → 生成 frontend_token + session_token
192
+ - 返回: {type: "paired", token, session_token, module_id, role}
193
+
194
+ 3. 配对码失效
195
+ - 使用后立即失效(一次性)
196
+ - 5 分钟后自动过期
197
+ ```
198
+
199
+ **配对码格式:**
200
+ ```json
201
+ {
202
+ "code": "ABC123",
203
+ "role": "admin",
204
+ "status": "pending",
205
+ "created_at": "2026-03-08T12:00:00Z"
206
+ }
207
+ ```
208
+
209
+ ### 方式 2: 手机验证码配对
210
+
211
+ **适用场景:** 生产环境、移动应用、公网访问
212
+
213
+ **流程:**
214
+
215
+ ```
216
+ 1. 客户端请求验证码
217
+ - 客户端连接 /ws/relay
218
+ - 发送请求: {type: "request_sms", phone: "+8613800138000"}
219
+ - 中转服务调用短信 API 发送验证码
220
+ - 验证码 6 位数字,5 分钟有效
221
+
222
+ 2. 客户端验证
223
+ - 发送验证消息: {type: "verify_sms", phone: "+8613800138000", code: "123456"}
224
+ - 中转服务验证验证码
225
+ - 验证成功 → 生成 frontend_token + session_token
226
+ - 返回: {type: "paired", token, session_token, module_id, role}
227
+
228
+ 3. 角色分配
229
+ - 首次验证的手机号 → admin 角色
230
+ - 后续手机号 → 根据配置分配角色(operator/viewer)
231
+ ```
232
+
233
+ **验证码记录格式:**
234
+ ```json
235
+ {
236
+ "phone": "+8613800138000",
237
+ "code": "123456",
238
+ "role": "admin",
239
+ "status": "pending",
240
+ "created_at": "2026-03-08T12:00:00Z",
241
+ "expires_at": "2026-03-08T12:05:00Z"
242
+ }
243
+ ```
244
+
245
+ ## 连接流程
246
+
247
+ ### 首次配对(配对码)
248
+
249
+ ```
250
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
251
+ │ 客户端 │ │ 中转服务 │ │ Launcher │
252
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
253
+ │ │ │
254
+ │ 1. WebSocket 连接 │ │
255
+ ├────────────────────────────>│ │
256
+ │ │ │
257
+ │ 2. 配对消息 │ │
258
+ │ {type:"pair",code:"ABC123"} │ │
259
+ ├────────────────────────────>│ │
260
+ │ │ │
261
+ │ │ 3. 验证配对码 │
262
+ │ │ │
263
+ │ │ 4. 生成 frontend_token │
264
+ │ │ session_token │
265
+ │ │ module_id │
266
+ │ │ │
267
+ │ │ 5. RPC: request_client_token│
268
+ │ ├────────────────────────────>│
269
+ │ │ {module_id: "web-client-xxx"}
270
+ │ │ │
271
+ │ │ │ 6. 生成 kernel_token
272
+ │ │ │ 注册到 Kernel
273
+ │ │ │
274
+ │ │ 7. 返回 kernel_token │
275
+ │ │<────────────────────────────┤
276
+ │ │ {token: "abc123..."} │
277
+ │ │ │
278
+ │ │ 8. 连接 Kernel │
279
+ │ │ 注册模块 │
280
+ │ │ │
281
+ │ 9. 配对成功 │ │
282
+ │ {type:"paired",token,...} │ │
283
+ │<────────────────────────────┤ │
284
+ │ │ │
285
+ │ 10. 保存 token 到本地 │ │
286
+ │ │ │
287
+ │ 11. 连接升级为已认证状态 │ │
288
+ │ 可以发送 RPC 请求 │ │
289
+ │ │ │
290
+ ```
291
+
292
+ ### 首次配对(手机验证码)
293
+
294
+ ```
295
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
296
+ │ 客户端 │ │ 中转服务 │ │ 短信API │
297
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
298
+ │ │ │
299
+ │ 1. WebSocket 连接 │ │
300
+ ├────────────────────────────>│ │
301
+ │ │ │
302
+ │ 2. 请求验证码 │ │
303
+ │ {type:"request_sms", │ │
304
+ │ phone:"+8613800138000"} │ │
305
+ ├────────────────────────────>│ │
306
+ │ │ │
307
+ │ │ 3. 生成验证码 │
308
+ │ │ │
309
+ │ │ 4. 发送短信 │
310
+ │ ├────────────────────────────>│
311
+ │ │ │
312
+ │ 5. 请求成功 │ │
313
+ │ {type:"sms_sent"} │ │
314
+ │<────────────────────────────┤ │
315
+ │ │ │
316
+ │ 6. 用户收到短信 │ │
317
+ │ │ │
318
+ │ 7. 提交验证码 │ │
319
+ │ {type:"verify_sms", │ │
320
+ │ phone:"+8613800138000", │ │
321
+ │ code:"123456"} │ │
322
+ ├────────────────────────────>│ │
323
+ │ │ │
324
+ │ │ 8. 验证验证码 │
325
+ │ │ │
326
+ │ │ 9-11. 同配对码流程 │
327
+ │ │ (申请 token, 连接 Kernel) │
328
+ │ │ │
329
+ │ 12. 配对成功 │ │
330
+ │<────────────────────────────┤ │
331
+ │ │ │
332
+ ```
333
+
334
+ ### 已登录(有 token)
335
+
336
+ ```
337
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
338
+ │ 客户端 │ │ 中转服务 │ │ Launcher │
339
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
340
+ │ │ │
341
+ │ 1. WebSocket 连接 │ │
342
+ ├────────────────────────────>│ │
343
+ │ │ │
344
+ │ 2. 认证消息 │ │
345
+ │ {type:"auth", │ │
346
+ │ token:"tok_xxx", │ │
347
+ │ session_token:"sess_xxx"} │ │
348
+ ├────────────────────────────>│ │
349
+ │ │ │
350
+ │ │ 3. 验证 frontend_token │
351
+ │ │ │
352
+ │ │ 4. 检查 session_token │
353
+ │ │ - 不存在 → 创建新连接 │
354
+ │ │ - 存在 → 恢复连接(重连) │
355
+ │ │ │
356
+ │ │ 5. 如果是新连接: │
357
+ │ │ 申请 kernel_token │
358
+ │ ├────────────────────────────>│
359
+ │ │ │
360
+ │ │<────────────────────────────┤
361
+ │ │ │
362
+ │ │ 6. 连接 Kernel │
363
+ │ │ │
364
+ │ 7. 认证成功 │ │
365
+ │ {type:"authenticated", │ │
366
+ │ module_id:"web-client-xxx"}│ │
367
+ │<────────────────────────────┤ │
368
+ │ │ │
369
+ │ 8. 连接升级为已认证状态 │ │
370
+ │ │ │
371
+ ```
372
+
373
+ ### 刷新页面(平滑重连)
374
+
375
+ ```
376
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
377
+ │ 客户端 │ │ 中转服务 │ │ Kernel │
378
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
379
+ │ │ │
380
+ │ 1. 前端断开 WebSocket │ │
381
+ ├─────────────────────────X │ │
382
+ │ │ │
383
+ │ │ 2. 检测到客户端断开 │
384
+ │ │ - 标记 session 为 │
385
+ │ │ "waiting_reconnect" │
386
+ │ │ - 保持 Kernel 连接 │
387
+ │ │ - 启动 6 秒超时计时器 │
388
+ │ │ │
389
+ │ 3. 前端重新加载 │ │
390
+ │ 从 sessionStorage 读取 │ │
391
+ │ token + session_token │ │
392
+ │ │ │
393
+ │ 4. 重新连接 /ws/relay │ │
394
+ ├────────────────────────────>│ │
395
+ │ │ │
396
+ │ 5. 发送认证消息 │ │
397
+ │ {type:"auth", │ │
398
+ │ token:"tok_xxx", │ │
399
+ │ session_token:"sess_xxx"} │ │
400
+ ├────────────────────────────>│ │
401
+ │ │ │
402
+ │ │ 6. 识别到是重连: │
403
+ │ │ - 取消超时计时器 │
404
+ │ │ - 恢复 client_ws 引用 │
405
+ │ │ - 标记 session 为 active │
406
+ │ │ - 复用 kernel_ws │
407
+ │ │ - Kernel 无感知 │
408
+ │ │ │
409
+ │ 7. 重连成功 │ │
410
+ │ {type:"reconnected", │ │
411
+ │ module_id:"web-client-xxx"}│ │
412
+ │<────────────────────────────┤ │
413
+ │ │ │
414
+ ```
415
+
416
+ ### 关闭标签页(优雅退出)
417
+
418
+ **场景 A:客户端主动发送 disconnect**
419
+
420
+ ```
421
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
422
+ │ 客户端 │ │ 中转服务 │ │ Kernel │
423
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
424
+ │ │ │
425
+ │ 1. 监听 beforeunload │ │
426
+ │ 发送断开消息 │ │
427
+ │ {type:"disconnect"} │ │
428
+ ├────────────────────────────>│ │
429
+ │ │ │
430
+ │ │ 2. 发布 module.exiting │
431
+ │ │ data: { │
432
+ │ │ module_id, │
433
+ │ │ token_revoked: true │
434
+ │ │ } │
435
+ │ ├────────────────────────────>│
436
+ │ │ │
437
+ │ │ 3. 发布 module.shutdown.ready│
438
+ │ ├────────────────────────────>│
439
+ │ │ │
440
+ │ │ 4. 关闭 Kernel 连接 │
441
+ │ ├─────────────────────────X │
442
+ │ │ │
443
+ │ │ 5. 删除 session 映射 │
444
+ │ │ │
445
+ │ 6. 关闭客户端连接 │ │
446
+ ├─────────────────────────X │ │
447
+ │ │ │
448
+ ```
449
+
450
+ **场景 B:超时未重连(6秒)**
451
+
452
+ ```
453
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
454
+ │ 客户端 │ │ 中转服务 │ │ Kernel │
455
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
456
+ │ │ │
457
+ │ 1. 客户端断开 │ │
458
+ ├─────────────────────────X │ │
459
+ │ │ │
460
+ │ │ 2. 启动 6 秒超时计时器 │
461
+ │ │ │
462
+ │ │ 3. 等待 6 秒... │
463
+ │ │ │
464
+ │ │ 4. 超时触发 │
465
+ │ │ 执行优雅退出流程 │
466
+ │ │ │
467
+ │ │ 5. 发布 module.exiting │
468
+ │ │ data: { │
469
+ │ │ module_id, │
470
+ │ │ token_revoked: true │
471
+ │ │ } │
472
+ │ ├────────────────────────────>│
473
+ │ │ │
474
+ │ │ 6-8. 同场景 A │
475
+ │ │ │
476
+ ```
477
+
478
+ ## WebSocket 消息协议
479
+
480
+ ### 客户端 → 中转服务
481
+
482
+ **配对消息(配对码)**:
483
+ ```json
484
+ {
485
+ "type": "pair",
486
+ "code": "ABC123"
487
+ }
488
+ ```
489
+
490
+ **配对消息(手机验证码 - 请求)**:
491
+ ```json
492
+ {
493
+ "type": "request_sms",
494
+ "phone": "+8613800138000"
495
+ }
496
+ ```
497
+
498
+ **配对消息(手机验证码 - 验证)**:
499
+ ```json
500
+ {
501
+ "type": "verify_sms",
502
+ "phone": "+8613800138000",
503
+ "code": "123456"
504
+ }
505
+ ```
506
+
507
+ **认证消息**:
508
+ ```json
509
+ {
510
+ "type": "auth",
511
+ "token": "tok_xxx",
512
+ "session_token": "sess_a3f9e2"
513
+ }
514
+ ```
515
+
516
+ **断开消息**:
517
+ ```json
518
+ {
519
+ "type": "disconnect"
520
+ }
521
+ ```
522
+
523
+ **心跳消息**:
524
+ ```json
525
+ {
526
+ "type": "ping"
527
+ }
528
+ ```
529
+
530
+ **RPC 请求**(认证后):
531
+ ```json
532
+ {
533
+ "jsonrpc": "2.0",
534
+ "id": "req-123",
535
+ "method": "launcher.list_modules",
536
+ "params": {}
537
+ }
538
+ ```
539
+
540
+ **事件订阅**(认证后):
541
+ ```json
542
+ {
543
+ "jsonrpc": "2.0",
544
+ "id": "sub-123",
545
+ "method": "event.subscribe",
546
+ "params": {
547
+ "events": ["module.started", "module.stopped"]
548
+ }
549
+ }
550
+ ```
551
+
552
+ ### 中转服务 → 客户端
553
+
554
+ **配对成功**:
555
+ ```json
556
+ {
557
+ "type": "paired",
558
+ "token": "tok_xxx",
559
+ "session_token": "sess_a3f9e2",
560
+ "module_id": "web-client-a3f9e2",
561
+ "role": "admin",
562
+ "expires_at": "2026-04-07T12:00:00Z"
563
+ }
564
+ ```
565
+
566
+ **短信发送成功**:
567
+ ```json
568
+ {
569
+ "type": "sms_sent",
570
+ "phone": "+8613800138000",
571
+ "expires_in": 300
572
+ }
573
+ ```
574
+
575
+ **认证成功**:
576
+ ```json
577
+ {
578
+ "type": "authenticated",
579
+ "module_id": "web-client-a3f9e2",
580
+ "role": "admin"
581
+ }
582
+ ```
583
+
584
+ **重连成功**:
585
+ ```json
586
+ {
587
+ "type": "reconnected",
588
+ "module_id": "web-client-a3f9e2",
589
+ "role": "admin"
590
+ }
591
+ ```
592
+
593
+ **心跳响应**:
594
+ ```json
595
+ {
596
+ "type": "pong"
597
+ }
598
+ ```
599
+
600
+ **错误消息**:
601
+ ```json
602
+ {
603
+ "type": "error",
604
+ "code": "invalid_code",
605
+ "message": "Invalid pairing code"
606
+ }
607
+ ```
608
+
609
+ **RPC 响应**(来自 Kernel):
610
+ ```json
611
+ {
612
+ "jsonrpc": "2.0",
613
+ "id": "req-123",
614
+ "result": { ... }
615
+ }
616
+ ```
617
+
618
+ **事件通知**(来自 Kernel):
619
+ ```json
620
+ {
621
+ "jsonrpc": "2.0",
622
+ "method": "event",
623
+ "params": {
624
+ "event_id": "evt-123",
625
+ "event": "module.started",
626
+ "source": "launcher",
627
+ "timestamp": "2026-03-08T12:00:00Z",
628
+ "data": {
629
+ "module_id": "watchdog"
630
+ }
631
+ }
632
+ }
633
+ ```
634
+
635
+ ## Launcher 扩展
636
+
637
+ ### 配置文件扩展
638
+
639
+ **launcher/config.yaml** 新增配置块:
640
+
641
+ ```yaml
642
+ # 允许申请动态 Token 的模块白名单
643
+ relay_modules:
644
+ - evol
645
+ - web
646
+
647
+ # 每个 relay 模块的 Token 限额
648
+ relay_token_limits:
649
+ evol: 100 # 最多 100 个并发虚拟模块
650
+ web: 50 # 最多 50 个并发虚拟模块
651
+ ```
652
+
653
+ ### RPC 方法扩展
654
+
655
+ #### 1. launcher.request_client_token
656
+
657
+ **描述:** 为 relay 模块申请虚拟客户端 Token
658
+
659
+ **权限:** 只有在 `relay_modules` 白名单中的模块可调用
660
+
661
+ **请求:**
662
+ ```json
663
+ {
664
+ "jsonrpc": "2.0",
665
+ "id": "req-123",
666
+ "method": "launcher.request_client_token",
667
+ "params": {
668
+ "module_id": "web-client-a3f9e2"
669
+ }
670
+ }
671
+ ```
672
+
673
+ **响应(成功):**
674
+ ```json
675
+ {
676
+ "jsonrpc": "2.0",
677
+ "id": "req-123",
678
+ "result": {
679
+ "token": "abc123...",
680
+ "module_id": "web-client-a3f9e2"
681
+ }
682
+ }
683
+ ```
684
+
685
+ **响应(失败):**
686
+ ```json
687
+ {
688
+ "jsonrpc": "2.0",
689
+ "id": "req-123",
690
+ "error": {
691
+ "code": -32001,
692
+ "message": "Permission denied: caller not in relay_modules whitelist"
693
+ }
694
+ }
695
+ ```
696
+
697
+ **错误码:**
698
+ - `-32001`: 权限拒绝(调用者不在白名单中)
699
+ - `-32002`: module_id 格式不合法
700
+ - `-32003`: module_id 已存在
701
+ - `-32004`: Token 限额已满
702
+
703
+ **实现逻辑:**
704
+ ```python
705
+ async def _rpc_request_client_token(self, caller_id: str, params: dict) -> dict:
706
+ """为 relay 模块申请虚拟客户端 token"""
707
+
708
+ # 1. 权限检查
709
+ relay_modules = self.config.get("relay_modules", [])
710
+ if caller_id not in relay_modules:
711
+ raise PermissionError(f"Permission denied: {caller_id} not in relay_modules whitelist")
712
+
713
+ # 2. 参数验证
714
+ module_id = params.get("module_id")
715
+ if not module_id:
716
+ raise ValueError("module_id is required")
717
+
718
+ # 3. 命名规范验证
719
+ expected_prefix = f"{caller_id}-client-"
720
+ if not module_id.startswith(expected_prefix):
721
+ raise ValueError(f"module_id must start with {expected_prefix}")
722
+
723
+ suffix = module_id[len(expected_prefix):]
724
+ if not re.match(r'^[a-zA-Z0-9_-]+$', suffix):
725
+ raise ValueError("Invalid module_id suffix")
726
+
727
+ # 4. 检查是否已存在
728
+ if module_id in self._client_tokens:
729
+ # 已存在,返回已有 token(幂等)
730
+ return {
731
+ "token": self._client_tokens[module_id],
732
+ "module_id": module_id
733
+ }
734
+
735
+ # 5. 检查限额
736
+ limits = self.config.get("relay_token_limits", {})
737
+ limit = limits.get(caller_id, 100)
738
+ current_count = sum(1 for mid in self._client_tokens if mid.startswith(expected_prefix))
739
+ if current_count >= limit:
740
+ raise RuntimeError(f"Token limit reached: {current_count}/{limit}")
741
+
742
+ # 6. 生成 token
743
+ token = secrets.token_hex(32)
744
+
745
+ # 7. 注册到 Kernel
746
+ await self._rpc_call(self._ws, "kernel.register_tokens", {module_id: token})
747
+
748
+ # 8. 保存到本地映射
749
+ self._client_tokens[module_id] = token
750
+
751
+ # 9. 记录审计日志
752
+ self._log_token_request(caller_id, module_id, True)
753
+
754
+ return {
755
+ "token": token,
756
+ "module_id": module_id
757
+ }
758
+ ```
759
+
760
+ #### 2. launcher.release_client_token(可选)
761
+
762
+ **描述:** 释放虚拟客户端 Token
763
+
764
+ **权限:** 只有在 `relay_modules` 白名单中的模块可调用
765
+
766
+ **请求:**
767
+ ```json
768
+ {
769
+ "jsonrpc": "2.0",
770
+ "id": "req-124",
771
+ "method": "launcher.release_client_token",
772
+ "params": {
773
+ "module_id": "web-client-a3f9e2"
774
+ }
775
+ }
776
+ ```
777
+
778
+ **响应:**
779
+ ```json
780
+ {
781
+ "jsonrpc": "2.0",
782
+ "id": "req-124",
783
+ "result": {}
784
+ }
785
+ ```
786
+
787
+ **实现逻辑:**
788
+ ```python
789
+ async def _rpc_release_client_token(self, caller_id: str, params: dict) -> dict:
790
+ """释放虚拟客户端 token"""
791
+
792
+ # 1. 权限检查
793
+ relay_modules = self.config.get("relay_modules", [])
794
+ if caller_id not in relay_modules:
795
+ raise PermissionError(f"Permission denied")
796
+
797
+ # 2. 参数验证
798
+ module_id = params.get("module_id")
799
+ if not module_id:
800
+ raise ValueError("module_id is required")
801
+
802
+ # 3. 验证所有权
803
+ expected_prefix = f"{caller_id}-client-"
804
+ if not module_id.startswith(expected_prefix):
805
+ raise ValueError(f"module_id does not belong to {caller_id}")
806
+
807
+ # 4. 删除 token
808
+ if module_id in self._client_tokens:
809
+ del self._client_tokens[module_id]
810
+
811
+ # 5. 记录审计日志
812
+ self._log_token_release(caller_id, module_id)
813
+
814
+ return {}
815
+ ```
816
+
817
+ ### 事件监听
818
+
819
+ Launcher 监听 `module.exiting` 事件,自动释放 Token:
820
+
821
+ ```python
822
+ async def _handle_module_exiting(self, event_data: dict):
823
+ """处理模块退出事件"""
824
+ module_id = event_data.get("module_id")
825
+ token_revoked = event_data.get("token_revoked", False)
826
+
827
+ if token_revoked and module_id in self._client_tokens:
828
+ # 标记 token 失效
829
+ del self._client_tokens[module_id]
830
+ print(f"[launcher] Token revoked for {module_id}")
831
+ ```
832
+
833
+ ## 中转服务实现
834
+
835
+ ### 核心数据结构
836
+
837
+ ```python
838
+ class SessionInfo:
839
+ """前端会话信息"""
840
+ session_token: str # 会话标识(如 "sess_a3f9e2")
841
+ module_id: str # 虚拟模块 ID(如 "web-client-a3f9e2")
842
+ kernel_ws: WebSocket # Kernel 连接
843
+ kernel_token: str # Kernel Token
844
+ client_ws: WebSocket # 客户端连接(可能为 None)
845
+ frontend_token: str # 前端认证 Token
846
+ role: str # 用户角色(admin/operator/viewer)
847
+ created_at: float # 创建时间戳
848
+ last_active: float # 最后活跃时间戳
849
+ status: str # "active" | "waiting_reconnect"
850
+ ```
851
+
852
+ ### 关键方法
853
+
854
+ #### 1. 配对/认证处理
855
+
856
+ ```python
857
+ async def handle_client(self, client_ws: WebSocket):
858
+ """处理客户端连接"""
859
+ await client_ws.accept()
860
+
861
+ try:
862
+ # 接收第一条消息(配对/认证)
863
+ raw = await client_ws.receive_text()
864
+ msg = json.loads(raw)
865
+
866
+ if msg.get("type") == "pair":
867
+ # 配对码配对
868
+ await self._handle_pairing(client_ws, msg)
869
+ elif msg.get("type") == "request_sms":
870
+ # 请求手机验证码
871
+ await self._handle_sms_request(client_ws, msg)
872
+ elif msg.get("type") == "verify_sms":
873
+ # 验证手机验证码
874
+ await self._handle_sms_verify(client_ws, msg)
875
+ elif msg.get("type") == "auth":
876
+ # 已有 token,认证
877
+ await self._handle_auth(client_ws, msg)
878
+ else:
879
+ await client_ws.send_json({
880
+ "type": "error",
881
+ "message": "Invalid message type"
882
+ })
883
+ await client_ws.close()
884
+ except Exception as e:
885
+ print(f"[relay] Error handling client: {e}")
886
+ await client_ws.close()
887
+ ```
888
+
889
+ #### 2. 申请 Kernel Token
890
+
891
+ ```python
892
+ async def _request_kernel_token(self, module_id: str) -> str:
893
+ """向 Launcher 申请 Kernel Token"""
894
+ if not self.evol_server or not self.evol_server._ws:
895
+ raise RuntimeError("Not connected to Kernel")
896
+
897
+ # 调用 Launcher RPC
898
+ result = await self.evol_server._rpc_call(
899
+ self.evol_server._ws,
900
+ "launcher.request_client_token",
901
+ {"module_id": module_id}
902
+ )
903
+
904
+ if "error" in result:
905
+ raise RuntimeError(f"Failed to request token: {result['error']}")
906
+
907
+ return result["result"]["token"]
908
+ ```
909
+
910
+ #### 3. 连接 Kernel
911
+
912
+ ```python
913
+ async def _connect_kernel(self, module_id: str, kernel_token: str):
914
+ """使用 kernel_token 连接到 Kernel"""
915
+ url = f"ws://{self.kernel_host}:{self.kernel_port}/ws?token={kernel_token}&id={module_id}"
916
+
917
+ kernel_ws = await websockets.connect(
918
+ url,
919
+ open_timeout=5,
920
+ ping_interval=None,
921
+ close_timeout=10
922
+ )
923
+
924
+ # 注册模块
925
+ await self._send_to_kernel(kernel_ws, {
926
+ "jsonrpc": "2.0",
927
+ "id": str(uuid.uuid4()),
928
+ "method": "registry.register",
929
+ "params": {
930
+ "module_id": module_id,
931
+ "module_type": "web_client",
932
+ }
933
+ })
934
+
935
+ # 发送 module.ready
936
+ await self._send_to_kernel(kernel_ws, {
937
+ "jsonrpc": "2.0",
938
+ "id": str(uuid.uuid4()),
939
+ "method": "event.publish",
940
+ "params": {
941
+ "event_id": str(uuid.uuid4()),
942
+ "event": "module.ready",
943
+ "data": {
944
+ "module_id": module_id,
945
+ "graceful_shutdown": True,
946
+ }
947
+ }
948
+ })
949
+
950
+ return kernel_ws
951
+ ```
952
+
953
+ #### 4. 优雅退出
954
+
955
+ ```python
956
+ async def _graceful_shutdown(self, session: SessionInfo):
957
+ """执行优雅退出流程"""
958
+ try:
959
+ # 发布 module.exiting 事件(标记 token 失效)
960
+ await self._send_to_kernel(session.kernel_ws, {
961
+ "jsonrpc": "2.0",
962
+ "id": str(uuid.uuid4()),
963
+ "method": "event.publish",
964
+ "params": {
965
+ "event_id": str(uuid.uuid4()),
966
+ "event": "module.exiting",
967
+ "data": {
968
+ "module_id": session.module_id,
969
+ "token_revoked": True # 关键:标记 token 失效
970
+ }
971
+ }
972
+ })
973
+
974
+ # 发布 module.shutdown.ready 事件
975
+ await self._send_to_kernel(session.kernel_ws, {
976
+ "jsonrpc": "2.0",
977
+ "id": str(uuid.uuid4()),
978
+ "method": "event.publish",
979
+ "params": {
980
+ "event_id": str(uuid.uuid4()),
981
+ "event": "module.shutdown.ready",
982
+ "data": {
983
+ "module_id": session.module_id
984
+ }
985
+ }
986
+ })
987
+
988
+ # 关闭 Kernel 连接
989
+ await session.kernel_ws.close()
990
+
991
+ print(f"[relay] Graceful shutdown completed: {session.module_id}")
992
+ except Exception as e:
993
+ print(f"[relay] Graceful shutdown error: {e}")
994
+ ```
995
+
996
+ #### 5. 重连处理
997
+
998
+ ```python
999
+ async def _handle_reconnect(self, client_ws: WebSocket, session_token: str, token_info: dict):
1000
+ """处理客户端重连"""
1001
+ session = self.sessions.get(session_token)
1002
+ if not session:
1003
+ # session 不存在,创建新连接
1004
+ await self._create_new_connection(client_ws, session_token, token_info)
1005
+ return
1006
+
1007
+ # 取消超时计时器
1008
+ if session_token in self.reconnect_timers:
1009
+ self.reconnect_timers[session_token].cancel()
1010
+ del self.reconnect_timers[session_token]
1011
+
1012
+ # 恢复客户端连接
1013
+ session.client_ws = client_ws
1014
+ session.status = "active"
1015
+ session.last_active = time.time()
1016
+
1017
+ # 返回重连成功
1018
+ await client_ws.send_json({
1019
+ "type": "reconnected",
1020
+ "module_id": session.module_id,
1021
+ "role": session.role
1022
+ })
1023
+
1024
+ print(f"[relay] Reconnected: {session.module_id}")
1025
+
1026
+ # 继续双向转发
1027
+ await self._relay_messages(session)
1028
+ ```
1029
+
1030
+ ## 权限控制
1031
+
1032
+ ### 权限配置
1033
+
1034
+ ```json5
1035
+ // relay_config.json5
1036
+ {
1037
+ permissions: {
1038
+ // 管理员角色 - 完全权限
1039
+ admin: [
1040
+ "event.*", // 事件订阅(必需)
1041
+ "registry.*", // 注册表查询(必需)
1042
+ "launcher.*", // 所有 launcher RPC
1043
+ "kernel.health", // Kernel 健康检查
1044
+ "kernel.stats", // Kernel 统计信息
1045
+ "*.health", // 所有模块的健康检查
1046
+ "*.status", // 所有模块的状态查询
1047
+ "watchdog.*", // Watchdog 相关
1048
+ "backup.*", // Backup 相关
1049
+ "model_service.*", // Model Service 相关
1050
+ "web.*" // Web 管理相关
1051
+ ],
1052
+
1053
+ // 操作员角色 - 模块管理权限
1054
+ operator: [
1055
+ "event.*", // 事件订阅(必需)
1056
+ "registry.*", // 注册表查询(必需)
1057
+ "launcher.list_modules",
1058
+ "launcher.start_module",
1059
+ "launcher.stop_module",
1060
+ "launcher.restart_module",
1061
+ "*.health",
1062
+ "*.status"
1063
+ ],
1064
+
1065
+ // 查看者角色 - 只读权限
1066
+ viewer: [
1067
+ "event.*", // 事件订阅(必需)
1068
+ "registry.*", // 注册表查询(必需)
1069
+ "launcher.list_modules",
1070
+ "*.health",
1071
+ "*.status"
1072
+ ]
1073
+ }
1074
+ }
1075
+ ```
1076
+
1077
+ ### 权限检查
1078
+
1079
+ ```python
1080
+ def _check_permission(self, role: str, msg: dict) -> bool:
1081
+ """检查 RPC 权限"""
1082
+ method = msg.get("method")
1083
+ if not method:
1084
+ return True # 非 RPC 消息,放行
1085
+
1086
+ # 获取角色的权限列表
1087
+ permissions = self.permissions.get(role, [])
1088
+
1089
+ # 检查是否匹配
1090
+ for pattern in permissions:
1091
+ if self._match_pattern(pattern, method):
1092
+ return True
1093
+
1094
+ return False
1095
+
1096
+ def _match_pattern(self, pattern: str, method: str) -> bool:
1097
+ """匹配通配符模式"""
1098
+ if pattern == method:
1099
+ return True
1100
+ if pattern.endswith(".*"):
1101
+ prefix = pattern[:-2]
1102
+ return method.startswith(prefix + ".")
1103
+ return False
1104
+ ```
1105
+
1106
+ ## 连接韧性设计
1107
+
1108
+ ### 三层重连机制
1109
+
1110
+ ```
1111
+ ┌─────────────────────────────────────────────────────────┐
1112
+ │ 层次 1: 客户端 ↔ 中转服务 │
1113
+ │ - 客户端断开 → 中转服务保持 Kernel 连接 6 秒 │
1114
+ │ - 客户端重连 → 中转服务复用 Kernel 连接 │
1115
+ │ - 超时 → 中转服务执行优雅退出 │
1116
+ └─────────────────────────────────────────────────────────┘
1117
+
1118
+ ┌─────────────────────────────────────────────────────────┐
1119
+ │ 层次 2: 中转服务 ↔ Kernel │
1120
+ │ - 中转服务断开 → Kernel 启动 5 秒 debounce │
1121
+ │ - 中转服务重连 → Kernel 取消 debounce(使用同一 token) │
1122
+ │ - 超时 → Kernel 标记模块 offline │
1123
+ └─────────────────────────────────────────────────────────┘
1124
+
1125
+ ┌─────────────────────────────────────────────────────────┐
1126
+ │ 层次 3: 中转服务模块 ↔ Kernel │
1127
+ │ - 中转服务模块断开 → 自动重连(指数退避,最多 10 次) │
1128
+ │ - 每次重连使用同一 token │
1129
+ │ - 认证失败 → 退出(token 无效) │
1130
+ └─────────────────────────────────────────────────────────┘
1131
+ ```
1132
+
1133
+ ### Token 复用机制
1134
+
1135
+ **关键点:** Token 不是一次性的,可以多次重连使用。
1136
+
1137
+ **客户端重连:**
1138
+ - 客户端刷新页面 → 中转服务保持 Kernel 连接
1139
+ - 客户端重连 → 复用已有的 `kernel_ws` 和 `kernel_token`
1140
+ - 无需重新申请 token
1141
+
1142
+ **中转服务重连:**
1143
+ - 中转服务模块重启 → 使用同一 token 重连 Kernel
1144
+ - Kernel 验证 token,恢复连接
1145
+ - 虚拟模块的 token 需要重新申请(因为 session 映射丢失)
1146
+
1147
+ **Token 失效:**
1148
+ - 只有在优雅退出时,通过 `module.exiting` 事件标记 `token_revoked: true`
1149
+ - Launcher 监听事件,删除 token 映射
1150
+ - 客户端再次连接时,必须重新申请 token
1151
+
1152
+ ## 安全机制
1153
+
1154
+ ### 1. 权限白名单
1155
+
1156
+ **Launcher 配置:**
1157
+ ```yaml
1158
+ relay_modules:
1159
+ - evol
1160
+ - web
1161
+ ```
1162
+
1163
+ 只有在白名单中的模块可以调用 `launcher.request_client_token`。
1164
+
1165
+ ### 2. Token 限额
1166
+
1167
+ **Launcher 配置:**
1168
+ ```yaml
1169
+ relay_token_limits:
1170
+ evol: 100
1171
+ web: 50
1172
+ ```
1173
+
1174
+ 防止单个 relay 模块申请过多 token,避免资源耗尽。
1175
+
1176
+ ### 3. 命名规范验证
1177
+
1178
+ **规则:** `module_id` 必须以 `{caller_id}-client-` 开头
1179
+
1180
+ **示例:**
1181
+ - evol 模块申请:`evol-client-a3f9e2` ✅
1182
+ - evol 模块申请:`web-client-a3f9e2` ❌(不属于 evol)
1183
+ - web 模块申请:`web-client-xyz123` ✅
1184
+
1185
+ **目的:** 防止 relay 模块冒充其他模块。
1186
+
1187
+ ### 4. 审计日志
1188
+
1189
+ **Launcher 记录所有 token 申请:**
1190
+
1191
+ ```jsonl
1192
+ {"timestamp":"2026-03-08T12:00:00Z","caller_id":"evol","module_id":"evol-client-a3f9e2","action":"request","success":true}
1193
+ {"timestamp":"2026-03-08T12:05:00Z","caller_id":"evol","module_id":"evol-client-a3f9e2","action":"release","success":true}
1194
+ ```
1195
+
1196
+ **日志文件:** `launcher/log/token_requests.jsonl`
1197
+
1198
+ ### 5. RPC 权限控制
1199
+
1200
+ 中转服务根据用户角色过滤 RPC 请求:
1201
+
1202
+ ```python
1203
+ # 检查权限
1204
+ if not self._check_permission(session.role, msg):
1205
+ await session.client_ws.send_json({
1206
+ "jsonrpc": "2.0",
1207
+ "id": msg.get("id"),
1208
+ "error": {
1209
+ "code": -32001,
1210
+ "message": f"Permission denied: {msg.get('method')}"
1211
+ }
1212
+ })
1213
+ return
1214
+ ```
1215
+
1216
+ ### 6. Token 续期
1217
+
1218
+ **frontend_token 续期机制:**
1219
+
1220
+ ```python
1221
+ def verify_token(self, token: str) -> Optional[dict]:
1222
+ """验证 frontend_token,自动续期"""
1223
+ record = self._find_token_record(token)
1224
+ if not record:
1225
+ return None
1226
+
1227
+ # 检查是否过期
1228
+ expires_at = datetime.fromisoformat(record["expires_at"])
1229
+ now = datetime.now(timezone.utc)
1230
+
1231
+ if now > expires_at:
1232
+ return None # 已过期
1233
+
1234
+ # 检查是否需要续期(剩余 < 7 天)
1235
+ remaining = (expires_at - now).total_seconds()
1236
+ if remaining < 604800: # 7 天
1237
+ # 续期 30 天
1238
+ new_expires_at = now + timedelta(seconds=2592000)
1239
+ self._renew_token(token, new_expires_at)
1240
+
1241
+ return {
1242
+ "role": record["role"],
1243
+ "expires_at": record["expires_at"]
1244
+ }
1245
+ ```
1246
+
1247
+ ## 配置文件
1248
+
1249
+ ### relay_config.json5
1250
+
1251
+ ```json5
1252
+ {
1253
+ // 中转服务配置
1254
+ relay: {
1255
+ // 基础模块 ID(实际 module_id 会加上 session 后缀)
1256
+ base_module_id: "web-client",
1257
+
1258
+ // 重连超时时间(秒)
1259
+ // 客户端刷新页面或短暂断网时,中转服务保持 Kernel 连接的时长
1260
+ reconnect_timeout: 6,
1261
+
1262
+ // WebSocket 端点路径
1263
+ endpoint: "/ws/relay"
1264
+ },
1265
+
1266
+ // 认证配置
1267
+ auth: {
1268
+ // frontend_token 有效期(秒,30天)
1269
+ token_expiry: 2592000,
1270
+
1271
+ // token 续期阈值(秒,7天)
1272
+ // 当 token 剩余有效期小于此值时,自动续期
1273
+ token_renew_threshold: 604800,
1274
+
1275
+ // 配对码长度
1276
+ pairing_code_length: 6,
1277
+
1278
+ // 配对码文件路径(相对于模块数据目录)
1279
+ pairing_code_file: "pairing_codes.jsonl"
1280
+ },
1281
+
1282
+ // 短信配置(可选)
1283
+ sms: {
1284
+ // 短信 API 提供商(aliyun/tencent/twilio)
1285
+ provider: "aliyun",
1286
+
1287
+ // API 密钥
1288
+ access_key_id: "your_access_key",
1289
+ access_key_secret: "your_secret",
1290
+
1291
+ // 短信模板
1292
+ template_code: "SMS_123456",
1293
+ sign_name: "Kite管理平台",
1294
+
1295
+ // 验证码有效期(秒)
1296
+ code_expiry: 300
1297
+ },
1298
+
1299
+ // 权限配置(基于角色的 RPC 白名单)
1300
+ permissions: {
1301
+ // 管理员角色 - 完全权限
1302
+ admin: [
1303
+ "event.*",
1304
+ "registry.*",
1305
+ "launcher.*",
1306
+ "kernel.health",
1307
+ "kernel.stats",
1308
+ "*.health",
1309
+ "*.status",
1310
+ "watchdog.*",
1311
+ "backup.*",
1312
+ "model_service.*",
1313
+ "web.*"
1314
+ ],
1315
+
1316
+ // 操作员角色 - 模块管理权限
1317
+ operator: [
1318
+ "event.*",
1319
+ "registry.*",
1320
+ "launcher.list_modules",
1321
+ "launcher.start_module",
1322
+ "launcher.stop_module",
1323
+ "launcher.restart_module",
1324
+ "*.health",
1325
+ "*.status"
1326
+ ],
1327
+
1328
+ // 查看者角色 - 只读权限
1329
+ viewer: [
1330
+ "event.*",
1331
+ "registry.*",
1332
+ "launcher.list_modules",
1333
+ "*.health",
1334
+ "*.status"
1335
+ ]
1336
+ }
1337
+ }
1338
+ ```
1339
+
1340
+ ## 实现文件清单
1341
+
1342
+ ### 中转服务模块(evol/web)
1343
+
1344
+ 1. **relay.py** - 中转服务核心逻辑(独立可复用)
1345
+ 2. **pairing.py** - 配对码管理
1346
+ 3. **sms.py** - 短信验证码管理(可选)
1347
+ 4. **relay_config.json5** - 中转服务配置
1348
+
1349
+ ### Launcher 扩展
1350
+
1351
+ 1. **launcher/config.yaml** - 新增 `relay_modules` 和 `relay_token_limits` 配置
1352
+ 2. **launcher/entry.py** - 新增 RPC 方法:
1353
+ - `launcher.request_client_token`
1354
+ - `launcher.release_client_token`(可选)
1355
+ 3. **launcher/log/token_requests.jsonl** - Token 申请审计日志
1356
+
1357
+ ### 前端文件
1358
+
1359
+ 1. **static/js/kernel-client.js** - Kernel 客户端封装
1360
+ 2. **static/pairing.html** - 配对界面
1361
+ 3. **static/sms-verify.html** - 手机验证界面(可选)
1362
+
1363
+ ## 实施计划
1364
+
1365
+ ### 阶段 1: Launcher 扩展
1366
+
1367
+ 1. 修改 `launcher/config.yaml`,新增配置块
1368
+ 2. 实现 `launcher.request_client_token` RPC 方法
1369
+ 3. 实现 `launcher.release_client_token` RPC 方法(可选)
1370
+ 4. 实现 `module.exiting` 事件监听
1371
+ 5. 实现审计日志记录
1372
+
1373
+ ### 阶段 2: 中转服务核心
1374
+
1375
+ 1. 实现 `relay.py` 核心逻辑
1376
+ 2. 实现配对码配对流程
1377
+ 3. 实现 Token 申请和管理
1378
+ 4. 实现双向消息转发
1379
+ 5. 实现重连管理
1380
+ 6. 实现优雅退出
1381
+
1382
+ ### 阶段 3: 手机验证码(可选)
1383
+
1384
+ 1. 实现 `sms.py` 短信管理
1385
+ 2. 集成短信 API(阿里云/腾讯云/Twilio)
1386
+ 3. 实现验证码验证流程
1387
+
1388
+ ### 阶段 4: 前端客户端
1389
+
1390
+ 1. 实现 `KernelClient` 类
1391
+ 2. 实现配对界面
1392
+ 3. 实现手机验证界面(可选)
1393
+ 4. 实现自动重连逻辑
1394
+ 5. 实现 Token 续期处理
1395
+
1396
+ ### 阶段 5: 测试与优化
1397
+
1398
+ 1. 单元测试(配对、认证、权限)
1399
+ 2. 集成测试(完整流程)
1400
+ 3. 压力测试(并发连接)
1401
+ 4. 安全测试(权限绕过、Token 伪造)
1402
+ 5. 性能优化
1403
+
1404
+ ## 优势总结
1405
+
1406
+ 1. **安全可控** - Token 由 Launcher 集中管理,权限白名单控制
1407
+ 2. **平滑重连** - 客户端刷新页面时,Kernel 无感知
1408
+ 3. **灵活配对** - 支持配对码和手机验证码两种方式
1409
+ 4. **独立可复用** - relay.py 可以集成到任何模块
1410
+ 5. **完整生命周期** - 从配对到退出,全流程管理
1411
+ 6. **连接韧性** - 三层重连机制,Token 可复用
1412
+ 7. **审计追踪** - 所有 Token 申请都有日志记录
1413
+ 8. **权限细粒度** - 基于角色的 RPC 白名单
1414
+
1415
+ ## 技术难点与解决方案
1416
+
1417
+ ### 1. Token 管理复杂性
1418
+
1419
+ **难点:** 需要协调 Launcher、中转服务、Kernel 三方
1420
+
1421
+ **解决:**
1422
+ - Launcher 作为 Token 管理中心
1423
+ - 中转服务通过 RPC 申请 Token
1424
+ - Kernel 只负责验证 Token
1425
+
1426
+ ### 2. 重连状态同步
1427
+
1428
+ **难点:** 客户端重连时,如何恢复状态
1429
+
1430
+ **解决:**
1431
+ - 使用 `session_token` 识别重连
1432
+ - 中转服务保持 Kernel 连接 6 秒
1433
+ - 复用已有的 `kernel_ws` 和 `kernel_token`
1434
+
1435
+ ### 3. 优雅退出时机
1436
+
1437
+ **难点:** 如何判断客户端是刷新还是真正关闭
1438
+
1439
+ **解决:**
1440
+ - 客户端主动发送 `disconnect` 消息(beforeunload)
1441
+ - 超时机制(6 秒未重连 → 优雅退出)
1442
+ - 通过 `module.exiting` 事件标记 Token 失效
1443
+
1444
+ ### 4. 权限控制
1445
+
1446
+ **难点:** 如何防止客户端绕过权限检查
1447
+
1448
+ **解决:**
1449
+ - 中转服务在转发前检查权限
1450
+ - 基于角色的白名单机制
1451
+ - 拒绝的请求不转发到 Kernel
1452
+
1453
+ ### 5. 并发连接管理
1454
+
1455
+ **难点:** 大量客户端同时连接时的性能
1456
+
1457
+ **解决:**
1458
+ - Token 限额机制
1459
+ - 异步 I/O(asyncio)
1460
+ - 连接池管理
1461
+
1462
+ ## 附录
1463
+
1464
+ ### 错误码定义
1465
+
1466
+ | 错误码 | 说明 |
1467
+ |--------|------|
1468
+ | -32001 | 权限拒绝 |
1469
+ | -32002 | module_id 格式不合法 |
1470
+ | -32003 | module_id 已存在 |
1471
+ | -32004 | Token 限额已满 |
1472
+ | -32005 | 配对码无效 |
1473
+ | -32006 | 验证码无效 |
1474
+ | -32007 | frontend_token 无效或过期 |
1475
+
1476
+ ### 日志格式
1477
+
1478
+ **Token 申请日志:**
1479
+ ```jsonl
1480
+ {"timestamp":"2026-03-08T12:00:00Z","caller_id":"evol","module_id":"evol-client-a3f9e2","action":"request","success":true}
1481
+ ```
1482
+
1483
+ **Token 释放日志:**
1484
+ ```jsonl
1485
+ {"timestamp":"2026-03-08T12:05:00Z","caller_id":"evol","module_id":"evol-client-a3f9e2","action":"release","success":true}
1486
+ ```
1487
+
1488
+ **配对日志:**
1489
+ ```jsonl
1490
+ {"timestamp":"2026-03-08T12:00:00Z","type":"pair","code":"ABC123","role":"admin","success":true,"module_id":"evol-client-a3f9e2"}
1491
+ ```
1492
+
1493
+ **验证码日志:**
1494
+ ```jsonl
1495
+ {"timestamp":"2026-03-08T12:00:00Z","type":"sms","phone":"+8613800138000","code":"123456","success":true,"module_id":"evol-client-a3f9e2"}
1496
+ ```