@agentunion/kite 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (718) 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/CHANGELOG.md +102 -0
  23. package/cli.js +78 -5
  24. package/core/dependency_checker.py +250 -0
  25. package/core/env_checker.py +586 -0
  26. package/dependencies_lock.json +128 -0
  27. 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
  28. package/docs/ACP/345/215/217/350/256/256/345/205/274/345/256/271/346/226/271/346/241/210.md +138 -0
  29. 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
  30. package/docs/CLI/345/274/200/345/217/221/350/256/241/345/210/222.md +595 -0
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. package/docs/Evol/346/250/241/345/235/227/350/256/276/350/256/241/346/226/271/346/241/210.md +1154 -0
  37. 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
  38. 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
  39. package/docs/HTTP-RPC/350/277/201/347/247/273/345/210/260WebSocket/350/256/241/345/210/222.md +318 -0
  40. package/docs/INDEX.md +388 -0
  41. package/docs/KITE_DOCS_GUIDE.md +33 -0
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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
  58. package/docs/Kite/346/241/206/346/236/266/350/256/276/350/256/241/README.md +46 -0
  59. package/docs/Kite/347/263/273/347/273/237/345/220/257/345/212/250/346/265/201/347/250/213.md +567 -0
  60. package/docs/Launcher/345/220/257/345/212/250/345/231/250/346/226/207/346/241/243.md +745 -0
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. package/docs/Watchdog/350/265/204/346/272/220/347/233/221/346/216/247/347/255/226/347/225/245.md +92 -0
  67. 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
  68. 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
  69. package/docs/WebSocket/350/277/236/346/216/245/351/237/247/346/200/247/346/226/271/346/241/210.md +169 -0
  70. 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
  71. 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
  72. 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
  73. package/docs/audit-api-guide.md +68 -0
  74. package/docs/audit-module-design.md +315 -0
  75. package/docs/audit-module-implementation-summary.md +149 -0
  76. package/docs/llm-context-design.md +52 -0
  77. package/docs/llm-test-enhancement-plan.md +970 -0
  78. package/docs/logs-api-guide.md +42 -0
  79. 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
  80. 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
  81. 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
  82. 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
  83. package/docs//344/272/213/344/273/266/345/244/204/347/220/206/346/234/272/345/210/266.md +388 -0
  84. package/docs//344/272/213/344/273/266/345/244/204/347/220/206/350/247/204/350/214/203.md +113 -0
  85. 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
  86. 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
  87. 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
  88. 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
  89. 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
  90. package/docs//344/274/230/351/233/205/351/200/200/345/207/272/350/247/204/350/214/203.md +362 -0
  91. package/docs//344/276/235/350/265/226/347/256/241/347/220/206/350/257/264/346/230/216.md +141 -0
  92. 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
  93. package/docs//345/210/240/351/231/244kernel-client-example/345/256/214/346/210/220.md +309 -0
  94. package/docs//345/210/240/351/231/244ws-management/345/256/214/346/210/220.md +418 -0
  95. package/docs//345/220/257/345/212/250/344/274/230/345/214/226/346/226/271/346/241/210.md +522 -0
  96. 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
  97. 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
  98. 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
  99. package/docs//345/256/236/347/216/260/350/247/204/345/210/222.md +195 -0
  100. 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
  101. 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
  102. package/docs//346/217/241/346/211/213/350/256/244/350/257/201/346/226/271/346/241/210.md +908 -0
  103. package/docs//346/226/207/346/241/243/346/233/264/346/226/260/346/270/205/345/215/225.md +83 -0
  104. 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
  105. 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
  106. package/docs//346/236/266/346/236/204/345/200/237/351/211/264/346/214/207/345/215/227.md +977 -0
  107. 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
  108. 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
  109. 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
  110. 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
  111. package/docs//346/250/241/345/235/227/345/274/200/345/217/221/346/214/207/345/215/227.md +1824 -0
  112. package/docs//346/250/241/345/235/227/347/203/255/346/233/264/346/226/260.md +89 -0
  113. 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
  114. 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
  115. 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
  116. 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
  117. 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
  118. 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
  119. 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
  120. 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
  121. 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
  122. 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
  123. 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
  124. 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
  125. package/docs//350/277/234/347/250/213/346/250/241/345/235/227/350/256/276/350/256/241.md +451 -0
  126. package/docs//351/207/215/346/236/204/346/234/272/345/210/266/346/270/205/345/215/225.md +192 -0
  127. package/docs//351/223/276/350/267/257/350/277/275/350/270/252/346/226/271/346/241/210.md +242 -0
  128. 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
  129. package/extensions/agents/assistant/entry.py +113 -14
  130. package/extensions/agents/assistant/module.md +27 -22
  131. package/extensions/agents/assistant/server.py +308 -106
  132. package/extensions/channels/acp_channel/entry.py +114 -16
  133. package/extensions/channels/acp_channel/module.md +4 -0
  134. package/extensions/channels/acp_channel/server.py +412 -105
  135. package/extensions/channels/phone_channel/__init__.py +1 -0
  136. package/extensions/channels/phone_channel/entry.py +503 -0
  137. package/extensions/channels/phone_channel/module.md +31 -0
  138. package/extensions/channels/phone_channel/server.py +686 -0
  139. package/extensions/event_hub_bench/entry.py +55 -12
  140. package/extensions/event_hub_bench/module.md +27 -27
  141. package/extensions/services/audit/README.md +134 -0
  142. package/extensions/services/audit/collector.py +73 -0
  143. package/extensions/services/audit/entry.py +444 -0
  144. package/extensions/services/audit/module.md +66 -0
  145. package/extensions/services/audit/query_audit.py +111 -0
  146. package/extensions/services/audit/routes/__init__.py +1 -0
  147. package/extensions/services/audit/routes/routes_audit.py +113 -0
  148. package/extensions/services/audit/schemas/__init__.py +5 -0
  149. package/extensions/services/audit/schemas/audit_event.py +92 -0
  150. package/extensions/services/audit/server.py +542 -0
  151. package/extensions/services/audit/storage.py +95 -0
  152. package/extensions/services/auth/entry.py +1054 -0
  153. package/extensions/services/auth/module.md +31 -0
  154. package/extensions/services/auth/token_store.py +185 -0
  155. package/extensions/services/auth/verifiers/evol_account.py +101 -0
  156. package/extensions/services/auth/verifiers/kite_token.py +38 -0
  157. package/extensions/services/auth/verifiers/pairing_code.py +71 -0
  158. package/extensions/services/backup/entry.py +505 -201
  159. package/extensions/services/backup/module.md +4 -2
  160. package/extensions/services/dataclaw/api/__init__.py +0 -0
  161. package/extensions/services/dataclaw/api/admin.py +367 -0
  162. package/extensions/services/dataclaw/api/copyright.py +175 -0
  163. package/extensions/services/dataclaw/api/credits.py +177 -0
  164. package/extensions/services/dataclaw/api/data.py +179 -0
  165. package/extensions/services/dataclaw/api/demands.py +269 -0
  166. package/extensions/services/dataclaw/api/feeds.py +262 -0
  167. package/extensions/services/dataclaw/api/identity.py +505 -0
  168. package/extensions/services/dataclaw/api/notifications.py +104 -0
  169. package/extensions/services/dataclaw/api/reviews.py +138 -0
  170. package/extensions/services/dataclaw/api/search.py +153 -0
  171. package/extensions/services/dataclaw/api/subscriptions.py +157 -0
  172. package/extensions/services/dataclaw/config.json5 +96 -0
  173. package/extensions/services/dataclaw/core/__init__.py +0 -0
  174. package/extensions/services/dataclaw/core/auth.py +95 -0
  175. package/extensions/services/dataclaw/core/config.py +50 -0
  176. package/extensions/services/dataclaw/core/database.py +70 -0
  177. package/extensions/services/dataclaw/entry.py +416 -0
  178. 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
  179. package/extensions/services/dataclaw/migrate.py +283 -0
  180. package/extensions/services/dataclaw/models/__init__.py +0 -0
  181. package/extensions/services/dataclaw/module.md +49 -0
  182. package/extensions/services/dataclaw/requirements.txt +18 -0
  183. package/extensions/services/dataclaw/server.py +759 -0
  184. package/extensions/services/dataclaw/services/__init__.py +0 -0
  185. package/extensions/services/dataclaw/services/agent_service.py +132 -0
  186. package/extensions/services/dataclaw/services/credit_service.py +235 -0
  187. package/extensions/services/dataclaw/services/email_service.py +140 -0
  188. package/extensions/services/dataclaw/services/feed_service.py +259 -0
  189. package/extensions/services/dataclaw/services/notification_service.py +209 -0
  190. package/extensions/services/dataclaw/services/oauth_service.py +275 -0
  191. package/extensions/services/dataclaw/services/pricing.py +102 -0
  192. package/extensions/services/dataclaw/services/quality.py +79 -0
  193. package/extensions/services/dataclaw/services/reputation.py +142 -0
  194. package/extensions/services/dataclaw/services/sms_service.py +174 -0
  195. package/extensions/services/dataclaw/static/css/common.css +853 -0
  196. package/extensions/services/dataclaw/static/css/themes/blue.css +42 -0
  197. package/extensions/services/dataclaw/static/css/themes/dark.css +42 -0
  198. package/extensions/services/dataclaw/static/css/themes/light.css +35 -0
  199. package/extensions/services/dataclaw/static/js/api.js +103 -0
  200. package/extensions/services/dataclaw/static/js/common.js +321 -0
  201. package/extensions/services/dataclaw/static/js/i18n.js +95 -0
  202. package/extensions/services/dataclaw/static/js/pages/admin.js +152 -0
  203. package/extensions/services/dataclaw/static/js/pages/dashboard.js +82 -0
  204. package/extensions/services/dataclaw/static/js/pages/feed-detail.js +180 -0
  205. package/extensions/services/dataclaw/static/js/pages/feed-manage.js +158 -0
  206. package/extensions/services/dataclaw/static/js/theme.js +46 -0
  207. package/extensions/services/dataclaw/static/locales/en-US.json +464 -0
  208. package/extensions/services/dataclaw/static/locales/ja-JP.json +464 -0
  209. package/extensions/services/dataclaw/static/locales/zh-CN.json +464 -0
  210. package/extensions/services/dataclaw/templates/admin/index.html +90 -0
  211. package/extensions/services/dataclaw/templates/base.html +136 -0
  212. package/extensions/services/dataclaw/templates/credits/balance.html +106 -0
  213. package/extensions/services/dataclaw/templates/credits/deposit.html +164 -0
  214. package/extensions/services/dataclaw/templates/credits/history.html +90 -0
  215. package/extensions/services/dataclaw/templates/dashboard.html +52 -0
  216. package/extensions/services/dataclaw/templates/demands/create.html +78 -0
  217. package/extensions/services/dataclaw/templates/demands/detail.html +136 -0
  218. package/extensions/services/dataclaw/templates/demands/list.html +94 -0
  219. package/extensions/services/dataclaw/templates/feeds/create.html +95 -0
  220. package/extensions/services/dataclaw/templates/feeds/detail.html +110 -0
  221. package/extensions/services/dataclaw/templates/feeds/list.html +110 -0
  222. package/extensions/services/dataclaw/templates/feeds/manage.html +88 -0
  223. package/extensions/services/dataclaw/templates/index.html +185 -0
  224. package/extensions/services/dataclaw/templates/login.html +246 -0
  225. package/extensions/services/dataclaw/templates/register.html +164 -0
  226. package/extensions/services/dataclaw/templates/settings/notifications.html +96 -0
  227. package/extensions/services/dataclaw/templates/settings/profile.html +167 -0
  228. package/extensions/services/dataclaw/templates/subscriptions/list.html +64 -0
  229. package/extensions/services/dataclaw/tests/__init__.py +0 -0
  230. package/extensions/services/dataclaw/tests/conftest.py +68 -0
  231. package/extensions/services/dataclaw/tests/integration/__init__.py +0 -0
  232. package/extensions/services/dataclaw/tests/integration/test_workflows.py +239 -0
  233. package/extensions/services/dataclaw/tests/unit/__init__.py +0 -0
  234. package/extensions/services/dataclaw/tests/unit/test_admin.py +70 -0
  235. package/extensions/services/dataclaw/tests/unit/test_copyright.py +63 -0
  236. package/extensions/services/dataclaw/tests/unit/test_credits.py +80 -0
  237. package/extensions/services/dataclaw/tests/unit/test_data.py +98 -0
  238. package/extensions/services/dataclaw/tests/unit/test_demands.py +106 -0
  239. package/extensions/services/dataclaw/tests/unit/test_feeds.py +98 -0
  240. package/extensions/services/dataclaw/tests/unit/test_identity.py +88 -0
  241. package/extensions/services/dataclaw/tests/unit/test_notifications.py +36 -0
  242. package/extensions/services/dataclaw/tests/unit/test_reviews.py +68 -0
  243. package/extensions/services/dataclaw/tests/unit/test_search.py +64 -0
  244. package/extensions/services/dataclaw/tests/unit/test_subscriptions.py +65 -0
  245. package/extensions/services/dataclaw/tests/unit/test_system.py +106 -0
  246. package/extensions/services/dataclaw/utils/__init__.py +0 -0
  247. package/extensions/services/dataclaw/utils/crypto.py +38 -0
  248. package/extensions/services/dataclaw/utils/id_generator.py +52 -0
  249. package/extensions/services/dataclaw/ws/__init__.py +0 -0
  250. package/extensions/services/dataclaw/ws/handler.py +163 -0
  251. 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
  252. 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
  253. package/extensions/services/evol/__init__.py +1 -0
  254. package/extensions/services/evol/async_http.py +551 -0
  255. package/extensions/services/evol/auth_manager.py +602 -0
  256. package/extensions/services/evol/config.json5 +16 -0
  257. package/extensions/services/evol/config_loader.py +117 -0
  258. package/extensions/services/evol/entry.py +568 -0
  259. package/extensions/services/evol/evol_api.py +969 -0
  260. package/extensions/services/evol/evol_config.json5 +29 -0
  261. package/extensions/services/evol/mfa_totp.py +77 -0
  262. package/extensions/services/evol/migrate_tokens.py +122 -0
  263. package/extensions/services/evol/module.md +150 -0
  264. package/extensions/services/evol/nonce_pool.py +113 -0
  265. package/extensions/services/evol/oauth_manager.py +223 -0
  266. package/extensions/services/evol/pairing.py +251 -0
  267. package/extensions/services/evol/pairing_codes.jsonl +2 -0
  268. package/extensions/services/evol/relay.py +1031 -0
  269. package/extensions/services/evol/relay_config.json5 +85 -0
  270. package/extensions/services/evol/routes/__init__.py +1 -0
  271. package/extensions/services/evol/routes/routes_llm.py +231 -0
  272. package/extensions/services/evol/routes/routes_rpc.py +90 -0
  273. package/extensions/services/evol/routes/routes_test.py +68 -0
  274. package/extensions/services/evol/server.py +2426 -0
  275. package/extensions/services/evol/static/assets/CommissionView-Cs_ys6Gm.js +1 -0
  276. package/extensions/services/evol/static/assets/CommissionView-DACet_Oo.css +1 -0
  277. package/extensions/services/evol/static/assets/IframePage-DbO11U9G.js +1 -0
  278. package/extensions/services/evol/static/assets/IframePage-c572lT8i.css +1 -0
  279. package/extensions/services/evol/static/assets/TeamDetailView-DULrGD7k.css +1 -0
  280. package/extensions/services/evol/static/assets/TeamDetailView-gy_MBEqG.js +139 -0
  281. package/extensions/services/evol/static/assets/element-plus-Bd7pZkkM.js +63 -0
  282. package/extensions/services/evol/static/assets/index-CmMONKzG.css +1 -0
  283. package/extensions/services/evol/static/assets/index-D44bBe__.js +2 -0
  284. package/extensions/services/evol/static/assets/vue-vendor-DtF-__I4.js +29 -0
  285. package/extensions/services/evol/static/index.html +16 -0
  286. package/extensions/services/evol/static/logo.png +0 -0
  287. package/extensions/services/evol/stats_manager.py +243 -0
  288. package/extensions/services/evol/web/README.md +89 -0
  289. package/extensions/services/evol/web/build.bat +44 -0
  290. package/extensions/services/evol/web/index.html +13 -0
  291. package/extensions/services/evol/web/package-lock.json +1718 -0
  292. package/extensions/services/evol/web/package.json +26 -0
  293. package/extensions/services/evol/web/public/logo.png +0 -0
  294. package/extensions/services/evol/web/src/App.vue +7 -0
  295. package/extensions/services/evol/web/src/components/layout/AppHeader.vue +202 -0
  296. package/extensions/services/evol/web/src/components/layout/AppLayout.vue +61 -0
  297. package/extensions/services/evol/web/src/components/layout/AppSidebar.vue +115 -0
  298. package/extensions/services/evol/web/src/components/login/LoginPage.vue +271 -0
  299. package/extensions/services/evol/web/src/components/team/AddMemberModal.vue +181 -0
  300. package/extensions/services/evol/web/src/components/team/GroupTreeNode.vue +156 -0
  301. package/extensions/services/evol/web/src/components/team/TeamAlertConfig.vue +221 -0
  302. package/extensions/services/evol/web/src/components/team/TeamBillModal.vue +165 -0
  303. package/extensions/services/evol/web/src/components/team/TeamMembersAndGroups.vue +499 -0
  304. package/extensions/services/evol/web/src/components/team/TeamStatsPanel.vue +907 -0
  305. package/extensions/services/evol/web/src/components/team/TreeNode.vue +331 -0
  306. package/extensions/services/evol/web/src/components/team/stats/StatsExportProgress.vue +44 -0
  307. package/extensions/services/evol/web/src/components/team/stats/StatsHeader.vue +89 -0
  308. package/extensions/services/evol/web/src/components/team/stats/StatsMemberDetail.vue +415 -0
  309. package/extensions/services/evol/web/src/components/team/stats/StatsSummary.vue +42 -0
  310. package/extensions/services/evol/web/src/components/team/stats/helpers.ts +195 -0
  311. package/extensions/services/evol/web/src/components/team/stats/stats.css +741 -0
  312. package/extensions/services/evol/web/src/components/team/stats/useStatsApi.ts +114 -0
  313. package/extensions/services/evol/web/src/components/team/stats/useStatsCharts.ts +242 -0
  314. package/extensions/services/evol/web/src/components/team/stats/useStatsExport.ts +232 -0
  315. package/extensions/services/evol/web/src/composables/useFormatters.ts +42 -0
  316. package/extensions/services/evol/web/src/composables/useTheme.ts +52 -0
  317. package/extensions/services/evol/web/src/env.d.ts +7 -0
  318. package/extensions/services/evol/web/src/i18n/en.ts +361 -0
  319. package/extensions/services/evol/web/src/i18n/index.ts +36 -0
  320. package/extensions/services/evol/web/src/i18n/zh.ts +379 -0
  321. package/extensions/services/evol/web/src/main.ts +21 -0
  322. package/extensions/services/evol/web/src/router/index.ts +81 -0
  323. package/extensions/services/evol/web/src/services/kernel-client.ts +406 -0
  324. package/extensions/services/evol/web/src/stores/auth.ts +189 -0
  325. package/extensions/services/evol/web/src/stores/connection.ts +134 -0
  326. package/extensions/services/evol/web/src/stores/pages.ts +79 -0
  327. package/extensions/services/evol/web/src/styles/base.css +213 -0
  328. package/extensions/services/evol/web/src/styles/variables.css +138 -0
  329. package/extensions/services/evol/web/src/types/rpc.ts +35 -0
  330. package/extensions/services/evol/web/src/types/token.ts +87 -0
  331. package/extensions/services/evol/web/src/views/AccountView.vue +1532 -0
  332. package/extensions/services/evol/web/src/views/AiServiceView.vue +219 -0
  333. package/extensions/services/evol/web/src/views/CommissionView.vue +1220 -0
  334. package/extensions/services/evol/web/src/views/CreditsView.vue +131 -0
  335. package/extensions/services/evol/web/src/views/EndpointView.vue +163 -0
  336. package/extensions/services/evol/web/src/views/IframePage.vue +120 -0
  337. package/extensions/services/evol/web/src/views/TeamDetailView.vue +473 -0
  338. package/extensions/services/evol/web/src/views/TeamView.vue +332 -0
  339. package/extensions/services/evol/web/tsconfig.json +31 -0
  340. package/extensions/services/evol/web/tsconfig.node.json +10 -0
  341. package/extensions/services/evol/web/vite.config.ts +49 -0
  342. package/extensions/services/evolmem/__init__.py +0 -0
  343. package/extensions/services/evolmem/entry.py +387 -0
  344. package/extensions/services/evolmem/hooks/__init__.py +0 -0
  345. package/extensions/services/evolmem/hooks/assistant_stop.py +228 -0
  346. package/extensions/services/evolmem/hooks/common.py +76 -0
  347. package/extensions/services/evolmem/hooks/pre_tool_use.py +56 -0
  348. package/extensions/services/evolmem/hooks/session_end.py +133 -0
  349. package/extensions/services/evolmem/hooks/session_start.py +229 -0
  350. package/extensions/services/evolmem/hooks/user_prompt.py +122 -0
  351. package/extensions/services/evolmem/module.md +48 -0
  352. package/extensions/services/evolmem/prompts/00-server-info.md +28 -0
  353. package/extensions/services/evolmem/prompts/01-behavior.md +46 -0
  354. package/extensions/services/evolmem/prompts/02-summary-format.md +112 -0
  355. package/extensions/services/evolmem/prompts/03-file-query.md +92 -0
  356. package/extensions/services/evolmem/prompts/04-topic-stats.md +11 -0
  357. package/extensions/services/evolmem/prompts/05-recent-topics.md +84 -0
  358. package/extensions/services/evolmem/scripts/__init__.py +0 -0
  359. package/extensions/services/evolmem/scripts/extract_keywords.py +40 -0
  360. package/extensions/services/evolmem/scripts/search_topics.py +91 -0
  361. package/extensions/services/evolmem/server.py +641 -0
  362. package/extensions/services/gateway/entry.py +964 -0
  363. package/extensions/services/gateway/module.md +29 -0
  364. package/extensions/services/gateway/nonce_pool.py +65 -0
  365. package/extensions/services/gateway/relay.py +133 -0
  366. package/extensions/services/gateway/ws_server.py +285 -0
  367. package/extensions/services/kite_console/auth_manager.py +603 -0
  368. package/extensions/services/kite_console/config.json5 +19 -0
  369. package/extensions/services/kite_console/config_loader.py +117 -0
  370. package/extensions/services/kite_console/entry.py +528 -0
  371. package/extensions/services/kite_console/evol_api.py +179 -0
  372. package/extensions/services/kite_console/evol_config.json5 +29 -0
  373. package/extensions/services/kite_console/mfa_totp.py +77 -0
  374. package/extensions/services/kite_console/migrate_tokens.py +122 -0
  375. package/extensions/services/kite_console/module.md +37 -0
  376. package/extensions/services/kite_console/nonce_pool.py +113 -0
  377. package/extensions/services/kite_console/oauth_manager.py +223 -0
  378. package/extensions/services/kite_console/pairing.py +280 -0
  379. package/extensions/services/kite_console/pairing_codes.jsonl +2 -0
  380. package/extensions/services/kite_console/relay.py +1350 -0
  381. package/extensions/services/kite_console/relay_config.json5 +96 -0
  382. package/extensions/services/kite_console/routes/__init__.py +1 -0
  383. package/extensions/services/kite_console/routes/routes_llm.py +231 -0
  384. package/extensions/services/kite_console/routes/routes_proxy.py +115 -0
  385. package/extensions/services/kite_console/routes/routes_rpc.py +89 -0
  386. package/extensions/services/kite_console/routes/routes_test.py +68 -0
  387. package/extensions/services/kite_console/server.py +1742 -0
  388. package/extensions/services/kite_console/static/css/style.css +1854 -0
  389. package/extensions/services/kite_console/static/index.html +1524 -0
  390. package/extensions/services/kite_console/static/js/dialog.js +292 -0
  391. package/extensions/services/kite_console/static/js/evol-app.js +7740 -0
  392. package/extensions/services/kite_console/static/js/evol-app.js.backup +2777 -0
  393. package/extensions/services/kite_console/static/js/kernel-client.js +560 -0
  394. package/extensions/services/kite_console/static/js/kernel-client.js.backup +434 -0
  395. package/extensions/services/kite_console/static/js/registry-tests.js +592 -0
  396. package/extensions/services/kite_console/static/js/tests/ARCHITECTURE.md +67 -0
  397. package/extensions/services/kite_console/static/js/tests/README.md +140 -0
  398. package/extensions/services/kite_console/static/js/tests/index.js +161 -0
  399. package/extensions/services/kite_console/static/js/tests/integration/auth.js +120 -0
  400. package/extensions/services/kite_console/static/js/tests/integration/channel-interaction.js +188 -0
  401. package/extensions/services/kite_console/static/js/tests/integration/elastic-connection.js +115 -0
  402. package/extensions/services/kite_console/static/js/tests/integration/full-workflow.js +43 -0
  403. package/extensions/services/kite_console/static/js/tests/integration/multi-instance.js +304 -0
  404. package/extensions/services/kite_console/static/js/tests/integration/nested-rpc.js +266 -0
  405. package/extensions/services/kite_console/static/js/tests/integration/pingpong.js +25 -0
  406. package/extensions/services/kite_console/static/js/tests/integration/redis.js +227 -0
  407. package/extensions/services/kite_console/static/js/tests/integration/registry-core.js +52 -0
  408. package/extensions/services/kite_console/static/js/tests/integration/remote-deploy.js +85 -0
  409. package/extensions/services/kite_console/static/js/tests/integration/require-init.js +96 -0
  410. package/extensions/services/kite_console/static/js/tests/integration/scaling-control.js +193 -0
  411. package/extensions/services/kite_console/static/js/tests/integration/trace.js +109 -0
  412. package/extensions/services/kite_console/static/js/tests/modules/acp_channel.js +339 -0
  413. package/extensions/services/kite_console/static/js/tests/modules/auth.js +96 -0
  414. package/extensions/services/kite_console/static/js/tests/modules/backup.js +49 -0
  415. package/extensions/services/kite_console/static/js/tests/modules/gateway.js +41 -0
  416. package/extensions/services/kite_console/static/js/tests/modules/kernel.js +90 -0
  417. package/extensions/services/kite_console/static/js/tests/modules/launcher.js +75 -0
  418. package/extensions/services/kite_console/static/js/tests/modules/multi_instance.js +129 -0
  419. package/extensions/services/kite_console/static/js/tests/modules/phone_channel.js +364 -0
  420. package/extensions/services/kite_console/static/js/tests/modules/redis.js +178 -0
  421. package/extensions/services/kite_console/static/js/tests/modules/watchdog.js +60 -0
  422. package/extensions/services/kite_console/static/js/tests/modules/web.js +70 -0
  423. package/extensions/services/kite_console/static/js/tests/test-runner.js +123 -0
  424. package/extensions/services/kite_console/static/js/virtual-list.js +200 -0
  425. package/extensions/services/kite_console/static/pairing.html +248 -0
  426. package/extensions/services/kite_console/static/test_kernel_client_token.html +352 -0
  427. package/extensions/services/kite_console/static/test_registry.html +262 -0
  428. package/extensions/services/kite_console/static/test_relay.html +462 -0
  429. package/extensions/services/kite_console/stats_manager.py +247 -0
  430. package/extensions/services/logs/README.md +215 -0
  431. package/extensions/services/logs/api_logger.py +37 -0
  432. package/extensions/services/logs/baseline.py +121 -0
  433. package/extensions/services/logs/cleaner.py +76 -0
  434. package/extensions/services/logs/entry.py +449 -0
  435. package/extensions/services/logs/formatter.py +129 -0
  436. package/extensions/services/logs/module.md +38 -0
  437. package/extensions/services/logs/quick_diagnostic.py +128 -0
  438. package/extensions/services/logs/routes/__init__.py +1 -0
  439. package/extensions/services/logs/routes/routes_logs.py +218 -0
  440. package/extensions/services/logs/routes/routes_logs.py.backup +173 -0
  441. package/extensions/services/logs/scanner.py +100 -0
  442. package/extensions/services/logs/searcher.py +263 -0
  443. package/extensions/services/logs/server.py +553 -0
  444. package/extensions/services/logs.zip +0 -0
  445. package/extensions/services/model_service/config.json5 +30 -0
  446. package/extensions/services/model_service/entry.py +633 -162
  447. package/extensions/services/model_service/module.md +11 -2
  448. package/extensions/services/proxy/.claude/settings.local.json +13 -0
  449. package/extensions/services/proxy/__init__.py +0 -0
  450. package/extensions/services/proxy/agentcp/LICENCE +178 -0
  451. package/extensions/services/proxy/agentcp/README copy.md +85 -0
  452. package/extensions/services/proxy/agentcp/README.md +260 -0
  453. package/extensions/services/proxy/agentcp/__init__.py +16 -0
  454. package/extensions/services/proxy/agentcp/agent.py +4 -0
  455. package/extensions/services/proxy/agentcp/agentcp.py +2494 -0
  456. package/extensions/services/proxy/agentcp/agentprofile.json +89 -0
  457. package/extensions/services/proxy/agentcp/ap/__init__.py +16 -0
  458. package/extensions/services/proxy/agentcp/ap/ap_client.py +316 -0
  459. package/extensions/services/proxy/agentcp/assets/images/wechat_qr.png +0 -0
  460. package/extensions/services/proxy/agentcp/backup/metrics.json +31 -0
  461. package/extensions/services/proxy/agentcp/base/__init__.py +20 -0
  462. package/extensions/services/proxy/agentcp/base/auth_client.py +257 -0
  463. package/extensions/services/proxy/agentcp/base/client.py +112 -0
  464. package/extensions/services/proxy/agentcp/base/env.py +34 -0
  465. package/extensions/services/proxy/agentcp/base/html_util.py +336 -0
  466. package/extensions/services/proxy/agentcp/base/log.py +98 -0
  467. package/extensions/services/proxy/agentcp/ca/__init__.py +17 -0
  468. package/extensions/services/proxy/agentcp/ca/ca_client.py +414 -0
  469. package/extensions/services/proxy/agentcp/ca/ca_root.py +74 -0
  470. package/extensions/services/proxy/agentcp/context/__init__.py +20 -0
  471. package/extensions/services/proxy/agentcp/context/context.py +73 -0
  472. package/extensions/services/proxy/agentcp/context/exceptions.py +114 -0
  473. package/extensions/services/proxy/agentcp/create_profile.py +125 -0
  474. package/extensions/services/proxy/agentcp/create_profile_weather.py +125 -0
  475. package/extensions/services/proxy/agentcp/db/__init__.py +15 -0
  476. package/extensions/services/proxy/agentcp/db/db_mananger.py +550 -0
  477. package/extensions/services/proxy/agentcp/docs/UDP_HEARTBEAT_FIX_REPORT.md +265 -0
  478. package/extensions/services/proxy/agentcp/docs/heartbeat_issue_analysis.md +291 -0
  479. package/extensions/services/proxy/agentcp/file/__init__.py +16 -0
  480. package/extensions/services/proxy/agentcp/file/file_client.py +141 -0
  481. package/extensions/services/proxy/agentcp/file/wss_binary_message.py +137 -0
  482. package/extensions/services/proxy/agentcp/hcp.py +299 -0
  483. package/extensions/services/proxy/agentcp/heartbeat/__init__.py +16 -0
  484. package/extensions/services/proxy/agentcp/heartbeat/heartbeat_client.py +360 -0
  485. package/extensions/services/proxy/agentcp/improved_scheduler.py +498 -0
  486. package/extensions/services/proxy/agentcp/llm_agent_utils.py +249 -0
  487. package/extensions/services/proxy/agentcp/llm_server.py +172 -0
  488. package/extensions/services/proxy/agentcp/mermaid.py +210 -0
  489. package/extensions/services/proxy/agentcp/message.py +149 -0
  490. package/extensions/services/proxy/agentcp/metrics.py +256 -0
  491. package/extensions/services/proxy/agentcp/monitoring/__init__.py +20 -0
  492. package/extensions/services/proxy/agentcp/monitoring/global_monitor.py +27 -0
  493. package/extensions/services/proxy/agentcp/monitoring/metrics_store.py +325 -0
  494. package/extensions/services/proxy/agentcp/monitoring/monitoring_service.py +269 -0
  495. package/extensions/services/proxy/agentcp/monitoring/sliding_window.py +222 -0
  496. package/extensions/services/proxy/agentcp/monitoring/standalone_reader.py +224 -0
  497. package/extensions/services/proxy/agentcp/msg/__init__.py +21 -0
  498. package/extensions/services/proxy/agentcp/msg/connection_manager.py +456 -0
  499. package/extensions/services/proxy/agentcp/msg/message_client.py +2058 -0
  500. package/extensions/services/proxy/agentcp/msg/message_serialize.py +263 -0
  501. package/extensions/services/proxy/agentcp/msg/open_ai_message.py +88 -0
  502. package/extensions/services/proxy/agentcp/msg/session_manager.py +1062 -0
  503. package/extensions/services/proxy/agentcp/msg/stream_client.py +267 -0
  504. package/extensions/services/proxy/agentcp/msg/websocket_file_receiver.py +89 -0
  505. package/extensions/services/proxy/agentcp/msg/ws_logger.py +685 -0
  506. package/extensions/services/proxy/agentcp/msg/wss_binary_message.py +137 -0
  507. package/extensions/services/proxy/agentcp/requirements.txt +7 -0
  508. package/extensions/services/proxy/agentcp/samples/agent_graph/README.md +37 -0
  509. package/extensions/services/proxy/agentcp/samples/agent_graph/agentprofile.json +89 -0
  510. package/extensions/services/proxy/agentcp/samples/agent_graph/create_profile.py +138 -0
  511. package/extensions/services/proxy/agentcp/samples/agent_graph/main.py +164 -0
  512. package/extensions/services/proxy/agentcp/samples/agent_use/create_profile.py +123 -0
  513. package/extensions/services/proxy/agentcp/samples/agent_use/llm/create_profile.py +129 -0
  514. package/extensions/services/proxy/agentcp/samples/agent_use/llm/env.json +5 -0
  515. package/extensions/services/proxy/agentcp/samples/agent_use/llm/main.py +146 -0
  516. package/extensions/services/proxy/agentcp/samples/agent_use/main.py +123 -0
  517. package/extensions/services/proxy/agentcp/samples/agent_use/readme.md +379 -0
  518. package/extensions/services/proxy/agentcp/samples/agent_use/search/create_profile.py +129 -0
  519. package/extensions/services/proxy/agentcp/samples/agent_use/search/main.py +28 -0
  520. package/extensions/services/proxy/agentcp/samples/agent_use/tool/create_profile.py +129 -0
  521. package/extensions/services/proxy/agentcp/samples/agent_use/tool/main.py +20 -0
  522. package/extensions/services/proxy/agentcp/samples/ali_amap/README.md +97 -0
  523. package/extensions/services/proxy/agentcp/samples/ali_amap/amap_agent.py +88 -0
  524. package/extensions/services/proxy/agentcp/samples/ali_amap/create_profile.py +125 -0
  525. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/powershell.py +228 -0
  526. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/software.py +63 -0
  527. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/tools.py +36 -0
  528. package/extensions/services/proxy/agentcp/samples/compute_agent/browser_user.py +41 -0
  529. package/extensions/services/proxy/agentcp/samples/deepseek/README.md +79 -0
  530. package/extensions/services/proxy/agentcp/samples/deepseek/create_profile.py +126 -0
  531. package/extensions/services/proxy/agentcp/samples/deepseek/deepseek.py +42 -0
  532. package/extensions/services/proxy/agentcp/samples/dify_chat/README.md +78 -0
  533. package/extensions/services/proxy/agentcp/samples/dify_chat/create_profile.py +126 -0
  534. package/extensions/services/proxy/agentcp/samples/dify_chat/dify_chat.py +47 -0
  535. package/extensions/services/proxy/agentcp/samples/dify_workflow/README.md +78 -0
  536. package/extensions/services/proxy/agentcp/samples/dify_workflow/create_profile.py +126 -0
  537. package/extensions/services/proxy/agentcp/samples/dify_workflow/dify_workflow.py +46 -0
  538. package/extensions/services/proxy/agentcp/samples/executor/README.md +44 -0
  539. package/extensions/services/proxy/agentcp/samples/executor/agentprofile.json +89 -0
  540. package/extensions/services/proxy/agentcp/samples/executor/create_profile.py +139 -0
  541. package/extensions/services/proxy/agentcp/samples/executor/main.py +160 -0
  542. package/extensions/services/proxy/agentcp/samples/filereader/README.md +45 -0
  543. package/extensions/services/proxy/agentcp/samples/filereader/agentprofile.json +90 -0
  544. package/extensions/services/proxy/agentcp/samples/filereader/create_profile.py +137 -0
  545. package/extensions/services/proxy/agentcp/samples/filereader/main.py +253 -0
  546. package/extensions/services/proxy/agentcp/samples/filewriter/README.md +38 -0
  547. package/extensions/services/proxy/agentcp/samples/filewriter/agentprofile.json +91 -0
  548. package/extensions/services/proxy/agentcp/samples/filewriter/create_profile.py +138 -0
  549. package/extensions/services/proxy/agentcp/samples/filewriter/main.py +289 -0
  550. package/extensions/services/proxy/agentcp/samples/hcp/README.md +85 -0
  551. package/extensions/services/proxy/agentcp/samples/hcp/acp_weather_agent.zip +0 -0
  552. package/extensions/services/proxy/agentcp/samples/hcp/create_profile.py +125 -0
  553. package/extensions/services/proxy/agentcp/samples/hcp/hcp.py +237 -0
  554. package/extensions/services/proxy/agentcp/samples/helloworld/README.md +68 -0
  555. package/extensions/services/proxy/agentcp/samples/helloworld/hello_world.py +40 -0
  556. package/extensions/services/proxy/agentcp/samples/llm_agent/MEADME.md +117 -0
  557. package/extensions/services/proxy/agentcp/samples/llm_agent/create_profile.py +125 -0
  558. package/extensions/services/proxy/agentcp/samples/llm_agent/qwen_agent.py +136 -0
  559. package/extensions/services/proxy/agentcp/samples/local_llm_agent/README.md +90 -0
  560. package/extensions/services/proxy/agentcp/samples/local_llm_agent/create_profile.py +125 -0
  561. package/extensions/services/proxy/agentcp/samples/local_llm_agent/main.py +49 -0
  562. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/README.md +55 -0
  563. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/create_profile.py +125 -0
  564. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/main.py +23 -0
  565. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/README.md +103 -0
  566. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/create_profile.py +125 -0
  567. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/main.py +69 -0
  568. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/README.md +58 -0
  569. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/create_profile.py +125 -0
  570. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/main.py +25 -0
  571. package/extensions/services/proxy/agentcp/samples/qwen3/README.md +71 -0
  572. package/extensions/services/proxy/agentcp/samples/qwen3/create_profile.py +126 -0
  573. package/extensions/services/proxy/agentcp/samples/qwen3/qwen3.py +37 -0
  574. package/extensions/services/proxy/agentcp/samples/qwen3_tools/README.md +133 -0
  575. package/extensions/services/proxy/agentcp/samples/qwen3_tools/create_profile.py +126 -0
  576. package/extensions/services/proxy/agentcp/samples/qwen3_tools/qwen3_tools.py +98 -0
  577. package/extensions/services/proxy/agentcp/samples/search/create_profile_qwen.py +125 -0
  578. package/extensions/services/proxy/agentcp/samples/search/create_profile_search.py +125 -0
  579. package/extensions/services/proxy/agentcp/samples/search/qwen_agent.py +136 -0
  580. package/extensions/services/proxy/agentcp/samples/search/search_agent.py +170 -0
  581. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/README.md +89 -0
  582. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/create_profile.py +125 -0
  583. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/main.py +44 -0
  584. package/extensions/services/proxy/agentcp/utils/__init__.py +15 -0
  585. package/extensions/services/proxy/agentcp/utils/file_util.py +117 -0
  586. package/extensions/services/proxy/agentcp/utils/proxy_bypass.py +99 -0
  587. package/extensions/services/proxy/agentcp/workflow.py +203 -0
  588. package/extensions/services/proxy/aid_manager.py +419 -0
  589. package/extensions/services/proxy/auth_bridge.py +182 -0
  590. package/extensions/services/proxy/config_store.py +79 -0
  591. package/extensions/services/proxy/entry.py +528 -0
  592. package/extensions/services/proxy/evol/__init__.py +1 -0
  593. package/extensions/services/proxy/evol/config.py +37 -0
  594. package/extensions/services/proxy/evol/http/__init__.py +1 -0
  595. package/extensions/services/proxy/evol/http/async_http.py +551 -0
  596. package/extensions/services/proxy/evol/log.py +28 -0
  597. package/extensions/services/proxy/evol/presenter/__init__.py +2 -0
  598. package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +1031 -0
  599. package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +96 -0
  600. package/extensions/services/proxy/evol/presenter/configPresenter.py +234 -0
  601. package/extensions/services/proxy/evol/presenter/userPresenter.py +71 -0
  602. package/extensions/services/proxy/evol/server/__init__.py +1 -0
  603. package/extensions/services/proxy/evol/server/claude_proxy_async.py +3434 -0
  604. package/extensions/services/proxy/evol/server/openclaw_proxy.py +1861 -0
  605. package/extensions/services/proxy/evol/server/proxy_config.py +15 -0
  606. package/extensions/services/proxy/evol/server/proxy_engine.py +501 -0
  607. package/extensions/services/proxy/evol/version.py +24 -0
  608. package/extensions/services/proxy/module.md +151 -0
  609. package/extensions/services/proxy/server.py +952 -0
  610. package/extensions/services/redis/ALIGNMENT_CHECKLIST.md +121 -0
  611. package/extensions/services/redis/ALIGNMENT_STATUS.md +548 -0
  612. package/extensions/services/redis/config.json5 +8 -0
  613. package/extensions/services/redis/entry.py +1509 -0
  614. package/extensions/services/redis/entry.py.backup +405 -0
  615. package/extensions/services/redis/module.md +48 -0
  616. package/extensions/services/redis/redis_builtin.py +332 -0
  617. package/extensions/services/redis/redis_external.py +164 -0
  618. package/extensions/services/testUi/entry.py +446 -0
  619. package/extensions/services/testUi/module.md +18 -0
  620. package/extensions/services/testUi/ui/cards.html +131 -0
  621. package/extensions/services/testUi/ui/index.html +22 -0
  622. package/extensions/services/testUi/ui/particles.html +143 -0
  623. package/extensions/services/watchdog/entry.py +1258 -767
  624. package/extensions/services/watchdog/module.md +3 -0
  625. package/extensions/services/watchdog/monitor.py +483 -75
  626. package/extensions/services/web/auth_manager.py +602 -0
  627. package/extensions/services/web/config.json5 +11 -0
  628. package/extensions/services/web/entry.py +598 -478
  629. package/extensions/services/web/mfa_totp.py +77 -0
  630. package/extensions/services/web/module.md +17 -14
  631. package/extensions/services/web/nonce_pool.py +113 -0
  632. package/extensions/services/web/oauth_manager.py +223 -0
  633. package/extensions/services/web/pairing.py +3 -2
  634. package/extensions/services/web/pairing_codes.jsonl +1 -0
  635. package/extensions/services/web/relay.py +442 -63
  636. package/extensions/services/web/relay_config.json5 +1 -2
  637. package/extensions/services/web/routes/routes_rpc.py +6 -6
  638. package/extensions/services/web/server.py +380 -181
  639. package/extensions/services/web/static/index.html +1752 -1738
  640. package/extensions/services/web/static/js/app.js +32 -0
  641. package/extensions/services/web/static/js/kernel-client.js +48 -9
  642. package/extensions/services/web/static/js/token-manager.js +10 -10
  643. package/extensions/services/web/vendor/bluetooth/audio.py +1 -1
  644. package/extensions/services/web/vendor/config.py +2 -2
  645. package/extensions/services/web/vendor/storage/identity.py +1 -1
  646. package/kernel/entry.py +77 -23
  647. package/kernel/event_hub.py +1122 -74
  648. package/kernel/module.md +26 -1
  649. package/kernel/registry_store.py +209 -36
  650. package/kernel/rpc_router.py +1400 -465
  651. package/kernel/server.py +1084 -108
  652. package/kite_cli/builders/__init__.py +4 -0
  653. package/kite_cli/builders/base.py +67 -0
  654. package/kite_cli/builders/custom.py +31 -0
  655. package/kite_cli/builders/detector.py +56 -0
  656. package/kite_cli/builders/go.py +34 -0
  657. package/kite_cli/builders/gradle.py +41 -0
  658. package/kite_cli/builders/maven.py +36 -0
  659. package/kite_cli/builders/npm.py +44 -0
  660. package/kite_cli/builders/python.py +37 -0
  661. package/kite_cli/commands/BUILD_GUIDE.md +109 -0
  662. package/kite_cli/commands/build.py +142 -0
  663. package/kite_cli/commands/check.py +60 -0
  664. package/kite_cli/commands/config.py +156 -0
  665. package/kite_cli/commands/deps.py +58 -0
  666. package/kite_cli/commands/deps_install.py +67 -0
  667. package/kite_cli/commands/disable.py +162 -0
  668. package/kite_cli/commands/enable.py +162 -0
  669. package/kite_cli/commands/env_check.py +45 -0
  670. package/kite_cli/commands/export.py +96 -0
  671. package/kite_cli/commands/import_cmd.py +110 -0
  672. package/kite_cli/commands/install.py +50 -23
  673. package/kite_cli/commands/install_skill.py +107 -0
  674. package/kite_cli/commands/list.py +128 -31
  675. package/kite_cli/commands/outdated.py +202 -0
  676. package/kite_cli/commands/prepare.py +49 -0
  677. package/kite_cli/commands/search.py +33 -17
  678. package/kite_cli/commands/update.py +115 -2
  679. package/kite_cli/commands/venv_setup.py +56 -0
  680. package/kite_cli/commands/why.py +48 -0
  681. package/kite_cli/core/config_manager.py +145 -0
  682. package/kite_cli/core/downloader.py +32 -2
  683. package/kite_cli/main.py +179 -5
  684. package/kite_cli/utils/colors.py +153 -0
  685. package/kite_cli/utils/dependency_graph.py +209 -0
  686. package/kite_cli/utils/process.py +55 -0
  687. package/kite_cli/utils/progress.py +207 -0
  688. package/kite_cli/utils/table.py +101 -0
  689. package/launcher/count_lines.py +192 -43
  690. package/launcher/entry.py +4543 -2517
  691. package/launcher/logging_setup.py +54 -1
  692. package/launcher/module.md +37 -2
  693. package/launcher/module_scanner.py +103 -20
  694. package/launcher/process_manager.py +355 -76
  695. package/main.py +10 -1
  696. package/package.json +11 -1
  697. package/python_version.json +4 -0
  698. package/requirements.txt +41 -0
  699. package/scripts/auto-fix-deps.py +128 -0
  700. package/scripts/env-manager.js +351 -0
  701. package/scripts/final-test.js +78 -0
  702. package/scripts/python-env.js +79 -0
  703. package/scripts/scan_dependencies.py +461 -0
  704. package/scripts/setup-python-env.js +700 -0
  705. package/scripts/test-alluser.js +48 -0
  706. package/scripts/test-different-version.js +86 -0
  707. package/scripts/test-direct.js +63 -0
  708. package/scripts/test-extract-installer.js +28 -0
  709. package/scripts/test-install-log.js +54 -0
  710. package/scripts/test-installer.js +39 -0
  711. package/scripts/test-integration.js +250 -0
  712. package/scripts/test-real-install.js +210 -0
  713. package/scripts/test-targetdir.js +49 -0
  714. package/scripts/test-venv-real.js +47 -0
  715. package/scripts/test-venv-simple.js +57 -0
  716. package/scripts/test-wait.js +49 -0
  717. package/scripts/test-with-log.js +63 -0
  718. package/extensions/services/web/config.yaml +0 -149
