@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,1054 @@
1
+ """
2
+ Auth 模块入口 - 纯 RPC 认证服务
3
+
4
+ 从 stdin 读 boot_info → 连接 Kernel → auth → registry.register → module.ready → 消息循环
5
+ 无 HTTP 服务器,所有功能通过 RPC 提供。
6
+ """
7
+
8
+ import builtins
9
+ import json
10
+ import os
11
+ import sys
12
+ import threading
13
+ import re
14
+ import time
15
+ from datetime import datetime, timezone
16
+
17
+ import asyncio
18
+ import traceback
19
+ import uuid
20
+ import random
21
+
22
+ import websockets
23
+
24
+
25
+ # System broadcast events
26
+ SYSTEM_BROADCAST_EVENTS = {
27
+ "module.ready", "module.registered", "module.started", "module.stopped",
28
+ "module.crashed", "module.exiting", "module.offline",
29
+ "module.shutdown.ack", "module.shutdown.ready",
30
+ "system.ready", "registry.updated",
31
+ "system.instance.started", "system.instance.stopped",
32
+ }
33
+
34
+
35
+ # ── Module configuration ──
36
+
37
+ def _load_module_config() -> dict:
38
+ _this_dir = os.path.dirname(os.path.abspath(__file__))
39
+ module_md = os.path.join(_this_dir, "module.md")
40
+ project_root = os.environ.get("KITE_PROJECT", "")
41
+ if project_root and _this_dir.startswith(project_root):
42
+ rel_path = os.path.relpath(_this_dir, project_root)
43
+ else:
44
+ rel_path = _this_dir
45
+ result = {"name": "", "preferred_port": 0, "advertise_ip": "0.0.0.0"}
46
+ if not os.path.exists(module_md):
47
+ print(f"[{rel_path}] ERROR: module.md not found")
48
+ sys.exit(1)
49
+ try:
50
+ with open(module_md, encoding="utf-8") as f:
51
+ text = f.read()
52
+ m = re.match(r'^---\s*\n(.*?)\n---', text, re.DOTALL)
53
+ if not m:
54
+ print(f"[{rel_path}] ERROR: Missing YAML frontmatter")
55
+ sys.exit(1)
56
+ try:
57
+ import yaml
58
+ fm = yaml.safe_load(m.group(1)) or {}
59
+ except ImportError:
60
+ print(f"[{rel_path}] ERROR: PyYAML not installed")
61
+ sys.exit(1)
62
+ if "name" not in fm:
63
+ print(f"[{rel_path}] ERROR: Missing 'name' field")
64
+ sys.exit(1)
65
+ raw_name = str(fm["name"]).strip()
66
+ sanitized = re.sub(r'[^a-zA-Z0-9_\-]', '', raw_name)
67
+ if sanitized != raw_name or not sanitized:
68
+ print(f"[{rel_path}] ERROR: Invalid module name '{raw_name}'")
69
+ sys.exit(1)
70
+ result["name"] = sanitized
71
+ if "preferred_port" in fm:
72
+ try:
73
+ result["preferred_port"] = int(fm["preferred_port"])
74
+ except (ValueError, TypeError):
75
+ pass
76
+ if "advertise_ip" in fm:
77
+ result["advertise_ip"] = str(fm["advertise_ip"])
78
+ # max_connections(弹性连接上限)
79
+ try:
80
+ result["max_connections"] = max(1, min(10, int(fm.get("max_connections", 1))))
81
+ except (ValueError, TypeError):
82
+ result["max_connections"] = 1
83
+ except SystemExit:
84
+ raise
85
+ except Exception as e:
86
+ print(f"[{rel_path}] ERROR: Failed to read module.md: {e}")
87
+ sys.exit(1)
88
+ return result
89
+
90
+ _module_config = _load_module_config()
91
+ MODULE_NAME = _module_config["name"]
92
+
93
+
94
+ # ── Safe stdout/stderr ──
95
+
96
+ class _SafeWriter:
97
+ def __init__(self, stream):
98
+ self._stream = stream
99
+ def write(self, s):
100
+ try:
101
+ self._stream.write(s)
102
+ except (BrokenPipeError, OSError):
103
+ pass
104
+ def flush(self):
105
+ try:
106
+ self._stream.flush()
107
+ except (BrokenPipeError, OSError):
108
+ pass
109
+ def __getattr__(self, name):
110
+ return getattr(self._stream, name)
111
+
112
+ sys.stdout = _SafeWriter(sys.stdout)
113
+ sys.stderr = _SafeWriter(sys.stderr)
114
+
115
+
116
+ # ── Timestamped print + log file writer ──
117
+
118
+ _builtin_print = builtins.print
119
+ _start_ts = time.monotonic()
120
+ _last_ts = time.monotonic()
121
+ _ANSI_RE = re.compile(r"\033\[[0-9;]*m")
122
+ _log_lock = threading.Lock()
123
+ _log_latest_path = None
124
+ _log_daily_path = None
125
+ _log_daily_date = ""
126
+ _log_dir = None
127
+ _crash_log_path = None
128
+
129
+ def _strip_ansi(s: str) -> str:
130
+ return _ANSI_RE.sub("", s)
131
+
132
+ def _resolve_daily_log_path():
133
+ global _log_daily_path, _log_daily_date
134
+ if not _log_dir:
135
+ return
136
+ today = datetime.now().strftime("%Y-%m-%d")
137
+ if today == _log_daily_date and _log_daily_path:
138
+ return
139
+ month_dir = os.path.join(_log_dir, today[:7])
140
+ os.makedirs(month_dir, exist_ok=True)
141
+ _log_daily_path = os.path.join(month_dir, f"{today}.log")
142
+ _log_daily_date = today
143
+
144
+ def _write_log(plain_line: str):
145
+ with _log_lock:
146
+ if _log_latest_path:
147
+ try:
148
+ with open(_log_latest_path, "a", encoding="utf-8") as f:
149
+ f.write(plain_line)
150
+ except Exception:
151
+ pass
152
+ _resolve_daily_log_path()
153
+ if _log_daily_path:
154
+ try:
155
+ with open(_log_daily_path, "a", encoding="utf-8") as f:
156
+ f.write(plain_line)
157
+ except Exception:
158
+ pass
159
+
160
+ def _write_crash(exc_type, exc_value, exc_tb, thread_name=None, severity="critical", handled=False):
161
+ record = {
162
+ "timestamp": datetime.now(timezone.utc).isoformat(),
163
+ "module": MODULE_NAME,
164
+ "thread": thread_name or threading.current_thread().name,
165
+ "exception_type": exc_type.__name__ if exc_type else "Unknown",
166
+ "exception_message": str(exc_value),
167
+ "traceback": "".join(traceback.format_exception(exc_type, exc_value, exc_tb)),
168
+ "severity": severity, "handled": handled,
169
+ "process_id": os.getpid(), "platform": sys.platform,
170
+ "runtime_version": f"Python {sys.version.split()[0]}",
171
+ }
172
+ if exc_tb:
173
+ tb_entries = traceback.extract_tb(exc_tb)
174
+ if tb_entries:
175
+ last = tb_entries[-1]
176
+ record["context"] = {"function": last.name, "file": os.path.basename(last.filename), "line": last.lineno}
177
+ line = json.dumps(record, ensure_ascii=False) + "\n"
178
+ if _crash_log_path:
179
+ try:
180
+ with open(_crash_log_path, "a", encoding="utf-8") as f:
181
+ f.write(line)
182
+ except Exception:
183
+ pass
184
+ if _log_dir:
185
+ try:
186
+ today = datetime.now().strftime("%Y-%m-%d")
187
+ archive_dir = os.path.join(_log_dir, "crashes", today[:7])
188
+ os.makedirs(archive_dir, exist_ok=True)
189
+ with open(os.path.join(archive_dir, f"{today}.jsonl"), "a", encoding="utf-8") as f:
190
+ f.write(line)
191
+ except Exception:
192
+ pass
193
+
194
+ def _setup_exception_hooks():
195
+ _orig = sys.excepthook
196
+ def _excepthook(exc_type, exc_value, exc_tb):
197
+ _write_crash(exc_type, exc_value, exc_tb, severity="critical", handled=False)
198
+ _orig(exc_type, exc_value, exc_tb)
199
+ sys.excepthook = _excepthook
200
+ if hasattr(threading, "excepthook"):
201
+ def _thread_excepthook(args):
202
+ _write_crash(args.exc_type, args.exc_value, args.exc_traceback,
203
+ thread_name=args.thread.name if args.thread else "unknown",
204
+ severity="error", handled=False)
205
+ threading.excepthook = _thread_excepthook
206
+
207
+ def _tprint(*args, **kwargs):
208
+ global _last_ts
209
+ now = time.monotonic()
210
+ elapsed = now - _start_ts
211
+ delta = now - _last_ts
212
+ _last_ts = now
213
+ elapsed_str = f"{elapsed*1000:.0f}ms" if elapsed < 1 else (f"{elapsed:.1f}s" if elapsed < 100 else f"{elapsed:.0f}s")
214
+ delta_str = "" if delta < 0.001 else (f"+{delta*1000:.0f}ms" if delta < 1 else (f"+{delta:.1f}s" if delta < 100 else f"+{delta:.0f}s"))
215
+ _builtin_print(*args, **kwargs)
216
+ if _log_latest_path or _log_daily_path:
217
+ sep = kwargs.get("sep", " ")
218
+ end = kwargs.get("end", "\n")
219
+ text = sep.join(str(a) for a in args)
220
+ ts = datetime.now().strftime("%H:%M:%S.%f")[:-3]
221
+ prefix = f"[{elapsed_str:>6}] {ts} {delta_str:>8} "
222
+ _write_log(prefix + _strip_ansi(text) + end)
223
+
224
+ builtins.print = _tprint
225
+
226
+ _project_root = os.environ.get("KITE_PROJECT") or os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
227
+ if _project_root not in sys.path:
228
+ sys.path.insert(0, _project_root)
229
+
230
+
231
+ def _fmt_elapsed(t0: float) -> str:
232
+ d = time.monotonic() - t0
233
+ if d < 1: return f"{d*1000:.0f}ms"
234
+ if d < 10: return f"{d:.1f}s"
235
+ return f"{d:.0f}s"
236
+
237
+
238
+ def _read_stdin_kite_message(expected_type: str, timeout: float = 10) -> dict | None:
239
+ result = [None]
240
+ def _read():
241
+ try:
242
+ line = sys.stdin.readline().strip()
243
+ if line:
244
+ msg = json.loads(line)
245
+ if isinstance(msg, dict) and msg.get("kite") == expected_type:
246
+ result[0] = msg
247
+ except Exception:
248
+ pass
249
+ t = threading.Thread(target=_read, daemon=True)
250
+ t.start()
251
+ t.join(timeout=timeout)
252
+ return result[0]
253
+
254
+
255
+ # ── Global state ──
256
+
257
+ _ws_global = None
258
+ _shutting_down = False
259
+ _exit_code = 0
260
+ _pairing_verifier = None
261
+ _kite_token_verifier = None
262
+ _evol_account_verifier = None
263
+ _token_store = None
264
+
265
+ # 弹性多连接
266
+ _extra_ws: dict = {} # slot → WebSocket(附加连接)
267
+ _extra_ws_tasks: dict = {} # slot → recv loop Task
268
+ _kernel_port = "" # 缓存 kernel_port,供 offer handler 使用
269
+
270
+ # RPC 响应等待
271
+ _pending_rpc: dict[str, asyncio.Future] = {}
272
+
273
+ _has_registered = False
274
+
275
+
276
+ # ── Auth RPC handlers ──
277
+
278
+ async def _rpc_verify(params: dict) -> dict:
279
+ """auth.verify — 统一认证入口"""
280
+ method = params.get("method", "")
281
+
282
+ if method == "pairing_code":
283
+ code = params.get("code", "")
284
+ result = _pairing_verifier.verify(code)
285
+ if result is None:
286
+ return {"success": False, "error": "invalid_code"}
287
+ # 配对码验证成功,生成 kite_token
288
+ client_info = params.get("client_info", {})
289
+ kite_token = _token_store.create_token(
290
+ auth_method="pairing_code",
291
+ client_info=client_info,
292
+ trust_level="high",
293
+ role=result["role"],
294
+ )
295
+ # 发布成功事件
296
+ if _ws_global:
297
+ await _publish_event(_ws_global, "auth.success", {
298
+ "method": "pairing_code", "role": result["role"],
299
+ "device_id": client_info.get("device_id", "unknown"),
300
+ })
301
+ await _publish_event(_ws_global, "auth.token.created", {
302
+ "method": "pairing_code", "token_prefix": kite_token[:10] + "...",
303
+ })
304
+ return {"success": True, "role": result["role"], "trust_level": "high", "token": kite_token}
305
+
306
+ elif method == "evol_account":
307
+ phone = params.get("phone", "")
308
+ code = params.get("code", "")
309
+ result = await _evol_account_verifier.verify(phone, code)
310
+ if result is None:
311
+ if _ws_global:
312
+ await _publish_event(_ws_global, "auth.failed", {
313
+ "method": "evol_account", "error": "verification_failed",
314
+ })
315
+ return {"success": False, "error": "verification_failed"}
316
+ # Evol 账号验证成功,生成 kite_token
317
+ client_info = params.get("client_info", {})
318
+ client_info["phone"] = result["phone"]
319
+ kite_token = _token_store.create_token(
320
+ auth_method="evol_account",
321
+ client_info=client_info,
322
+ trust_level="medium",
323
+ role=result["role"],
324
+ )
325
+ if _ws_global:
326
+ await _publish_event(_ws_global, "auth.success", {
327
+ "method": "evol_account", "role": result["role"],
328
+ "device_id": client_info.get("device_id", "unknown"),
329
+ })
330
+ await _publish_event(_ws_global, "auth.token.created", {
331
+ "method": "evol_account", "token_prefix": kite_token[:10] + "...",
332
+ })
333
+ return {"success": True, "role": result["role"], "trust_level": "medium", "token": kite_token}
334
+
335
+ elif method == "kite_token":
336
+ token = params.get("token", "")
337
+ result = _kite_token_verifier.verify(token)
338
+ if result is None:
339
+ if _ws_global:
340
+ await _publish_event(_ws_global, "auth.failed", {
341
+ "method": "kite_token", "error": "invalid_token",
342
+ })
343
+ return {"success": False, "error": "invalid_token"}
344
+ return {"success": True, "role": result["role"], "trust_level": result["trust_level"]}
345
+
346
+ else:
347
+ return {"success": False, "error": f"unsupported method: {method}"}
348
+
349
+
350
+ async def _rpc_request_pairing_code(params: dict) -> dict:
351
+ """auth.request_pairing_code — 生成配对码"""
352
+ role = params.get("role", "admin")
353
+ try:
354
+ code = _pairing_verifier.generate(role=role)
355
+ except RuntimeError as e:
356
+ return {"success": False, "error": str(e)}
357
+ # 配对码仅在控制台输出,不返回给远程客户端
358
+ print(f"\033[1;31m[auth] 配对码: {code}\033[0m")
359
+ if _ws_global:
360
+ await _publish_event(_ws_global, "auth.code_generated", {
361
+ "role": role, "ttl": _pairing_verifier.code_ttl, "timestamp": time.time(),
362
+ })
363
+ return {"status": "generated", "ttl": _pairing_verifier.code_ttl}
364
+
365
+
366
+ async def _rpc_list_tokens(params: dict) -> dict:
367
+ """auth.list_tokens — 列出所有有效 token"""
368
+ tokens = _token_store.list_tokens()
369
+ return {"tokens": tokens, "count": len(tokens)}
370
+
371
+
372
+ async def _rpc_revoke_token(params: dict) -> dict:
373
+ """auth.revoke_token — 撤销指定 token"""
374
+ token = params.get("token", "")
375
+ if not token:
376
+ return {"success": False, "error": "missing token"}
377
+ ok = _token_store.revoke(token)
378
+ if ok and _ws_global:
379
+ await _publish_event(_ws_global, "auth.token.revoked", {
380
+ "token_prefix": token[:10] + "...",
381
+ })
382
+ return {"success": ok}
383
+
384
+
385
+ async def _rpc_get_pending_codes(params: dict) -> dict:
386
+ """auth.get_pending_codes — 返回当前有效的配对码列表(供本地控制台展示)"""
387
+ _pairing_verifier._cleanup_expired()
388
+ codes = []
389
+ now = time.time()
390
+ for code, info in _pairing_verifier._pending_codes.items():
391
+ remaining = _pairing_verifier.code_ttl - (now - info["created_at"])
392
+ if remaining > 0:
393
+ codes.append({"code": code, "role": info["role"], "remaining_ttl": round(remaining)})
394
+ return {"codes": codes, "count": len(codes)}
395
+
396
+
397
+ async def _rpc_send_sms_code(params: dict) -> dict:
398
+ """auth.send_sms_code — 发送短信验证码(pre-auth 方法)"""
399
+ phone = params.get("phone", "")
400
+ if not phone:
401
+ return {"success": False, "msg": "缺少手机号"}
402
+ result = await _evol_account_verifier.send_sms_code(phone)
403
+ return result
404
+
405
+
406
+ async def _rpc_get_supported_methods(params: dict) -> dict:
407
+ """auth.get_supported_methods — 返回支持的认证方式"""
408
+ return {"methods": ["pairing_code", "evol_account", "kite_token"]}
409
+
410
+
411
+ # ── WebSocket connection + message loop ──
412
+
413
+ async def _ws_loop(token: str, kernel_port: int, _t0: float):
414
+ global _shutting_down, _exit_code
415
+ retry_delay = 0.5
416
+ max_delay = 10.0
417
+ attempt = 0
418
+ cooldown_attempts = 0
419
+ conn_refused_count = 0
420
+
421
+ while not _shutting_down:
422
+ try:
423
+ await _ws_connect(token, kernel_port, _t0)
424
+ retry_delay = 0.5
425
+ attempt = 0
426
+ cooldown_attempts = 0
427
+ conn_refused_count = 0
428
+ except asyncio.CancelledError:
429
+ return
430
+ except Exception as e:
431
+ if _shutting_down:
432
+ return
433
+ code = _get_close_code(e)
434
+ if code in (4001, 4003, 4004, 1008, 4010):
435
+ print(f"[auth] 致命错误 (code {code}),退出")
436
+ _exit_code = 1
437
+ _shutting_down = True
438
+ return
439
+ if code == 4020:
440
+ cooldown_attempts += 1
441
+ if cooldown_attempts >= 5:
442
+ print(f"[auth] 速率限制重试 5 次,退出")
443
+ _exit_code = 1
444
+ _shutting_down = True
445
+ return
446
+ print(f"[auth] 速率限制,10s 后重试 ({cooldown_attempts}/5)")
447
+ await asyncio.sleep(10.0)
448
+ continue
449
+
450
+ # 连接被拒绝/重置 — Kernel 可能正在关闭
451
+ # Windows 的 [WinError 1225] 是 OSError 不是 ConnectionRefusedError
452
+ _is_conn_refused = isinstance(e, (ConnectionRefusedError, ConnectionResetError))
453
+ if not _is_conn_refused and isinstance(e, OSError) and getattr(e, 'winerror', None) == 1225:
454
+ _is_conn_refused = True
455
+ if _is_conn_refused:
456
+ conn_refused_count += 1
457
+ if conn_refused_count >= 3:
458
+ print(f"[auth] Kernel 持续不可达 ({conn_refused_count} 次),正常退出")
459
+ _exit_code = 0
460
+ _shutting_down = True
461
+ return
462
+ jitter = retry_delay * 0.2 * random.random()
463
+ sleep_time = retry_delay + jitter
464
+ print(f"[auth] Kernel 连接失败: {type(e).__name__}, {sleep_time:.1f}s 后重试 ({conn_refused_count}/3)")
465
+ else:
466
+ conn_refused_count = 0
467
+ attempt += 1
468
+ jitter = retry_delay * 0.2 * random.random()
469
+ sleep_time = retry_delay + jitter
470
+ _write_crash(type(e), e, e.__traceback__, severity="error", handled=True)
471
+ print(f"[auth] 连接错误: {e}, {sleep_time:.1f}s 后重试 (attempt {attempt})")
472
+ if attempt >= 10:
473
+ print(f"[auth] 连续 {attempt} 次连接失败,正常退出")
474
+ _exit_code = 0
475
+ _shutting_down = True
476
+ return
477
+
478
+ _ws_global_clear()
479
+ if _shutting_down:
480
+ return
481
+ await asyncio.sleep(sleep_time if 'sleep_time' in locals() else retry_delay)
482
+ retry_delay = min(retry_delay * 2, max_delay)
483
+
484
+
485
+ def _get_close_code(e: Exception) -> int:
486
+ if hasattr(e, 'rcvd') and e.rcvd is not None:
487
+ return getattr(e.rcvd, 'code', 0)
488
+ return 0
489
+
490
+
491
+ def _ws_global_clear():
492
+ global _ws_global
493
+ _ws_global = None
494
+
495
+
496
+ async def _do_init(ws):
497
+ """收到 system.require_init 后执行:subscribe + register + module.ready"""
498
+ global _has_registered
499
+ reason = "startup" if not _has_registered else "recovery"
500
+ print(f"[auth] Received system.require_init (reason={reason})")
501
+
502
+ # 1. Subscribe(等待响应)
503
+ await _rpc_call(ws, "event.subscribe", {
504
+ "events": ["module.ready", "module.shutdown"],
505
+ })
506
+ print(f"[auth] Subscribed to events")
507
+
508
+ # 2. Register(等待响应)
509
+ await _rpc_call(ws, "registry.register", {
510
+ "module_id": "auth",
511
+ "module_type": "service",
512
+ "launcher_id": "launcher",
513
+ "tools": {
514
+ "rpc": {
515
+ "auth": {
516
+ "verify": {"method": "verify", "description": "统一认证入口"},
517
+ "request_pairing_code": {"method": "request_pairing_code", "description": "生成配对码"},
518
+ "send_sms_code": {"method": "send_sms_code", "description": "发送短信验证码"},
519
+ "list_tokens": {"method": "list_tokens", "description": "列出所有 Token"},
520
+ "revoke_token": {"method": "revoke_token", "description": "撤销 Token"},
521
+ "get_supported_methods": {"method": "get_supported_methods", "description": "支持的认证方式"},
522
+ "get_pending_codes": {"method": "get_pending_codes", "description": "获取当前有效配对码"},
523
+ },
524
+ "module": {
525
+ "health": {"method": "health", "description": "健康检查"},
526
+ "status": {"method": "status", "description": "状态查询"},
527
+ }
528
+ }
529
+ },
530
+ "events_publish": {
531
+ "auth": {
532
+ "success": {"description": "认证成功"},
533
+ "failed": {"description": "认证失败"},
534
+ "code_generated": {"description": "配对码已生成"},
535
+ "token.created": {"description": "Token 已创建"},
536
+ "token.revoked": {"description": "Token 已撤销"},
537
+ }
538
+ },
539
+ "events_subscribe": ["module.ready", "module.shutdown"],
540
+ })
541
+ print(f"[auth] Registered to Kernel")
542
+
543
+ # 3. module.ready(不等响应)
544
+ if not _shutting_down:
545
+ await _publish_event(ws, "module.ready", {
546
+ "module_id": "auth",
547
+ "graceful_shutdown": True,
548
+ "startup_time": time.monotonic() - _start_ts,
549
+ "reason": reason,
550
+ })
551
+ print(f"[auth] module.ready published (reason={reason})")
552
+
553
+ _has_registered = True
554
+
555
+
556
+ async def _ws_connect(token: str, kernel_port: int, _t0: float):
557
+ global _ws_global, _kernel_port
558
+
559
+ _kernel_port = kernel_port
560
+ ws_url = f"ws://127.0.0.1:{kernel_port}/ws?id=auth"
561
+ print(f"[auth] Connecting to Kernel: {ws_url}")
562
+
563
+ async with websockets.connect(ws_url, open_timeout=5, ping_interval=None, close_timeout=10) as ws:
564
+ # 1. Auth(手动等待,不走 _rpc_call)
565
+ await ws.send(json.dumps({
566
+ "jsonrpc": "2.0", "id": "auth", "method": "auth",
567
+ "params": {"token": token}
568
+ }))
569
+ auth_resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
570
+ if "error" in auth_resp:
571
+ raise Exception(f"Auth failed: {auth_resp['error']}")
572
+
573
+ _ws_global = ws
574
+ print(f"[auth] Connected to Kernel ({_fmt_elapsed(_t0)})")
575
+
576
+ # 启动接收循环(后台任务),等待 system.require_init 触发 _do_init
577
+ receiver_task = asyncio.create_task(_ws_receiver(ws))
578
+
579
+ try:
580
+ # 等待接收循环结束(连接断开时自然退出)
581
+ await receiver_task
582
+ finally:
583
+ receiver_task.cancel()
584
+ # 断连清理 pending futures
585
+ for fut in _pending_rpc.values():
586
+ if not fut.done():
587
+ fut.set_result({"error": {"code": -32001, "message": "Connection lost"}})
588
+ _pending_rpc.clear()
589
+
590
+
591
+ async def _ws_receiver(ws):
592
+ """WebSocket 接收循环(后台任务)— 三路分发,检测 system.require_init"""
593
+ try:
594
+ async for raw in ws:
595
+ try:
596
+ msg = json.loads(raw)
597
+ except (json.JSONDecodeError, TypeError):
598
+ continue
599
+ try:
600
+ has_method = "method" in msg
601
+ has_id = "id" in msg
602
+ if has_method and not has_id:
603
+ # 检测 system.require_init 事件
604
+ params = msg.get("params", {})
605
+ event_type = params.get("event", "")
606
+ if event_type == "system.require_init":
607
+ asyncio.create_task(_do_init(ws))
608
+ continue
609
+ asyncio.create_task(_handle_event_notification(msg))
610
+ elif has_method and has_id:
611
+ asyncio.create_task(_handle_rpc_request(ws, msg))
612
+ elif not has_method and has_id:
613
+ _handle_rpc_response(msg)
614
+ except Exception as e:
615
+ print(f"[auth] 消息处理异常(已忽略): {e}")
616
+ except Exception as e:
617
+ if not _shutting_down:
618
+ print(f"[auth] Receive loop exited: {e}")
619
+
620
+
621
+ # ── RPC call + event publish helpers ──
622
+
623
+ async def _rpc_call(ws, method: str, params: dict = None,
624
+ wait_response: bool = True, timeout: float = 3.0) -> dict:
625
+ """JSON-RPC 2.0 request。默认等待响应。"""
626
+ rpc_id = str(uuid.uuid4())
627
+ msg = {"jsonrpc": "2.0", "id": rpc_id, "method": method}
628
+ if params:
629
+ msg["params"] = params
630
+
631
+ if not wait_response:
632
+ await ws.send(json.dumps(msg))
633
+ return {}
634
+
635
+ future = asyncio.get_event_loop().create_future()
636
+ _pending_rpc[rpc_id] = future
637
+ await ws.send(json.dumps(msg))
638
+ try:
639
+ return await asyncio.wait_for(future, timeout=timeout)
640
+ except asyncio.TimeoutError:
641
+ _pending_rpc.pop(rpc_id, None)
642
+ return {"error": {"code": -32000, "message": f"RPC timeout: {method} ({timeout}s)"}}
643
+
644
+
645
+ def _handle_rpc_response(msg: dict):
646
+ """Route JSON-RPC response to pending future."""
647
+ rpc_id = msg.get("id")
648
+ future = _pending_rpc.pop(rpc_id, None)
649
+ if future and not future.done():
650
+ future.set_result(msg)
651
+
652
+
653
+ async def _publish_event(ws, event: str, data: dict = None):
654
+ """Publish event via event.publish RPC (fire-and-forget)."""
655
+ await _rpc_call(ws, "event.publish", {
656
+ "event_id": str(uuid.uuid4()),
657
+ "event": event,
658
+ "data": data or {},
659
+ }, wait_response=False)
660
+
661
+
662
+ # ── Event + RPC handlers ──
663
+
664
+ async def _handle_ping_event(data: dict):
665
+ if _ws_global:
666
+ await _publish_event(_ws_global, "system.pong", {
667
+ "module_id": MODULE_NAME, "ping_time": data.get("ping_time"), "pong_time": time.time(),
668
+ })
669
+
670
+
671
+ async def _handle_event_notification(msg: dict):
672
+ params = msg.get("params", {})
673
+ event_type = params.get("event", "")
674
+ data = params.get("data", {})
675
+
676
+ if event_type == "system.ping":
677
+ await _handle_ping_event(data)
678
+ return
679
+
680
+ # 弹性连接 offer/release
681
+ if event_type == "system.connection.offer":
682
+ asyncio.create_task(_handle_connection_offer(data))
683
+ return
684
+ if event_type == "system.connection.release":
685
+ asyncio.create_task(_handle_connection_release(data))
686
+ return
687
+
688
+ if event_type == "module.shutdown":
689
+ target = data.get("module_id", "")
690
+ reason = data.get("reason", "")
691
+ if target == "auth" or not target or reason == "launcher_lost":
692
+ await _handle_shutdown()
693
+ return
694
+
695
+ if event_type in SYSTEM_BROADCAST_EVENTS:
696
+ return
697
+
698
+
699
+ async def _handle_rpc_request(ws, msg: dict):
700
+ rpc_id = msg.get("id", "")
701
+ method = msg.get("method", "")
702
+ params = msg.get("params", {})
703
+
704
+ handlers = {
705
+ "verify": _rpc_verify,
706
+ "request_pairing_code": _rpc_request_pairing_code,
707
+ "send_sms_code": _rpc_send_sms_code,
708
+ "list_tokens": _rpc_list_tokens,
709
+ "revoke_token": _rpc_revoke_token,
710
+ "get_supported_methods": _rpc_get_supported_methods,
711
+ "get_pending_codes": _rpc_get_pending_codes,
712
+ "health": lambda p: _rpc_health(),
713
+ "status": lambda p: _rpc_status(),
714
+ }
715
+ handler = handlers.get(method)
716
+ if handler:
717
+ try:
718
+ result = await handler(params)
719
+ await ws.send(json.dumps({"jsonrpc": "2.0", "id": rpc_id, "result": result}))
720
+ except Exception as e:
721
+ await ws.send(json.dumps({
722
+ "jsonrpc": "2.0", "id": rpc_id,
723
+ "error": {"code": -32603, "message": str(e)},
724
+ }))
725
+ else:
726
+ await ws.send(json.dumps({
727
+ "jsonrpc": "2.0", "id": rpc_id,
728
+ "error": {"code": -32601, "message": f"Method not found: {method}"},
729
+ }))
730
+
731
+
732
+ async def _rpc_health() -> dict:
733
+ return {"status": "healthy", "details": {"uptime_seconds": round(time.monotonic() - _start_ts)}}
734
+
735
+
736
+ async def _rpc_status() -> dict:
737
+ return {"module": "auth", "status": "running", "uptime_seconds": round(time.monotonic() - _start_ts)}
738
+
739
+
740
+ async def _handle_connection_offer(data):
741
+ """处理 Kernel 下发的 slot token,建立附加连接。"""
742
+ slots = data.get("slots", {})
743
+ for slot_str, info in slots.items():
744
+ slot = int(slot_str)
745
+ token = info.get("token", "")
746
+ if not token or slot in _extra_ws:
747
+ continue
748
+ asyncio.create_task(_connect_slot(slot, token))
749
+
750
+
751
+ async def _connect_slot(slot, token):
752
+ """建立单个 slot 附加连接。"""
753
+ ws_url = f"ws://127.0.0.1:{_kernel_port}/ws"
754
+ try:
755
+ ws = await websockets.connect(ws_url, open_timeout=5, ping_interval=None, close_timeout=5)
756
+ auth_req = {"jsonrpc": "2.0", "id": f"auth-slot-{slot}", "method": "auth", "params": {"token": token}}
757
+ await ws.send(json.dumps(auth_req))
758
+ resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
759
+ if "error" in resp:
760
+ await ws.close()
761
+ return
762
+ _extra_ws[slot] = ws
763
+ _extra_ws_tasks[slot] = asyncio.create_task(_slot_recv_loop(slot, ws))
764
+ print(f"[auth] Slot {slot} connected")
765
+ except Exception as e:
766
+ print(f"[auth] Slot {slot} connect failed: {e}")
767
+
768
+
769
+ async def _slot_recv_loop(slot, ws):
770
+ """附加连接的接收循环:与主连接平等处理所有消息。"""
771
+ try:
772
+ async for raw in ws:
773
+ try:
774
+ msg = json.loads(raw)
775
+ except (json.JSONDecodeError, TypeError):
776
+ continue
777
+ try:
778
+ has_method = "method" in msg
779
+ has_id = "id" in msg
780
+ if has_method and not has_id:
781
+ asyncio.create_task(_handle_event_notification(msg))
782
+ elif has_method and has_id:
783
+ asyncio.create_task(_handle_rpc_request(ws, msg))
784
+ elif not has_method and has_id:
785
+ _handle_rpc_response(msg)
786
+ except Exception as e:
787
+ print(f"[auth] Slot {slot} 消息处理异常(已忽略): {e}")
788
+ except Exception:
789
+ pass
790
+ finally:
791
+ _extra_ws.pop(slot, None)
792
+ _extra_ws_tasks.pop(slot, None)
793
+
794
+
795
+ async def _handle_connection_release(data):
796
+ """Kernel 请求释放 slot,优雅关闭。"""
797
+ for slot in data.get("slots", []):
798
+ ws = _extra_ws.pop(slot, None)
799
+ task = _extra_ws_tasks.pop(slot, None)
800
+ if ws:
801
+ try:
802
+ await ws.close(code=1000, reason="release")
803
+ except Exception:
804
+ pass
805
+ if task:
806
+ task.cancel()
807
+
808
+
809
+ async def _handle_shutdown():
810
+ global _shutting_down
811
+ print("[auth] Received shutdown request")
812
+ _shutting_down = True
813
+ await _publish_event(_ws_global, "module.shutdown.ack", {"module_id": "auth"})
814
+ await _publish_event(_ws_global, "module.exiting", {
815
+ "module_id": "auth", "type": "passive",
816
+ "reason": "shutdown_requested", "restart": "auto",
817
+ "action": "none", "timeout": 2.0, "restart_delay": 0.0,
818
+ })
819
+ # 关闭所有附加连接
820
+ for _s, _w in list(_extra_ws.items()):
821
+ try:
822
+ await _w.close(code=1000, reason="shutdown")
823
+ except Exception:
824
+ pass
825
+ for _t in _extra_ws_tasks.values():
826
+ _t.cancel()
827
+ _extra_ws.clear()
828
+ _extra_ws_tasks.clear()
829
+ await _publish_event(_ws_global, "module.shutdown.ready", {"module_id": "auth"})
830
+ print("[auth] Shutdown ready, exiting")
831
+ await asyncio.sleep(0.1)
832
+ if _ws_global:
833
+ try:
834
+ await _ws_global.close(code=1000, reason="Graceful shutdown")
835
+ except Exception:
836
+ pass
837
+
838
+
839
+ # ── Startup ──
840
+
841
+
842
+
843
+ def _init_logs_and_auth(log_base_dir: str = None, suffix: str = ""):
844
+ """初始化日志和认证组件(本地/远程共用)。"""
845
+ global _log_dir, _log_latest_path, _crash_log_path
846
+ global _pairing_verifier, _kite_token_verifier, _evol_account_verifier, _token_store
847
+
848
+ if log_base_dir:
849
+ _log_dir = os.path.join(log_base_dir, "log")
850
+ os.makedirs(_log_dir, exist_ok=True)
851
+ _log_latest_path = os.path.join(_log_dir, f"latest{suffix}.log")
852
+ try:
853
+ with open(_log_latest_path, "w", encoding="utf-8") as f: pass
854
+ except Exception: _log_latest_path = None
855
+ _crash_log_path = os.path.join(_log_dir, f"crashes{suffix}.jsonl")
856
+ try:
857
+ with open(_crash_log_path, "w", encoding="utf-8") as f: pass
858
+ except Exception: _crash_log_path = None
859
+ _resolve_daily_log_path()
860
+
861
+ _setup_exception_hooks()
862
+
863
+ # 初始化认证组件
864
+ module_data = os.environ.get("KITE_MODULE_DATA")
865
+ data_dir = os.path.join(module_data, "data") if module_data else os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
866
+ os.makedirs(data_dir, exist_ok=True)
867
+
868
+ from verifiers.pairing_code import PairingCodeVerifier
869
+ from verifiers.kite_token import KiteTokenVerifier
870
+ from verifiers.evol_account import EvolAccountVerifier
871
+ from token_store import TokenStore
872
+
873
+ _token_store = TokenStore(data_dir)
874
+ _pairing_verifier = PairingCodeVerifier()
875
+ _kite_token_verifier = KiteTokenVerifier(_token_store)
876
+ _evol_account_verifier = EvolAccountVerifier()
877
+ print(f"[auth] 认证组件初始化完成,数据目录: {data_dir}")
878
+
879
+
880
+ def _run_local_mode(kernel_port: int):
881
+ """本地模式:从 stdin 读 boot_info,连接 Kernel。"""
882
+ module_data = os.environ.get("KITE_MODULE_DATA")
883
+ suffix = os.environ.get("KITE_INSTANCE_SUFFIX", "")
884
+ _init_logs_and_auth(log_base_dir=module_data, suffix=suffix)
885
+
886
+ _t0 = time.monotonic()
887
+ line = sys.stdin.readline().strip()
888
+ if not line:
889
+ print(f"[{MODULE_NAME}] ERROR: stdin closed"); sys.exit(1)
890
+ try: msg = json.loads(line)
891
+ except json.JSONDecodeError as e:
892
+ print(f"[{MODULE_NAME}] ERROR: Invalid JSON: {e}"); sys.exit(1)
893
+ if "error" in msg:
894
+ print(f"[{MODULE_NAME}] 启动失败: {msg.get('message')}"); sys.exit(1)
895
+ token = msg.get("token", "")
896
+ if not token:
897
+ print(f"[{MODULE_NAME}] ERROR: No token"); sys.exit(1)
898
+
899
+ print(f"[{MODULE_NAME}] Local mode: port={kernel_port}")
900
+ try:
901
+ asyncio.run(_ws_loop(token, kernel_port, _t0))
902
+ except (ConnectionRefusedError, ConnectionResetError, OSError) as e:
903
+ if isinstance(e, OSError) and getattr(e, 'winerror', None) != 1225 and not isinstance(e, (ConnectionRefusedError, ConnectionResetError)):
904
+ raise
905
+ print(f"[{MODULE_NAME}] Kernel 不可达,正常退出")
906
+ sys.exit(0)
907
+ except Exception as e:
908
+ _write_crash(type(e), e, e.__traceback__, severity="critical", handled=True)
909
+ _print_crash_summary(type(e), e.__traceback__)
910
+ sys.exit(1)
911
+ sys.exit(_exit_code)
912
+
913
+
914
+ def _run_remote_mode(gateway_url: str):
915
+ """远程模式:通过 Gateway 连接 Kernel。"""
916
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
917
+ data_dir = os.path.join(home, ".kite", "remote", MODULE_NAME)
918
+ os.makedirs(data_dir, exist_ok=True)
919
+ _init_logs_and_auth(log_base_dir=data_dir)
920
+
921
+ _t0 = time.monotonic()
922
+ kite_token = _get_kite_token(MODULE_NAME, gateway_url)
923
+ print(f"[{MODULE_NAME}] Remote mode: gateway={gateway_url}")
924
+
925
+ try:
926
+ asyncio.run(_remote_ws_loop(gateway_url, kite_token, _t0))
927
+ except Exception as e:
928
+ _write_crash(type(e), e, e.__traceback__, severity="critical", handled=True)
929
+ _print_crash_summary(type(e), e.__traceback__)
930
+ sys.exit(1)
931
+ sys.exit(_exit_code)
932
+
933
+
934
+ async def _remote_ws_loop(gateway_url: str, kite_token: str, _t0: float):
935
+ """远程模式重连循环。"""
936
+ global _shutting_down, _exit_code
937
+ retry_delay = 0.5
938
+ max_delay = 10.0
939
+
940
+ while not _shutting_down:
941
+ try:
942
+ await _remote_connect(gateway_url, kite_token, _t0)
943
+ retry_delay = 0.5
944
+ except asyncio.CancelledError:
945
+ return
946
+ except Exception as e:
947
+ if _shutting_down: return
948
+ _write_crash(type(e), e, e.__traceback__, severity="error", handled=True)
949
+ jitter = retry_delay * 0.2 * random.random()
950
+ print(f"[{MODULE_NAME}] 远程连接错误: {e}, {retry_delay + jitter:.1f}s 后重试")
951
+ await asyncio.sleep(retry_delay + jitter)
952
+ retry_delay = min(retry_delay * 2, max_delay)
953
+
954
+ _ws_global_clear()
955
+ if _shutting_down: return
956
+
957
+
958
+ async def _remote_connect(gateway_url: str, kite_token: str, _t0: float):
959
+ """远程模式:连接 Gateway 并走认证+注册流程。"""
960
+ global _ws_global
961
+
962
+ print(f"[{MODULE_NAME}] Connecting to Gateway: {gateway_url}")
963
+ async with websockets.connect(gateway_url, open_timeout=10, ping_interval=None, close_timeout=10) as ws:
964
+ # 1. 接收 challenge
965
+ challenge = json.loads(await asyncio.wait_for(ws.recv(), timeout=10))
966
+ nonce = challenge.get("params", {}).get("nonce", "")
967
+
968
+ # 2. 发送 auth.connect
969
+ await ws.send(json.dumps({
970
+ "jsonrpc": "2.0", "id": "auth-connect",
971
+ "method": "auth.connect",
972
+ "params": {
973
+ "nonce": nonce,
974
+ "module_id": MODULE_NAME,
975
+ "auth": {"method": "kite_token", "token": kite_token},
976
+ "client": {"type": "module"}
977
+ }
978
+ }))
979
+
980
+ # 3. 等待认证响应
981
+ resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=10))
982
+ if "error" in resp:
983
+ error = resp["error"]
984
+ code = error.get("code", 0)
985
+ if code in (4001, 4010, 4011):
986
+ _clear_token_cache(MODULE_NAME, gateway_url)
987
+ print(f"[{MODULE_NAME}] Token 无效,请重新配对")
988
+ sys.exit(1)
989
+ raise Exception(f"Gateway 认证失败: {error}")
990
+
991
+ _ws_global = ws
992
+ print(f"[{MODULE_NAME}] Connected via Gateway ({_fmt_elapsed(_t0)})")
993
+
994
+ # 启动接收循环,等待 system.require_init 触发 _do_init
995
+ receiver_task = asyncio.create_task(_ws_receiver(ws))
996
+
997
+ try:
998
+ # 等待接收循环结束
999
+ await receiver_task
1000
+ finally:
1001
+ receiver_task.cancel()
1002
+ for fut in _pending_rpc.values():
1003
+ if not fut.done():
1004
+ fut.set_result({"error": {"code": -32001, "message": "Connection lost"}})
1005
+ _pending_rpc.clear()
1006
+
1007
+
1008
+ # ── Token 管理(远程模式)──
1009
+
1010
+ def _gateway_to_filename(gateway_url: str) -> str:
1011
+ try:
1012
+ from urllib.parse import urlparse
1013
+ parsed = urlparse(gateway_url)
1014
+ host = parsed.hostname or "unknown"
1015
+ port = parsed.port or (443 if parsed.scheme == "wss" else 80)
1016
+ return f"{host}-{port}.json".replace(":", "-").replace("/", "-")
1017
+ except Exception: return "default.json"
1018
+
1019
+ def _load_token_cache(module_name: str, gateway_url: str) -> dict | None:
1020
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
1021
+ token_file = os.path.join(home, ".kite", "remote", module_name, "tokens", _gateway_to_filename(gateway_url))
1022
+ if not os.path.exists(token_file): return None
1023
+ try:
1024
+ with open(token_file, "r") as f: return json.load(f)
1025
+ except Exception: return None
1026
+
1027
+ def _clear_token_cache(module_name: str, gateway_url: str):
1028
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
1029
+ token_file = os.path.join(home, ".kite", "remote", module_name, "tokens", _gateway_to_filename(gateway_url))
1030
+ try: os.remove(token_file)
1031
+ except Exception: pass
1032
+
1033
+ def _get_kite_token(module_name: str, gateway_url: str) -> str:
1034
+ token = os.environ.get("KITE_TOKEN")
1035
+ if token: return token
1036
+ cache = _load_token_cache(module_name, gateway_url)
1037
+ if cache: return cache["token"]
1038
+ print(f"[{module_name}] No token for {gateway_url}")
1039
+ print(f" export KITE_TOKEN=<token>")
1040
+ sys.exit(1)
1041
+
1042
+
1043
+ if __name__ == "__main__":
1044
+ kernel_port = os.environ.get("KITE_KERNEL_PORT")
1045
+ if kernel_port:
1046
+ _run_local_mode(int(kernel_port))
1047
+ else:
1048
+ config = _load_module_config()
1049
+ gateway_url = config.get("gateway_url") or os.environ.get("KITE_GATEWAY_URL")
1050
+ if gateway_url:
1051
+ _run_remote_mode(gateway_url)
1052
+ else:
1053
+ print(f"[{MODULE_NAME}] ERROR: No KITE_KERNEL_PORT and no gateway_url")
1054
+ sys.exit(1)