myagent-ai 1.0.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 (486) hide show
  1. package/Dockerfile +30 -0
  2. package/README.md +333 -0
  3. package/agents/__init__.py +6 -0
  4. package/agents/__pycache__/main_agent.cpython-312.pyc +0 -0
  5. package/agents/base.py +115 -0
  6. package/agents/main_agent.py +695 -0
  7. package/agents/memory_agent.py +313 -0
  8. package/agents/tool_agent.py +248 -0
  9. package/chatbot/__init__.py +5 -0
  10. package/chatbot/base.py +124 -0
  11. package/chatbot/discord_bot.py +146 -0
  12. package/chatbot/feishu_bot.py +548 -0
  13. package/chatbot/manager.py +164 -0
  14. package/chatbot/qq_bot.py +189 -0
  15. package/chatbot/telegram_bot.py +167 -0
  16. package/chatbot/wechat_bot.py +558 -0
  17. package/communication/__init__.py +66 -0
  18. package/communication/channel.py +576 -0
  19. package/communication/crypto.py +347 -0
  20. package/communication/manager.py +397 -0
  21. package/communication/peer.py +156 -0
  22. package/config.py +464 -0
  23. package/core/__init__.py +10 -0
  24. package/core/config_broadcast.py +276 -0
  25. package/core/llm.py +878 -0
  26. package/core/logger.py +241 -0
  27. package/core/task_queue.py +362 -0
  28. package/core/utils.py +184 -0
  29. package/executor/__init__.py +4 -0
  30. package/executor/__pycache__/engine.cpython-312.pyc +0 -0
  31. package/executor/engine.py +1215 -0
  32. package/groups/__init__.py +15 -0
  33. package/groups/manager.py +724 -0
  34. package/knowledge/__init__.py +4 -0
  35. package/knowledge/rag.py +444 -0
  36. package/main.py +801 -0
  37. package/memory/__init__.py +4 -0
  38. package/memory/manager.py +840 -0
  39. package/organization/__init__.py +4 -0
  40. package/organization/manager.py +350 -0
  41. package/package.json +58 -0
  42. package/requirements.txt +59 -0
  43. package/setup.py +40 -0
  44. package/skills/ASR/LICENSE.txt +21 -0
  45. package/skills/ASR/SKILL.md +580 -0
  46. package/skills/ASR/scripts/asr.ts +27 -0
  47. package/skills/LLM/LICENSE.txt +21 -0
  48. package/skills/LLM/SKILL.md +856 -0
  49. package/skills/LLM/scripts/chat.ts +32 -0
  50. package/skills/TTS/LICENSE.txt +21 -0
  51. package/skills/TTS/SKILL.md +735 -0
  52. package/skills/TTS/tts.ts +25 -0
  53. package/skills/VLM/LICENSE.txt +21 -0
  54. package/skills/VLM/SKILL.md +588 -0
  55. package/skills/VLM/scripts/vlm.ts +57 -0
  56. package/skills/__init__.py +5 -0
  57. package/skills/agent-browser/SKILL.md +328 -0
  58. package/skills/ai-news-collectors/SKILL.md +157 -0
  59. package/skills/ai-news-collectors/_meta.json +6 -0
  60. package/skills/ai-news-collectors/references/sources.md +128 -0
  61. package/skills/aminer-open-academic/SKILL.md +312 -0
  62. package/skills/aminer-open-academic/_meta.json +6 -0
  63. package/skills/aminer-open-academic/evals/evals.json +46 -0
  64. package/skills/aminer-open-academic/references/api-catalog.md +1032 -0
  65. package/skills/aminer-open-academic/scripts/__pycache__/aminer_client.cpython-312.pyc +0 -0
  66. package/skills/aminer-open-academic/scripts/aminer_client.py +875 -0
  67. package/skills/auto-target-tracker/SKILL.md +317 -0
  68. package/skills/base.py +147 -0
  69. package/skills/blog-writer/2024-02-17-radical-transparency-sales.md +35 -0
  70. package/skills/blog-writer/2024-02-17-raycast-spotlight-superpowers.md +33 -0
  71. package/skills/blog-writer/2024-02-17-short-form-content-marketing.md +47 -0
  72. package/skills/blog-writer/2024-02-17-typing-speed-benefits.md +33 -0
  73. package/skills/blog-writer/2024-03-14-effective-ai-prompts.md +55 -0
  74. package/skills/blog-writer/2024-11-08-ai-revolutionizing-entry-level-sales.md +43 -0
  75. package/skills/blog-writer/2025-11-12-why-ai-art-is-useless.md +49 -0
  76. package/skills/blog-writer/README.md +2 -0
  77. package/skills/blog-writer/SKILL.md +158 -0
  78. package/skills/blog-writer/__pycache__/manage_examples.cpython-312.pyc +0 -0
  79. package/skills/blog-writer/_meta.json +6 -0
  80. package/skills/blog-writer/manage_examples.py +90 -0
  81. package/skills/blog-writer/style-guide.md +160 -0
  82. package/skills/browser_skill.py +146 -0
  83. package/skills/coding-agent/SKILL.md +120 -0
  84. package/skills/coding-agent/_meta.json +6 -0
  85. package/skills/coding-agent/criteria.md +48 -0
  86. package/skills/coding-agent/execution.md +42 -0
  87. package/skills/coding-agent/memory-template.md +38 -0
  88. package/skills/coding-agent/planning.md +31 -0
  89. package/skills/coding-agent/state.md +60 -0
  90. package/skills/coding-agent/verification.md +39 -0
  91. package/skills/content-strategy/SKILL.md +181 -0
  92. package/skills/content-strategy/_meta.json +6 -0
  93. package/skills/contentanalysis/ExtractWisdom/SKILL.md +229 -0
  94. package/skills/contentanalysis/ExtractWisdom/Workflows/Extract.md +60 -0
  95. package/skills/contentanalysis/SKILL.md +14 -0
  96. package/skills/docx/CHANGELOG.md +85 -0
  97. package/skills/docx/LICENSE.txt +30 -0
  98. package/skills/docx/SKILL.md +455 -0
  99. package/skills/docx/docx-js.md +681 -0
  100. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  101. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  102. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  103. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  104. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  105. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  106. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  107. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  108. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  109. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  110. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  111. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  112. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  113. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  114. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  115. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  116. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  117. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  118. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  119. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  120. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  121. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  122. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  123. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  124. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  125. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  126. package/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  127. package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  128. package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  129. package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  130. package/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  131. package/skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  132. package/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  133. package/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  134. package/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  135. package/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  136. package/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  137. package/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  138. package/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  139. package/skills/docx/ooxml/scripts/__pycache__/pack.cpython-312.pyc +0 -0
  140. package/skills/docx/ooxml/scripts/__pycache__/unpack.cpython-312.pyc +0 -0
  141. package/skills/docx/ooxml/scripts/__pycache__/validate.cpython-312.pyc +0 -0
  142. package/skills/docx/ooxml/scripts/pack.py +159 -0
  143. package/skills/docx/ooxml/scripts/unpack.py +29 -0
  144. package/skills/docx/ooxml/scripts/validate.py +69 -0
  145. package/skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  146. package/skills/docx/ooxml/scripts/validation/__pycache__/__init__.cpython-312.pyc +0 -0
  147. package/skills/docx/ooxml/scripts/validation/__pycache__/base.cpython-312.pyc +0 -0
  148. package/skills/docx/ooxml/scripts/validation/__pycache__/docx.cpython-312.pyc +0 -0
  149. package/skills/docx/ooxml/scripts/validation/__pycache__/pptx.cpython-312.pyc +0 -0
  150. package/skills/docx/ooxml/scripts/validation/__pycache__/redlining.cpython-312.pyc +0 -0
  151. package/skills/docx/ooxml/scripts/validation/base.py +951 -0
  152. package/skills/docx/ooxml/scripts/validation/docx.py +274 -0
  153. package/skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  154. package/skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  155. package/skills/docx/ooxml.md +615 -0
  156. package/skills/docx/scripts/__init__.py +1 -0
  157. package/skills/docx/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  158. package/skills/docx/scripts/__pycache__/add_toc_placeholders.cpython-312.pyc +0 -0
  159. package/skills/docx/scripts/__pycache__/document.cpython-312.pyc +0 -0
  160. package/skills/docx/scripts/__pycache__/utilities.cpython-312.pyc +0 -0
  161. package/skills/docx/scripts/add_toc_placeholders.py +220 -0
  162. package/skills/docx/scripts/document.py +1302 -0
  163. package/skills/docx/scripts/templates/comments.xml +3 -0
  164. package/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  165. package/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  166. package/skills/docx/scripts/templates/commentsIds.xml +3 -0
  167. package/skills/docx/scripts/templates/people.xml +3 -0
  168. package/skills/docx/scripts/utilities.py +374 -0
  169. package/skills/dream-interpreter/SKILL.md +88 -0
  170. package/skills/dream-interpreter/assets/example_asset.txt +24 -0
  171. package/skills/dream-interpreter/references/api_reference.md +34 -0
  172. package/skills/dream-interpreter/references/interpretation-guide.md +83 -0
  173. package/skills/dream-interpreter/references/output-schema.md +65 -0
  174. package/skills/dream-interpreter/references/questioning-strategy.md +62 -0
  175. package/skills/dream-interpreter/references/visual-mapping.md +81 -0
  176. package/skills/dream-interpreter/scripts/__pycache__/example.cpython-312.pyc +0 -0
  177. package/skills/dream-interpreter/scripts/example.py +19 -0
  178. package/skills/dream-interpreter/skill.json +7 -0
  179. package/skills/file_skill.py +246 -0
  180. package/skills/finance/Finance_API_Doc.md +445 -0
  181. package/skills/finance/SKILL.md +53 -0
  182. package/skills/fullstack-dev/SKILL.md +205 -0
  183. package/skills/get-fortune-analysis/SKILL.md +370 -0
  184. package/skills/get-fortune-analysis/lunar_python.py +91 -0
  185. package/skills/gift-evaluator/SKILL.md +83 -0
  186. package/skills/gift-evaluator/__pycache__/html_tools.cpython-312.pyc +0 -0
  187. package/skills/gift-evaluator/html_tools.py +268 -0
  188. package/skills/image-edit/LICENSE.txt +21 -0
  189. package/skills/image-edit/SKILL.md +896 -0
  190. package/skills/image-edit/scripts/image-edit.ts +36 -0
  191. package/skills/image-generation/LICENSE.txt +21 -0
  192. package/skills/image-generation/SKILL.md +583 -0
  193. package/skills/image-generation/scripts/image-generation.ts +28 -0
  194. package/skills/image-understand/LICENSE.txt +21 -0
  195. package/skills/image-understand/SKILL.md +855 -0
  196. package/skills/image-understand/scripts/image-understand.ts +41 -0
  197. package/skills/interview-designer/README.md +70 -0
  198. package/skills/interview-designer/SKILL.md +53 -0
  199. package/skills/interview-designer/_meta.json +6 -0
  200. package/skills/interview-designer/references/design_rationale.md +43 -0
  201. package/skills/interview-designer/templates/interview_guide_template.md +62 -0
  202. package/skills/market-research-reports/SKILL.md +901 -0
  203. package/skills/market-research-reports/assets/FORMATTING_GUIDE.md +428 -0
  204. package/skills/market-research-reports/assets/market_report_template.tex +1380 -0
  205. package/skills/market-research-reports/assets/market_research.sty +564 -0
  206. package/skills/market-research-reports/references/data_analysis_patterns.md +548 -0
  207. package/skills/market-research-reports/references/report_structure_guide.md +999 -0
  208. package/skills/market-research-reports/references/visual_generation_guide.md +1077 -0
  209. package/skills/market-research-reports/scripts/__pycache__/generate_market_visuals.cpython-312.pyc +0 -0
  210. package/skills/market-research-reports/scripts/generate_market_visuals.py +529 -0
  211. package/skills/marketing-mode/README.md +49 -0
  212. package/skills/marketing-mode/SKILL.md +693 -0
  213. package/skills/marketing-mode/_meta.json +6 -0
  214. package/skills/marketing-mode/mode-prompt.md +39 -0
  215. package/skills/marketing-mode/skill.json +51 -0
  216. package/skills/mindfulness-meditation/SKILL.md +65 -0
  217. package/skills/mindfulness-meditation/_meta.json +6 -0
  218. package/skills/multi-search-engine/CHANGELOG.md +15 -0
  219. package/skills/multi-search-engine/CHANNELLOG.md +48 -0
  220. package/skills/multi-search-engine/SKILL.md +78 -0
  221. package/skills/multi-search-engine/_meta.json +6 -0
  222. package/skills/multi-search-engine/config.json +14 -0
  223. package/skills/multi-search-engine/metadata.json +7 -0
  224. package/skills/multi-search-engine/references/international-search.md +651 -0
  225. package/skills/pdf/LICENSE.txt +30 -0
  226. package/skills/pdf/SKILL.md +1534 -0
  227. package/skills/pdf/forms.md +205 -0
  228. package/skills/pdf/reference.md +765 -0
  229. package/skills/pdf/scripts/__pycache__/add_zai_metadata.cpython-312.pyc +0 -0
  230. package/skills/pdf/scripts/__pycache__/check_bounding_boxes.cpython-312.pyc +0 -0
  231. package/skills/pdf/scripts/__pycache__/check_bounding_boxes_test.cpython-312.pyc +0 -0
  232. package/skills/pdf/scripts/__pycache__/check_fillable_fields.cpython-312.pyc +0 -0
  233. package/skills/pdf/scripts/__pycache__/convert_pdf_to_images.cpython-312.pyc +0 -0
  234. package/skills/pdf/scripts/__pycache__/create_validation_image.cpython-312.pyc +0 -0
  235. package/skills/pdf/scripts/__pycache__/extract_form_field_info.cpython-312.pyc +0 -0
  236. package/skills/pdf/scripts/__pycache__/fill_fillable_fields.cpython-312.pyc +0 -0
  237. package/skills/pdf/scripts/__pycache__/fill_pdf_form_with_annotations.cpython-312.pyc +0 -0
  238. package/skills/pdf/scripts/__pycache__/sanitize_code.cpython-312.pyc +0 -0
  239. package/skills/pdf/scripts/add_zai_metadata.py +172 -0
  240. package/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  241. package/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  242. package/skills/pdf/scripts/check_fillable_fields.py +12 -0
  243. package/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  244. package/skills/pdf/scripts/create_validation_image.py +41 -0
  245. package/skills/pdf/scripts/extract_form_field_info.py +152 -0
  246. package/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  247. package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  248. package/skills/pdf/scripts/sanitize_code.py +110 -0
  249. package/skills/podcast-generate/LICENSE.txt +21 -0
  250. package/skills/podcast-generate/SKILL.md +198 -0
  251. package/skills/podcast-generate/generate.ts +661 -0
  252. package/skills/podcast-generate/package.json +30 -0
  253. package/skills/podcast-generate/readme.md +177 -0
  254. package/skills/podcast-generate/test_data/segments.jsonl +3 -0
  255. package/skills/podcast-generate/tsconfig.json +26 -0
  256. package/skills/pptx/LICENSE.txt +30 -0
  257. package/skills/pptx/SKILL.md +507 -0
  258. package/skills/pptx/html2pptx.md +625 -0
  259. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  260. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  261. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  262. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  263. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  264. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  265. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  266. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  267. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  268. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  269. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  270. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  271. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  272. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  273. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  274. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  275. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  276. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  277. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  278. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  279. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  280. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  281. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  282. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  283. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  284. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  285. package/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  286. package/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  287. package/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  288. package/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  289. package/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  290. package/skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  291. package/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  292. package/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  293. package/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  294. package/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  295. package/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  296. package/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  297. package/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  298. package/skills/pptx/ooxml/scripts/__pycache__/pack.cpython-312.pyc +0 -0
  299. package/skills/pptx/ooxml/scripts/__pycache__/unpack.cpython-312.pyc +0 -0
  300. package/skills/pptx/ooxml/scripts/__pycache__/validate.cpython-312.pyc +0 -0
  301. package/skills/pptx/ooxml/scripts/pack.py +159 -0
  302. package/skills/pptx/ooxml/scripts/unpack.py +29 -0
  303. package/skills/pptx/ooxml/scripts/validate.py +69 -0
  304. package/skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  305. package/skills/pptx/ooxml/scripts/validation/__pycache__/__init__.cpython-312.pyc +0 -0
  306. package/skills/pptx/ooxml/scripts/validation/__pycache__/base.cpython-312.pyc +0 -0
  307. package/skills/pptx/ooxml/scripts/validation/__pycache__/docx.cpython-312.pyc +0 -0
  308. package/skills/pptx/ooxml/scripts/validation/__pycache__/pptx.cpython-312.pyc +0 -0
  309. package/skills/pptx/ooxml/scripts/validation/__pycache__/redlining.cpython-312.pyc +0 -0
  310. package/skills/pptx/ooxml/scripts/validation/base.py +951 -0
  311. package/skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  312. package/skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  313. package/skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  314. package/skills/pptx/ooxml.md +427 -0
  315. package/skills/pptx/scripts/__pycache__/inventory.cpython-312.pyc +0 -0
  316. package/skills/pptx/scripts/__pycache__/inventory.cpython-313.pyc +0 -0
  317. package/skills/pptx/scripts/__pycache__/rearrange.cpython-312.pyc +0 -0
  318. package/skills/pptx/scripts/__pycache__/replace.cpython-312.pyc +0 -0
  319. package/skills/pptx/scripts/__pycache__/thumbnail.cpython-312.pyc +0 -0
  320. package/skills/pptx/scripts/html2pptx.js +1044 -0
  321. package/skills/pptx/scripts/inventory.py +1020 -0
  322. package/skills/pptx/scripts/rearrange.py +231 -0
  323. package/skills/pptx/scripts/replace.py +385 -0
  324. package/skills/pptx/scripts/thumbnail.py +450 -0
  325. package/skills/qingyan-research/SKILL.md +294 -0
  326. package/skills/qingyan-research/__pycache__/generate_html.cpython-312.pyc +0 -0
  327. package/skills/qingyan-research/generate_html.py +33 -0
  328. package/skills/registry.py +344 -0
  329. package/skills/search_skill.py +228 -0
  330. package/skills/seo-content-writer/SKILL.md +661 -0
  331. package/skills/seo-content-writer/_meta.json +6 -0
  332. package/skills/seo-content-writer/references/content-structure-templates.md +875 -0
  333. package/skills/seo-content-writer/references/title-formulas.md +339 -0
  334. package/skills/skill-creator/LICENSE.txt +202 -0
  335. package/skills/skill-creator/SKILL.md +485 -0
  336. package/skills/skill-creator/agents/analyzer.md +274 -0
  337. package/skills/skill-creator/agents/comparator.md +202 -0
  338. package/skills/skill-creator/agents/grader.md +223 -0
  339. package/skills/skill-creator/assets/eval_review.html +146 -0
  340. package/skills/skill-creator/eval-viewer/__pycache__/generate_review.cpython-312.pyc +0 -0
  341. package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  342. package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  343. package/skills/skill-creator/references/schemas.md +430 -0
  344. package/skills/skill-creator/scripts/__init__.py +0 -0
  345. package/skills/skill-creator/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  346. package/skills/skill-creator/scripts/__pycache__/aggregate_benchmark.cpython-312.pyc +0 -0
  347. package/skills/skill-creator/scripts/__pycache__/generate_report.cpython-312.pyc +0 -0
  348. package/skills/skill-creator/scripts/__pycache__/improve_description.cpython-312.pyc +0 -0
  349. package/skills/skill-creator/scripts/__pycache__/package_skill.cpython-312.pyc +0 -0
  350. package/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  351. package/skills/skill-creator/scripts/__pycache__/run_eval.cpython-312.pyc +0 -0
  352. package/skills/skill-creator/scripts/__pycache__/run_loop.cpython-312.pyc +0 -0
  353. package/skills/skill-creator/scripts/__pycache__/utils.cpython-312.pyc +0 -0
  354. package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  355. package/skills/skill-creator/scripts/generate_report.py +326 -0
  356. package/skills/skill-creator/scripts/improve_description.py +236 -0
  357. package/skills/skill-creator/scripts/package_skill.py +136 -0
  358. package/skills/skill-creator/scripts/quick_validate.py +103 -0
  359. package/skills/skill-creator/scripts/run_eval.py +310 -0
  360. package/skills/skill-creator/scripts/run_loop.py +328 -0
  361. package/skills/skill-creator/scripts/utils.py +47 -0
  362. package/skills/skill-finder-cn/SKILL.md +66 -0
  363. package/skills/skill-finder-cn/_meta.json +6 -0
  364. package/skills/skill-finder-cn/package.json +5 -0
  365. package/skills/skill-finder-cn/scripts/search.sh +15 -0
  366. package/skills/skill-vetter/SKILL.md +137 -0
  367. package/skills/stock-analysis-skill/SKILL.md +156 -0
  368. package/skills/stock-analysis-skill/package.json +21 -0
  369. package/skills/stock-analysis-skill/src/analyzer.ts +264 -0
  370. package/skills/stock-analysis-skill/src/dataFetcher.ts +130 -0
  371. package/skills/stock-analysis-skill/src/dividend.ts +226 -0
  372. package/skills/stock-analysis-skill/src/index.ts +327 -0
  373. package/skills/stock-analysis-skill/src/rumorScanner.ts +200 -0
  374. package/skills/stock-analysis-skill/src/types.ts +167 -0
  375. package/skills/stock-analysis-skill/src/watchlist.ts +292 -0
  376. package/skills/stock-analysis-skill/tsconfig.json +15 -0
  377. package/skills/storyboard-manager/SKILL.md +532 -0
  378. package/skills/storyboard-manager/index.js +9 -0
  379. package/skills/storyboard-manager/package.json +11 -0
  380. package/skills/storyboard-manager/references/character_development.md +232 -0
  381. package/skills/storyboard-manager/references/story_structures.md +148 -0
  382. package/skills/storyboard-manager/scripts/__pycache__/consistency_checker.cpython-312.pyc +0 -0
  383. package/skills/storyboard-manager/scripts/__pycache__/timeline_tracker.cpython-312.pyc +0 -0
  384. package/skills/storyboard-manager/scripts/consistency_checker.py +391 -0
  385. package/skills/storyboard-manager/scripts/timeline_tracker.py +352 -0
  386. package/skills/system_skill.py +249 -0
  387. package/skills/ui-ux-pro-max/SKILL.md +43 -0
  388. package/skills/ui-ux-pro-max/_meta.json +6 -0
  389. package/skills/ui-ux-pro-max/assets/data/charts.csv +26 -0
  390. package/skills/ui-ux-pro-max/assets/data/colors.csv +97 -0
  391. package/skills/ui-ux-pro-max/assets/data/icons.csv +101 -0
  392. package/skills/ui-ux-pro-max/assets/data/landing.csv +31 -0
  393. package/skills/ui-ux-pro-max/assets/data/products.csv +97 -0
  394. package/skills/ui-ux-pro-max/assets/data/react-performance.csv +45 -0
  395. package/skills/ui-ux-pro-max/assets/data/stacks/astro.csv +54 -0
  396. package/skills/ui-ux-pro-max/assets/data/stacks/flutter.csv +53 -0
  397. package/skills/ui-ux-pro-max/assets/data/stacks/html-tailwind.csv +56 -0
  398. package/skills/ui-ux-pro-max/assets/data/stacks/jetpack-compose.csv +53 -0
  399. package/skills/ui-ux-pro-max/assets/data/stacks/nextjs.csv +53 -0
  400. package/skills/ui-ux-pro-max/assets/data/stacks/nuxt-ui.csv +51 -0
  401. package/skills/ui-ux-pro-max/assets/data/stacks/nuxtjs.csv +59 -0
  402. package/skills/ui-ux-pro-max/assets/data/stacks/react-native.csv +52 -0
  403. package/skills/ui-ux-pro-max/assets/data/stacks/react.csv +54 -0
  404. package/skills/ui-ux-pro-max/assets/data/stacks/shadcn.csv +61 -0
  405. package/skills/ui-ux-pro-max/assets/data/stacks/svelte.csv +54 -0
  406. package/skills/ui-ux-pro-max/assets/data/stacks/swiftui.csv +51 -0
  407. package/skills/ui-ux-pro-max/assets/data/stacks/vue.csv +50 -0
  408. package/skills/ui-ux-pro-max/assets/data/styles.csv +68 -0
  409. package/skills/ui-ux-pro-max/assets/data/typography.csv +58 -0
  410. package/skills/ui-ux-pro-max/assets/data/ui-reasoning.csv +101 -0
  411. package/skills/ui-ux-pro-max/assets/data/ux-guidelines.csv +100 -0
  412. package/skills/ui-ux-pro-max/assets/data/web-interface.csv +31 -0
  413. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  414. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  415. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  416. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  417. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  418. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  419. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  420. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  421. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  422. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  423. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  424. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  425. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  426. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  427. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  428. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  429. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  430. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  431. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  432. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  433. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  434. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  435. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  436. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  437. package/skills/ui-ux-pro-max/references/upstream-README.md +488 -0
  438. package/skills/ui-ux-pro-max/references/upstream-skill-content.md +288 -0
  439. package/skills/ui-ux-pro-max/scripts/__init__.py +0 -0
  440. package/skills/ui-ux-pro-max/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  441. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  442. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  443. package/skills/ui-ux-pro-max/scripts/__pycache__/search.cpython-312.pyc +0 -0
  444. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  445. package/skills/ui-ux-pro-max/scripts/design_system.py +1071 -0
  446. package/skills/ui-ux-pro-max/scripts/search.py +111 -0
  447. package/skills/video-generation/LICENSE.txt +21 -0
  448. package/skills/video-generation/SKILL.md +1082 -0
  449. package/skills/video-generation/scripts/video.ts +168 -0
  450. package/skills/video-understand/LICENSE.txt +21 -0
  451. package/skills/video-understand/SKILL.md +916 -0
  452. package/skills/video-understand/scripts/video-understand.ts +41 -0
  453. package/skills/visual-design-foundations/SKILL.md +318 -0
  454. package/skills/visual-design-foundations/references/color-systems.md +417 -0
  455. package/skills/visual-design-foundations/references/spacing-iconography.md +425 -0
  456. package/skills/visual-design-foundations/references/typography-systems.md +432 -0
  457. package/skills/web-reader/LICENSE.txt +21 -0
  458. package/skills/web-reader/SKILL.md +1140 -0
  459. package/skills/web-reader/scripts/web-reader.ts +37 -0
  460. package/skills/web-search/LICENSE.txt +21 -0
  461. package/skills/web-search/SKILL.md +912 -0
  462. package/skills/web-search/scripts/web_search.ts +44 -0
  463. package/skills/web-shader-extractor/SKILL.md +145 -0
  464. package/skills/web-shader-extractor/references/config-extraction.md +50 -0
  465. package/skills/web-shader-extractor/references/encoded-definitions.md +53 -0
  466. package/skills/web-shader-extractor/references/extraction-workflow.md +61 -0
  467. package/skills/web-shader-extractor/references/porting-strategy.md +164 -0
  468. package/skills/web-shader-extractor/references/shader-injection.md +126 -0
  469. package/skills/web-shader-extractor/references/shaders-com.md +190 -0
  470. package/skills/web-shader-extractor/references/tech-signatures.md +54 -0
  471. package/skills/web-shader-extractor/references/tsl-extraction.md +41 -0
  472. package/skills/web-shader-extractor/references/unicorn-studio.md +353 -0
  473. package/skills/web-shader-extractor/scripts/fetch-rendered-dom.mjs +153 -0
  474. package/skills/web-shader-extractor/scripts/scan-bundle.sh +76 -0
  475. package/skills/writing-plans/SKILL.md +116 -0
  476. package/skills/writing-plans/_meta.json +6 -0
  477. package/skills/xlsx/LICENSE.txt +30 -0
  478. package/skills/xlsx/SKILL.md +496 -0
  479. package/skills/xlsx/__pycache__/recalc.cpython-312.pyc +0 -0
  480. package/skills/xlsx/recalc.py +178 -0
  481. package/start.sh +36 -0
  482. package/web/__init__.py +1 -0
  483. package/web/__pycache__/api_server.cpython-312.pyc +0 -0
  484. package/web/api_server.py +2043 -0
  485. package/web/ui/chat.html +3235 -0
  486. package/web/ui/index.html +458 -0