@@ -15,6 +15,7 @@ from datetime import datetime, timezone
15
15
  import asyncio
16
16
  import traceback
17
17
  import uuid
18
+ import random
18
19
 
19
20
  import websockets
20
21
 
@@ -120,6 +121,19 @@ def _load_module_config() -> dict:
120
121
  if "advertise_ip" in fm:
121
122
  result["advertise_ip"] = str(fm["advertise_ip"])
122
123
 
124
+ # max_connections(弹性连接上限)
125
+ try:
126
+ result["max_connections"] = max(1, min(10, int(fm.get("max_connections", 1))))
127
+ except (ValueError, TypeError):
128
+ result["max_connections"] = 1
129
+
130
+ # business_config(从 businesses 数组取)
131
+ businesses = fm.get("businesses")
132
+ if isinstance(businesses, list) and businesses:
133
+ cfg_file = businesses[0].get("config_file") if isinstance(businesses[0], dict) else None
134
+ if cfg_file:
135
+ result["business_config"] = str(cfg_file).strip()
136
+
123
137
  except SystemExit:
124
138
  raise # Re-raise exit to prevent catching by outer except
125
139
  except Exception as e:
@@ -131,6 +145,20 @@ def _load_module_config() -> dict:
131
145
  _module_config = _load_module_config()
