@jack200714/mafw 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/.opencode/mafw/.backup-v61/parametric/base-skill-manifest.yaml +2 -0
  2. package/.opencode/mafw/STATUS.md +6 -0
  3. package/.opencode/mafw/ledger.md +20 -0
  4. package/.opencode/mafw/memory/.harmonic_index.json +28 -0
  5. package/.opencode/mafw/memory/.review_queue.json +1 -0
  6. package/.opencode/mafw/memory/tier3/parametric.json +13 -0
  7. package/.opencode/mafw/memory/tier3/test-goal.json +19 -0
  8. package/.opencode/mafw/memory-index.json +6 -0
  9. package/.opencode/mafw/parametric/base-skill-manifest.yaml +2 -0
  10. package/.opencode/mafw/waves.json +4 -0
  11. package/.opencode/opencode.json +3 -0
  12. package/.opencode/plugins/mafw-plugin.ts +8 -0
  13. package/.opencode/skills/banner-design/SKILL.md +196 -0
  14. package/.opencode/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
  15. package/.opencode/skills/brand/SKILL.md +97 -0
  16. package/.opencode/skills/brand/references/approval-checklist.md +169 -0
  17. package/.opencode/skills/brand/references/asset-organization.md +157 -0
  18. package/.opencode/skills/brand/references/brand-guideline-template.md +140 -0
  19. package/.opencode/skills/brand/references/color-palette-management.md +186 -0
  20. package/.opencode/skills/brand/references/consistency-checklist.md +94 -0
  21. package/.opencode/skills/brand/references/logo-usage-rules.md +185 -0
  22. package/.opencode/skills/brand/references/messaging-framework.md +85 -0
  23. package/.opencode/skills/brand/references/typography-specifications.md +214 -0
  24. package/.opencode/skills/brand/references/update.md +118 -0
  25. package/.opencode/skills/brand/references/visual-identity.md +96 -0
  26. package/.opencode/skills/brand/references/voice-framework.md +88 -0
  27. package/.opencode/skills/brand/scripts/extract-colors.cjs +341 -0
  28. package/.opencode/skills/brand/scripts/inject-brand-context.cjs +349 -0
  29. package/.opencode/skills/brand/scripts/sync-brand-to-tokens.cjs +248 -0
  30. package/.opencode/skills/brand/scripts/tests/test_sync_brand_to_tokens.py +52 -0
  31. package/.opencode/skills/brand/scripts/validate-asset.cjs +387 -0
  32. package/.opencode/skills/brand/templates/brand-guidelines-starter.md +275 -0
  33. package/.opencode/skills/design/SKILL.md +313 -0
  34. package/.opencode/skills/design/data/cip/deliverables.csv +51 -0
  35. package/.opencode/skills/design/data/cip/industries.csv +21 -0
  36. package/.opencode/skills/design/data/cip/mockup-contexts.csv +21 -0
  37. package/.opencode/skills/design/data/cip/styles.csv +21 -0
  38. package/.opencode/skills/design/data/icon/styles.csv +16 -0
  39. package/.opencode/skills/design/data/logo/colors.csv +56 -0
  40. package/.opencode/skills/design/data/logo/industries.csv +56 -0
  41. package/.opencode/skills/design/data/logo/styles.csv +56 -0
  42. package/.opencode/skills/design/references/banner-sizes-and-styles.md +118 -0
  43. package/.opencode/skills/design/references/cip-deliverable-guide.md +95 -0
  44. package/.opencode/skills/design/references/cip-design.md +121 -0
  45. package/.opencode/skills/design/references/cip-prompt-engineering.md +84 -0
  46. package/.opencode/skills/design/references/cip-style-guide.md +68 -0
  47. package/.opencode/skills/design/references/design-routing.md +207 -0
  48. package/.opencode/skills/design/references/icon-design.md +122 -0
  49. package/.opencode/skills/design/references/logo-color-psychology.md +101 -0
  50. package/.opencode/skills/design/references/logo-design.md +92 -0
  51. package/.opencode/skills/design/references/logo-prompt-engineering.md +158 -0
  52. package/.opencode/skills/design/references/logo-style-guide.md +109 -0
  53. package/.opencode/skills/design/references/slides-copywriting-formulas.md +84 -0
  54. package/.opencode/skills/design/references/slides-create.md +4 -0
  55. package/.opencode/skills/design/references/slides-html-template.md +295 -0
  56. package/.opencode/skills/design/references/slides-layout-patterns.md +137 -0
  57. package/.opencode/skills/design/references/slides-strategies.md +94 -0
  58. package/.opencode/skills/design/references/slides.md +42 -0
  59. package/.opencode/skills/design/references/social-photos-design.md +329 -0
  60. package/.opencode/skills/design/scripts/cip/core.py +215 -0
  61. package/.opencode/skills/design/scripts/cip/generate.py +484 -0
  62. package/.opencode/skills/design/scripts/cip/render-html.py +424 -0
  63. package/.opencode/skills/design/scripts/cip/search.py +127 -0
  64. package/.opencode/skills/design/scripts/icon/generate.py +487 -0
  65. package/.opencode/skills/design/scripts/logo/core.py +175 -0
  66. package/.opencode/skills/design/scripts/logo/generate.py +362 -0
  67. package/.opencode/skills/design/scripts/logo/search.py +114 -0
  68. package/.opencode/skills/design-system/SKILL.md +244 -0
  69. package/.opencode/skills/design-system/data/slide-backgrounds.csv +11 -0
  70. package/.opencode/skills/design-system/data/slide-charts.csv +26 -0
  71. package/.opencode/skills/design-system/data/slide-color-logic.csv +14 -0
  72. package/.opencode/skills/design-system/data/slide-copy.csv +26 -0
  73. package/.opencode/skills/design-system/data/slide-layout-logic.csv +16 -0
  74. package/.opencode/skills/design-system/data/slide-layouts.csv +26 -0
  75. package/.opencode/skills/design-system/data/slide-strategies.csv +16 -0
  76. package/.opencode/skills/design-system/data/slide-typography.csv +15 -0
  77. package/.opencode/skills/design-system/references/component-specs.md +236 -0
  78. package/.opencode/skills/design-system/references/component-tokens.md +214 -0
  79. package/.opencode/skills/design-system/references/primitive-tokens.md +203 -0
  80. package/.opencode/skills/design-system/references/semantic-tokens.md +215 -0
  81. package/.opencode/skills/design-system/references/states-and-variants.md +241 -0
  82. package/.opencode/skills/design-system/references/tailwind-integration.md +251 -0
  83. package/.opencode/skills/design-system/references/token-architecture.md +224 -0
  84. package/.opencode/skills/design-system/scripts/embed-tokens.cjs +99 -0
  85. package/.opencode/skills/design-system/scripts/fetch-background.py +317 -0
  86. package/.opencode/skills/design-system/scripts/generate-slide.py +770 -0
  87. package/.opencode/skills/design-system/scripts/generate-tokens.cjs +205 -0
  88. package/.opencode/skills/design-system/scripts/html-token-validator.py +327 -0
  89. package/.opencode/skills/design-system/scripts/search-slides.py +218 -0
  90. package/.opencode/skills/design-system/scripts/slide-token-validator.py +35 -0
  91. package/.opencode/skills/design-system/scripts/slide_search_core.py +453 -0
  92. package/.opencode/skills/design-system/scripts/tests/test_validate_tokens.py +48 -0
  93. package/.opencode/skills/design-system/scripts/validate-tokens.cjs +246 -0
  94. package/.opencode/skills/design-system/templates/design-tokens-starter.json +143 -0
  95. package/.opencode/skills/frontend-design/LICENSE.txt +21 -0
  96. package/.opencode/skills/frontend-design/SKILL.md +115 -0
  97. package/.opencode/skills/mafw-automation-interview/SKILL.md +43 -0
  98. package/.opencode/skills/mafw-cli-scanner/SKILL.md +37 -0
  99. package/.opencode/skills/mafw-compression-verifier/SKILL.md +52 -0
  100. package/.opencode/skills/mafw-desktop-inspector/SKILL.md +170 -0
  101. package/.opencode/skills/mafw-execute/SKILL.md +62 -0
  102. package/.opencode/skills/mafw-gateway-restart/SKILL.md +87 -0
  103. package/.opencode/skills/mafw-github-scanner/SKILL.md +38 -0
  104. package/.opencode/skills/mafw-goal/SKILL.md +76 -0
  105. package/.opencode/skills/mafw-interview/SKILL.md +68 -0
  106. package/.opencode/skills/mafw-memory-extractor/SKILL.md +65 -0
  107. package/.opencode/skills/mafw-plan/SKILL.md +58 -0
  108. package/.opencode/skills/mafw-review/SKILL.md +85 -0
  109. package/.opencode/skills/runtime-plugin-authoring/SKILL.md +791 -0
  110. package/.opencode/skills/slides/SKILL.md +40 -0
  111. package/.opencode/skills/slides/references/copywriting-formulas.md +84 -0
  112. package/.opencode/skills/slides/references/create.md +4 -0
  113. package/.opencode/skills/slides/references/html-template.md +295 -0
  114. package/.opencode/skills/slides/references/layout-patterns.md +137 -0
  115. package/.opencode/skills/slides/references/slide-strategies.md +94 -0
  116. package/.opencode/skills/ui-styling/LICENSE.txt +202 -0
  117. package/.opencode/skills/ui-styling/SKILL.md +324 -0
  118. package/.opencode/skills/ui-styling/references/canvas-design-system.md +320 -0
  119. package/.opencode/skills/ui-styling/references/shadcn-accessibility.md +471 -0
  120. package/.opencode/skills/ui-styling/references/shadcn-components.md +424 -0
  121. package/.opencode/skills/ui-styling/references/shadcn-theming.md +373 -0
  122. package/.opencode/skills/ui-styling/references/tailwind-customization.md +483 -0
  123. package/.opencode/skills/ui-styling/references/tailwind-responsive.md +382 -0
  124. package/.opencode/skills/ui-styling/references/tailwind-utilities.md +455 -0
  125. package/.opencode/skills/ui-styling/scripts/requirements.txt +17 -0
  126. package/.opencode/skills/ui-styling/scripts/shadcn_add.py +308 -0
  127. package/.opencode/skills/ui-styling/scripts/tailwind_config_gen.py +473 -0
  128. package/.opencode/skills/ui-styling/scripts/tests/coverage-ui.json +1 -0
  129. package/.opencode/skills/ui-styling/scripts/tests/requirements.txt +3 -0
  130. package/.opencode/skills/ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  131. package/.opencode/skills/ui-styling/scripts/tests/test_tailwind_config_gen.py +394 -0
  132. package/.opencode/skills/ui-ux-pro-max/SKILL.md +388 -0
  133. package/.opencode/skills/ui-ux-pro-max/data/app-interface.csv +31 -0
  134. package/.opencode/skills/ui-ux-pro-max/data/charts.csv +26 -0
  135. package/.opencode/skills/ui-ux-pro-max/data/colors.csv +193 -0
  136. package/.opencode/skills/ui-ux-pro-max/data/google-fonts.csv +1924 -0
  137. package/.opencode/skills/ui-ux-pro-max/data/icons.csv +106 -0
  138. package/.opencode/skills/ui-ux-pro-max/data/landing.csv +35 -0
  139. package/.opencode/skills/ui-ux-pro-max/data/motion.csv +17 -0
  140. package/.opencode/skills/ui-ux-pro-max/data/products.csv +193 -0
  141. package/.opencode/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  142. package/.opencode/skills/ui-ux-pro-max/data/stacks/angular.csv +51 -0
  143. package/.opencode/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  144. package/.opencode/skills/ui-ux-pro-max/data/stacks/avalonia.csv +57 -0
  145. package/.opencode/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  146. package/.opencode/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  147. package/.opencode/skills/ui-ux-pro-max/data/stacks/javafx.csv +76 -0
  148. package/.opencode/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  149. package/.opencode/skills/ui-ux-pro-max/data/stacks/laravel.csv +51 -0
  150. package/.opencode/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  151. package/.opencode/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +71 -0
  152. package/.opencode/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  153. package/.opencode/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  154. package/.opencode/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  155. package/.opencode/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  156. package/.opencode/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  157. package/.opencode/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  158. package/.opencode/skills/ui-ux-pro-max/data/stacks/threejs.csv +54 -0
  159. package/.opencode/skills/ui-ux-pro-max/data/stacks/uno.csv +60 -0
  160. package/.opencode/skills/ui-ux-pro-max/data/stacks/uwp.csv +56 -0
  161. package/.opencode/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  162. package/.opencode/skills/ui-ux-pro-max/data/stacks/winui.csv +60 -0
  163. package/.opencode/skills/ui-ux-pro-max/data/stacks/wpf.csv +57 -0
  164. package/.opencode/skills/ui-ux-pro-max/data/styles.csv +85 -0
  165. package/.opencode/skills/ui-ux-pro-max/data/typography.csv +75 -0
  166. package/.opencode/skills/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
  167. package/.opencode/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  168. package/.opencode/skills/ui-ux-pro-max/scripts/core.py +464 -0
  169. package/.opencode/skills/ui-ux-pro-max/scripts/design_system.py +1479 -0
  170. package/.opencode/skills/ui-ux-pro-max/scripts/search.py +162 -0
  171. package/.opencode/skills/ui-ux-pro-max/scripts/tests/test_core.py +134 -0
  172. package/.opencode/skills/ui-ux-pro-max/scripts/tests/test_design_system_mode.py +159 -0
  173. package/.opencode/skills/ui-ux-pro-max/scripts/validate_data.py +114 -0
  174. package/LICENSE +21 -0
  175. package/README.md +199 -0
  176. package/bin/mafw.js +436 -0
  177. package/dist/hooks/bash-python-guide.d.ts +4 -0
  178. package/dist/hooks/bash-python-guide.d.ts.map +1 -0
  179. package/dist/hooks/bash-python-guide.js +67 -0
  180. package/dist/hooks/bash-python-guide.js.map +1 -0
  181. package/dist/hooks/handoff.d.ts +9 -0
  182. package/dist/hooks/handoff.d.ts.map +1 -0
  183. package/dist/hooks/handoff.js +8 -0
  184. package/dist/hooks/handoff.js.map +1 -0
  185. package/dist/hooks/hook-manager.d.ts +32 -0
  186. package/dist/hooks/hook-manager.d.ts.map +1 -0
  187. package/dist/hooks/hook-manager.js +91 -0
  188. package/dist/hooks/hook-manager.js.map +1 -0
  189. package/dist/hooks/llm-after.d.ts +8 -0
  190. package/dist/hooks/llm-after.d.ts.map +1 -0
  191. package/dist/hooks/llm-after.js +8 -0
  192. package/dist/hooks/llm-after.js.map +1 -0
  193. package/dist/hooks/media-ingest.d.ts +43 -0
  194. package/dist/hooks/media-ingest.d.ts.map +1 -0
  195. package/dist/hooks/media-ingest.js +269 -0
  196. package/dist/hooks/media-ingest.js.map +1 -0
  197. package/dist/hooks/memory-guide.d.ts +3 -0
  198. package/dist/hooks/memory-guide.d.ts.map +1 -0
  199. package/dist/hooks/memory-guide.js +47 -0
  200. package/dist/hooks/memory-guide.js.map +1 -0
  201. package/dist/hooks/observation-capture.d.ts +17 -0
  202. package/dist/hooks/observation-capture.d.ts.map +1 -0
  203. package/dist/hooks/observation-capture.js +20 -0
  204. package/dist/hooks/observation-capture.js.map +1 -0
  205. package/dist/hooks/session-compacting.d.ts +6 -0
  206. package/dist/hooks/session-compacting.d.ts.map +1 -0
  207. package/dist/hooks/session-compacting.js +6 -0
  208. package/dist/hooks/session-compacting.js.map +1 -0
  209. package/dist/hooks/session-ending.d.ts +20 -0
  210. package/dist/hooks/session-ending.d.ts.map +1 -0
  211. package/dist/hooks/session-ending.js +113 -0
  212. package/dist/hooks/session-ending.js.map +1 -0
  213. package/dist/hooks/session-recall.d.ts +2 -0
  214. package/dist/hooks/session-recall.d.ts.map +1 -0
  215. package/dist/hooks/session-recall.js +103 -0
  216. package/dist/hooks/session-recall.js.map +1 -0
  217. package/dist/hooks/session-start.d.ts +9 -0
  218. package/dist/hooks/session-start.d.ts.map +1 -0
  219. package/dist/hooks/session-start.js +42 -0
  220. package/dist/hooks/session-start.js.map +1 -0
  221. package/dist/hooks/tool-before.d.ts +10 -0
  222. package/dist/hooks/tool-before.d.ts.map +1 -0
  223. package/dist/hooks/tool-before.js +6 -0
  224. package/dist/hooks/tool-before.js.map +1 -0
  225. package/dist/hooks/tool-executed.d.ts +19 -0
  226. package/dist/hooks/tool-executed.d.ts.map +1 -0
  227. package/dist/hooks/tool-executed.js +12 -0
  228. package/dist/hooks/tool-executed.js.map +1 -0
  229. package/dist/hooks/user-profile.d.ts +2 -0
  230. package/dist/hooks/user-profile.d.ts.map +1 -0
  231. package/dist/hooks/user-profile.js +30 -0
  232. package/dist/hooks/user-profile.js.map +1 -0
  233. package/dist/hooks/user-prompt.d.ts +9 -0
  234. package/dist/hooks/user-prompt.d.ts.map +1 -0
  235. package/dist/hooks/user-prompt.js +8 -0
  236. package/dist/hooks/user-prompt.js.map +1 -0
  237. package/dist/hooks/voice-guide.d.ts +8 -0
  238. package/dist/hooks/voice-guide.d.ts.map +1 -0
  239. package/dist/hooks/voice-guide.js +101 -0
  240. package/dist/hooks/voice-guide.js.map +1 -0
  241. package/dist/plugin.d.ts +55 -0
  242. package/dist/plugin.d.ts.map +1 -0
  243. package/dist/plugin.js +342 -0
  244. package/dist/plugin.js.map +1 -0
  245. package/dist/tools/add-memory.d.ts +17 -0
  246. package/dist/tools/add-memory.d.ts.map +1 -0
  247. package/dist/tools/add-memory.js +60 -0
  248. package/dist/tools/add-memory.js.map +1 -0
  249. package/dist/tools/media-ask.d.ts +14 -0
  250. package/dist/tools/media-ask.d.ts.map +1 -0
  251. package/dist/tools/media-ask.js +224 -0
  252. package/dist/tools/media-ask.js.map +1 -0
  253. package/dist/tools/media-speak.d.ts +16 -0
  254. package/dist/tools/media-speak.d.ts.map +1 -0
  255. package/dist/tools/media-speak.js +78 -0
  256. package/dist/tools/media-speak.js.map +1 -0
  257. package/dist/tools/media-upload.d.ts +14 -0
  258. package/dist/tools/media-upload.d.ts.map +1 -0
  259. package/dist/tools/media-upload.js +155 -0
  260. package/dist/tools/media-upload.js.map +1 -0
  261. package/dist/tools/python-exec.d.ts +13 -0
  262. package/dist/tools/python-exec.d.ts.map +1 -0
  263. package/dist/tools/python-exec.js +99 -0
  264. package/dist/tools/python-exec.js.map +1 -0
  265. package/dist/tools/python-restart.d.ts +11 -0
  266. package/dist/tools/python-restart.d.ts.map +1 -0
  267. package/dist/tools/python-restart.js +33 -0
  268. package/dist/tools/python-restart.js.map +1 -0
  269. package/dist/utils/circuit-breaker.d.ts +23 -0
  270. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  271. package/dist/utils/circuit-breaker.js +75 -0
  272. package/dist/utils/circuit-breaker.js.map +1 -0
  273. package/dist/utils/config-loader.d.ts +20 -0
  274. package/dist/utils/config-loader.d.ts.map +1 -0
  275. package/dist/utils/config-loader.js +194 -0
  276. package/dist/utils/config-loader.js.map +1 -0
  277. package/dist/utils/fallback.d.ts +7 -0
  278. package/dist/utils/fallback.d.ts.map +1 -0
  279. package/dist/utils/fallback.js +20 -0
  280. package/dist/utils/fallback.js.map +1 -0
  281. package/dist/utils/git.d.ts +24 -0
  282. package/dist/utils/git.d.ts.map +1 -0
  283. package/dist/utils/git.js +71 -0
  284. package/dist/utils/git.js.map +1 -0
  285. package/dist/utils/github.d.ts +37 -0
  286. package/dist/utils/github.d.ts.map +1 -0
  287. package/dist/utils/github.js +53 -0
  288. package/dist/utils/github.js.map +1 -0
  289. package/dist/utils/global-path.d.ts +2 -0
  290. package/dist/utils/global-path.d.ts.map +1 -0
  291. package/dist/utils/global-path.js +32 -0
  292. package/dist/utils/global-path.js.map +1 -0
  293. package/dist/utils/logger.d.ts +6 -0
  294. package/dist/utils/logger.d.ts.map +1 -0
  295. package/dist/utils/logger.js +69 -0
  296. package/dist/utils/logger.js.map +1 -0
  297. package/dist/utils/obs-capture.d.ts +7 -0
  298. package/dist/utils/obs-capture.d.ts.map +1 -0
  299. package/dist/utils/obs-capture.js +49 -0
  300. package/dist/utils/obs-capture.js.map +1 -0
  301. package/dist/utils/retry.d.ts +11 -0
  302. package/dist/utils/retry.d.ts.map +1 -0
  303. package/dist/utils/retry.js +45 -0
  304. package/dist/utils/retry.js.map +1 -0
  305. package/dist/utils/self-wiring.d.ts +13 -0
  306. package/dist/utils/self-wiring.d.ts.map +1 -0
  307. package/dist/utils/self-wiring.js +86 -0
  308. package/dist/utils/self-wiring.js.map +1 -0
  309. package/dist/utils/state.d.ts +106 -0
  310. package/dist/utils/state.d.ts.map +1 -0
  311. package/dist/utils/state.js +166 -0
  312. package/dist/utils/state.js.map +1 -0
  313. package/dist/utils/status.d.ts +47 -0
  314. package/dist/utils/status.d.ts.map +1 -0
  315. package/dist/utils/status.js +147 -0
  316. package/dist/utils/status.js.map +1 -0
  317. package/dist/utils/ttl-map.d.ts +17 -0
  318. package/dist/utils/ttl-map.d.ts.map +1 -0
  319. package/dist/utils/ttl-map.js +67 -0
  320. package/dist/utils/ttl-map.js.map +1 -0
  321. package/gateway/dist/automation-engine.js +729 -0
  322. package/gateway/dist/chat/chat-sessions.js +95 -0
  323. package/gateway/dist/chat/graph-runner.js +76 -0
  324. package/gateway/dist/chat/index.js +7 -0
  325. package/gateway/dist/chat/intent-classifier.js +23 -0
  326. package/gateway/dist/config.js +416 -0
  327. package/gateway/dist/core/auth.js +96 -0
  328. package/gateway/dist/core/budget-guard.js +52 -0
  329. package/gateway/dist/core/compression/bm25-index.js +176 -0
  330. package/gateway/dist/core/compression/compression-pipeline.js +157 -0
  331. package/gateway/dist/core/compression/compression-strategy-selector.js +32 -0
  332. package/gateway/dist/core/compression/compression-verifier.js +79 -0
  333. package/gateway/dist/core/compression/diff-compressor.js +69 -0
  334. package/gateway/dist/core/compression/hybrid-compressor.js +104 -0
  335. package/gateway/dist/core/compression/lesson-compactor.js +114 -0
  336. package/gateway/dist/core/compression/memory-index.js +190 -0
  337. package/gateway/dist/core/compression/observation-classifier.js +41 -0
  338. package/gateway/dist/core/compression/observation-deduplicator.js +43 -0
  339. package/gateway/dist/core/compression/rrf-fusion.js +63 -0
  340. package/gateway/dist/core/compression/session-pruner.js +137 -0
  341. package/gateway/dist/core/compression/token-budget-allocator.js +141 -0
  342. package/gateway/dist/core/compression/vector-index.js +117 -0
  343. package/gateway/dist/core/compression/zero-token-compressor.js +80 -0
  344. package/gateway/dist/core/cost/cognitive-router.js +41 -0
  345. package/gateway/dist/core/cost/cost-estimator.js +63 -0
  346. package/gateway/dist/core/cost/types.js +19 -0
  347. package/gateway/dist/core/engine/degradation.js +159 -0
  348. package/gateway/dist/core/engine/goal-worktree-manager.js +131 -0
  349. package/gateway/dist/core/engine/lesson-manager.js +222 -0
  350. package/gateway/dist/core/engine/optimistic-sync.js +100 -0
  351. package/gateway/dist/core/engine/phase-orchestrator.js +153 -0
  352. package/gateway/dist/core/engine/report-generator.js +131 -0
  353. package/gateway/dist/core/engine/state-lock.js +91 -0
  354. package/gateway/dist/core/engine/task-branch-manager.js +102 -0
  355. package/gateway/dist/core/engine/wave-dependency.js +67 -0
  356. package/gateway/dist/core/engine/wave-executor.js +112 -0
  357. package/gateway/dist/core/goal-budget.js +63 -0
  358. package/gateway/dist/core/graph/entity-extractor.js +53 -0
  359. package/gateway/dist/core/graph/graph-searcher.js +120 -0
  360. package/gateway/dist/core/graph/knowledge-graph-manager.js +138 -0
  361. package/gateway/dist/core/graph/relation-inferencer.js +67 -0
  362. package/gateway/dist/core/graph/types.js +2 -0
  363. package/gateway/dist/core/hooks/handoff.js +7 -0
  364. package/gateway/dist/core/hooks/hook-manager.js +91 -0
  365. package/gateway/dist/core/hooks/llm-after.js +7 -0
  366. package/gateway/dist/core/hooks/observation-capture.js +19 -0
  367. package/gateway/dist/core/hooks/session-compacting.js +5 -0
  368. package/gateway/dist/core/hooks/session-ending.js +123 -0
  369. package/gateway/dist/core/hooks/session-start.js +51 -0
  370. package/gateway/dist/core/hooks/tool-before.js +5 -0
  371. package/gateway/dist/core/hooks/tool-executed.js +11 -0
  372. package/gateway/dist/core/hooks/user-prompt.js +7 -0
  373. package/gateway/dist/core/index.js +119 -0
  374. package/gateway/dist/core/langchain/agent-adapter.js +39 -0
  375. package/gateway/dist/core/langchain/index.js +12 -0
  376. package/gateway/dist/core/langchain/memory.js +35 -0
  377. package/gateway/dist/core/langchain/node-runner.js +115 -0
  378. package/gateway/dist/core/langchain/retriever.js +28 -0
  379. package/gateway/dist/core/langgraph/checkpointer.js +200 -0
  380. package/gateway/dist/core/langgraph/graph.js +57 -0
  381. package/gateway/dist/core/langgraph/index.js +25 -0
  382. package/gateway/dist/core/langgraph/loop-state.js +71 -0
  383. package/gateway/dist/core/langgraph/nodes/archive.node.js +27 -0
  384. package/gateway/dist/core/langgraph/nodes/execute.node.js +5 -0
  385. package/gateway/dist/core/langgraph/nodes/plan.node.js +101 -0
  386. package/gateway/dist/core/langgraph/nodes/review.node.js +89 -0
  387. package/gateway/dist/core/langgraph/nodes/sync.node.js +70 -0
  388. package/gateway/dist/core/langgraph/review-parser.js +35 -0
  389. package/gateway/dist/core/langgraph/signature-detector.js +23 -0
  390. package/gateway/dist/core/manager/goal-snapshot.js +73 -0
  391. package/gateway/dist/core/manager/milestone-push.js +81 -0
  392. package/gateway/dist/core/manager/question-ledger.js +121 -0
  393. package/gateway/dist/core/manager/system-rule-templates.js +76 -0
  394. package/gateway/dist/core/mcp/tools.js +562 -0
  395. package/gateway/dist/core/mcp/validator.js +165 -0
  396. package/gateway/dist/core/mcp-server.js +86 -0
  397. package/gateway/dist/core/memory/abstraction-distiller.js +44 -0
  398. package/gateway/dist/core/memory/cognitive-graph.js +103 -0
  399. package/gateway/dist/core/memory/energy-system.js +69 -0
  400. package/gateway/dist/core/memory/extractor.js +164 -0
  401. package/gateway/dist/core/memory/harmonic-index.js +530 -0
  402. package/gateway/dist/core/memory/harmonic-types.js +6 -0
  403. package/gateway/dist/core/memory/injector.js +111 -0
  404. package/gateway/dist/core/memory/l5-store.js +141 -0
  405. package/gateway/dist/core/memory/matcher.js +66 -0
  406. package/gateway/dist/core/memory/merger.js +95 -0
  407. package/gateway/dist/core/memory/migrate-v6.1.js +133 -0
  408. package/gateway/dist/core/memory/minhash-merger.js +195 -0
  409. package/gateway/dist/core/memory/observation-service.js +87 -0
  410. package/gateway/dist/core/memory/privacy-filter.js +163 -0
  411. package/gateway/dist/core/memory/reranker.js +208 -0
  412. package/gateway/dist/core/memory/review-scheduler.js +100 -0
  413. package/gateway/dist/core/memory/salience-perceptor.js +24 -0
  414. package/gateway/dist/core/memory/store.js +284 -0
  415. package/gateway/dist/core/memory/t1-store.js +183 -0
  416. package/gateway/dist/core/memory/t1-to-t2-compressor.js +119 -0
  417. package/gateway/dist/core/memory/validator.js +66 -0
  418. package/gateway/dist/core/plugin.js +902 -0
  419. package/gateway/dist/core/skills/mafw-execute/entry.js +226 -0
  420. package/gateway/dist/core/skills/mafw-goal/entry.js +203 -0
  421. package/gateway/dist/core/skills/mafw-plan/entry.js +184 -0
  422. package/gateway/dist/core/skills/mafw-review/entry.js +200 -0
  423. package/gateway/dist/core/storage/file-storage.js +120 -0
  424. package/gateway/dist/core/storage/sqlite-storage.js +205 -0
  425. package/gateway/dist/core/storage/types.js +2 -0
  426. package/gateway/dist/core/tools/archive-worktree.js +208 -0
  427. package/gateway/dist/core/tools/remote-cli.js +106 -0
  428. package/gateway/dist/core/tools/run-ask-user.js +79 -0
  429. package/gateway/dist/core/tools/run-execute-wave.js +32 -0
  430. package/gateway/dist/core/tools/run-plan.js +42 -0
  431. package/gateway/dist/core/tools/run-record-feedback.js +55 -0
  432. package/gateway/dist/core/tools/run-review.js +46 -0
  433. package/gateway/dist/core/tools/write-lesson.js +97 -0
  434. package/gateway/dist/core/utils/circuit-breaker.js +74 -0
  435. package/gateway/dist/core/utils/config-loader.js +203 -0
  436. package/gateway/dist/core/utils/fallback.js +19 -0
  437. package/gateway/dist/core/utils/git.js +70 -0
  438. package/gateway/dist/core/utils/github.js +52 -0
  439. package/gateway/dist/core/utils/global-path.js +41 -0
  440. package/gateway/dist/core/utils/logger.js +71 -0
  441. package/gateway/dist/core/utils/retry.js +44 -0
  442. package/gateway/dist/core/utils/state.js +175 -0
  443. package/gateway/dist/core/utils/status.js +156 -0
  444. package/gateway/dist/cost/service.js +17 -0
  445. package/gateway/dist/dashboard/api.js +1156 -0
  446. package/gateway/dist/dashboard/public/assets/index-DOXm39dm.css +1 -0
  447. package/gateway/dist/dashboard/public/index.html +13 -0
  448. package/gateway/dist/dashboard/server.js +140 -0
  449. package/gateway/dist/dashboard/types.js +2 -0
  450. package/gateway/dist/desktop-client.js +124 -0
  451. package/gateway/dist/eval-endpoint.js +219 -0
  452. package/gateway/dist/event-bus.js +7 -0
  453. package/gateway/dist/feedback/anchor-promotion.js +99 -0
  454. package/gateway/dist/feedback/deferred-memory.js +13 -0
  455. package/gateway/dist/feedback/miss-attribution.js +20 -0
  456. package/gateway/dist/graph/anchor-graph-store.js +113 -0
  457. package/gateway/dist/graph/anchor-graph.js +48 -0
  458. package/gateway/dist/health.js +53 -0
  459. package/gateway/dist/heartbeat.js +109 -0
  460. package/gateway/dist/index.js +6377 -0
  461. package/gateway/dist/interceptors/memory-injector.js +79 -0
  462. package/gateway/dist/ledger.js +121 -0
  463. package/gateway/dist/loop-monitor.js +74 -0
  464. package/gateway/dist/mcp/handlers/add-memory.js +113 -0
  465. package/gateway/dist/mcp/handlers/ask-user.js +63 -0
  466. package/gateway/dist/mcp/handlers/commit-heuristic.js +19 -0
  467. package/gateway/dist/mcp/handlers/create-goal.js +83 -0
  468. package/gateway/dist/mcp/handlers/desktop-click.js +18 -0
  469. package/gateway/dist/mcp/handlers/desktop-get-state.js +15 -0
  470. package/gateway/dist/mcp/handlers/desktop-navigate.js +18 -0
  471. package/gateway/dist/mcp/handlers/desktop-screenshot.js +16 -0
  472. package/gateway/dist/mcp/handlers/desktop-scroll.js +19 -0
  473. package/gateway/dist/mcp/handlers/desktop-type.js +19 -0
  474. package/gateway/dist/mcp/handlers/draft-automation-rule.js +45 -0
  475. package/gateway/dist/mcp/handlers/get-automation-history.js +15 -0
  476. package/gateway/dist/mcp/handlers/get-automation-rule.js +26 -0
  477. package/gateway/dist/mcp/handlers/get-axioms.js +14 -0
  478. package/gateway/dist/mcp/handlers/get-deltas.js +77 -0
  479. package/gateway/dist/mcp/handlers/get-memory.js +67 -0
  480. package/gateway/dist/mcp/handlers/get-model-route.js +16 -0
  481. package/gateway/dist/mcp/handlers/get-triage-item.js +17 -0
  482. package/gateway/dist/mcp/handlers/list-automation-rules.js +24 -0
  483. package/gateway/dist/mcp/handlers/list-triage-items.js +14 -0
  484. package/gateway/dist/mcp/handlers/load-state.js +54 -0
  485. package/gateway/dist/mcp/handlers/manager-answer-question.js +67 -0
  486. package/gateway/dist/mcp/handlers/manager-cancel-goal.js +58 -0
  487. package/gateway/dist/mcp/handlers/manager-get-evidence.js +57 -0
  488. package/gateway/dist/mcp/handlers/manager-get-goal-status.js +58 -0
  489. package/gateway/dist/mcp/handlers/manager-list-goals.js +60 -0
  490. package/gateway/dist/mcp/handlers/manager-list-pending-questions.js +67 -0
  491. package/gateway/dist/mcp/handlers/manager-set-goal.js +78 -0
  492. package/gateway/dist/mcp/handlers/merge-memory.js +184 -0
  493. package/gateway/dist/mcp/handlers/pin-memory.js +53 -0
  494. package/gateway/dist/mcp/handlers/propose-triage-decision.js +38 -0
  495. package/gateway/dist/mcp/handlers/record-feedback.js +59 -0
  496. package/gateway/dist/mcp/handlers/resolve-merge.js +92 -0
  497. package/gateway/dist/mcp/handlers/restart-agent.js +22 -0
  498. package/gateway/dist/mcp/handlers/run-automation.js +28 -0
  499. package/gateway/dist/mcp/handlers/search-hybrid.js +181 -0
  500. package/gateway/dist/mcp/handlers/supersede-memory.js +47 -0
  501. package/gateway/dist/mcp/handlers/update-state.js +59 -0
  502. package/gateway/dist/mcp/handlers/validate-rule.js +39 -0
  503. package/gateway/dist/mcp/sse-transport.js +97 -0
  504. package/gateway/dist/mcp/streamable-endpoint.js +98 -0
  505. package/gateway/dist/mcp/tool-registry.js +630 -0
  506. package/gateway/dist/media/media-agent.js +755 -0
  507. package/gateway/dist/media/media-plugin-loader.js +254 -0
  508. package/gateway/dist/media/media-runtime-executor.js +227 -0
  509. package/gateway/dist/media/media-service.js +199 -0
  510. package/gateway/dist/media/pi-adapter.js +159 -0
  511. package/gateway/dist/media/plugin-context.js +14 -0
  512. package/gateway/dist/media/tts-service.js +173 -0
  513. package/gateway/dist/memory/abstraction-matcher.js +28 -0
  514. package/gateway/dist/memory/consolidation-service.js +209 -0
  515. package/gateway/dist/memory/derived-terms.js +50 -0
  516. package/gateway/dist/memory/embedding-provider.js +330 -0
  517. package/gateway/dist/memory/embedding-runtime.js +174 -0
  518. package/gateway/dist/memory/event-log.js +84 -0
  519. package/gateway/dist/memory/gateway-db.js +465 -0
  520. package/gateway/dist/memory/harmonic-file-store.js +338 -0
  521. package/gateway/dist/memory/llamacpp-provider.js +370 -0
  522. package/gateway/dist/memory/okf-index-renderer.js +61 -0
  523. package/gateway/dist/memory/okf-migrator.js +71 -0
  524. package/gateway/dist/memory/okf-parser.js +57 -0
  525. package/gateway/dist/memory/okf-writer.js +107 -0
  526. package/gateway/dist/memory/service.js +81 -0
  527. package/gateway/dist/memory/t1-db.js +139 -0
  528. package/gateway/dist/memory/unmerge-cleanup.js +82 -0
  529. package/gateway/dist/memory/vector-store.js +246 -0
  530. package/gateway/dist/memory/write-queue.js +31 -0
  531. package/gateway/dist/metrics/collector.js +28 -0
  532. package/gateway/dist/mobile/device-store.js +123 -0
  533. package/gateway/dist/mobile/mdns-advertiser.js +55 -0
  534. package/gateway/dist/mobile/media-proxy.js +292 -0
  535. package/gateway/dist/mobile/pairing.js +139 -0
  536. package/gateway/dist/mobile/push-gateway.js +126 -0
  537. package/gateway/dist/mobile/tts-artifact.js +43 -0
  538. package/gateway/dist/opencode-adapter.js +241 -0
  539. package/gateway/dist/orchestration/outcome-recorder.js +218 -0
  540. package/gateway/dist/orchestration/policy.js +57 -0
  541. package/gateway/dist/orchestration/registry.js +47 -0
  542. package/gateway/dist/plugins/hub.js +188 -0
  543. package/gateway/dist/poll.js +110 -0
  544. package/gateway/dist/python/kernel-service.js +762 -0
  545. package/gateway/dist/recall/constraints-migrate.js +108 -0
  546. package/gateway/dist/recall/data-dir-migrate.js +120 -0
  547. package/gateway/dist/recall/gateway-db-migrate.js +134 -0
  548. package/gateway/dist/recall/index-scan.js +437 -0
  549. package/gateway/dist/recall/inject-format.js +222 -0
  550. package/gateway/dist/recall/legacy-t1-archive.js +86 -0
  551. package/gateway/dist/recall/memory-worker.js +128 -0
  552. package/gateway/dist/recall/pipeline-rules.js +76 -0
  553. package/gateway/dist/recall/recall-context.js +297 -0
  554. package/gateway/dist/recall/reflect-cursor.js +50 -0
  555. package/gateway/dist/recall/reflection.js +318 -0
  556. package/gateway/dist/recall/session-worker-pool.js +100 -0
  557. package/gateway/dist/recall/stale-verify.js +72 -0
  558. package/gateway/dist/recall/step-inject.js +173 -0
  559. package/gateway/dist/recall/time-anchor.js +143 -0
  560. package/gateway/dist/recall/ttl-map.js +72 -0
  561. package/gateway/dist/recall/turn-completion.js +44 -0
  562. package/gateway/dist/recall/turn-pipeline.js +150 -0
  563. package/gateway/dist/recovery.js +158 -0
  564. package/gateway/dist/resources/sdk-session.js +202 -0
  565. package/gateway/dist/retrieval/guided-retriever.js +131 -0
  566. package/gateway/dist/retrieval/idf-stats.js +31 -0
  567. package/gateway/dist/routes/embedding-config.js +100 -0
  568. package/gateway/dist/routes/goal-sessions.js +45 -0
  569. package/gateway/dist/routes/manager-rotate.js +55 -0
  570. package/gateway/dist/routes/media-switch.js +78 -0
  571. package/gateway/dist/routes/model-config.js +132 -0
  572. package/gateway/dist/routes/note-board.js +51 -0
  573. package/gateway/dist/routes/permission.js +43 -0
  574. package/gateway/dist/routes/pinned-recall.js +36 -0
  575. package/gateway/dist/routes/plugins.js +77 -0
  576. package/gateway/dist/routes/restart-agent.js +28 -0
  577. package/gateway/dist/routes/runtime-switch.js +80 -0
  578. package/gateway/dist/routes/session-branch.js +63 -0
  579. package/gateway/dist/routes/session-mutations.js +58 -0
  580. package/gateway/dist/routes/session-summarize.js +49 -0
  581. package/gateway/dist/routes/usage-plugins.js +251 -0
  582. package/gateway/dist/runtime/agent-definition.js +2 -0
  583. package/gateway/dist/runtime/auth.js +80 -0
  584. package/gateway/dist/runtime/completion-http.js +97 -0
  585. package/gateway/dist/runtime/contract.js +37 -0
  586. package/gateway/dist/runtime/loader.js +240 -0
  587. package/gateway/dist/runtime/normalize.js +59 -0
  588. package/gateway/dist/runtime/opencode-runtime.js +336 -0
  589. package/gateway/dist/runtime/pi/pi-agent-config.js +294 -0
  590. package/gateway/dist/runtime/pi/pi-approval-bridge.js +44 -0
  591. package/gateway/dist/runtime/pi/pi-approval-extension.js +62 -0
  592. package/gateway/dist/runtime/pi/pi-events.js +122 -0
  593. package/gateway/dist/runtime/pi/pi-messages.js +20 -0
  594. package/gateway/dist/runtime/pi/pi-provider.js +19 -0
  595. package/gateway/dist/runtime/pi/pi-session-storage.js +44 -0
  596. package/gateway/dist/runtime/pi/pi-session.js +328 -0
  597. package/gateway/dist/runtime/plugins/pi-runtime.js +285 -0
  598. package/gateway/dist/runtime/serve-for-runtime.js +22 -0
  599. package/gateway/dist/runtime/serve-sidecar.js +164 -0
  600. package/gateway/dist/runtime/serve-supervisor.js +80 -0
  601. package/gateway/dist/self-update.js +309 -0
  602. package/gateway/dist/skills/manager-agent-config.js +37 -0
  603. package/gateway/dist/skills/manager-identity.js +11 -0
  604. package/gateway/dist/skills/memory-curator-agent.js +55 -0
  605. package/gateway/dist/trajectory/api.js +154 -0
  606. package/gateway/dist/trajectory/backfill-provider.js +41 -0
  607. package/gateway/dist/trajectory/collector.js +337 -0
  608. package/gateway/dist/trajectory/trajectory-store.js +336 -0
  609. package/gateway/dist/trajectory/types.js +17 -0
  610. package/gateway/dist/tray/index.js +131 -0
  611. package/gateway/dist/tray/tray.ps1 +96 -0
  612. package/gateway/dist/types.js +2 -0
  613. package/gateway/dist/usage/builtin-plugins/commandcode.js +71 -0
  614. package/gateway/dist/usage/builtin-plugins/deepseek.js +56 -0
  615. package/gateway/dist/usage/builtin-plugins/gateway.js +127 -0
  616. package/gateway/dist/usage/builtin-plugins/kimi-for-coding.js +93 -0
  617. package/gateway/dist/usage/builtin-plugins/kimi.js +48 -0
  618. package/gateway/dist/usage/builtin-plugins/opencode-go.js +54 -0
  619. package/gateway/dist/usage/builtin-plugins/openrouter.js +48 -0
  620. package/gateway/dist/usage/builtin-plugins/siliconflow-cn.js +49 -0
  621. package/gateway/dist/usage/builtin-plugins/zhipuai-coding-plan.js +44 -0
  622. package/gateway/dist/usage/model-prices.js +39 -0
  623. package/gateway/dist/usage/model-stats.js +21 -0
  624. package/gateway/dist/usage/plugin-context.js +79 -0
  625. package/gateway/dist/usage/plugin-loader.js +280 -0
  626. package/gateway/dist/usage/templates.js +227 -0
  627. package/gateway/dist/usage/types.js +2 -0
  628. package/gateway/dist/usage/usage-poller.js +216 -0
  629. package/gateway/package.json +37 -0
  630. package/package.json +78 -0
  631. package/packages/tui/dist/cli.js +4664 -0