@@ -0,0 +1,397 @@
1
+ """
2
+ communication/manager.py - Communication Manager
3
+ ================================================
4
+ Central manager for agent-to-agent encrypted communication.
5
+ Orchestrates crypto keys, peer store, local/remote channels, and offline queue.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import logging
11
+ import time
12
+ from pathlib import Path
13
+ from typing import Optional, List, Callable, Awaitable
14
+
15
+ from .crypto import (
16
+ generate_ed25519_keypair,
17
+ generate_agent_id,
18
+ serialize_public_key,
19
+ serialize_private_key,
20
+ deserialize_public_key,
21
+ deserialize_private_key,
22
+ decrypt_message,
23
+ verify,
24
+ generate_x25519_keypair,
25
+ x25519_key_exchange,
26
+ derive_shared_key,
27
+ )
28
+ from .peer import Peer, PeerStore
29
+ from .channel import (
30
+ Message,
31
+ MessageCallback,
32
+ LocalChannel,
33
+ RemoteChannel,
34
+ )
35
+
36
+ logger = logging.getLogger("myagent.communication")
37
+
38
+
39
+ class CommunicationManager:
40
+ """
41
+ Manages all aspects of agent-to-agent encrypted communication.
42
+
43
+ Responsibilities:
44
+ - Initialize/load Ed25519 identity keys
45
+ - Manage the peer store (add/remove/list)
46
+ - Run local channel (same-machine messaging)
47
+ - Run remote channel (cross-machine via AICQ WebSocket)
48
+ - Route incoming messages to registered callbacks
49
+ - Offline message queue with automatic retry
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ config,
55
+ data_dir: str | Path = "",
56
+ ):
57
+ """
58
+ Args:
59
+ config: A ``CommunicationConfig`` dataclass instance.
60
+ data_dir: Base data directory for persistent storage.
61
+ """
62
+ self.config = config
63
+ self._data_dir = Path(data_dir) if data_dir else Path.home() / ".myagent" / "data"
64
+
65
+ # Identity keys (Ed25519)
66
+ self._ed_priv: bytes = b""
67
+ self._ed_pub: bytes = b""
68
+ self.agent_id: str = ""
69
+
70
+ # DH keys (X25519, standalone from Ed25519)
71
+ self._x_priv: bytes = b""
72
+ self._x_pub: bytes = b""
73
+
74
+ # Components
75
+ self._peer_store: Optional[PeerStore] = None
76
+ self._local_channel: Optional[LocalChannel] = None
77
+ self._remote_channel: Optional[RemoteChannel] = None
78
+
79
+ # State
80
+ self._running = False
81
+ self._message_callbacks: List[MessageCallback] = []
82
+ self._received_messages: List[Message] = [] # In-memory recent messages
83
+ self._max_stored_messages = 500
84
+
85
+ # Paths
86
+ self._peers_path = self._data_dir / "communication" / "peers.json"
87
+ self._queue_db_path = self._data_dir / "communication" / "message_queue.db"
88
+
89
+ # ==================================================================
90
+ # Initialization
91
+ # ==================================================================
92
+
93
+ def initialize(self):
94
+ """Load or generate identity keys, initialize peer store."""
95
+ # Ensure directories
96
+ self._peers_path.parent.mkdir(parents=True, exist_ok=True)
97
+ self._queue_db_path.parent.mkdir(parents=True, exist_ok=True)
98
+
99
+ # Load or generate Ed25519 identity keys
100
+ if self.config.agent_id and self.config.private_key:
101
+ self._ed_priv = deserialize_private_key(self.config.private_key)
102
+ self._ed_pub = deserialize_public_key(self.config.agent_id)
103
+ self.agent_id = generate_agent_id(self._ed_pub)
104
+ else:
105
+ self._ed_priv, self._ed_pub = generate_ed25519_keypair()
106
+ self.agent_id = generate_agent_id(self._ed_pub)
107
+ self.config.agent_id = serialize_public_key(self._ed_pub)
108
+ self.config.private_key = serialize_private_key(self._ed_priv)
109
+ logger.info(f"CommunicationManager: generated new identity, agent_id={self.agent_id}")
110
+
111
+ # Generate standalone X25519 keypair for DH
112
+ self._x_priv, self._x_pub = generate_x25519_keypair()
113
+
114
+ # Initialize peer store
115
+ self._peer_store = PeerStore(self._peers_path)
116
+
117
+ logger.info(
118
+ f"CommunicationManager initialized: agent_id={self.agent_id}, "
119
+ f"peers={self._peer_store.peer_count()}, "
120
+ f"has_crypto={True}"
121
+ )
122
+
123
+ async def start(self):
124
+ """Start communication channels (must be called from async context)."""
125
+ if not self.config.enabled:
126
+ logger.info("CommunicationManager: disabled by config")
127
+ return
128
+
129
+ if self._running:
130
+ return
131
+
132
+ self._running = True
133
+
134
+ # Initialize local channel
135
+ LocalChannel.register_agent(self.agent_id)
136
+ self._local_channel = LocalChannel(
137
+ agent_id=self.agent_id,
138
+ ed25519_private_key=self._ed_priv,
139
+ ed25519_public_key=self._ed_pub,
140
+ )
141
+ self._local_channel.on_message(self._on_local_message)
142
+ self._local_channel.start()
143
+
144
+ # Initialize remote channel if server URL configured
145
+ if self.config.server_url:
146
+ self._remote_channel = RemoteChannel(
147
+ agent_id=self.agent_id,
148
+ ed25519_private_key=self._ed_priv,
149
+ ed25519_public_key=self._ed_pub,
150
+ server_url=self.config.server_url,
151
+ queue_db_path=str(self._queue_db_path),
152
+ )
153
+ self._remote_channel.on_message(self._on_remote_message)
154
+ self._remote_channel.start()
155
+
156
+ logger.info("CommunicationManager started")
157
+
158
+ async def stop(self):
159
+ """Stop all communication channels."""
160
+ self._running = False
161
+ if self._local_channel:
162
+ await self._local_channel.stop()
163
+ if self._remote_channel:
164
+ await self._remote_channel.stop()
165
+ logger.info("CommunicationManager stopped")
166
+
167
+ # ==================================================================
168
+ # Message Handlers
169
+ # ==================================================================
170
+
171
+ async def _on_local_message(self, msg: Message):
172
+ """Handle a message received via LocalChannel."""
173
+ await self._dispatch_message(msg)
174
+
175
+ async def _on_remote_message(self, msg: Message):
176
+ """Handle a message received via RemoteChannel."""
177
+ # If encrypted, attempt to decrypt
178
+ if msg.encrypted and msg.from_agent:
179
+ peer = self._peer_store.get_peer(msg.from_agent) if self._peer_store else None
180
+ if peer and peer.public_key:
181
+ try:
182
+ # Use the peer's stored X25519 public key for decryption
183
+ their_x_pub_hex = peer.permissions.get("x25519_public_key", "")
184
+ if their_x_pub_hex:
185
+ their_x_pub = bytes.fromhex(their_x_pub_hex)
186
+ shared = x25519_key_exchange(self._x_priv, their_x_pub)
187
+ shared_key = derive_shared_key(shared)
188
+ payload = decrypt_message(shared_key, msg.content)
189
+ their_ed_pub = deserialize_public_key(peer.public_key)
190
+ if payload.get("signature"):
191
+ sig = bytes.fromhex(payload["signature"])
192
+ if verify(their_ed_pub, msg.content.encode("utf-8"), sig):
193
+ msg.content = payload.get("content", msg.content)
194
+ msg.encrypted = False
195
+ else:
196
+ logger.warning(f"Remote message from {msg.from_agent}: signature verification failed")
197
+ else:
198
+ msg.content = payload.get("content", msg.content)
199
+ msg.encrypted = False
200
+ else:
201
+ logger.debug(f"No X25519 key for peer {msg.from_agent}, cannot decrypt")
202
+ except Exception as e:
203
+ logger.warning(f"Remote message decrypt failed: {e}")
204
+
205
+ await self._dispatch_message(msg)
206
+
207
+ async def _dispatch_message(self, msg: Message):
208
+ """Store message and dispatch to callbacks."""
209
+ # Store in memory
210
+ self._received_messages.append(msg)
211
+ if len(self._received_messages) > self._max_stored_messages:
212
+ self._received_messages = self._received_messages[-self._max_stored_messages:]
213
+
214
+ # Notify callbacks
215
+ for cb in self._message_callbacks:
216
+ try:
217
+ await cb(msg)
218
+ except Exception as e:
219
+ logger.error(f"Message callback error: {e}", exc_info=True)
220
+
221
+ # ==================================================================
222
+ # Send Message
223
+ # ==================================================================
224
+
225
+ async def send_message(
226
+ self,
227
+ to_agent: str,
228
+ content: str,
229
+ msg_type: str = "text",
230
+ ) -> Message:
231
+ """
232
+ Send an encrypted message to another agent.
233
+
234
+ Args:
235
+ to_agent: Recipient agent ID.
236
+ content: Plaintext message content.
237
+ msg_type: Message type (text, heartbeat, ack, etc.)
238
+
239
+ Returns:
240
+ The sent Message object.
241
+
242
+ Raises:
243
+ RuntimeError: If the peer is not found.
244
+ """
245
+ if not self._running or not self.config.enabled:
246
+ raise RuntimeError("Communication is not enabled")
247
+
248
+ peer = self._peer_store.get_peer(to_agent) if self._peer_store else None
249
+ if not peer:
250
+ raise RuntimeError(f"Peer '{to_agent}' not found")
251
+
252
+ their_pub = deserialize_public_key(peer.public_key)
253
+
254
+ # Try local first, then remote
255
+ msg = None
256
+ # Check if the peer is on this machine (has a local queue)
257
+ if to_agent in LocalChannel._queues:
258
+ msg = await self._local_channel.send(
259
+ to_agent=to_agent,
260
+ content=content,
261
+ msg_type=msg_type,
262
+ their_public_key=their_pub,
263
+ )
264
+ elif self._remote_channel:
265
+ their_x_pub_hex = peer.permissions.get("x25519_public_key", "")
266
+ msg = await self._remote_channel.send(
267
+ to_agent=to_agent,
268
+ content=content,
269
+ their_ed_pub_hex=peer.public_key,
270
+ their_x25519_pub_hex=their_x_pub_hex,
271
+ msg_type=msg_type,
272
+ )
273
+ else:
274
+ # No channel available — queue locally
275
+ msg = Message(
276
+ from_agent=self.agent_id,
277
+ to_agent=to_agent,
278
+ content=content,
279
+ msg_type=msg_type,
280
+ )
281
+ # Store in offline queue manually
282
+ import json
283
+ wire = json.dumps({
284
+ "type": msg_type,
285
+ "from": msg.from_agent,
286
+ "to": msg.to_agent,
287
+ "content": content,
288
+ "encrypted": False,
289
+ "timestamp": msg.timestamp,
290
+ "msg_id": msg.id,
291
+ })
292
+ if self._remote_channel:
293
+ self._remote_channel._queue_message(msg.from_agent, msg.to_agent, wire)
294
+
295
+ return msg
296
+
297
+ # ==================================================================
298
+ # Peer Management
299
+ # ==================================================================
300
+
301
+ def add_peer(
302
+ self,
303
+ agent_id: str,
304
+ public_key: str,
305
+ display_name: str = "",
306
+ ) -> bool:
307
+ """
308
+ Add a known peer.
309
+
310
+ Args:
311
+ agent_id: The peer's short agent ID (or full hex public key).
312
+ public_key: The peer's Ed25519 public key in hex.
313
+ display_name: Optional human-readable name.
314
+
315
+ Returns:
316
+ True if added, False if already exists.
317
+ """
318
+ if not self._peer_store:
319
+ return False
320
+
321
+ peer = Peer(
322
+ agent_id=agent_id,
323
+ public_key=public_key,
324
+ display_name=display_name or agent_id,
325
+ added_at=time.time(),
326
+ )
327
+ return self._peer_store.add_peer(peer)
328
+
329
+ def remove_peer(self, agent_id: str) -> bool:
330
+ """Remove a peer by agent_id."""
331
+ if not self._peer_store:
332
+ return False
333
+ return self._peer_store.remove_peer(agent_id)
334
+
335
+ def get_peer(self, agent_id: str) -> Optional[Peer]:
336
+ """Get a peer by agent_id."""
337
+ if not self._peer_store:
338
+ return None
339
+ return self._peer_store.get_peer(agent_id)
340
+
341
+ def get_peer_list(self) -> List[Peer]:
342
+ """Return all known peers."""
343
+ if not self._peer_store:
344
+ return []
345
+ return self._peer_store.list_peers()
346
+
347
+ # ==================================================================
348
+ # Message History
349
+ # ==================================================================
350
+
351
+ def get_messages(
352
+ self,
353
+ limit: int = 50,
354
+ from_agent: str = "",
355
+ to_agent: str = "",
356
+ ) -> List[dict]:
357
+ """Get recent received messages with optional filtering."""
358
+ msgs = list(self._received_messages)
359
+ if from_agent:
360
+ msgs = [m for m in msgs if m.from_agent == from_agent]
361
+ if to_agent:
362
+ msgs = [m for m in msgs if m.to_agent == to_agent]
363
+ msgs = msgs[-limit:]
364
+ return [m.to_dict() for m in msgs]
365
+
366
+ # ==================================================================
367
+ # Callbacks
368
+ # ==================================================================
369
+
370
+ def on_message(self, callback: MessageCallback):
371
+ """Register a callback for incoming messages."""
372
+ self._message_callbacks.append(callback)
373
+
374
+ # ==================================================================
375
+ # Status
376
+ # ==================================================================
377
+
378
+ def get_status(self) -> dict:
379
+ """Return current communication status."""
380
+ remote_connected = False
381
+ if self._remote_channel:
382
+ remote_connected = self._remote_channel._connected
383
+
384
+ return {
385
+ "enabled": self.config.enabled,
386
+ "running": self._running,
387
+ "agent_id": self.agent_id,
388
+ "public_key": serialize_public_key(self._ed_pub) if self._ed_pub else "",
389
+ "x25519_public_key": self._x_pub.hex() if self._x_pub else "",
390
+ "peers_count": self._peer_store.peer_count() if self._peer_store else 0,
391
+ "online_peers": len(self._peer_store.get_online_peers()) if self._peer_store else 0,
392
+ "remote_connected": remote_connected,
393
+ "server_url": self.config.server_url,
394
+ "local_channel": self._local_channel is not None,
395
+ "remote_channel": self._remote_channel is not None,
396
+ "messages_received": len(self._received_messages),
397
+ }
@@ -0,0 +1,156 @@
1
+ """
2
+ communication/peer.py - Peer Management
3
+ ========================================
4
+ Manages known peers (other agents) with persistent JSON storage.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import time
10
+ from dataclasses import dataclass, field, asdict
11
+ from pathlib import Path
12
+ from typing import Optional, List, Dict
13
+
14
+
15
+ @dataclass
16
+ class Peer:
17
+ """Represents a known remote/local agent peer."""
18
+
19
+ agent_id: str # Short hex ID (16 chars)
20
+ public_key: str # Ed25519 public key (hex, 64 chars)
21
+ display_name: str = "" # Human-readable name
22
+ added_at: float = 0.0 # Unix timestamp
23
+ permissions: Dict[str, bool] = field(default_factory=lambda: {
24
+ "send_messages": True,
25
+ "receive_messages": True,
26
+ })
27
+ last_seen: float = 0.0 # Last online timestamp
28
+ online: bool = False # Current online status
29
+
30
+ def to_dict(self) -> dict:
31
+ return {
32
+ "agent_id": self.agent_id,
33
+ "public_key": self.public_key,
34
+ "display_name": self.display_name,
35
+ "added_at": self.added_at,
36
+ "permissions": self.permissions,
37
+ "last_seen": self.last_seen,
38
+ "online": self.online,
39
+ }
40
+
41
+ @classmethod
42
+ def from_dict(cls, data: dict) -> "Peer":
43
+ return cls(
44
+ agent_id=data.get("agent_id", ""),
45
+ public_key=data.get("public_key", ""),
46
+ display_name=data.get("display_name", ""),
47
+ added_at=data.get("added_at", 0.0),
48
+ permissions=data.get("permissions", {
49
+ "send_messages": True,
50
+ "receive_messages": True,
51
+ }),
52
+ last_seen=data.get("last_seen", 0.0),
53
+ online=data.get("online", False),
54
+ )
55
+
56
+
57
+ class PeerStore:
58
+ """Persistent store for known peers backed by a JSON file."""
59
+
60
+ def __init__(self, store_path: str | Path):
61
+ self._path = Path(store_path)
62
+ self._peers: Dict[str, Peer] = {}
63
+ self._load()
64
+
65
+ # ------------------------------------------------------------------
66
+ # Persistence
67
+ # ------------------------------------------------------------------
68
+
69
+ def _load(self):
70
+ """Load peers from disk."""
71
+ if not self._path.exists():
72
+ return
73
+ try:
74
+ data = json.loads(self._path.read_text(encoding="utf-8"))
75
+ for peer_data in data.get("peers", []):
76
+ p = Peer.from_dict(peer_data)
77
+ if p.agent_id:
78
+ self._peers[p.agent_id] = p
79
+ except (json.JSONDecodeError, IOError) as e:
80
+ # Corrupt file — start fresh
81
+ self._peers = {}
82
+
83
+ def _save(self):
84
+ """Save peers to disk."""
85
+ if self._path.suffix:
86
+ # Path is a file (e.g., /tmp/peers.json)
87
+ self._path.parent.mkdir(parents=True, exist_ok=True)
88
+ else:
89
+ # Path is a directory, use peers.json inside
90
+ self._path.mkdir(parents=True, exist_ok=True)
91
+ self._path = self._path / "peers.json"
92
+ data = {
93
+ "peers": [p.to_dict() for p in self._peers.values()],
94
+ "updated_at": time.time(),
95
+ }
96
+ self._path.write_text(
97
+ json.dumps(data, indent=2, ensure_ascii=False),
98
+ encoding="utf-8",
99
+ )
100
+
101
+ # ------------------------------------------------------------------
102
+ # CRUD
103
+ # ------------------------------------------------------------------
104
+
105
+ def add_peer(self, peer: Peer) -> bool:
106
+ """Add a peer. Returns False if already exists."""
107
+ if peer.agent_id in self._peers:
108
+ return False
109
+ if peer.added_at == 0.0:
110
+ peer.added_at = time.time()
111
+ self._peers[peer.agent_id] = peer
112
+ self._save()
113
+ return True
114
+
115
+ def remove_peer(self, agent_id: str) -> bool:
116
+ """Remove a peer by agent_id. Returns False if not found."""
117
+ if agent_id not in self._peers:
118
+ return False
119
+ del self._peers[agent_id]
120
+ self._save()
121
+ return True
122
+
123
+ def get_peer(self, agent_id: str) -> Optional[Peer]:
124
+ """Get a peer by agent_id."""
125
+ return self._peers.get(agent_id)
126
+
127
+ def update_peer(self, agent_id: str, **fields) -> bool:
128
+ """Update fields on an existing peer. Returns False if not found."""
129
+ peer = self._peers.get(agent_id)
130
+ if not peer:
131
+ return False
132
+ for k, v in fields.items():
133
+ if hasattr(peer, k):
134
+ setattr(peer, k, v)
135
+ self._save()
136
+ return True
137
+
138
+ def list_peers(self) -> List[Peer]:
139
+ """Return all peers."""
140
+ return list(self._peers.values())
141
+
142
+ def peer_count(self) -> int:
143
+ """Return the number of stored peers."""
144
+ return len(self._peers)
145
+
146
+ def set_online(self, agent_id: str, online: bool):
147
+ """Mark a peer as online/offline."""
148
+ if agent_id in self._peers:
149
+ self._peers[agent_id].online = online
150
+ if online:
151
+ self._peers[agent_id].last_seen = time.time()
152
+ self._save()
153
+
154
+ def get_online_peers(self) -> List[Peer]:
155
+ """Return peers currently marked as online."""
156
+ return [p for p in self._peers.values() if p.online]