132
146
  MODULE_NAME = _module_config["name"]
133
147
 
148
+ # 读取业务配置
149
+ _business_config = {}
150
+ config_file = _module_config.get("business_config")
151
+ if config_file:
152
+ config_path = os.path.join(os.path.dirname(__file__), config_file)
153
+ if os.path.exists(config_path):
154
+ try:
155
+ import json5
156
+ with open(config_path, 'r', encoding='utf-8') as f:
157
+ _business_config = json5.load(f)
158
+ print(f"[{MODULE_NAME}] 业务配置已加载: {config_file}")
159
+ except Exception as e:
160
+ print(f"[{MODULE_NAME}] 业务配置读取失败: {e}")
161
+
134
162
 
135
163
  class _SafeWriter:
136
164
  """Wraps a stream to silently swallow BrokenPipeError on write/flush."""
@@ -372,6 +400,14 @@ _ws_global = None
372
400
  _shutting_down = False
373
401
  _exit_code = 0 # Exit code for main() to use
374
402
 
403
+ # 弹性多连接
404
+ _extra_ws: dict = {} # slot → WebSocket(附加连接)
405
+ _extra_ws_tasks: dict = {} # slot → recv loop Task
406
+ _kernel_port = "" # 缓存 kernel_port,供 offer handler 使用
407
+ _pending_rpc: dict[str, asyncio.Future] = {} # rpc_id → Future(等待响应)
408
+
409
+ _has_registered = False
410
+
375
411
 