@@ -0,0 +1,755 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MediaAgent = exports.MAX_IMAGE_BYTES = exports.MAX_AUDIO_BYTES = exports.MAX_VIDEO_BYTES = exports.MEDIA_TASK_PREFIX = exports.ARTIFACT_SCHEME = void 0;
37
+ const crypto_1 = require("crypto");
38
+ const fs = __importStar(require("fs"));
39
+ const os = __importStar(require("os"));
40
+ const path = __importStar(require("path"));
41
+ const server_1 = require("@a2a-js/sdk/server");
42
+ const sdk_1 = require("@a2a-js/sdk");
43
+ const errors_1 = require("@a2a-js/sdk/errors");
44
+ const sdk_2 = require("@a2a-js/sdk");
45
+ const media_service_1 = require("./media-service");
46
+ const logger_1 = require("../core/utils/logger");
47
+ /**
48
+ * MediaAgent — an A2A (Agent2Agent) v1.0 agent that answers multi-turn
49
+ * questions about image / video / audio media via the configured multimodal
50
+ * API (MediaService). Each modality can use its own model (media 配置段).
51
+ *
52
+ * Protocol surface (all standard A2A, JSON-RPC binding):
53
+ * message/send — first turn carries the media as a FilePart (raw bytes);
54
+ * follow-ups carry text only, the task keeps the media.
55
+ * tasks/get, tasks/cancel, tasks/list
56
+ * Agent card — GET /.well-known/agent-card.json
57
+ * Artifacts — task outputs (the stored media) exposed via artifact URL,
58
+ * per spec §6.7 output-reference pattern.
59
+ *
60
+ * Internals:
61
+ * - ArtifactStore: LRU(500) + TTL(24h) map of media bytes (data URLs).
62
+ * - The media is stored once as a task artifact; revive flows (new task
63
+ * after the old one completed) reference the old artifact via its URL,
64
+ * so the bytes are never re-uploaded.
65
+ * - messageId idempotency: a repeated messageId on the same task returns
66
+ * the current task without re-running the media model.
67
+ */
68
+ exports.ARTIFACT_SCHEME = 'mafw-artifact://';
69
+ exports.MEDIA_TASK_PREFIX = 'mtask_';
70
+ // Bytes above this threshold are written to a temp file instead of being kept
71
+ // as a base64 string in memory (50MB video → ~67MB string otherwise).
72
+ const DISK_THRESHOLD_BYTES = 5 * 1024 * 1024;
73
+ class ArtifactStore {
74
+ max;
75
+ ttlMs;
76
+ now;
77
+ map = new Map();
78
+ index = new Map();
79
+ storageDir;
80
+ indexPath;
81
+ constructor(storageDir, max = 500, ttlMs = 24 * 60 * 60 * 1000, now = Date.now) {
82
+ this.max = max;
83
+ this.ttlMs = ttlMs;
84
+ this.now = now;
85
+ this.storageDir = storageDir || path.join(os.tmpdir(), 'mafw-media');
86
+ this.indexPath = path.join(this.storageDir, 'artifacts.json');
87
+ if (!fs.existsSync(this.storageDir))
88
+ fs.mkdirSync(this.storageDir, { recursive: true });
89
+ this.loadIndex();
90
+ }
91
+ loadIndex() {
92
+ try {
93
+ if (fs.existsSync(this.indexPath)) {
94
+ const raw = fs.readFileSync(this.indexPath, 'utf-8');
95
+ const entries = JSON.parse(raw);
96
+ const now = this.now();
97
+ for (const entry of entries) {
98
+ if (now - entry.createdAt > this.ttlMs)
99
+ continue; // expired
100
+ const filePath = path.join(this.storageDir, entry.filename);
101
+ if (!fs.existsSync(filePath))
102
+ continue; // file missing
103
+ this.index.set(entry.id, entry);
104
+ this.map.set(entry.id, {
105
+ dataUrl: null,
106
+ bytes: null,
107
+ filePath,
108
+ mediaType: entry.mediaType,
109
+ size: entry.size,
110
+ createdAt: entry.createdAt,
111
+ });
112
+ }
113
+ logger_1.log.info(`[ArtifactStore] loaded ${this.map.size} artifacts from disk`);
114
+ }
115
+ }
116
+ catch (err) {
117
+ logger_1.log.warn(`[ArtifactStore] failed to load index: ${err.message}`);
118
+ }
119
+ }
120
+ saveIndex() {
121
+ try {
122
+ const entries = [];
123
+ for (const [id, entry] of this.map) {
124
+ if (!entry.filePath)
125
+ continue; // skip in-memory-only entries
126
+ entries.push({
127
+ id,
128
+ mediaType: entry.mediaType,
129
+ size: entry.size,
130
+ createdAt: entry.createdAt,
131
+ filename: path.basename(entry.filePath),
132
+ });
133
+ }
134
+ fs.writeFileSync(this.indexPath, JSON.stringify(entries, null, 2));
135
+ }
136
+ catch (err) {
137
+ logger_1.log.warn(`[ArtifactStore] failed to save index: ${err.message}`);
138
+ }
139
+ }
140
+ put(dataUrl) {
141
+ return this.putBytes(Buffer.from(dataUrl.slice(dataUrl.indexOf(',') + 1), 'base64'), this.mediaTypeFromDataUrl(dataUrl));
142
+ }
143
+ /** Store raw bytes to disk (persistent across restarts). */
144
+ putBytes(bytes, mediaType) {
145
+ this.prune();
146
+ const id = (0, crypto_1.randomUUID)();
147
+ const createdAt = this.now();
148
+ const ext = mediaType.split('/')[1]?.split(';')[0] || 'bin';
149
+ const filename = `${id}.${ext}`;
150
+ const filePath = path.join(this.storageDir, filename);
151
+ try {
152
+ fs.writeFileSync(filePath, bytes);
153
+ }
154
+ catch (err) {
155
+ logger_1.log.warn(`[ArtifactStore] disk write failed, using memory fallback: ${err.message}`);
156
+ const dataUrl = `data:${mediaType || 'application/octet-stream'};base64,${bytes.toString('base64')}`;
157
+ this.map.set(id, { dataUrl, bytes, filePath: null, mediaType, size: bytes.length, createdAt });
158
+ if (this.map.size > this.max) {
159
+ const oldest = this.map.keys().next().value;
160
+ if (oldest !== undefined)
161
+ this.delete(oldest);
162
+ }
163
+ return id;
164
+ }
165
+ this.map.set(id, { dataUrl: null, bytes: null, filePath, mediaType, size: bytes.length, createdAt });
166
+ if (this.map.size > this.max) {
167
+ const oldest = this.map.keys().next().value;
168
+ if (oldest !== undefined)
169
+ this.delete(oldest);
170
+ }
171
+ this.saveIndex();
172
+ return id;
173
+ }
174
+ /** Return the artifact as a data URL (reads from disk). */
175
+ get(id) {
176
+ const entry = this.map.get(id);
177
+ if (!entry)
178
+ return undefined;
179
+ if (this.now() - entry.createdAt > this.ttlMs) {
180
+ this.delete(id);
181
+ return undefined;
182
+ }
183
+ // LRU touch
184
+ this.map.delete(id);
185
+ this.map.set(id, entry);
186
+ if (entry.dataUrl)
187
+ return entry.dataUrl;
188
+ if (entry.filePath) {
189
+ try {
190
+ const buf = fs.readFileSync(entry.filePath);
191
+ return `data:${entry.mediaType || 'application/octet-stream'};base64,${buf.toString('base64')}`;
192
+ }
193
+ catch {
194
+ return undefined;
195
+ }
196
+ }
197
+ return undefined;
198
+ }
199
+ getMediaType(id) {
200
+ return this.map.get(id)?.mediaType;
201
+ }
202
+ size() {
203
+ return this.map.size;
204
+ }
205
+ delete(id) {
206
+ const entry = this.map.get(id);
207
+ this.map.delete(id);
208
+ this.index.delete(id);
209
+ if (entry?.filePath) {
210
+ try {
211
+ fs.unlinkSync(entry.filePath);
212
+ }
213
+ catch { /* ignore */ }
214
+ }
215
+ this.saveIndex();
216
+ }
217
+ prune() {
218
+ const now = this.now();
219
+ let pruned = false;
220
+ for (const [id, entry] of this.map) {
221
+ if (now - entry.createdAt > this.ttlMs) {
222
+ this.map.delete(id);
223
+ this.index.delete(id);
224
+ if (entry?.filePath) {
225
+ try {
226
+ fs.unlinkSync(entry.filePath);
227
+ }
228
+ catch { /* ignore */ }
229
+ }
230
+ pruned = true;
231
+ }
232
+ }
233
+ if (pruned)
234
+ this.saveIndex();
235
+ }
236
+ mediaTypeFromDataUrl(dataUrl) {
237
+ const m = dataUrl.match(/^data:([^;,]+)/);
238
+ return m ? m[1] : 'application/octet-stream';
239
+ }
240
+ }
241
+ const SUPPORTED_INPUT_MODES = ['text', 'image', 'video', 'audio'];
242
+ // Size guards: base64 data-URL character length → raw bytes ≈ len * 0.75.
243
+ // Video is expensive to ship around and to encode; cap both conservatively.
244
+ exports.MAX_VIDEO_BYTES = 50 * 1024 * 1024;
245
+ exports.MAX_AUDIO_BYTES = 25 * 1024 * 1024;
246
+ exports.MAX_IMAGE_BYTES = 20 * 1024 * 1024;
247
+ function taskStatus(state, message, timestamp = new Date().toISOString()) {
248
+ return { state, timestamp, message };
249
+ }
250
+ function textPart(text) {
251
+ return {
252
+ content: { $case: 'text', value: text },
253
+ mediaType: 'text/plain',
254
+ filename: '',
255
+ metadata: {},
256
+ };
257
+ }
258
+ function makeMessage(role, taskId, contextId, parts) {
259
+ return {
260
+ role,
261
+ messageId: (0, crypto_1.randomUUID)(),
262
+ taskId,
263
+ contextId,
264
+ parts,
265
+ metadata: {},
266
+ extensions: [],
267
+ referenceTaskIds: [],
268
+ };
269
+ }
270
+ class MediaAgent {
271
+ media;
272
+ options;
273
+ artifacts;
274
+ taskStore;
275
+ jsonRpc;
276
+ handler;
277
+ agentCardData;
278
+ seenMessages = new Map();
279
+ constructor(media, options) {
280
+ this.media = media;
281
+ this.options = options;
282
+ this.artifacts = new ArtifactStore(options.storageDir);
283
+ this.taskStore = new server_1.InMemoryTaskStore();
284
+ this.agentCardData = this.buildAgentCard();
285
+ const executor = {
286
+ execute: (ctx, bus) => this.execute(ctx, bus),
287
+ cancelTask: async (taskId, bus) => this.cancelTask(taskId, bus),
288
+ };
289
+ this.handler = new server_1.DefaultRequestHandler(this.agentCardData, this.taskStore, executor);
290
+ this.jsonRpc = new server_1.JsonRpcTransportHandler(this.handler);
291
+ logger_1.log.info(`[MediaAgent] A2A agent ready at ${options.baseUrl}/a2a`);
292
+ }
293
+ get agentCard() {
294
+ return this.agentCardData;
295
+ }
296
+ artifactCount() {
297
+ return this.artifacts.size();
298
+ }
299
+ getArtifact(id) {
300
+ const dataUrl = this.artifacts.get(id);
301
+ if (!dataUrl)
302
+ return undefined;
303
+ const mime = dataUrl.match(/^data:([^;]+);/)?.[1] || 'application/octet-stream';
304
+ return { dataUrl, mediaType: mime };
305
+ }
306
+ /** 存入 artifact(TTS 输出等 gateway 侧产物),返回 artifact ID。mime 从 dataUrl 前缀推导。 */
307
+ putArtifact(dataUrl) {
308
+ return this.artifacts.put(dataUrl);
309
+ }
310
+ /** 存入原始媒体字节(桌面端二进制上传),大文件落盘。 */
311
+ putArtifactBytes(bytes, mediaType) {
312
+ return this.artifacts.putBytes(bytes, mediaType);
313
+ }
314
+ getArtifactMediaType(id) {
315
+ return this.artifacts.getMediaType(id);
316
+ }
317
+ async resolveTaskArtifactId(taskId) {
318
+ try {
319
+ const task = await this.taskStore.load(taskId, {});
320
+ if (!task?.artifacts?.length)
321
+ return undefined;
322
+ return task.artifacts[0]?.artifactId;
323
+ }
324
+ catch {
325
+ return undefined;
326
+ }
327
+ }
328
+ /**
329
+ * Create a task immediately and start analysis in the background.
330
+ * Returns the task ID synchronously; analysis runs asynchronously.
331
+ */
332
+ createTaskAsync(artifactId, mediaType, question) {
333
+ const t0 = Date.now();
334
+ const taskId = `mtask_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
335
+ const contextId = `mctx_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
336
+ // Build artifact reference upfront so follow-up SendMessage (via
337
+ // referenceTaskIds) can find the media immediately, even before the
338
+ // background analysis completes.
339
+ const artifactUrl = `${this.options.baseUrl}${this.options.artifactPath}/${artifactId}`;
340
+ const artifact = {
341
+ artifactId,
342
+ name: 'upload.bin',
343
+ description: '原始媒体工件',
344
+ parts: [
345
+ {
346
+ content: { $case: 'url', value: artifactUrl },
347
+ mediaType,
348
+ filename: 'upload.bin',
349
+ metadata: {},
350
+ },
351
+ ],
352
+ metadata: {},
353
+ extensions: [],
354
+ };
355
+ // Create task in store (state=working) with artifact already set
356
+ const task = {
357
+ id: taskId,
358
+ contextId,
359
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_WORKING),
360
+ history: [],
361
+ artifacts: [artifact],
362
+ metadata: {},
363
+ };
364
+ // Save task synchronously (use same context as SendMessage handler)
365
+ const saveContext = new server_1.ServerCallContext({
366
+ headers: {},
367
+ requestedVersion: this.options.defaultVersion || '1.0',
368
+ user: new server_1.UnauthenticatedUser(),
369
+ extensions: undefined,
370
+ });
371
+ this.taskStore.save(task, saveContext).catch(err => {
372
+ logger_1.log.error(`[MediaAgent] createTaskAsync: failed to save task ${taskId}: ${err.message}`);
373
+ });
374
+ // Build message with correct A2A part format: content.$case = 'url'
375
+ const mediaPart = {
376
+ content: { $case: 'url', value: artifactUrl },
377
+ mediaType,
378
+ filename: 'upload.bin',
379
+ metadata: {},
380
+ };
381
+ const userMessage = makeMessage(1, taskId, contextId, [
382
+ mediaPart,
383
+ ...(question ? [textPart(question)] : []),
384
+ ]);
385
+ // Trigger async analysis in background
386
+ const requestContext = {
387
+ taskId,
388
+ contextId,
389
+ userMessage,
390
+ task, // pass the task with its artifact so execute's working-state publish
391
+ // does not clobber artifacts with an empty array
392
+ referenceTasks: [],
393
+ };
394
+ // Simple event bus that updates task store (same context as the initial save)
395
+ const bus = {
396
+ publish: (event) => {
397
+ if (event.kind === 'task') {
398
+ this.taskStore.save(event.data, saveContext).catch(err => {
399
+ logger_1.log.error(`[MediaAgent] createTaskAsync: failed to update task ${taskId}: ${err.message}`);
400
+ });
401
+ }
402
+ },
403
+ on: () => bus,
404
+ off: () => bus,
405
+ once: () => bus,
406
+ removeAllListeners: () => bus,
407
+ finished: () => { },
408
+ };
409
+ const t1 = Date.now();
410
+ console.log(`[MediaAgent] createTaskAsync: prep ${t1 - t0}ms, starting background analysis for task ${taskId}`);
411
+ // Fire-and-forget: execute analysis in background (don't wait)
412
+ void this.execute(requestContext, bus).then(() => {
413
+ const t2 = Date.now();
414
+ console.log(`[MediaAgent] createTaskAsync: analysis completed for task ${taskId} in ${t2 - t1}ms`);
415
+ }).catch(err => {
416
+ console.error(`[MediaAgent] createTaskAsync: analysis failed for task ${taskId}: ${err.message}`);
417
+ });
418
+ return { taskId, contextId };
419
+ }
420
+ /**
421
+ * Handle a JSON-RPC A2A request (POST /a2a). Returns the HTTP response.
422
+ */
423
+ async handleJsonRpc(body, headers) {
424
+ // 诊断:打印 SendMessage 收到的 parts 原始结构(定位桌面 createTask 失败根因)
425
+ try {
426
+ const rawBody = typeof body === 'string' ? JSON.parse(body) : body;
427
+ const msg = rawBody?.params?.message;
428
+ if (rawBody?.method === 'SendMessage' && Array.isArray(msg?.parts)) {
429
+ logger_1.log.info(`[MediaAgent] SendMessage parts: ${JSON.stringify(msg.parts).slice(0, 400)} | ` +
430
+ `msgId=${String(msg?.messageId ?? '').slice(0, 24)} hasRef=${Array.isArray(msg?.referenceTaskIds) ? msg.referenceTaskIds.length : 0}`);
431
+ }
432
+ }
433
+ catch { /* 诊断日志失败不影响主流程 */ }
434
+ const requestedVersion = headers[sdk_2.A2A_VERSION_HEADER?.toLowerCase()] || this.options.defaultVersion || '1.0';
435
+ const context = new server_1.ServerCallContext({
436
+ headers,
437
+ requestedVersion,
438
+ user: new server_1.UnauthenticatedUser(),
439
+ extensions: undefined,
440
+ });
441
+ const result = await this.jsonRpc.handle(body, context);
442
+ if (typeof result?.[Symbol.asyncIterator] === 'function') {
443
+ // Streaming response (message/stream) — collect the first event for the
444
+ // internal synchronous path; the gateway does not expose streaming yet.
445
+ const generator = result;
446
+ const first = await generator.next();
447
+ if (first.done) {
448
+ return { status: 200, headers: { [sdk_2.A2A_VERSION_HEADER]: '1.0' }, body: JSON.stringify({ jsonrpc: '2.0', result: null }) };
449
+ }
450
+ return { status: 200, headers: { [sdk_2.A2A_VERSION_HEADER]: '1.0' }, body: JSON.stringify(first.value) };
451
+ }
452
+ return {
453
+ status: 200,
454
+ headers: { [sdk_2.A2A_VERSION_HEADER]: '1.0', 'Content-Type': 'application/a2a+json' },
455
+ body: JSON.stringify(result),
456
+ };
457
+ }
458
+ // -------------------------------------------------------------------------
459
+ // Executor
460
+ async execute(requestContext, bus) {
461
+ const taskId = requestContext.taskId;
462
+ const contextId = requestContext.contextId;
463
+ const userMessage = requestContext.userMessage;
464
+ console.log(`[MediaAgent] execute called: taskId=${taskId}, contextId=${contextId}, userMessageId=${userMessage.messageId}`);
465
+ logger_1.log.info(`[MediaAgent] execute called: taskId=${taskId}, contextId=${contextId}, userMessageId=${userMessage.messageId}`);
466
+ // Idempotency: a message already processed for this task is a replay.
467
+ const seen = this.seenMessages.get(taskId) ?? new Set();
468
+ if (requestContext.task && seen.has(userMessage.messageId)) {
469
+ logger_1.log.info(`[MediaAgent] execute: replay detected, returning cached task`);
470
+ bus.publish(server_1.AgentEvent.task(requestContext.task));
471
+ return;
472
+ }
473
+ seen.add(userMessage.messageId);
474
+ this.seenMessages.set(taskId, seen);
475
+ // Working state on entry.
476
+ const workingTask = requestContext.task ?? {
477
+ id: taskId,
478
+ contextId,
479
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_SUBMITTED),
480
+ history: [],
481
+ artifacts: [],
482
+ metadata: {},
483
+ };
484
+ workingTask.status = taskStatus(sdk_1.TaskState.TASK_STATE_WORKING);
485
+ bus.publish(server_1.AgentEvent.task(workingTask));
486
+ try {
487
+ // Resolve the media: first turn extracts it from the message parts;
488
+ // follow-up turns reference the prior task (referenceTaskIds) and reuse
489
+ // its artifact — the bytes are never re-uploaded.
490
+ logger_1.log.info(`[MediaAgent] execute: taskId=${taskId}, referenceTasks=${requestContext.referenceTasks?.length ?? 0}, hasTask=${!!requestContext.task}`);
491
+ if (requestContext.referenceTasks && requestContext.referenceTasks.length > 0) {
492
+ for (const rt of requestContext.referenceTasks) {
493
+ logger_1.log.info(`[MediaAgent] execute: refTask ${rt.id}, artifacts=${rt.artifacts?.length ?? 0}`);
494
+ }
495
+ }
496
+ const media = await this.resolveMedia(requestContext, userMessage);
497
+ if (!media) {
498
+ throw new errors_1.ContentTypeNotSupportedError('A2A media agent requires an image/video/audio part (raw bytes or a known artifact URL) on the first message.');
499
+ }
500
+ const kind = (0, media_service_1.kindFromMediaType)(media.mediaType);
501
+ // Build the prompt from referenced/history context + the new question.
502
+ const priorTasks = requestContext.referenceTasks ?? [];
503
+ const historyText = this.historyToText([...priorTasks.flatMap((t) => t.history ?? []), ...(requestContext.task?.history ?? [])]);
504
+ const questionText = this.messageToText(userMessage);
505
+ // 音频首轮(无历史上下文)→ 叙述式分析(内容 + 情绪/语调轨迹 + 意图,自然语言);
506
+ // 追问轮保持自由提问(主 Agent 可追问细节)。
507
+ if (kind === 'audio' && !historyText) {
508
+ const description = await this.media.analyzeAudioNarrative({
509
+ kind,
510
+ dataUrl: media.dataUrl,
511
+ mediaType: media.mediaType,
512
+ });
513
+ const answerMessage = makeMessage(2, taskId, contextId, [textPart(description)]);
514
+ const history = [...(requestContext.task?.history ?? []), userMessage, answerMessage];
515
+ const artifact = media.artifact;
516
+ const finalTask = {
517
+ id: taskId,
518
+ contextId,
519
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_COMPLETED, answerMessage),
520
+ history,
521
+ artifacts: artifact ? [artifact] : requestContext.task?.artifacts ?? [],
522
+ metadata: {},
523
+ };
524
+ bus.publish(server_1.AgentEvent.task(finalTask));
525
+ return;
526
+ }
527
+ const prompt = [historyText, questionText].filter(Boolean).join('\n\n') || '请描述这个媒体内容。';
528
+ const description = await this.media.analyze({ kind, dataUrl: media.dataUrl, mediaType: media.mediaType }, prompt);
529
+ const answerMessage = makeMessage(2, taskId, contextId, [textPart(description)]);
530
+ const history = [...(requestContext.task?.history ?? []), userMessage, answerMessage];
531
+ const artifact = media.artifact;
532
+ const finalTask = {
533
+ id: taskId,
534
+ contextId,
535
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_COMPLETED, answerMessage),
536
+ history,
537
+ artifacts: artifact ? [artifact] : requestContext.task?.artifacts ?? [],
538
+ metadata: {},
539
+ };
540
+ bus.publish(server_1.AgentEvent.task(finalTask));
541
+ }
542
+ catch (err) {
543
+ logger_1.log.error(`[MediaAgent] task ${taskId} failed: ${err.message}`);
544
+ const errorMessage = makeMessage(2, taskId, contextId, [textPart(`[media agent] 媒体分析失败:${err.message}`)]);
545
+ const failedTask = {
546
+ id: taskId,
547
+ contextId,
548
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_FAILED, errorMessage),
549
+ history: [...(requestContext.task?.history ?? []), userMessage],
550
+ artifacts: requestContext.task?.artifacts ?? [],
551
+ metadata: {},
552
+ };
553
+ bus.publish(server_1.AgentEvent.task(failedTask));
554
+ }
555
+ }
556
+ async cancelTask(taskId, bus) {
557
+ const task = await this.taskStore.load(taskId, {});
558
+ if (!task)
559
+ throw new errors_1.TaskNotFoundError(`Task ${taskId} not found`);
560
+ const canceled = {
561
+ ...task,
562
+ status: taskStatus(sdk_1.TaskState.TASK_STATE_CANCELED),
563
+ };
564
+ bus.publish(server_1.AgentEvent.task(canceled));
565
+ // fail-open:中止进行中的媒体分析(executor.cancelInflight)
566
+ try {
567
+ await this.options.cancelHook?.(taskId);
568
+ }
569
+ catch { /* ignore */ }
570
+ }
571
+ // -------------------------------------------------------------------------
572
+ // Media resolution
573
+ async resolveMedia(requestContext, userMessage) {
574
+ // Follow-up turn: reuse the media artifact of a referenced prior task.
575
+ const refTasks = requestContext.referenceTasks ?? [];
576
+ logger_1.log.info(`[MediaAgent] resolveMedia: referenceTasks=${refTasks.length}, hasTask=${!!requestContext.task}`);
577
+ for (const refTask of refTasks) {
578
+ logger_1.log.info(`[MediaAgent] resolveMedia: checking refTask ${refTask.id}, artifacts=${refTask.artifacts?.length ?? 0}`);
579
+ const media = this.mediaFromTask(refTask);
580
+ if (media) {
581
+ logger_1.log.info(`[MediaAgent] resolveMedia: found media from refTask ${refTask.id}`);
582
+ return media;
583
+ }
584
+ }
585
+ // Or from the current task (e.g. resumed history).
586
+ if (requestContext.task) {
587
+ logger_1.log.info(`[MediaAgent] resolveMedia: checking current task ${requestContext.task.id}, artifacts=${requestContext.task.artifacts?.length ?? 0}`);
588
+ const media = this.mediaFromTask(requestContext.task);
589
+ if (media) {
590
+ logger_1.log.info(`[MediaAgent] resolveMedia: found media from current task`);
591
+ return media;
592
+ }
593
+ }
594
+ // First turn: extract from the message parts.
595
+ const mediaPart = userMessage.parts.find((p) => p.content?.$case === 'raw' || p.content?.$case === 'url');
596
+ if (!mediaPart)
597
+ return undefined;
598
+ const mediaType = mediaPart.mediaType || (mediaPart.content?.$case === 'raw' ? 'application/octet-stream' : '');
599
+ if (!mediaType.startsWith('image/') && !mediaType.startsWith('video/') && !mediaType.startsWith('audio/')) {
600
+ throw new errors_1.ContentTypeNotSupportedError(`Unsupported media type: ${mediaType || 'unknown'}`);
601
+ }
602
+ if (mediaPart.content?.$case === 'raw') {
603
+ const raw = mediaPart.content.value;
604
+ // The SDK may deliver raw bytes as a Buffer or as a Uint8Array/number[] —
605
+ // normalize before re-encoding to base64.
606
+ const bytes = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
607
+ this.assertSize(mediaType, bytes.length);
608
+ const dataUrl = `data:${mediaType};base64,${bytes.toString('base64')}`;
609
+ const artifactId = this.artifacts.put(dataUrl);
610
+ const artifactUrl = `${this.options.baseUrl}${this.options.artifactPath}/${artifactId}`;
611
+ return {
612
+ dataUrl,
613
+ mediaType,
614
+ artifact: {
615
+ artifactId,
616
+ name: mediaPart.filename || this.defaultMediaName(mediaType),
617
+ description: '原始媒体工件',
618
+ parts: [
619
+ {
620
+ content: { $case: 'url', value: artifactUrl },
621
+ mediaType,
622
+ filename: mediaPart.filename || this.defaultMediaName(mediaType),
623
+ metadata: {},
624
+ },
625
+ ],
626
+ metadata: {},
627
+ },
628
+ };
629
+ }
630
+ // url part — only our own artifact URLs are accepted (SSRF protection).
631
+ if (mediaPart.content?.$case !== 'url')
632
+ return undefined;
633
+ const url = mediaPart.content.value;
634
+ const id = this.artifactUrlToId(url) ?? (url.startsWith(exports.ARTIFACT_SCHEME) ? url.slice(exports.ARTIFACT_SCHEME.length) : undefined);
635
+ const dataUrl = id ? this.artifacts.get(id) : undefined;
636
+ if (!dataUrl) {
637
+ // 诊断:区分 artifact 内存丢失(upload 后 gateway 重启/TTL 淘汰)与解析失败
638
+ logger_1.log.warn(`[MediaAgent] artifact url part unresolvable | url=${url} id=${id ?? '(none)'} ` +
639
+ `storeSize=${this.artifacts.size()} storeHas=${id ? this.artifacts.get(id) !== undefined : 'n/a'}`);
640
+ throw new errors_1.ContentTypeNotSupportedError('外部媒体 URL 不被接受;请使用 raw 字节或本 agent 的工件引用。');
641
+ }
642
+ const mime = dataUrl.match(/^data:([^;]+);/)?.[1] || 'application/octet-stream';
643
+ // 与 raw 分支一致:把工件挂到任务 artifacts,追问轮(referenceTaskIds)才能
644
+ // 经 mediaFromTask 复用媒体——否则首轮成功后 artifacts 为空,追问必败。
645
+ const artifactUrl = `${this.options.baseUrl}${this.options.artifactPath}/${id}`;
646
+ return {
647
+ dataUrl,
648
+ mediaType: mime,
649
+ artifact: {
650
+ artifactId: id,
651
+ name: mediaPart.filename || this.defaultMediaName(mime),
652
+ description: '原始媒体工件',
653
+ parts: [
654
+ {
655
+ content: { $case: 'url', value: artifactUrl },
656
+ mediaType: mime,
657
+ filename: mediaPart.filename || this.defaultMediaName(mime),
658
+ metadata: {},
659
+ },
660
+ ],
661
+ metadata: {},
662
+ },
663
+ };
664
+ }
665
+ mediaFromTask(task) {
666
+ const urlPart = task.artifacts
667
+ ?.flatMap((a) => a.parts ?? [])
668
+ .find((p) => p.content?.$case === 'url');
669
+ if (!urlPart)
670
+ return undefined;
671
+ const id = this.artifactUrlToId(String(urlPart.content.value));
672
+ const dataUrl = id ? this.artifacts.get(id) : undefined;
673
+ if (!dataUrl)
674
+ return undefined;
675
+ const mime = dataUrl.match(/^data:([^;]+);/)?.[1] || 'application/octet-stream';
676
+ return { dataUrl, mediaType: mime };
677
+ }
678
+ assertSize(mediaType, byteLength) {
679
+ let max;
680
+ if (mediaType.startsWith('video/'))
681
+ max = exports.MAX_VIDEO_BYTES;
682
+ else if (mediaType.startsWith('audio/'))
683
+ max = exports.MAX_AUDIO_BYTES;
684
+ else
685
+ max = exports.MAX_IMAGE_BYTES;
686
+ if (byteLength > max) {
687
+ throw new errors_1.ContentTypeNotSupportedError(`媒体过大:${(byteLength / (1024 * 1024)).toFixed(1)}MB 超过上限 ${(max / (1024 * 1024)).toFixed(0)}MB(${mediaType})`);
688
+ }
689
+ }
690
+ defaultMediaName(mediaType) {
691
+ const ext = (mediaType.split('/')[1] || 'bin').split(';')[0].split('+')[0];
692
+ return `media.${ext || 'bin'}`;
693
+ }
694
+ artifactUrlToId(url) {
695
+ const marker = `${this.options.artifactPath}/`;
696
+ const idx = url.lastIndexOf(marker);
697
+ if (idx < 0)
698
+ return undefined;
699
+ const id = url.slice(idx + marker.length).split(/[?#]/)[0];
700
+ return id || undefined;
701
+ }
702
+ // -------------------------------------------------------------------------
703
+ // Text helpers
704
+ messageToText(message) {
705
+ return message.parts
706
+ .filter((p) => p.content?.$case === 'text')
707
+ .map((p) => String(p.content.value))
708
+ .join('\n')
709
+ .trim();
710
+ }
711
+ historyToText(history) {
712
+ return history
713
+ .map((m) => {
714
+ const role = m.role === 1 ? '用户' : '媒体Agent';
715
+ const text = this.messageToText(m);
716
+ return text ? `${role}: ${text}` : '';
717
+ })
718
+ .filter(Boolean)
719
+ .join('\n');
720
+ }
721
+ // -------------------------------------------------------------------------
722
+ // Agent card
723
+ buildAgentCard() {
724
+ const skill = {
725
+ id: 'media_analyze',
726
+ name: 'media_analyze',
727
+ description: '分析图片/视频/音频并回答关于媒体的多轮问题。首次消息需包含媒体(FilePart raw 字节或工件 URL 引用),后续消息只发送文本问题即可,媒体会保留在任务上下文中。',
728
+ tags: ['media', 'image', 'video', 'audio', 'multimodal'],
729
+ examples: [],
730
+ inputModes: SUPPORTED_INPUT_MODES,
731
+ outputModes: ['text'],
732
+ securityRequirements: [],
733
+ };
734
+ return {
735
+ name: 'MAFW MediaAgent',
736
+ description: 'MAFW 内置多模态 Agent:基于 gateway media 配置段(默认 xiaomi/mimo-v2.5,每模态可独立指定 provider/model)对图片、视频、音频进行多轮问答分析。',
737
+ url: `${this.options.baseUrl}/a2a`,
738
+ version: '1.0.0',
739
+ provider: { url: this.options.baseUrl, organization: 'MAFW' },
740
+ capabilities: {
741
+ streaming: false,
742
+ pushNotifications: false,
743
+ extensions: [],
744
+ },
745
+ defaultInputModes: SUPPORTED_INPUT_MODES,
746
+ defaultOutputModes: ['text'],
747
+ skills: [skill],
748
+ supportedInterfaces: [],
749
+ securitySchemes: {},
750
+ securityRequirements: [],
751
+ signatures: [],
752
+ };
753
+ }
754
+ }
755
+ exports.MediaAgent = MediaAgent;