@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,686 @@
1
+ """
2
+ Phone Channel WebSocket client.
3
+ Connects to Kernel via WebSocket JSON-RPC 2.0 for event publishing and subscription.
4
+ """
5
+
6
+ import asyncio
7
+ import json
8
+ import os
9
+ import time
10
+ import uuid
11
+ from datetime import datetime, timezone
12
+
13
+ import websockets
14
+
15
+
16
+ # System broadcast events (received by all modules, may not need handling)
17
+ SYSTEM_BROADCAST_EVENTS = {
18
+ "module.ready", "module.registered", "module.started", "module.stopped",
19
+ "module.crashed", "module.exiting", "module.offline",
20
+ "module.shutdown.ack", "module.shutdown.ready",
21
+ "system.ready", "registry.updated",
22
+ "system.instance.started", "system.instance.stopped",
23
+ }
24
+
25
+
26
+ class PhoneChannelServer:
27
+
28
+ def __init__(self, token: str = "", kernel_port: int = 0, boot_t0: float = 0, max_connections: int = 1,
29
+ max_instances: int = 1, instance_elastic: bool = False,
30
+ gateway_url: str = "", kite_token: str = ""):
31
+ self.token = token
32
+ self.kernel_port = kernel_port
33
+ self.boot_t0 = boot_t0
34
+ self.max_connections = max_connections
35
+ self.max_instances = max_instances
36
+ self.instance_elastic = instance_elastic
37
+ self.gateway_url = gateway_url
38
+ self.kite_token = kite_token
39
+ self._ws_task: asyncio.Task | None = None
40
+ self._test_task: asyncio.Task | None = None
41
+ self._ws: object | None = None
42
+ self._shutting_down = False
43
+ self._exit_code = 0 # Exit code for main() to use
44
+ self._auth_failed = False
45
+ self._start_time = time.time()
46
+ self._pending_rpc = {} # Track pending RPC calls: {id: future}
47
+ self._extra_ws: dict = {} # slot → WebSocket
48
+ self._extra_ws_tasks: dict = {} # slot → recv loop Task
49
+ self._has_registered = False
50
+ self._active_handlers = 0 # 当前正在处理的入站请求数
51
+ self._handler_capacity = 50 # 并发处理能力上限(用于压力计算)
52
+
53
+ async def run(self):
54
+ """Main entry point: start WebSocket loop and test event loop."""
55
+ if self.gateway_url:
56
+ # 远程模式:通过 Gateway 连接
57
+ self._ws_task = asyncio.create_task(self._remote_ws_loop())
58
+ elif self.kernel_port:
59
+ self._ws_task = asyncio.create_task(self._ws_loop())
60
+ self._test_task = asyncio.create_task(self._test_event_loop())
61
+
62
+ # Wait for tasks to complete
63
+ tasks = [t for t in [self._ws_task, self._test_task] if t]
64
+ if tasks:
65
+ await asyncio.gather(*tasks, return_exceptions=True)
66
+
67
+ print("[phone_channel] Shutdown complete")
68
+
69
+ # ── Kernel WebSocket client ──
70
+
71
+ # ── Remote mode (via Gateway) ──
72
+
73
+ async def _remote_ws_loop(self):
74
+ """远程模式:通过 Gateway 连接 Kernel,带重连。"""
75
+ retry_delay = 0.3
76
+ max_delay = 5.0
77
+ max_retries = 10
78
+ attempt = 0
79
+ while not self._shutting_down:
80
+ try:
81
+ await self._remote_connect()
82
+ retry_delay = 0.3
83
+ attempt = 0
84
+ except asyncio.CancelledError:
85
+ return
86
+ except SystemExit:
87
+ raise
88
+ except Exception as e:
89
+ attempt += 1
90
+ if attempt >= max_retries:
91
+ print(f"[phone_channel] Gateway 重连失败 {max_retries} 次,退出")
92
+ self._exit_code = 1
93
+ self._shutting_down = True
94
+ return
95
+ print(f"[phone_channel] Gateway connection error: {e}, retrying in {retry_delay:.1f}s ({attempt}/{max_retries})")
96
+ self._ws = None
97
+ if self._shutting_down:
98
+ return
99
+ await asyncio.sleep(retry_delay)
100
+ retry_delay = min(retry_delay * 2, max_delay)
101
+
102
+ async def _remote_connect(self):
103
+ """远程模式单次连接:challenge → auth.connect → 注册 → 消息循环。"""
104
+ import sys as _sys
105
+ print(f"[phone_channel] Connecting to Gateway: {self.gateway_url}")
106
+ async with websockets.connect(self.gateway_url, open_timeout=10, ping_interval=None, close_timeout=10) as ws:
107
+ # 1. 接收 challenge
108
+ challenge = json.loads(await asyncio.wait_for(ws.recv(), timeout=10))
109
+ nonce = challenge.get("params", {}).get("nonce", "")
110
+
111
+ # 2. 发送 auth.connect
112
+ await ws.send(json.dumps({
113
+ "jsonrpc": "2.0", "id": "auth-connect",
114
+ "method": "auth.connect",
115
+ "params": {
116
+ "nonce": nonce,
117
+ "module_id": "phone_channel",
118
+ "auth": {"method": "kite_token", "token": self.kite_token},
119
+ "client": {"type": "module"}
120
+ }
121
+ }))
122
+
123
+ # 3. 等待认证响应
124
+ resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=10))
125
+ if "error" in resp:
126
+ error = resp["error"]
127
+ code = error.get("code", 0)
128
+ if code in (4001, 4010, 4011):
129
+ # 认证失败 → 清除缓存,由 entry.py 的 _clear_token_cache 处理
130
+ print(f"[phone_channel] Token 无效 (code {code}),请重新配对")
131
+ self._exit_code = 1
132
+ self._auth_failed = True
133
+ self._shutting_down = True
134
+ return
135
+ raise Exception(f"Gateway 认证失败: {error}")
136
+
137
+ self._ws = ws
138
+ print(f"[phone_channel] Connected via Gateway ({self._fmt_elapsed(self.boot_t0)})")
139
+
140
+ # 启动接收循环(先于 RPC 调用,防止 wait_response 死锁)
141
+ recv_task = asyncio.create_task(self._ws_receiver(ws))
142
+
143
+ try:
144
+ # subscribe/register/module.ready 由 _do_init 在收到 system.require_init 后执行
145
+
146
+ # 等待接收循环结束(连接断开时自然退出)
147
+ await recv_task
148
+ finally:
149
+ recv_task.cancel()
150
+ self._cleanup_pending_rpc()
151
+
152
+ # ── Local mode ──
153
+ async def _ws_loop(self):
154
+ """Connect to Kernel, subscribe, register, and listen. Reconnect on failure."""
155
+ retry_delay = 0.3
156
+ max_delay = 5.0
157
+ max_retries = 10
158
+ attempt = 0
159
+ while not self._shutting_down:
160
+ try:
161
+ await self._ws_connect()
162
+ retry_delay = 0.3
163
+ attempt = 0
164
+ except asyncio.CancelledError:
165
+ return
166
+ except Exception as e:
167
+ attempt += 1
168
+ # Auth failure — don't retry
169
+ if hasattr(e, 'rcvd') and e.rcvd is not None:
170
+ code = e.rcvd.code if hasattr(e.rcvd, 'code') else 0
171
+ if code in (4001, 4003):
172
+ print(f"[phone_channel] Kernel 认证失败 (code {code}),退出")
173
+ self._exit_code = 1
174
+ self._auth_failed = True
175
+ self._shutting_down = True
176
+ return
177
+ if attempt >= max_retries:
178
+ print(f"[phone_channel] Kernel 重连失败 {max_retries} 次,退出")
179
+ self._exit_code = 1
180
+ self._shutting_down = True
181
+ return
182
+ print(f"[phone_channel] Kernel connection error: {e}, retrying in {retry_delay:.1f}s ({attempt}/{max_retries})")
183
+ self._ws = None
184
+ if self._shutting_down:
185
+ return
186
+ await asyncio.sleep(retry_delay)
187
+ retry_delay = min(retry_delay * 2, max_delay)
188
+
189
+ async def _ws_connect(self):
190
+ """Single WebSocket session: connect, auth, start receiver, subscribe, register, ready."""
191
+ url = f"ws://127.0.0.1:{self.kernel_port}/ws?id=phone_channel"
192
+ print(f"[phone_channel] Connecting to Kernel (port {self.kernel_port})")
193
+ async with websockets.connect(url, open_timeout=3, ping_interval=None, close_timeout=10) as ws:
194
+ # Send auth message first
195
+ auth_req = {
196
+ "jsonrpc": "2.0",
197
+ "id": "auth",
198
+ "method": "auth",
199
+ "params": {"token": self.token}
200
+ }
201
+ await ws.send(json.dumps(auth_req))
202
+
203
+ # Wait for auth response
204
+ auth_resp_raw = await asyncio.wait_for(ws.recv(), timeout=5)
205
+ auth_resp = json.loads(auth_resp_raw)
206
+ if "error" in auth_resp:
207
+ raise Exception(f"Auth failed: {auth_resp['error']}")
208
+
209
+ self._ws = ws
210
+ elapsed = time.monotonic() - self.boot_t0 if self.boot_t0 else 0
211
+ elapsed_str = f" ({elapsed:.1f}s)" if elapsed else ""
212
+ print(f"[phone_channel] Connected to Kernel{elapsed_str}")
213
+
214
+ # 启动接收循环(先于 RPC 调用,防止 wait_response 死锁)
215
+ recv_task = asyncio.create_task(self._ws_receiver(ws))
216
+
217
+ try:
218
+ # subscribe/register/module.ready 由 _do_init 在收到 system.require_init 后执行
219
+
220
+ # 等待接收循环结束(连接断开时自然退出)
221
+ await recv_task
222
+ finally:
223
+ recv_task.cancel()
224
+ self._cleanup_pending_rpc()
225
+
226
+ async def _ws_receiver(self, ws):
227
+ """Receive loop: dispatch RPC requests, event notifications, and RPC responses.
228
+
229
+ CRITICAL: RPC 死锁防范
230
+ - 入站 RPC 请求必须用 create_task() 异步执行,不可 await
231
+ - 原因:如果 handler 内部调用 rpc_call() 发出站请求,出站响应需要本接收循环来分发
232
+ - 如果接收循环被 await handler 阻塞,出站响应永远收不到 → 超时死锁
233
+ """
234
+ try:
235
+ async for raw in ws:
236
+ try:
237
+ msg = json.loads(raw)
238
+ except (json.JSONDecodeError, TypeError):
239
+ continue
240
+
241
+ try:
242
+ has_method = "method" in msg
243
+ has_id = "id" in msg
244
+
245
+ # 检测 system.require_init 事件,触发注册流程
246
+ if has_method and not has_id:
247
+ params = msg.get("params", {})
248
+ event = params.get("event", "")
249
+ if event == "system.require_init":
250
+ asyncio.create_task(self._do_init(ws))
251
+ continue
252
+
253
+ if has_method and has_id:
254
+ asyncio.create_task(self._handle_rpc_request(ws, msg))
255
+ elif has_method and not has_id:
256
+ asyncio.create_task(self._handle_event_notification(msg))
257
+ elif not has_method and has_id:
258
+ self._handle_rpc_response(msg)
259
+ except Exception as e:
260
+ print(f"[phone_channel] 消息处理异常(已忽略): {e}")
261
+ except websockets.exceptions.ConnectionClosed:
262
+ pass # Kernel 连接关闭,正常退出接收循环
263
+
264
+ async def _do_init(self, ws):
265
+ """收到 system.require_init 后执行:订阅 + 注册 + module.ready"""
266
+ try:
267
+ reason = "startup" if not self._has_registered else "recovery"
268
+
269
+ # Step 1: Subscribe to events
270
+ await self._rpc_call(ws, "event.subscribe", {
271
+ "events": [
272
+ "module.started", "module.stopped", "module.shutdown", "acp_channel.test",
273
+ ],
274
+ })
275
+
276
+ # Step 2: Register to Kernel
277
+ await self._rpc_call(ws, "registry.register", {
278
+ "module_id": "phone_channel",
279
+ "module_type": "channel",
280
+ "name": "Phone Channel",
281
+ "tools": {
282
+ "rpc": {
283
+ "module": {
284
+ "echo": {"method": "echo", "description": "Echo test"},
285
+ "get_status": {"method": "get_status", "description": "Get channel status"},
286
+ "nested_call": {"method": "nested_call", "description": "Nested RPC call test"},
287
+ }
288
+ }
289
+ },
290
+ "events_publish": {
291
+ "phone_channel": {
292
+ "test": {},
293
+ "call_started": {},
294
+ "call_ended": {},
295
+ }
296
+ },
297
+ "events_subscribe": [
298
+ "module.started",
299
+ "module.stopped",
300
+ "module.shutdown",
301
+ "acp_channel.test",
302
+ ],
303
+ })
304
+
305
+ # Step 3: Publish module.ready
306
+ if not self._shutting_down:
307
+ startup_time = time.monotonic() - self.boot_t0 if self.boot_t0 else 0
308
+ await self._publish_event(ws, "module.ready", {
309
+ "module_id": "phone_channel",
310
+ "graceful_shutdown": True,
311
+ "startup_time": startup_time,
312
+ "reason": reason,
313
+ })
314
+ elapsed_str = self._fmt_elapsed(self.boot_t0)
315
+ print(f"[phone_channel] module.ready published (reason={reason}, {elapsed_str})")
316
+ self._has_registered = True
317
+ except Exception as e:
318
+ print(f"[phone_channel] _do_init failed: {e}")
319
+ self._has_registered = False
320
+
321
+ async def _handle_event_notification(self, msg: dict):
322
+ """Handle an event notification (JSON-RPC 2.0 Notification with method='event')."""
323
+ params = msg.get("params", {})
324
+ event_type = params.get("event", "")
325
+ data = params.get("data", {})
326
+
327
+ # Handle system.ping event
328
+ if event_type == "system.ping":
329
+ await self._handle_ping_event(data)
330
+ return
331
+
332
+ # 弹性连接 offer/release
333
+ if event_type == "system.connection.offer":
334
+ asyncio.create_task(self._handle_connection_offer(data))
335
+ return
336
+ if event_type == "system.connection.release":
337
+ asyncio.create_task(self._handle_connection_release(data))
338
+ return
339
+
340
+ # Handle acp_channel.test event (跨模块事件测试)
341
+ if event_type == "acp_channel.test":
342
+ print(f"[phone_channel] 收到 acp_channel.test 事件: {data.get('message', '')}")
343
+ return
344
+
345
+ # Layer 1: 处理订阅的事件
346
+ if event_type == "module.shutdown":
347
+ target = data.get("module_id", "")
348
+ reason = data.get("reason", "")
349
+ # Handle both targeted shutdown (module_id == "phone_channel") and broadcast shutdown (no module_id or launcher_lost)
350
+ if target.startswith("phone_channel") or not target or reason == "launcher_lost":
351
+ await self._handle_shutdown(self._ws)
352
+ return
353
+
354
+ # Layer 2: 忽略系统广播事件
355
+ if event_type in SYSTEM_BROADCAST_EVENTS:
356
+ return
357
+
358
+ # Layer 3: 警告未知事件(仅开发环境)
359
+ if os.environ.get("KITE_ENV") == "development":
360
+ print(f"[phone_channel] Debug: Unhandled event: {event_type}")
361
+
362
+ async def _handle_connection_offer(self, data):
363
+ """处理 Kernel 下发的 slot token,建立附加连接。"""
364
+ slots = data.get("slots", {})
365
+ for slot_str, info in slots.items():
366
+ slot = int(slot_str)
367
+ token = info.get("token", "")
368
+ if not token or slot in self._extra_ws:
369
+ continue
370
+ asyncio.create_task(self._connect_slot(slot, token))
371
+
372
+ async def _connect_slot(self, slot, token):
373
+ """建立单个 slot 附加连接(自动区分本地/远程模式)。"""
374
+ try:
375
+ if self.gateway_url:
376
+ # 远程模式:通过 Gateway 连接
377
+ ws = await websockets.connect(self.gateway_url, open_timeout=5, ping_interval=None, close_timeout=5)
378
+ challenge = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
379
+ nonce = challenge.get("params", {}).get("nonce", "")
380
+ auth_req = {
381
+ "jsonrpc": "2.0", "id": f"auth-slot-{slot}",
382
+ "method": "auth.connect_slot",
383
+ "params": {"nonce": nonce, "slot_token": token, "module_id": "phone_channel"}
384
+ }
385
+ else:
386
+ # 本地模式:直连 Kernel
387
+ ws = await websockets.connect(
388
+ f"ws://127.0.0.1:{self.kernel_port}/ws",
389
+ open_timeout=5, ping_interval=None, close_timeout=5)
390
+ auth_req = {"jsonrpc": "2.0", "id": f"auth-slot-{slot}", "method": "auth", "params": {"token": token}}
391
+
392
+ await ws.send(json.dumps(auth_req))
393
+ resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
394
+ if "error" in resp:
395
+ await ws.close()
396
+ return
397
+ self._extra_ws[slot] = ws
398
+ self._extra_ws_tasks[slot] = asyncio.create_task(self._slot_recv_loop(slot, ws))
399
+ print(f"[phone_channel] Slot {slot} connected")
400
+ except Exception as e:
401
+ print(f"[phone_channel] Slot {slot} connect failed: {e}")
402
+
403
+ async def _slot_recv_loop(self, slot, ws):
404
+ """附加 slot 接收循环:与主连接平等处理所有消息。"""
405
+ try:
406
+ async for raw in ws:
407
+ try:
408
+ msg = json.loads(raw)
409
+ except (json.JSONDecodeError, TypeError):
410
+ continue
411
+
412
+ try:
413
+ has_method = "method" in msg
414
+ has_id = "id" in msg
415
+
416
+ if has_method and has_id:
417
+ asyncio.create_task(self._handle_rpc_request(ws, msg))
418
+ elif has_method and not has_id:
419
+ asyncio.create_task(self._handle_event_notification(msg))
420
+ elif not has_method and has_id:
421
+ self._handle_rpc_response(msg)
422
+ except Exception as e:
423
+ print(f"[phone_channel] Slot {slot} 消息处理异常(已忽略): {e}")
424
+ except Exception as e:
425
+ print(f"[phone_channel] Slot {slot} recv loop exited: {e}")
426
+ finally:
427
+ self._extra_ws.pop(slot, None)
428
+ self._extra_ws_tasks.pop(slot, None)
429
+
430
+ async def _handle_connection_release(self, data):
431
+ """Kernel 请求释放 slot,优雅关闭。"""
432
+ for slot in data.get("slots", []):
433
+ ws = self._extra_ws.pop(slot, None)
434
+ task = self._extra_ws_tasks.pop(slot, None)
435
+ if ws:
436
+ try:
437
+ await ws.close(code=1000, reason="release")
438
+ except Exception:
439
+ pass
440
+ if task:
441
+ task.cancel()
442
+
443
+ async def _handle_shutdown(self, ws):
444
+ """Handle module.shutdown: ack → exiting → ready → cleanup → exit."""
445
+ print("[phone_channel] Received module.shutdown")
446
+ self._shutting_down = True
447
+
448
+ # Step 1: Send ack (立即确认收到)
449
+ await self._publish_event(ws, "module.shutdown.ack", {
450
+ "module_id": "phone_channel", "estimated_cleanup": 2,
451
+ })
452
+ print("[phone_channel] shutdown ack sent")
453
+
454
+ # Step 2: Send module.exiting (开始清理)
455
+ await self._publish_event(ws, "module.exiting", {
456
+ "module_id": "phone_channel", "action": "none",
457
+ })
458
+
459
+ # Step 3: Send ready(必须在关闭连接之前发送)
460
+ await self._publish_event(ws, "module.shutdown.ready", {
461
+ "module_id": "phone_channel",
462
+ })
463
+ print("[phone_channel] Shutdown ready sent")
464
+
465
+ # Step 4: 等待 Kernel 处理 shutdown.ready
466
+ await asyncio.sleep(0.01)
467
+
468
+ # Step 5: Cleanup - 关闭所有附加连接
469
+ for _s, _w in list(self._extra_ws.items()):
470
+ try:
471
+ await _w.close(code=1000, reason="shutdown")
472
+ except Exception:
473
+ pass
474
+ for _t in self._extra_ws_tasks.values():
475
+ _t.cancel()
476
+ self._extra_ws.clear()
477
+ self._extra_ws_tasks.clear()
478
+
479
+ if self._test_task:
480
+ self._test_task.cancel()
481
+
482
+ # Step 6: Close WebSocket connection gracefully
483
+ try:
484
+ await ws.close(code=1000, reason="Graceful shutdown")
485
+ print("[phone_channel] WebSocket closed")
486
+ except Exception as e:
487
+ print(f"[phone_channel] Failed to close WebSocket: {e}")
488
+
489
+ async def _handle_rpc_request(self, ws, msg: dict):
490
+ """Handle incoming RPC request."""
491
+ method = msg.get("method", "")
492
+ params = msg.get("params", {})
493
+ req_id = msg.get("id")
494
+
495
+ self._active_handlers += 1
496
+ try:
497
+ # 支持带前缀和不带前缀的方法名
498
+ bare_method = method.split(".")[-1] if "." in method else method
499
+
500
+ if bare_method == "echo":
501
+ result = {"echo": params.get("message", ""), "timestamp": time.time()}
502
+ elif bare_method == "get_status":
503
+ result = {
504
+ "status": "running",
505
+ "uptime": time.time() - self._start_time,
506
+ "module_id": "phone_channel",
507
+ }
508
+ elif bare_method == "nested_call":
509
+ # 嵌套调用:调用 acp_channel.echo
510
+ message = params.get("message", "")
511
+ print(f"[phone_channel] 嵌套调用: 准备调用 acp_channel.echo")
512
+ nested_result = await self._call_remote_rpc(
513
+ "acp_channel",
514
+ "echo",
515
+ {"message": f"nested from phone: {message}"}
516
+ )
517
+ result = {
518
+ "module_id": "phone_channel",
519
+ "nested_call_to": "acp_channel.echo",
520
+ "nested_result": nested_result,
521
+ "original_message": message
522
+ }
523
+ else:
524
+ raise Exception(f"Unknown method: {method}")
525
+
526
+ response = {"jsonrpc": "2.0", "id": req_id, "result": result}
527
+ await ws.send(json.dumps(response))
528
+ print(f"[phone_channel] RPC 请求处理: {method}")
529
+ except Exception as e:
530
+ error_response = {
531
+ "jsonrpc": "2.0",
532
+ "id": req_id,
533
+ "error": {"code": -32603, "message": str(e)},
534
+ }
535
+ await ws.send(json.dumps(error_response))
536
+ print(f"[phone_channel] RPC 请求失败: {method} - {e}")
537
+ finally:
538
+ self._active_handlers -= 1
539
+
540
+ def _compute_pressure_level(self) -> str:
541
+ """根据并发处理量计算压力等级。"""
542
+ depth = self._active_handlers + len(self._pending_rpc)
543
+ ratio = depth / self._handler_capacity if self._handler_capacity > 0 else 0
544
+ if ratio >= 0.9:
545
+ return "critical"
546
+ elif ratio >= 0.5:
547
+ return "overload"
548
+ elif depth > 0:
549
+ return "normal"
550
+ return "idle"
551
+
552
+ def _handle_rpc_response(self, msg: dict):
553
+ """Handle RPC response from other modules."""
554
+ rpc_id = msg.get("id")
555
+ future = self._pending_rpc.pop(rpc_id, None)
556
+ if future and not future.done():
557
+ future.set_result(msg)
558
+
559
+ def _cleanup_pending_rpc(self):
560
+ """Fail all pending RPC futures on disconnect."""
561
+ for rpc_id, future in self._pending_rpc.items():
562
+ if not future.done():
563
+ future.set_result({"error": {"code": -32000, "message": "WebSocket disconnected"}})
564
+ self._pending_rpc.clear()
565
+
566
+ async def _rpc_call(self, ws, method: str, params: dict = None,
567
+ wait_response: bool = True, timeout: float = 3.0) -> dict:
568
+ """Send a JSON-RPC 2.0 request."""
569
+ req_id = str(uuid.uuid4())
570
+ msg = {"jsonrpc": "2.0", "id": req_id, "method": method}
571
+ if params:
572
+ msg["params"] = params
573
+
574
+ if wait_response:
575
+ future = asyncio.Future()
576
+ self._pending_rpc[req_id] = future
577
+ await ws.send(json.dumps(msg))
578
+ try:
579
+ return await asyncio.wait_for(future, timeout=timeout)
580
+ except asyncio.TimeoutError:
581
+ self._pending_rpc.pop(req_id, None)
582
+ return {"error": {"code": -32000, "message": f"RPC timeout: {method} ({timeout}s)"}}
583
+ else:
584
+ await ws.send(json.dumps(msg))
585
+
586
+ async def _handle_ping_event(self, data: dict):
587
+ """Handle system.ping event and reply with system.pong."""
588
+ t1 = data.get("ping_time")
589
+ t2 = time.time()
590
+
591
+ await self._publish_event(self._ws, "system.pong", {
592
+ "module_id": "phone_channel",
593
+ "ping_time": t1,
594
+ "pong_time": t2,
595
+ })
596
+
597
+ def _fmt_elapsed(self, t0: float) -> str:
598
+ """Format elapsed time since t0."""
599
+ d = time.monotonic() - t0 if t0 else 0
600
+ if d < 1:
601
+ return f"{d * 1000:.0f}ms"
602
+ if d < 10:
603
+ return f"{d:.1f}s"
604
+ return f"{d:.0f}s"
605
+
606
+ async def _publish_event(self, ws, event: str, data: dict = None):
607
+ """Publish an event via JSON-RPC event.publish."""
608
+ await self._rpc_call(ws, "event.publish", {
609
+ "event_id": str(uuid.uuid4()),
610
+ "event": event,
611
+ "data": data or {},
612
+ }, wait_response=False)
613
+
614
+ async def _call_remote_rpc(self, target_module: str, method: str, params: dict = None):
615
+ """Call RPC method on another module via Kernel."""
616
+ if not self._ws:
617
+ return None
618
+ result = await self._rpc_call(
619
+ self._ws,
620
+ f"{target_module}.{method}",
621
+ params or {},
622
+ wait_response=True
623
+ )
624
+ if result and "error" in result:
625
+ err = result["error"]
626
+ print(f"[phone_channel] 跨模块 RPC 调用失败 ({target_module}.{method}): {err.get('message', 'RPC error')}")
627
+ return None
628
+ return result.get("result") if result else None
629
+
630
+ # ── Test event loop ──
631
+
632
+ async def _test_event_loop(self):
633
+ """Publish test events and call cross-module RPC every 15 seconds."""
634
+ try:
635
+ await asyncio.sleep(5) # Wait for initial setup
636
+ counter = 0
637
+ while not self._shutting_down:
638
+ counter += 1
639
+
640
+ # Test 1: Publish event
641
+ if self._ws:
642
+ await self._publish_event(self._ws, "phone_channel.test", {
643
+ "message": f"test event from phone_channel #{counter}",
644
+ "timestamp": datetime.now(timezone.utc).isoformat(),
645
+ })
646
+
647
+ # Test 2: Call acp_channel RPC (every other cycle)
648
+ if counter % 2 == 0:
649
+ print(f"[phone_channel] 测试跨模块 RPC 调用 acp_channel.echo")
650
+ result = await self._call_remote_rpc(
651
+ "acp_channel",
652
+ "echo",
653
+ {"message": f"Hello from phone_channel #{counter}"}
654
+ )
655
+ if result:
656
+ print(f"[phone_channel] acp_channel.echo 返回: {result}")
657
+
658
+ # Test 3: Redis 状态持久化测试 (每 4 次)
659
+ if counter % 4 == 0:
660
+ try:
661
+ # 保存状态到 Redis
662
+ await self._call_remote_rpc("redis", "set", {
663
+ "key": "phone_channel:counter",
664
+ "value": str(counter)
665
+ })
666
+ # 读取验证
667
+ result = await self._call_remote_rpc("redis", "get", {
668
+ "key": "phone_channel:counter"
669
+ })
670
+ if result and result.get("value") == str(counter):
671
+ print(f"[phone_channel] ✓ Redis 状态已保存: counter={counter}")
672
+ except Exception as e:
673
+ print(f"[phone_channel] Redis 测试失败: {e}")
674
+
675
+ # 上报队列压力(供 Kernel 自动缩容决策)
676
+ if self._ws:
677
+ depth = self._active_handlers + len(self._pending_rpc)
678
+ await self._publish_event(self._ws, "module.queue_pressure", {
679
+ "level": self._compute_pressure_level(),
680
+ "depth": depth,
681
+ "capacity": self._handler_capacity,
682
+ })
683
+
684
+ await asyncio.sleep(15)
685
+ except Exception:
686
+ pass