376
412
  def _is_auth_failure(e: Exception) -> bool:
377
413
  """Check if a WebSocket exception indicates authentication failure."""
@@ -381,197 +417,317 @@ def _is_auth_failure(e: Exception) -> bool:
381
417
  return False
382
418
 
383
419
 
384
- async def main():
385
- global _ws_global, _shutting_down
386
- # Initialize log file paths
387
- global _log_dir, _log_latest_path, _crash_log_path
388
- module_data = os.environ.get("KITE_MODULE_DATA")
389
- if module_data:
390
- _log_dir = os.path.join(module_data, "log")
391
- os.makedirs(_log_dir, exist_ok=True)
392
- suffix = os.environ.get("KITE_INSTANCE_SUFFIX", "")
420
+ # ── 远程模式:Token 管理 ──
393
421
 
394
- _log_latest_path = os.path.join(_log_dir, f"latest{suffix}.log")
395
- try:
396
- with open(_log_latest_path, "w", encoding="utf-8") as f:
397
- pass
398
- except Exception:
399
- _log_latest_path = None
400
-
401
- _crash_log_path = os.path.join(_log_dir, f"crashes{suffix}.jsonl")
402
- try:
403
- with open(_crash_log_path, "w", encoding="utf-8") as f:
404
- pass
405
- except Exception:
406
- _crash_log_path = None
422
+ def _gateway_to_filename(gateway_url: str) -> str:
423
+ """从 gateway_url 生成缓存文件名"""
424
+ try:
425
+ from urllib.parse import urlparse
426
+ parsed = urlparse(gateway_url)
427
+ host = parsed.hostname or "unknown"
428
+ port = parsed.port or (443 if parsed.scheme == "wss" else 80)
429
+ return f"{host}-{port}.json".replace(":", "-").replace("/", "-")
430
+ except Exception:
431
+ return "default.json"
407
432
 
408
- _resolve_daily_log_path()
409
433
 
410
- _setup_exception_hooks()
434
+ def _load_token_cache(module_name: str, gateway_url: str) -> dict | None:
435
+ """加载 token 缓存"""
436
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
437
+ data_dir = os.path.join(home, ".kite", "remote", module_name, "tokens")
438
+ filename = _gateway_to_filename(gateway_url)
439
+ token_file = os.path.join(data_dir, filename)
411
440
 
412
- _t0 = time.monotonic()
441
+ if not os.path.exists(token_file):
442
+ return None
413
443
 
414
- # Read boot_info from stdin (only token)
415
- token = ""
416
444
  try:
417
- line = sys.stdin.readline().strip()
418
- if line:
419
- boot_info = json.loads(line)
420
- token = boot_info.get("token", "")
445
+ with open(token_file, "r") as f:
446
+ return json.load(f)
421
447
  except Exception:
422
- pass
448
+ return None
423
449
 
424
- # Read kernel_port: env first (fast path), stdin fallback (parallel start)
425
- kernel_port = int(os.environ.get("KITE_KERNEL_PORT", "0"))
426
- if not kernel_port:
427
- msg = _read_stdin_kite_message("kernel_port", timeout=10)
428
- if msg:
429
- kernel_port = int(msg.get("kernel_port", 0))
430
450
 
431
- if not token or not kernel_port:
432
- print("[model_service] ERROR: Missing token or kernel_port")
433
- sys.exit(1)
451
+ def _clear_token_cache(module_name: str, gateway_url: str):
452
+ """清除 token 缓存"""
453
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
454
+ data_dir = os.path.join(home, ".kite", "remote", module_name, "tokens")
455
+ filename = _gateway_to_filename(gateway_url)
456
+ token_file = os.path.join(data_dir, filename)
457
+
458
+ if os.path.exists(token_file):
459
+ try:
460
+ os.remove(token_file)
461
+ except Exception:
462
+ pass
463
+
464
+
465
+ def _get_kite_token(module_name: str, gateway_url: str) -> str:
466
+ """获取 kite_token(环境变量 > 缓存 > 提示配对)"""
467
+ # 1. 环境变量优先
468
+ token = os.environ.get("KITE_TOKEN")
469
+ if token:
470
+ return token
471
+
472
+ # 2. 从缓存加载
473
+ cache = _load_token_cache(module_name, gateway_url)
474
+ if cache:
475
+ return cache["token"]
434
476
 
435
- print(f"[model_service] Token received ({len(token)} chars), kernel port: {kernel_port} ({_fmt_elapsed(_t0)})")
477
+ # 3. 提示首次配对
478
+ print(f"[{module_name}] No token found for {gateway_url}")
479
+ print(f" Please authenticate:")
480
+ print(f" export KITE_TOKEN=<your_token>")
481
+ print(f" # Or use kite-cli:")
482
+ print(f" kite-cli auth --module {module_name} --gateway {gateway_url}")
483
+ sys.exit(1)
436
484
 
437
- # Start reconnect loop
438
- await _ws_loop(token, kernel_port, _t0)
485
+
486
+ async def main():
487
+ global _ws_global, _shutting_down
488
+ # 根据启动模式选择连接方式
489
+ if _startup_config.get("mode") == "remote":
490
+ await _remote_mode_loop(_startup_config["gateway_url"], _startup_config["kite_token"], _startup_config["t0"])
491
+ else:
492
+ await _ws_loop(_startup_config["token"], _startup_config["kernel_port"], _startup_config["t0"])
439
493
 
440
494
 
441
495
  async def _ws_loop(token: str, kernel_port: int, _t0: float):
442
496
  """Connect to Kernel with exponential backoff reconnection."""
443
497
  global _shutting_down, _exit_code
444
- retry_delay = 0.3
445
- max_delay = 5.0
446
- max_retries = 10
498
+ retry_delay = 0.5
499
+ max_delay = 10.0
447
500
  attempt = 0
501
+ cooldown_attempts = 0
502
+
448
503
  while not _shutting_down:
449
504
  try:
450
505
  await _ws_connect(token, kernel_port, _t0)
451
- retry_delay = 0.3
506
+ retry_delay = 0.5
452
507
  attempt = 0
508
+ cooldown_attempts = 0
453
509
  except asyncio.CancelledError:
454
510
  return
455
511
  except Exception as e:
456
- attempt += 1
457
- if _is_auth_failure(e):
458
- print(f"[model_service] Kernel 认证失败,退出")
459
- _exit_code = 1
460
- _shutting_down = True
512
+ if _shutting_down:
461
513
  return
462
- if attempt >= max_retries:
463
- print(f"[model_service] 重连失败 {max_retries} 次,退出")
514
+
515
+ code = _get_close_code(e)
516
+
517
+ # never: 永不重连
518
+ if code in (4001, 4003, 4004, 1008, 4010):
519
+ print(f"[model_service] 致命错误 (code {code}),退出")
464
520
  _exit_code = 1
465
521
  _shutting_down = True
466
522
  return
523
+
524
+ # cooldown: 速率限制
525
+ if code == 4020:
526
+ cooldown_attempts += 1
527
+ if cooldown_attempts >= 5:
528
+ print(f"[model_service] 速率限制重试 5 次,退出")
529
+ _exit_code = 1
530
+ _shutting_down = True
531
+ return
532
+ print(f"[model_service] 速率限制,10.0s 后重试 ({cooldown_attempts}/5)")
533
+ await asyncio.sleep(10.0)
534
+ continue
535
+
536
+ # standard: 指数退避 + jitter
537
+ attempt += 1
538
+ jitter = retry_delay * 0.2 * random.random()
539
+ sleep_time = retry_delay + jitter
467
540
  _write_crash(type(e), e, e.__traceback__, severity="error", handled=True)
468
- print(f"[model_service] 连接错误: {e}, {retry_delay:.1f}s 后重试 ({attempt}/{max_retries})")
541
+ print(f"[model_service] 连接错误: {e}, {sleep_time:.1f}s 后重试 (attempt {attempt})")
542
+
469
543
  _ws_global_clear()
470
544
  if _shutting_down:
471
545
  return
472
- await asyncio.sleep(retry_delay)
546
+ await asyncio.sleep(sleep_time if 'sleep_time' in locals() else retry_delay)
473
547
  retry_delay = min(retry_delay * 2, max_delay)
474
548
 
475
549
 
550
+ def _get_close_code(e: Exception) -> int:
551
+ """从 websockets 异常中提取关闭码"""
552
+ if hasattr(e, 'rcvd') and e.rcvd is not None:
553
+ return getattr(e.rcvd, 'code', 0)
554
+ return 0
555
+
556
+
476
557
  def _ws_global_clear():
477
558
  global _ws_global
478
559
  _ws_global = None
479
560
 
480
561
 
562
+ async def _do_init(ws):
563
+ """收到 system.require_init 后执行:subscribe + register + module.ready"""
564
+ global _has_registered
565
+ reason = "startup" if not _has_registered else "recovery"
566
+ print(f"[model_service] Received system.require_init (reason={reason})")
567
+
568
+ # 1. Subscribe to events
569
+ await _rpc_call(ws, "event.subscribe", {
570
+ "events": [
571
+ "module.started",
572
+ "module.stopped",
573
+ "module.shutdown",
574
+ ],
575
+ })
576
+ print(f"[model_service] Subscribed to events")
577
+
578
+ # 2. Register to Kernel Registry via RPC
579
+ await _rpc_call(ws, "registry.register", {
580
+ "module_id": "model_service",
581
+ "module_type": "service",
582
+ "events_publish": {
583
+ "model_service": {
584
+ "test": {"description": "Test event from model_service module"},
585
+ }
586
+ },
587
+ "events_subscribe": [
588
+ "module.started",
589
+ "module.stopped",
590
+ "module.shutdown",
591
+ ],
592
+ })
593
+ print(f"[model_service] Registered to Kernel")
594
+
595
+ # 3. Publish module.ready
596
+ if not _shutting_down:
597
+ startup_time = time.monotonic() - _start_ts
598
+ await _publish_event(ws, "module.ready", {
599
+ "module_id": "model_service",
600
+ "graceful_shutdown": True,
601
+ "startup_time": startup_time,
602
+ "reason": reason,
603
+ })
604
+ print(f"[model_service] module.ready published (reason={reason})")
605
+
606
+ _has_registered = True
607
+
608
+ # Start test event loop in background
609
+ asyncio.create_task(_test_event_loop(ws))
610
+
611
+
481
612
  async def _ws_connect(token: str, kernel_port: int, _t0: float):
482
- """Single WebSocket session: connect → subscriberegisterready receive loop."""
483
- global _ws_global
613
+ """Single WebSocket session: connect → authstart receiver wait for system.require_init."""
614
+ global _ws_global, _kernel_port
484
615
 
485
- ws_url = f"ws://127.0.0.1:{kernel_port}/ws?token={token}&id=model_service"
616
+ _kernel_port = kernel_port
617
+ ws_url = f"ws://127.0.0.1:{kernel_port}/ws?id=model_service"
486
618
  print(f"[model_service] Connecting to Kernel: {ws_url}")
487
619
 
488
- async with websockets.connect(ws_url, open_timeout=5, ping_interval=20, ping_timeout=20, close_timeout=10) as ws:
620
+ async with websockets.connect(ws_url, open_timeout=5, ping_interval=None, close_timeout=10) as ws:
621
+ # Send auth message first
622
+ auth_req = {
623
+ "jsonrpc": "2.0",
624
+ "id": "auth",
625
+ "method": "auth",
626
+ "params": {"token": token}
627
+ }
628
+ await ws.send(json.dumps(auth_req))
629
+
630
+ # Wait for auth response
631
+ auth_resp_raw = await asyncio.wait_for(ws.recv(), timeout=5)
632
+ auth_resp = json.loads(auth_resp_raw)
633
+ if "error" in auth_resp:
634
+ raise Exception(f"Auth failed: {auth_resp['error']}")
635
+
489
636
  _ws_global = ws
490
637
  print(f"[model_service] Connected to Kernel ({_fmt_elapsed(_t0)})")
491
638
 
492
- # Subscribe to events
493
- await _rpc_call(ws, "event.subscribe", {
494
- "events": [
495
- "module.started",
496
- "module.stopped",
497
- "module.shutdown",
498
- ],
499
- })
500
- print(f"[model_service] Subscribed to events ({_fmt_elapsed(_t0)})")
639
+ # Start receiver task — wait for system.require_init to trigger _do_init
640
+ receiver_task = asyncio.create_task(_ws_receiver(ws))
641
+ try:
642
+ # Wait for receiver to finish (connection closed or error)
643
+ await receiver_task
644
+ finally:
645
+ receiver_task.cancel()
646
+ for fut in _pending_rpc.values():
647
+ if not fut.done():
648
+ fut.set_result({"error": {"code": -32001, "message": "Connection lost"}})
649
+ _pending_rpc.clear()
650
+
651
+
652
+ async def _ws_receiver(ws):
653
+ """Main connection receive loop: route events, RPC requests, and RPC responses.
654
+ Detects system.require_init to trigger _do_init."""
655
+ async for raw in ws:
656
+ try:
657
+ msg = json.loads(raw)
658
+ except (json.JSONDecodeError, TypeError):
659
+ continue
501
660
 
502
- # Register to Kernel Registry via RPC
503
- await _rpc_call(ws, "registry.register", {
504
- "module_id": "model_service",
505
- "module_type": "service",
506
- "events_publish": {
507
- "model_service": {
508
- "test": {"description": "Test event from model_service module"},
509
- }
510
- },
511
- "events_subscribe": [
512
- "module.started",
513
- "module.stopped",
514
- "module.shutdown",
515
- ],
516
- })
517
- print(f"[model_service] Registered to Kernel ({_fmt_elapsed(_t0)})")
518
-
519
- # Publish module.ready (every reconnect)
520
- if not _shutting_down:
521
- await _rpc_call(ws, "event.publish", {
522
- "event_id": str(uuid.uuid4()),
523
- "event": "module.ready",
524
- "data": {
525
- "module_id": "model_service",
526
- "graceful_shutdown": True,
527
- },
528
- })
529
- print(f"[model_service] module.ready published ({_fmt_elapsed(_t0)})")
661
+ try:
662
+ has_method = "method" in msg
663
+ has_id = "id" in msg
664
+
665
+ if has_method and not has_id:
666
+ # 检测 system.require_init 事件
667
+ params = msg.get("params", {})
668
+ event_type = params.get("event", "")
669
+ if event_type == "system.require_init":
670
+ asyncio.create_task(_do_init(ws))
671
+ continue
672
+ # Event Notification — run in background to prevent deadlock
673
+ asyncio.create_task(_handle_event_notification(msg))
674
+ elif has_method and has_id:
675
+ # Incoming RPC request — run in background to prevent deadlock
676
+ asyncio.create_task(_handle_rpc_request(ws, msg))
677
+ elif not has_method and has_id:
678
+ _handle_rpc_response(msg)
679
+ except Exception as e:
680
+ print(f"[model_service] 消息处理异常(已忽略): {e}")
530
681
 
531
- # Start test event loop in background
532
- test_task = asyncio.create_task(_test_event_loop(ws))
533
682
 
534
- # Message loop: handle incoming RPC + events
535
- # CRITICAL: RPC 死锁防范
536
- # - 入站 RPC 请求必须用 create_task() 异步执行,不可 await
537
- # - 原因:如果 handler 内部调用 rpc_call() 发出站请求,出站响应需要本接收循环来分发
538
- # - 如果接收循环被 await handler 阻塞,出站响应永远收不到 超时死锁
539
- # - 事件通知和 RPC 响应可以同步处理(它们不会反向调用 rpc_call)
540
- async for raw in ws:
541
- try:
542
- msg = json.loads(raw)
543
- except (json.JSONDecodeError, TypeError):
544
- continue
683
+ async def _rpc_call(ws, method: str, params: dict = None,
684
+ wait_response: bool = True, timeout: float = 3.0) -> dict:
685
+ """JSON-RPC 2.0 request。默认等待响应。"""
686
+ rpc_id = str(uuid.uuid4())
687
+ msg = {"jsonrpc": "2.0", "id": rpc_id, "method": method}
688
+ if params:
689
+ msg["params"] = params
545
690
 
546
- try:
547
- has_method = "method" in msg
548
- has_id = "id" in msg
691
+ if not wait_response:
692
+ await ws.send(json.dumps(msg))
693
+ return {}
549
694
 
550
- if has_method and not has_id:
551
- # Event Notification
552
- await _handle_event_notification(msg)
553
- elif has_method and has_id:
554
- # Incoming RPC request — run in background to prevent deadlock
555
- asyncio.create_task(_handle_rpc_request(ws, msg))
556
- # Ignore RPC responses (we don't await them in this simple impl)
557
- except Exception as e:
558
- print(f"[model_service] 消息处理异常(已忽略): {e}")
695
+ future = asyncio.get_event_loop().create_future()
696
+ _pending_rpc[rpc_id] = future
697
+ await ws.send(json.dumps(msg))
698
+ try:
699
+ return await asyncio.wait_for(future, timeout=timeout)
700
+ except asyncio.TimeoutError:
701
+ _pending_rpc.pop(rpc_id, None)
702
+ return {"error": {"code": -32000, "message": f"RPC timeout: {method} ({timeout}s)"}}
559
703
 
560
704
 
561
- async def _rpc_call(ws, method: str, params: dict = None):
562
- """Send a JSON-RPC 2.0 request (fire-and-forget, no response awaited)."""
563
- msg = {"jsonrpc": "2.0", "id": str(uuid.uuid4()), "method": method}
564
- if params:
565
- msg["params"] = params
566
- await ws.send(json.dumps(msg))
705
+ def _handle_rpc_response(msg: dict):
706
+ """Route JSON-RPC response to pending future."""
707
+ rpc_id = msg.get("id")
708
+ future = _pending_rpc.pop(rpc_id, None)
709
+ if future and not future.done():
710
+ future.set_result(msg)
567
711
 
568
712
 
569
- async def _publish_event(ws, event: dict):
570
- """Publish an event via RPC event.publish."""
713
+ async def _publish_event(ws, event: str, data: dict = None):
714
+ """Publish event via event.publish RPC (fire-and-forget)."""
571
715
  await _rpc_call(ws, "event.publish", {
572
716
  "event_id": str(uuid.uuid4()),
573
- "event": event.get("event", ""),
574
- "data": event.get("data", {}),
717
+ "event": event,
718
+ "data": data or {},
719
+ }, wait_response=False)
720
+
721
+
722
+ async def _handle_ping_event(data: dict):
723
+ """Handle system.ping event and reply with system.pong."""
724
+ t1 = data.get("ping_time")
725
+ t2 = time.time()
726
+
727
+ await _publish_event(_ws_global, "system.pong", {
728
+ "module_id": MODULE_NAME,
729
+ "ping_time": t1,
730
+ "pong_time": t2,
575
731
  })
576
732
 
577
733
 
@@ -581,6 +737,19 @@ async def _handle_event_notification(msg: dict):
581
737
  event_type = params.get("event", "")
582
738
  data = params.get("data", {})
583
739
 
740
+ # Handle system.ping event
741
+ if event_type == "system.ping":
742
+ await _handle_ping_event(data)
743
+ return
744
+
745
+ # 弹性连接 offer/release
746
+ if event_type == "system.connection.offer":
747
+ asyncio.create_task(_handle_connection_offer(data))
748
+ return
749
+ if event_type == "system.connection.release":
750
+ asyncio.create_task(_handle_connection_release(data))
751
+ return
752
+
584
753
  # Special handling for module.shutdown
585
754
  if event_type == "module.shutdown":
586
755
  target = data.get("module_id", "")
@@ -640,53 +809,355 @@ async def _rpc_status() -> dict:
640
809
  }
641
810
 
642
811
 
812
+ async def _handle_connection_offer(data):
813
+ """处理 Kernel 下发的 slot token,建立附加连接。"""
814
+ slots = data.get("slots", {})
815
+ for slot_str, info in slots.items():
816
+ slot = int(slot_str)
817
+ token = info.get("token", "")
818
+ if not token or slot in _extra_ws:
819
+ continue
820
+ asyncio.create_task(_connect_slot(slot, token))
821
+
822
+
823
+ async def _connect_slot(slot, token):
824
+ """建立单个 slot 附加连接。"""
825
+ ws_url = f"ws://127.0.0.1:{_kernel_port}/ws"
826
+ try:
827
+ ws = await websockets.connect(ws_url, open_timeout=5, ping_interval=None, close_timeout=5)
828
+ auth_req = {"jsonrpc": "2.0", "id": f"auth-slot-{slot}", "method": "auth", "params": {"token": token}}
829
+ await ws.send(json.dumps(auth_req))
830
+ resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
831
+ if "error" in resp:
832
+ await ws.close()
833
+ return
834
+ _extra_ws[slot] = ws
835
+ _extra_ws_tasks[slot] = asyncio.create_task(_slot_recv_loop(slot, ws))
836
+ print(f"[model_service] Slot {slot} connected")
837
+ except Exception as e:
838
+ print(f"[model_service] Slot {slot} connect failed: {e}")
839
+
840
+
841
+ async def _slot_recv_loop(slot, ws):
842
+ """附加连接的接收循环:与主连接平等处理所有消息。"""
843
+ try:
844
+ async for raw in ws:
845
+ try:
846
+ msg = json.loads(raw)
847
+ except (json.JSONDecodeError, TypeError):
848
+ continue
849
+ try:
850
+ has_method = "method" in msg
851
+ has_id = "id" in msg
852
+
853
+ if has_method and not has_id:
854
+ asyncio.create_task(_handle_event_notification(msg))
855
+ elif has_method and has_id:
856
+ asyncio.create_task(_handle_rpc_request(ws, msg))
857
+ elif not has_method and has_id:
858
+ _handle_rpc_response(msg)
859
+ except Exception as e:
860
+ print(f"[model_service] Slot {slot} 消息处理异常(已忽略): {e}")
861
+ except Exception as e:
862
+ print(f"[model_service] Slot {slot} 接收循环异常: {e}")
863
+ finally:
864
+ _extra_ws.pop(slot, None)
865
+ _extra_ws_tasks.pop(slot, None)
866
+
867
+
868
+ async def _handle_connection_release(data):
869
+ """Kernel 请求释放 slot,优雅关闭。"""
870
+ for slot in data.get("slots", []):
871
+ ws = _extra_ws.pop(slot, None)
872
+ task = _extra_ws_tasks.pop(slot, None)
873
+ if ws:
874
+ try:
875
+ await ws.close(code=1000, reason="release")
876
+ except Exception:
877
+ pass
878
+ if task:
879
+ task.cancel()
880
+
881
+
643
882
  async def _handle_shutdown():
644
883
  """Handle module.shutdown event — ack → exiting → cleanup → ready → exit."""
645
884
  global _shutting_down
646
885
  print("[model_service] Received shutdown request")
647
886
  _shutting_down = True
648
887
  # Step 1: Send ack (立即确认收到)
649
- await _publish_event(_ws_global, {
650
- "event": "module.shutdown.ack",
651
- "data": {"module_id": "model_service"},
652
- })
888
+ await _publish_event(_ws_global, "module.shutdown.ack", {"module_id": "model_service"})
653
889
  # Step 2: Send module.exiting (开始清理)
654
- await _publish_event(_ws_global, {
655
- "event": "module.exiting",
656
- "data": {
657
- "module_id": "model_service",
658
- "type": "passive",
659
- "reason": "shutdown_requested",
660
- "restart": "auto",
661
- "action": "none",
662
- "timeout": 2.0,
663
- "restart_delay": 0.0,
664
- },
890
+ await _publish_event(_ws_global, "module.exiting", {
891
+ "module_id": "model_service",
892
+ "type": "passive",
893
+ "reason": "shutdown_requested",
894
+ "restart": "auto",
895
+ "action": "none",
896
+ "timeout": 2.0,
897
+ "restart_delay": 0.0,
665
898
  })
666
899
  # Step 3: Cleanup (nothing to clean up for model_service)
900
+ # 关闭所有附加连接
901
+ for _s, _w in list(_extra_ws.items()):
902
+ try:
903
+ await _w.close(code=1000, reason="shutdown")
904
+ except Exception:
905
+ pass
906
+ for _t in _extra_ws_tasks.values():
907
+ _t.cancel()
908
+ _extra_ws.clear()
909
+ _extra_ws_tasks.clear()
667
910
  # Step 4: Send ready (清理完成)
668
- await _publish_event(_ws_global, {
669
- "event": "module.shutdown.ready",
670
- "data": {"module_id": "model_service"},
671
- })
911
+ await _publish_event(_ws_global, "module.shutdown.ready", {"module_id": "model_service"})
672
912
  print("[model_service] Shutdown ready, exiting")
673
- # Step 5: Exit
674
- sys.exit(_exit_code)
913
+
914
+ # 等待 Kernel 处理 shutdown.ready(防止 Close 帧抢先)
915
+ await asyncio.sleep(0.1)
916
+
917
+ # Step 5: Close WebSocket connection gracefully
918
+ if _ws_global:
919
+ try:
920
+ await _ws_global.close(code=1000, reason="Graceful shutdown")
921
+ print("[model_service] WebSocket closed")
922
+ except Exception as e:
923
+ print(f"[model_service] Failed to close WebSocket: {e}")
924
+
925
+ # Note: Do NOT call sys.exit() in async context
926
+ # Let the event loop naturally complete
675
927
 
676
928
 
677
929
  async def _test_event_loop(ws):
678
930
  """Publish a test event every 10 seconds."""
679
- while True:
680
- await asyncio.sleep(10)
681
- await _publish_event(ws, {
682
- "event": "model_service.test",
683
- "data": {
931
+ try:
932
+ counter = 0
933
+ while True:
934
+ await asyncio.sleep(10)
935
+ counter += 1
936
+
937
+ await _publish_event(ws, "model_service.test", {
684
938
  "message": "test event from model_service",
685
939
  "timestamp": datetime.now(timezone.utc).isoformat(),
686
- },
687
- })
688
- print("[model_service] test event published")
940
+ })
941
+
942
+ # Redis 测试:每 3 次保存模型调用统计
943
+ if counter % 3 == 0:
944
+ try:
945
+ await _rpc_call(ws, "redis.hset", {
946
+ "key": "model_service:stats",
947
+ "field": "last_test",
948
+ "value": str(int(time.time()))
949
+ })
950
+ result = await _rpc_call(ws, "redis.hget", {
951
+ "key": "model_service:stats",
952
+ "field": "last_test"
953
+ })
954
+ if result:
955
+ value = result.get("result", {}).get("value")
956
+ print(f"[model_service] ✓ Redis 统计已更新: {value}")
957
+ except Exception as e:
958
+ print(f"[model_service] Redis 测试失败: {e}")
959
+ except Exception:
960
+ pass
961
+
962
+
963
+ _startup_config = {} # populated by _validate_and_prepare()
964
+
965
+
966
+ def _validate_and_prepare() -> dict:
967
+ """同步启动验证:日志初始化、读取 token 和 kernel_port。
968
+ 失败直接 sys.exit(1),成功返回启动参数。在 asyncio.run() 之前调用。"""
969
+ global _log_dir, _log_latest_path, _crash_log_path
970
+
971
+ t0 = time.monotonic()
972
+
973
+ # 优先级1:检查KITE_KERNEL_PORT(本地模式)
974
+ kernel_port = os.environ.get("KITE_KERNEL_PORT")
975
+
976
+ if kernel_port:
977
+ # 本地模式:从stdin读取boot_info
978
+ return _prepare_local_mode(int(kernel_port), t0)
979
+
980
+ # 优先级2:检查gateway_url(远程模式)
981
+ config = _load_module_config()
982
+ gateway_url = config.get("gateway_url") or os.environ.get("KITE_GATEWAY_URL")
983
+
984
+ if gateway_url:
985
+ # 远程模式
986
+ return _prepare_remote_mode(gateway_url, t0)
987
+
988
+ # 都没有 → 报错
989
+ print(f"[{MODULE_NAME}] ERROR: No KITE_KERNEL_PORT and no gateway_url in module.md")
990
+ sys.exit(1)
991
+
992
+
993
+ def _prepare_local_mode(kernel_port: int, t0: float) -> dict:
994
+ """本地模式启动准备"""
995
+ global _log_dir, _log_latest_path, _crash_log_path
996
+
997
+ module_data = os.environ.get("KITE_MODULE_DATA")
998
+ if module_data:
999
+ _log_dir = os.path.join(module_data, "log")
1000
+ os.makedirs(_log_dir, exist_ok=True)
1001
+ suffix = os.environ.get("KITE_INSTANCE_SUFFIX", "")
1002
+
1003
+ _log_latest_path = os.path.join(_log_dir, f"latest{suffix}.log")
1004
+ try:
1005
+ with open(_log_latest_path, "w", encoding="utf-8") as f:
1006
+ pass
1007
+ except Exception:
1008
+ _log_latest_path = None
1009
+
1010
+ _crash_log_path = os.path.join(_log_dir, f"crashes{suffix}.jsonl")
1011
+ try:
1012
+ with open(_crash_log_path, "w", encoding="utf-8") as f:
1013
+ pass
1014
+ except Exception:
1015
+ _crash_log_path = None
1016
+
1017
+ _resolve_daily_log_path()
1018
+
1019
+ _setup_exception_hooks()
1020
+
1021
+ # Read boot_info from stdin (only token)
1022
+ line = sys.stdin.readline().strip()
1023
+ if not line:
1024
+ print(f"[{MODULE_NAME}] ERROR: stdin closed")
1025
+ sys.exit(1)
1026
+
1027
+ try:
1028
+ msg = json.loads(line)
1029
+ except json.JSONDecodeError as e:
1030
+ print(f"[{MODULE_NAME}] ERROR: Invalid JSON from stdin: {e}")
1031
+ sys.exit(1)
1032
+
1033
+ if "error" in msg:
1034
+ print(f"[{MODULE_NAME}] 启动失败: {msg.get('message', 'unknown')}")
1035
+ sys.exit(1)
1036
+
1037
+ token = msg.get("token", "")
1038
+ if not token:
1039
+ print(f"[{MODULE_NAME}] ERROR: No token in stdin message")
1040
+ sys.exit(1)
1041
+
1042
+ print(f"[{MODULE_NAME}] Token received ({len(token)} chars), kernel port: {kernel_port} ({_fmt_elapsed(t0)})")
1043
+
1044
+ return {"mode": "local", "token": token, "kernel_port": kernel_port, "t0": t0}
1045
+
1046
+
1047
+ def _prepare_remote_mode(gateway_url: str, t0: float) -> dict:
1048
+ """远程模式启动准备"""
1049
+ global _log_dir, _log_latest_path, _crash_log_path
1050
+
1051
+ # 远程模式使用独立的数据目录
1052
+ home = os.environ.get("HOME") or os.environ.get("USERPROFILE") or os.path.expanduser("~")
1053
+ data_dir = os.path.join(home, ".kite", "remote", MODULE_NAME)
1054
+ os.makedirs(data_dir, exist_ok=True)
1055
+
1056
+ _log_dir = os.path.join(data_dir, "log")
1057
+ os.makedirs(_log_dir, exist_ok=True)
1058
+
1059
+ _log_latest_path = os.path.join(_log_dir, "latest.log")
1060
+ try:
1061
+ with open(_log_latest_path, "w", encoding="utf-8") as f:
1062
+ pass
1063
+ except Exception:
1064
+ _log_latest_path = None
1065
+
1066
+ _crash_log_path = os.path.join(_log_dir, "crashes.jsonl")
1067
+ try:
1068
+ with open(_crash_log_path, "w", encoding="utf-8") as f:
1069
+ pass
1070
+ except Exception:
1071
+ _crash_log_path = None
1072
+
1073
+ _resolve_daily_log_path()
1074
+ _setup_exception_hooks()
1075
+
1076
+ # 获取kite_token
1077
+ kite_token = _get_kite_token(MODULE_NAME, gateway_url)
1078
+
1079
+ print(f"[{MODULE_NAME}] Remote mode: gateway={gateway_url} ({_fmt_elapsed(t0)})")
1080
+
1081
+ return {"mode": "remote", "gateway_url": gateway_url, "kite_token": kite_token, "t0": t0}
1082
+
1083
+
1084
+ # ── 远程模式:连接循环 ──
1085
+
1086
+ async def _remote_mode_loop(gateway_url: str, kite_token: str, _t0: float):
1087
+ """通过 Gateway 连接到 Kernel(带重连)"""
1088
+ global _shutting_down, _exit_code
1089
+ retry_count = 0
1090
+ max_retries = 10
1091
+
1092
+ while not _shutting_down and retry_count < max_retries:
1093
+ try:
1094
+ await _remote_connect(gateway_url, kite_token, _t0)
1095
+ retry_count = 0 # 连接成功,重置计数
1096
+ except asyncio.CancelledError:
1097
+ break
1098
+ except Exception as e:
1099
+ if _shutting_down:
1100
+ break
1101
+ retry_count += 1
1102
+ backoff = min(2 ** retry_count, 60)
1103
+ print(f"[{MODULE_NAME}] Connection error: {e}, retrying in {backoff}s...")
1104
+ await asyncio.sleep(backoff)
1105
+
1106
+ if retry_count >= max_retries:
1107
+ print(f"[{MODULE_NAME}] Max retries reached, exiting")
1108
+ _exit_code = 1
1109
+
1110
+
1111
+ async def _remote_connect(gateway_url: str, kite_token: str, _t0: float):
1112
+ """单次 Gateway 连接"""
1113
+ global _ws_global
1114
+
1115
+ async with websockets.connect(gateway_url, open_timeout=10, ping_interval=30) as ws:
1116
+ # 1. 接收 challenge
1117
+ challenge = json.loads(await ws.recv())
1118
+ nonce = challenge["params"]["nonce"]
1119
+
1120
+ # 2. 发送 auth.connect
1121
+ auth_req = {
1122
+ "jsonrpc": "2.0",
1123
+ "id": "auth",
1124
+ "method": "auth.connect",
1125
+ "params": {
1126
+ "nonce": nonce,
1127
+ "module_id": MODULE_NAME,
1128
+ "auth": {"method": "kite_token", "token": kite_token},
1129
+ "client": {"type": "module", "platform": sys.platform}
1130
+ }
1131
+ }
1132
+ await ws.send(json.dumps(auth_req))
1133
+
1134
+ # 3. 等待 hello-ok
1135
+ hello_resp = json.loads(await ws.recv())
1136
+ if "error" in hello_resp:
1137
+ error = hello_resp["error"]
1138
+ # 认证失败 → 清除缓存
1139
+ if error.get("code") in (4001, 4010, 4011):
1140
+ _clear_token_cache(MODULE_NAME, gateway_url)
1141
+ print(f"[{MODULE_NAME}] Token invalid, please re-authenticate")
1142
+ sys.exit(1)
1143
+ raise Exception(f"Connection failed: {error}")
1144
+
1145
+ print(f"[{MODULE_NAME}] Connected via Gateway ({_fmt_elapsed(_t0)})")
1146
+ _ws_global = ws
1147
+
1148
+ # Start receiver task — wait for system.require_init to trigger _do_init
1149
+ receiver_task = asyncio.create_task(_ws_receiver(ws))
1150
+ try:
1151
+ await receiver_task
1152
+ finally:
1153
+ receiver_task.cancel()
1154
+ for fut in _pending_rpc.values():
1155
+ if not fut.done():
1156
+ fut.set_result({"error": {"code": -32001, "message": "Connection lost"}})
1157
+ _pending_rpc.clear()
689
1158
 
690
1159
 
691
1160
  if __name__ == "__main__":
1161
+ _startup_config = _validate_and_prepare()
692
1162
  asyncio.run(main())
1163
+ sys.exit(_exit_code)