@jcheesepkg/nanobot 0.9.1 → 0.9.2

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 (245) hide show
  1. package/README.md +18 -18
  2. package/dist/agent/context.d.mts +4 -4
  3. package/dist/agent/context.d.mts.map +1 -1
  4. package/dist/agent/context.mjs +27 -28
  5. package/dist/agent/context.mjs.map +1 -1
  6. package/dist/agent/loop.d.mts +5 -3
  7. package/dist/agent/loop.d.mts.map +1 -1
  8. package/dist/agent/loop.mjs +64 -55
  9. package/dist/agent/loop.mjs.map +1 -1
  10. package/dist/agent/memory.d.mts.map +1 -1
  11. package/dist/agent/memory.mjs +3 -3
  12. package/dist/agent/memory.mjs.map +1 -1
  13. package/dist/agent/skills.d.mts.map +1 -1
  14. package/dist/agent/skills.mjs +4 -4
  15. package/dist/agent/skills.mjs.map +1 -1
  16. package/dist/agent/subagent.d.mts.map +1 -1
  17. package/dist/agent/subagent.mjs +22 -22
  18. package/dist/agent/subagent.mjs.map +1 -1
  19. package/dist/agent/tools/base.mjs +2 -2
  20. package/dist/agent/tools/base.mjs.map +1 -1
  21. package/dist/agent/tools/cron.d.mts +1 -1
  22. package/dist/agent/tools/cron.d.mts.map +1 -1
  23. package/dist/agent/tools/cron.mjs +11 -11
  24. package/dist/agent/tools/cron.mjs.map +1 -1
  25. package/dist/agent/tools/filesystem.d.mts +4 -4
  26. package/dist/agent/tools/filesystem.d.mts.map +1 -1
  27. package/dist/agent/tools/filesystem.mjs +20 -20
  28. package/dist/agent/tools/filesystem.mjs.map +1 -1
  29. package/dist/agent/tools/flex.d.mts +1 -1
  30. package/dist/agent/tools/flex.d.mts.map +1 -1
  31. package/dist/agent/tools/flex.mjs +112 -112
  32. package/dist/agent/tools/flex.mjs.map +1 -1
  33. package/dist/agent/tools/flex.test.mjs +60 -59
  34. package/dist/agent/tools/flex.test.mjs.map +1 -1
  35. package/dist/agent/tools/message.d.mts +1 -1
  36. package/dist/agent/tools/message.d.mts.map +1 -1
  37. package/dist/agent/tools/message.mjs +4 -4
  38. package/dist/agent/tools/message.mjs.map +1 -1
  39. package/dist/agent/tools/registry.d.mts.map +1 -1
  40. package/dist/agent/tools/registry.mjs +4 -4
  41. package/dist/agent/tools/registry.mjs.map +1 -1
  42. package/dist/agent/tools/shell.d.mts +1 -1
  43. package/dist/agent/tools/shell.mjs +4 -4
  44. package/dist/agent/tools/shell.mjs.map +1 -1
  45. package/dist/agent/tools/spawn.d.mts +1 -1
  46. package/dist/agent/tools/spawn.d.mts.map +1 -1
  47. package/dist/agent/tools/spawn.mjs +4 -4
  48. package/dist/agent/tools/spawn.mjs.map +1 -1
  49. package/dist/agent/tools/web.d.mts +2 -2
  50. package/dist/agent/tools/web.d.mts.map +1 -1
  51. package/dist/agent/tools/web.mjs +36 -36
  52. package/dist/agent/tools/web.mjs.map +1 -1
  53. package/dist/bus/events.mjs +1 -1
  54. package/dist/bus/events.mjs.map +1 -1
  55. package/dist/bus/queue.d.mts.map +1 -1
  56. package/dist/bus/queue.mjs.map +1 -1
  57. package/dist/channels/base.d.mts.map +1 -1
  58. package/dist/channels/base.mjs +2 -2
  59. package/dist/channels/base.mjs.map +1 -1
  60. package/dist/channels/line.d.mts +1 -0
  61. package/dist/channels/line.d.mts.map +1 -1
  62. package/dist/channels/line.mjs +65 -65
  63. package/dist/channels/line.mjs.map +1 -1
  64. package/dist/channels/line.test.mjs +26 -27
  65. package/dist/channels/line.test.mjs.map +1 -1
  66. package/dist/channels/manager.d.mts.map +1 -1
  67. package/dist/channels/manager.mjs +9 -9
  68. package/dist/channels/manager.mjs.map +1 -1
  69. package/dist/channels/telegram.mjs +34 -34
  70. package/dist/channels/telegram.mjs.map +1 -1
  71. package/dist/cli/index.mjs +36 -36
  72. package/dist/cli/index.mjs.map +1 -1
  73. package/dist/config/loader.d.mts.map +1 -1
  74. package/dist/config/loader.mjs +1 -1
  75. package/dist/config/loader.mjs.map +1 -1
  76. package/dist/config/schema.d.mts +387 -387
  77. package/dist/config/schema.d.mts.map +1 -1
  78. package/dist/config/schema.mjs +42 -42
  79. package/dist/config/schema.mjs.map +1 -1
  80. package/dist/gateway/server.d.mts.map +1 -1
  81. package/dist/gateway/server.mjs +48 -54
  82. package/dist/gateway/server.mjs.map +1 -1
  83. package/dist/heartbeat/service.d.mts.map +1 -1
  84. package/dist/heartbeat/service.mjs +8 -8
  85. package/dist/heartbeat/service.mjs.map +1 -1
  86. package/dist/index.d.mts +1 -1
  87. package/dist/index.d.mts.map +1 -1
  88. package/dist/index.mjs +2 -2
  89. package/dist/index.mjs.map +1 -1
  90. package/dist/node_modules/{@jridgewell → .bun/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell}/sourcemap-codec/dist/sourcemap-codec.mjs +1 -1
  91. package/dist/node_modules/.bun/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +1 -0
  92. package/dist/node_modules/{@vitest → .bun/@vitest_expect@2.1.9/node_modules/@vitest}/expect/dist/index.mjs +8 -8
  93. package/dist/node_modules/.bun/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.mjs.map +1 -0
  94. package/dist/node_modules/{@vitest → .bun/@vitest_pretty-format@2.1.9/node_modules/@vitest}/pretty-format/dist/index.mjs +2 -2
  95. package/dist/node_modules/.bun/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.mjs.map +1 -0
  96. package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/chunk-tasks.mjs +1 -1
  97. package/dist/node_modules/.bun/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.mjs.map +1 -0
  98. package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/index.mjs +6 -6
  99. package/dist/node_modules/.bun/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.mjs.map +1 -0
  100. package/dist/node_modules/{@vitest → .bun/@vitest_snapshot@2.1.9/node_modules/@vitest}/snapshot/dist/index.mjs +5 -5
  101. package/dist/node_modules/.bun/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.mjs.map +1 -0
  102. package/dist/node_modules/{@vitest → .bun/@vitest_spy@2.1.9/node_modules/@vitest}/spy/dist/index.mjs +2 -2
  103. package/dist/node_modules/.bun/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.mjs.map +1 -0
  104. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/chunk-_commonjsHelpers.mjs +3 -3
  105. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.mjs.map +1 -0
  106. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/diff.mjs +4 -4
  107. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.mjs.map +1 -0
  108. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/error.mjs +3 -3
  109. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.mjs.map +1 -0
  110. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/helpers.mjs +1 -1
  111. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.mjs.map +1 -0
  112. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/index.mjs +3 -3
  113. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.mjs.map +1 -0
  114. package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/source-map.mjs +1 -1
  115. package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.mjs.map +1 -0
  116. package/dist/node_modules/{chai → .bun/chai@5.3.3/node_modules/chai}/index.mjs +1 -1
  117. package/dist/node_modules/.bun/chai@5.3.3/node_modules/chai/index.mjs.map +1 -0
  118. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/arguments.mjs +1 -1
  119. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/arguments.mjs.map +1 -0
  120. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/array.mjs +1 -1
  121. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/array.mjs.map +1 -0
  122. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/bigint.mjs +1 -1
  123. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/bigint.mjs.map +1 -0
  124. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/class.mjs +1 -1
  125. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/class.mjs.map +1 -0
  126. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/date.mjs +1 -1
  127. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/date.mjs.map +1 -0
  128. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/error.mjs +1 -1
  129. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/error.mjs.map +1 -0
  130. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/function.mjs +1 -1
  131. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/function.mjs.map +1 -0
  132. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/helpers.mjs +1 -1
  133. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/helpers.mjs.map +1 -0
  134. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/html.mjs +1 -1
  135. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/html.mjs.map +1 -0
  136. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/index.mjs +1 -1
  137. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/index.mjs.map +1 -0
  138. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/map.mjs +1 -1
  139. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/map.mjs.map +1 -0
  140. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/number.mjs +1 -1
  141. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/number.mjs.map +1 -0
  142. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/object.mjs +1 -1
  143. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/object.mjs.map +1 -0
  144. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/promise.mjs +6 -0
  145. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/promise.mjs.map +1 -0
  146. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/regexp.mjs +1 -1
  147. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/regexp.mjs.map +1 -0
  148. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/set.mjs +1 -1
  149. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/set.mjs.map +1 -0
  150. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/string.mjs +1 -1
  151. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/string.mjs.map +1 -0
  152. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/symbol.mjs +1 -1
  153. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/symbol.mjs.map +1 -0
  154. package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/typedarray.mjs +1 -1
  155. package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/typedarray.mjs.map +1 -0
  156. package/dist/node_modules/{magic-string → .bun/magic-string@0.30.21/node_modules/magic-string}/dist/magic-string.es.mjs +2 -2
  157. package/dist/node_modules/.bun/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs.map +1 -0
  158. package/dist/node_modules/{@vitest/snapshot → .bun/pathe@1.1.2}/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +1 -1
  159. package/dist/node_modules/.bun/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs.map +1 -0
  160. package/dist/node_modules/{tinyrainbow → .bun/tinyrainbow@1.2.0/node_modules/tinyrainbow}/dist/chunk-BVHSVHOK.mjs +1 -1
  161. package/dist/node_modules/.bun/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.mjs.map +1 -0
  162. package/dist/node_modules/{tinyrainbow → .bun/tinyrainbow@1.2.0/node_modules/tinyrainbow}/dist/node.mjs +1 -1
  163. package/dist/node_modules/.bun/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.mjs.map +1 -0
  164. package/dist/node_modules/{tinyspy → .bun/tinyspy@3.0.2/node_modules/tinyspy}/dist/index.mjs +1 -1
  165. package/dist/node_modules/.bun/tinyspy@3.0.2/node_modules/tinyspy/dist/index.mjs.map +1 -0
  166. package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs +1 -1
  167. package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs.map +1 -0
  168. package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/date.W2xKR2qe.mjs +1 -1
  169. package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/date.W2xKR2qe.mjs.map +1 -0
  170. package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/utils.C8RiOc4B.mjs +2 -2
  171. package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/utils.C8RiOc4B.mjs.map +1 -0
  172. package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/vi.DgezovHB.mjs +11 -11
  173. package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/vi.DgezovHB.mjs.map +1 -0
  174. package/dist/providers/base.d.mts +2 -2
  175. package/dist/providers/base.d.mts.map +1 -1
  176. package/dist/providers/openai-provider.d.mts.map +1 -1
  177. package/dist/providers/openai-provider.mjs +10 -9
  178. package/dist/providers/openai-provider.mjs.map +1 -1
  179. package/dist/providers/registry.d.mts +1 -1
  180. package/dist/providers/registry.d.mts.map +1 -1
  181. package/dist/providers/registry.mjs +99 -99
  182. package/dist/providers/registry.mjs.map +1 -1
  183. package/dist/session/manager.d.mts +2 -2
  184. package/dist/session/manager.d.mts.map +1 -1
  185. package/dist/session/manager.mjs +18 -19
  186. package/dist/session/manager.mjs.map +1 -1
  187. package/dist/utils/helpers.d.mts.map +1 -1
  188. package/dist/utils/helpers.mjs.map +1 -1
  189. package/package.json +11 -11
  190. package/skills/cron/SKILL.md +12 -8
  191. package/skills/daily-summary/SKILL.md +4 -0
  192. package/skills/english/SKILL.md +21 -7
  193. package/skills/expense/SKILL.md +11 -7
  194. package/skills/fortune/SKILL.md +24 -20
  195. package/skills/habit/SKILL.md +2 -1
  196. package/skills/hydration/SKILL.md +3 -0
  197. package/skills/memory/SKILL.md +1 -0
  198. package/skills/mood/SKILL.md +10 -6
  199. package/skills/skill-creator/SKILL.md +3 -0
  200. package/skills/summarize/SKILL.md +1 -0
  201. package/skills/weather/SKILL.md +10 -8
  202. package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +0 -1
  203. package/dist/node_modules/@vitest/expect/dist/index.mjs.map +0 -1
  204. package/dist/node_modules/@vitest/pretty-format/dist/index.mjs.map +0 -1
  205. package/dist/node_modules/@vitest/runner/dist/chunk-tasks.mjs.map +0 -1
  206. package/dist/node_modules/@vitest/runner/dist/index.mjs.map +0 -1
  207. package/dist/node_modules/@vitest/snapshot/dist/index.mjs.map +0 -1
  208. package/dist/node_modules/@vitest/snapshot/node_modules/pathe/dist/shared/pathe.ff20891b.mjs.map +0 -1
  209. package/dist/node_modules/@vitest/spy/dist/index.mjs.map +0 -1
  210. package/dist/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.mjs.map +0 -1
  211. package/dist/node_modules/@vitest/utils/dist/diff.mjs.map +0 -1
  212. package/dist/node_modules/@vitest/utils/dist/error.mjs.map +0 -1
  213. package/dist/node_modules/@vitest/utils/dist/helpers.mjs.map +0 -1
  214. package/dist/node_modules/@vitest/utils/dist/index.mjs.map +0 -1
  215. package/dist/node_modules/@vitest/utils/dist/source-map.mjs.map +0 -1
  216. package/dist/node_modules/chai/index.mjs.map +0 -1
  217. package/dist/node_modules/loupe/lib/arguments.mjs.map +0 -1
  218. package/dist/node_modules/loupe/lib/array.mjs.map +0 -1
  219. package/dist/node_modules/loupe/lib/bigint.mjs.map +0 -1
  220. package/dist/node_modules/loupe/lib/class.mjs.map +0 -1
  221. package/dist/node_modules/loupe/lib/date.mjs.map +0 -1
  222. package/dist/node_modules/loupe/lib/error.mjs.map +0 -1
  223. package/dist/node_modules/loupe/lib/function.mjs.map +0 -1
  224. package/dist/node_modules/loupe/lib/helpers.mjs.map +0 -1
  225. package/dist/node_modules/loupe/lib/html.mjs.map +0 -1
  226. package/dist/node_modules/loupe/lib/index.mjs.map +0 -1
  227. package/dist/node_modules/loupe/lib/map.mjs.map +0 -1
  228. package/dist/node_modules/loupe/lib/number.mjs.map +0 -1
  229. package/dist/node_modules/loupe/lib/object.mjs.map +0 -1
  230. package/dist/node_modules/loupe/lib/promise.mjs +0 -6
  231. package/dist/node_modules/loupe/lib/promise.mjs.map +0 -1
  232. package/dist/node_modules/loupe/lib/regexp.mjs.map +0 -1
  233. package/dist/node_modules/loupe/lib/set.mjs.map +0 -1
  234. package/dist/node_modules/loupe/lib/string.mjs.map +0 -1
  235. package/dist/node_modules/loupe/lib/symbol.mjs.map +0 -1
  236. package/dist/node_modules/loupe/lib/typedarray.mjs.map +0 -1
  237. package/dist/node_modules/magic-string/dist/magic-string.es.mjs.map +0 -1
  238. package/dist/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.mjs.map +0 -1
  239. package/dist/node_modules/tinyrainbow/dist/node.mjs.map +0 -1
  240. package/dist/node_modules/tinyspy/dist/index.mjs.map +0 -1
  241. package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs.map +0 -1
  242. package/dist/node_modules/vitest/dist/chunks/date.W2xKR2qe.mjs.map +0 -1
  243. package/dist/node_modules/vitest/dist/chunks/utils.C8RiOc4B.mjs.map +0 -1
  244. package/dist/node_modules/vitest/dist/chunks/vi.DgezovHB.mjs.map +0 -1
  245. /package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/utils.mjs +0 -0
@@ -12,7 +12,6 @@ var FlexTool = class extends Tool {
12
12
  name = "flex_message";
13
13
  description = "Build a LINE Flex Message from a template. Returns JSON that will be rendered as a rich card in LINE. Use this instead of outputting raw JSON.";
14
14
  parameters = {
15
- type: "object",
16
15
  properties: {
17
16
  template: {
18
17
  type: "string",
@@ -145,7 +144,8 @@ var FlexTool = class extends Tool {
145
144
  }
146
145
  }
147
146
  },
148
- required: ["template", "data"]
147
+ required: ["template", "data"],
148
+ type: "object"
149
149
  };
150
150
  async execute(args) {
151
151
  const template = String(args.template);
@@ -177,8 +177,8 @@ var FlexTool = class extends Tool {
177
177
  default: return `Error: unknown template '${template}'. Use: fortune, info_card, action_buttons, receipt, morning_summary, hydration, custom.`;
178
178
  }
179
179
  return `${JSON.stringify(flex)}\n\n(Card sent automatically. Do NOT repeat the JSON. Just respond naturally.)`;
180
- } catch (err) {
181
- return `Error building flex message: ${err instanceof Error ? err.message : err}`;
180
+ } catch (error) {
181
+ return `Error building flex message: ${error instanceof Error ? error.message : error}`;
182
182
  }
183
183
  }
184
184
  buildFortune(data) {
@@ -190,38 +190,35 @@ var FlexTool = class extends Tool {
190
190
  const starText = "★".repeat(stars) + "☆".repeat(5 - stars);
191
191
  const contents = [
192
192
  {
193
- type: "text",
193
+ size: "xl",
194
194
  text: sign,
195
- weight: "bold",
196
- size: "xl"
195
+ type: "text",
196
+ weight: "bold"
197
197
  },
198
198
  {
199
- type: "text",
200
- text: "今日の運勢",
199
+ color: "#666666",
201
200
  size: "sm",
202
- color: "#666666"
201
+ text: "今日の運勢",
202
+ type: "text"
203
203
  },
204
204
  {
205
- type: "text",
206
- text: starText,
205
+ margin: "md",
207
206
  size: "xxl",
208
- margin: "md"
207
+ text: starText,
208
+ type: "text"
209
209
  }
210
210
  ];
211
211
  if (message) contents.push({
212
- type: "text",
212
+ margin: "sm",
213
213
  text: message,
214
- wrap: true,
215
- margin: "sm"
214
+ type: "text",
215
+ wrap: true
216
216
  });
217
217
  if (luckyColor || luckyItem) contents.push({
218
- type: "separator",
219
- margin: "md"
218
+ margin: "md",
219
+ type: "separator"
220
220
  });
221
221
  if (luckyColor) contents.push({
222
- type: "box",
223
- layout: "horizontal",
224
- margin: "md",
225
222
  contents: [{
226
223
  type: "text",
227
224
  text: "ラッキーカラー",
@@ -233,12 +230,12 @@ var FlexTool = class extends Tool {
233
230
  text: luckyColor,
234
231
  size: "sm",
235
232
  align: "end"
236
- }]
233
+ }],
234
+ layout: "horizontal",
235
+ margin: "md",
236
+ type: "box"
237
237
  });
238
238
  if (luckyItem) contents.push({
239
- type: "box",
240
- layout: "horizontal",
241
- margin: luckyColor ? "sm" : "md",
242
239
  contents: [{
243
240
  type: "text",
244
241
  text: "ラッキーアイテム",
@@ -250,44 +247,47 @@ var FlexTool = class extends Tool {
250
247
  text: luckyItem,
251
248
  size: "sm",
252
249
  align: "end"
253
- }]
250
+ }],
251
+ layout: "horizontal",
252
+ margin: luckyColor ? "sm" : "md",
253
+ type: "box"
254
254
  });
255
255
  return {
256
- type: "bubble",
257
- size: "kilo",
258
256
  body: {
259
257
  type: "box",
260
258
  layout: "vertical",
261
259
  paddingAll: "lg",
262
260
  contents
263
- }
261
+ },
262
+ size: "kilo",
263
+ type: "bubble"
264
264
  };
265
265
  }
266
266
  buildInfoCard(data) {
267
267
  const title = String(data.title ?? "お知らせ");
268
268
  const body = String(data.body ?? "");
269
269
  const contents = [{
270
- type: "text",
270
+ size: "lg",
271
271
  text: title,
272
- weight: "bold",
273
- size: "lg"
272
+ type: "text",
273
+ weight: "bold"
274
274
  }, {
275
- type: "separator",
276
- margin: "md"
275
+ margin: "md",
276
+ type: "separator"
277
277
  }];
278
278
  if (body) contents.push({
279
- type: "text",
279
+ margin: "md",
280
280
  text: body,
281
- wrap: true,
282
- margin: "md"
281
+ type: "text",
282
+ wrap: true
283
283
  });
284
284
  return {
285
- type: "bubble",
286
285
  body: {
287
286
  type: "box",
288
287
  layout: "vertical",
289
288
  contents
290
- }
289
+ },
290
+ type: "bubble"
291
291
  };
292
292
  }
293
293
  buildActionButtons(data) {
@@ -295,24 +295,23 @@ var FlexTool = class extends Tool {
295
295
  const buttons = data.buttons ?? [];
296
296
  if (buttons.length === 0) buttons.push({
297
297
  label: "はい",
298
- text: "はい",
299
- style: "primary"
298
+ style: "primary",
299
+ text: "はい"
300
300
  }, {
301
301
  label: "いいえ",
302
- text: "いいえ",
303
- style: "secondary"
302
+ style: "secondary",
303
+ text: "いいえ"
304
304
  });
305
305
  const buttonContents = buttons.map((btn) => ({
306
- type: "button",
307
- style: String(btn.style ?? "primary"),
308
306
  action: {
309
307
  type: "message",
310
308
  label: String(btn.label ?? ""),
311
309
  text: String(btn.text ?? btn.label ?? "")
312
- }
310
+ },
311
+ style: String(btn.style ?? "primary"),
312
+ type: "button"
313
313
  }));
314
314
  return {
315
- type: "bubble",
316
315
  body: {
317
316
  type: "box",
318
317
  layout: "vertical",
@@ -328,7 +327,8 @@ var FlexTool = class extends Tool {
328
327
  layout: "vertical",
329
328
  spacing: "sm",
330
329
  contents: buttonContents
331
- }
330
+ },
331
+ type: "bubble"
332
332
  };
333
333
  }
334
334
  buildReceipt(data) {
@@ -336,17 +336,14 @@ var FlexTool = class extends Tool {
336
336
  const items = data.items ?? [];
337
337
  const total = data.total ? String(data.total) : null;
338
338
  const contents = [{
339
- type: "text",
340
339
  text: `💰 ${title}`,
340
+ type: "text",
341
341
  weight: "bold"
342
342
  }, {
343
- type: "separator",
344
- margin: "lg"
343
+ margin: "lg",
344
+ type: "separator"
345
345
  }];
346
346
  for (const item of items) contents.push({
347
- type: "box",
348
- layout: "horizontal",
349
- margin: "md",
350
347
  contents: [{
351
348
  type: "text",
352
349
  text: String(item.name ?? ""),
@@ -355,15 +352,15 @@ var FlexTool = class extends Tool {
355
352
  type: "text",
356
353
  text: String(item.value ?? ""),
357
354
  align: "end"
358
- }]
355
+ }],
356
+ layout: "horizontal",
357
+ margin: "md",
358
+ type: "box"
359
359
  });
360
360
  if (total) contents.push({
361
- type: "separator",
362
- margin: "lg"
361
+ margin: "lg",
362
+ type: "separator"
363
363
  }, {
364
- type: "box",
365
- layout: "horizontal",
366
- margin: "md",
367
364
  contents: [{
368
365
  type: "text",
369
366
  text: "合計",
@@ -373,15 +370,18 @@ var FlexTool = class extends Tool {
373
370
  text: total,
374
371
  weight: "bold",
375
372
  align: "end"
376
- }]
373
+ }],
374
+ layout: "horizontal",
375
+ margin: "md",
376
+ type: "box"
377
377
  });
378
378
  return {
379
- type: "bubble",
380
379
  body: {
381
380
  type: "box",
382
381
  layout: "vertical",
383
382
  contents
384
- }
383
+ },
384
+ type: "bubble"
385
385
  };
386
386
  }
387
387
  buildMorningSummary(data) {
@@ -392,51 +392,43 @@ var FlexTool = class extends Tool {
392
392
  const schedule = data.schedule ?? [];
393
393
  const headerColor = String(data.header_color ?? "#1DB446");
394
394
  const headerContents = [{
395
- type: "text",
396
- text: greeting,
397
395
  color: "#ffffff",
398
- weight: "bold",
399
- size: "lg"
396
+ size: "lg",
397
+ text: greeting,
398
+ type: "text",
399
+ weight: "bold"
400
400
  }];
401
401
  if (date) headerContents.push({
402
- type: "text",
403
- text: date,
404
402
  color: "#ffffff",
405
- size: "sm"
403
+ size: "sm",
404
+ text: date,
405
+ type: "text"
406
406
  });
407
407
  const bodyContents = [];
408
408
  if (weather) bodyContents.push({
409
- type: "text",
410
409
  text: weather,
410
+ type: "text",
411
411
  weight: "bold"
412
412
  });
413
413
  if (advice) bodyContents.push({
414
- type: "text",
415
- text: advice,
414
+ color: "#666666",
416
415
  size: "sm",
417
- color: "#666666"
416
+ text: advice,
417
+ type: "text"
418
418
  });
419
419
  if (schedule.length > 0) {
420
420
  bodyContents.push({
421
- type: "separator",
422
- margin: "md"
421
+ margin: "md",
422
+ type: "separator"
423
423
  });
424
424
  for (const line of schedule) bodyContents.push({
425
- type: "text",
426
- text: line,
427
425
  margin: "md",
426
+ text: line,
427
+ type: "text",
428
428
  wrap: true
429
429
  });
430
430
  }
431
431
  return {
432
- type: "bubble",
433
- header: {
434
- type: "box",
435
- layout: "vertical",
436
- backgroundColor: headerColor,
437
- paddingAll: "lg",
438
- contents: headerContents
439
- },
440
432
  body: {
441
433
  type: "box",
442
434
  layout: "vertical",
@@ -445,7 +437,15 @@ var FlexTool = class extends Tool {
445
437
  type: "text",
446
438
  text: "良い一日を!"
447
439
  }]
448
- }
440
+ },
441
+ header: {
442
+ type: "box",
443
+ layout: "vertical",
444
+ backgroundColor: headerColor,
445
+ paddingAll: "lg",
446
+ contents: headerContents
447
+ },
448
+ type: "bubble"
449
449
  };
450
450
  }
451
451
  buildHydration(data) {
@@ -456,8 +456,6 @@ var FlexTool = class extends Tool {
456
456
  const buttonLabel = String(data.button_label ?? "飲んだ!");
457
457
  const buttonText = String(data.button_text ?? "水飲んだ");
458
458
  return {
459
- type: "bubble",
460
- size: "kilo",
461
459
  body: {
462
460
  type: "box",
463
461
  layout: "vertical",
@@ -484,23 +482,25 @@ var FlexTool = class extends Tool {
484
482
  text: buttonText
485
483
  }
486
484
  }]
487
- }
485
+ },
486
+ size: "kilo",
487
+ type: "bubble"
488
488
  };
489
489
  }
490
490
  buildCustom(data) {
491
491
  const bubbles = data.bubbles;
492
492
  if (Array.isArray(bubbles) && bubbles.length > 0) return {
493
- type: "carousel",
494
- contents: bubbles
493
+ contents: bubbles,
494
+ type: "carousel"
495
495
  };
496
496
  const rawContents = data.contents;
497
497
  if (Array.isArray(rawContents) && rawContents.length > 0) return {
498
- type: "bubble",
499
498
  body: {
500
499
  type: "box",
501
500
  layout: "vertical",
502
501
  contents: rawContents
503
- }
502
+ },
503
+ type: "bubble"
504
504
  };
505
505
  const title = data.title ? String(data.title) : null;
506
506
  const body = data.body ? String(data.body) : null;
@@ -508,16 +508,16 @@ var FlexTool = class extends Tool {
508
508
  const headerColor = data.header_color ? String(data.header_color) : null;
509
509
  if (buttons.length === 0 && data.button_label) buttons = [{
510
510
  label: String(data.button_label),
511
- text: String(data.button_text ?? data.button_label),
512
- style: data.button_style ?? "primary"
511
+ style: data.button_style ?? "primary",
512
+ text: String(data.button_text ?? data.button_label)
513
513
  }];
514
514
  if (!title && !body && buttons.length === 0) throw new Error("custom template requires 'contents' array, or at least one of: title, body, buttons");
515
515
  const bodyContents = [];
516
516
  if (title) bodyContents.push({
517
- type: "text",
517
+ size: "lg",
518
518
  text: title,
519
- weight: "bold",
520
- size: "lg"
519
+ type: "text",
520
+ weight: "bold"
521
521
  });
522
522
  if (body) {
523
523
  if (title) bodyContents.push({
@@ -525,14 +525,13 @@ var FlexTool = class extends Tool {
525
525
  margin: "md"
526
526
  });
527
527
  bodyContents.push({
528
- type: "text",
528
+ margin: title ? "md" : void 0,
529
529
  text: body,
530
- wrap: true,
531
- margin: title ? "md" : void 0
530
+ type: "text",
531
+ wrap: true
532
532
  });
533
533
  }
534
534
  const bubble = {
535
- type: "bubble",
536
535
  body: {
537
536
  type: "box",
538
537
  layout: "vertical",
@@ -540,28 +539,26 @@ var FlexTool = class extends Tool {
540
539
  type: "text",
541
540
  text: " "
542
541
  }]
543
- }
542
+ },
543
+ type: "bubble"
544
544
  };
545
545
  if (headerColor && title) {
546
546
  bubble.header = {
547
- type: "box",
548
- layout: "vertical",
549
547
  backgroundColor: headerColor,
550
- paddingAll: "lg",
551
548
  contents: [{
552
549
  type: "text",
553
550
  text: title,
554
551
  color: "#ffffff",
555
552
  weight: "bold",
556
553
  size: "lg"
557
- }]
554
+ }],
555
+ layout: "vertical",
556
+ paddingAll: "lg",
557
+ type: "box"
558
558
  };
559
559
  bodyContents.shift();
560
560
  }
561
561
  if (buttons.length > 0) bubble.footer = {
562
- type: "box",
563
- layout: "vertical",
564
- spacing: "sm",
565
562
  contents: buttons.map((btn) => ({
566
563
  type: "button",
567
564
  style: String(btn.style ?? "primary"),
@@ -570,7 +567,10 @@ var FlexTool = class extends Tool {
570
567
  label: String(btn.label ?? ""),
571
568
  text: String(btn.text ?? btn.label ?? "")
572
569
  }
573
- }))
570
+ })),
571
+ layout: "vertical",
572
+ spacing: "sm",
573
+ type: "box"
574
574
  };
575
575
  return bubble;
576
576
  }
@@ -1 +1 @@
1
- {"version":3,"file":"flex.mjs","names":[],"sources":["../../../src/agent/tools/flex.ts"],"sourcesContent":["import { Tool } from \"./base.js\";\n\n/**\n * Tool for building LINE Flex Messages from structured data.\n *\n * The LLM calls this tool with a template name and data object,\n * and the tool returns valid Flex JSON that line.ts parseMessage()\n * will detect and send as a Flex Message.\n */\nexport class FlexTool extends Tool {\n readonly name = \"flex_message\";\n readonly description =\n \"Build a LINE Flex Message from a template. Returns JSON that will be rendered as a rich card in LINE. Use this instead of outputting raw JSON.\";\n readonly parameters = {\n type: \"object\",\n properties: {\n template: {\n type: \"string\",\n description:\n \"Template name. Available: fortune, info_card, action_buttons, receipt, morning_summary, hydration, custom.\",\n },\n data: {\n type: \"object\",\n description: \"Template-specific data. See each template for fields.\",\n properties: {\n // fortune\n sign: { type: \"string\", description: \"Zodiac sign with emoji (e.g. '♍ 乙女座')\" },\n stars: { type: \"integer\", description: \"1-5 star rating\" },\n message: { type: \"string\", description: \"Fortune message\" },\n lucky_color: { type: \"string\", description: \"Lucky color name\" },\n lucky_item: { type: \"string\", description: \"Lucky item name\" },\n // info_card\n title: { type: \"string\", description: \"Card title\" },\n body: { type: \"string\", description: \"Card body text\" },\n // action_buttons\n prompt: { type: \"string\", description: \"Question or prompt text\" },\n buttons: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\" },\n text: { type: \"string\" },\n style: { type: \"string\", enum: [\"primary\", \"secondary\", \"link\"] },\n },\n },\n description: \"Button definitions\",\n },\n // receipt\n items: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n value: { type: \"string\" },\n },\n },\n description: \"Line items\",\n },\n total: { type: \"string\", description: \"Total amount\" },\n // morning_summary\n greeting: { type: \"string\", description: \"Greeting text (e.g. 'おはよう!')\" },\n date: { type: \"string\", description: \"Date string (e.g. '2月13日 木曜日')\" },\n weather: { type: \"string\", description: \"Weather info (e.g. '東京 12°C 曇り')\" },\n advice: { type: \"string\", description: \"Short advice (e.g. 'コートでOK')\" },\n schedule: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Schedule/reminder lines\",\n },\n header_color: { type: \"string\", description: \"Header background color hex (default: #1DB446)\" },\n // hydration\n current: { type: \"integer\", description: \"Current count (e.g. glasses drunk)\" },\n goal: { type: \"integer\", description: \"Goal count\" },\n unit: { type: \"string\", description: \"Unit label (default: 杯)\" },\n button_label: { type: \"string\", description: \"Button label (default: '飲んだ!')\" },\n button_text: { type: \"string\", description: \"Button message text (default: '水飲んだ')\" },\n // custom\n contents: {\n type: \"array\",\n description: \"Raw Flex body contents array for custom template\",\n },\n bubbles: {\n type: \"array\",\n items: { type: \"object\" },\n description: \"Array of bubble objects for a carousel (horizontal swipeable cards). Each item should be a complete bubble with type, body, etc.\",\n },\n },\n },\n },\n required: [\"template\", \"data\"],\n };\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const template = String(args.template);\n const data = (args.data ?? {}) as Record<string, unknown>;\n\n try {\n let flex: Record<string, unknown>;\n\n switch (template) {\n case \"fortune\":\n flex = this.buildFortune(data);\n break;\n case \"info_card\":\n flex = this.buildInfoCard(data);\n break;\n case \"action_buttons\":\n flex = this.buildActionButtons(data);\n break;\n case \"receipt\":\n flex = this.buildReceipt(data);\n break;\n case \"morning_summary\":\n flex = this.buildMorningSummary(data);\n break;\n case \"hydration\":\n flex = this.buildHydration(data);\n break;\n case \"custom\":\n flex = this.buildCustom(data);\n break;\n default:\n return `Error: unknown template '${template}'. Use: fortune, info_card, action_buttons, receipt, morning_summary, hydration, custom.`;\n }\n\n const json = JSON.stringify(flex);\n return `${json}\\n\\n(Card sent automatically. Do NOT repeat the JSON. Just respond naturally.)`;\n } catch (err) {\n return `Error building flex message: ${err instanceof Error ? err.message : err}`;\n }\n }\n\n private buildFortune(data: Record<string, unknown>): Record<string, unknown> {\n const sign = String(data.sign ?? \"♈ 牡羊座\");\n const stars = Math.max(1, Math.min(5, Number(data.stars ?? 3)));\n const message = String(data.message ?? \"\");\n const luckyColor = data.lucky_color ? String(data.lucky_color) : null;\n const luckyItem = data.lucky_item ? String(data.lucky_item) : null;\n\n const starText = \"★\".repeat(stars) + \"☆\".repeat(5 - stars);\n\n const contents: Record<string, unknown>[] = [\n { type: \"text\", text: sign, weight: \"bold\", size: \"xl\" },\n { type: \"text\", text: \"今日の運勢\", size: \"sm\", color: \"#666666\" },\n { type: \"text\", text: starText, size: \"xxl\", margin: \"md\" },\n ];\n\n if (message) {\n contents.push({\n type: \"text\",\n text: message,\n wrap: true,\n margin: \"sm\",\n });\n }\n\n if (luckyColor || luckyItem) {\n contents.push({ type: \"separator\", margin: \"md\" });\n }\n\n if (luckyColor) {\n contents.push({\n type: \"box\",\n layout: \"horizontal\",\n margin: \"md\",\n contents: [\n { type: \"text\", text: \"ラッキーカラー\", size: \"sm\", color: \"#228B22\", flex: 0 },\n { type: \"text\", text: luckyColor, size: \"sm\", align: \"end\" },\n ],\n });\n }\n\n if (luckyItem) {\n contents.push({\n type: \"box\",\n layout: \"horizontal\",\n margin: luckyColor ? \"sm\" : \"md\",\n contents: [\n { type: \"text\", text: \"ラッキーアイテム\", size: \"sm\", color: \"#228B22\", flex: 0 },\n { type: \"text\", text: luckyItem, size: \"sm\", align: \"end\" },\n ],\n });\n }\n\n return {\n type: \"bubble\",\n size: \"kilo\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n paddingAll: \"lg\",\n contents,\n },\n };\n }\n\n private buildInfoCard(data: Record<string, unknown>): Record<string, unknown> {\n const title = String(data.title ?? \"お知らせ\");\n const body = String(data.body ?? \"\");\n\n const contents: Record<string, unknown>[] = [\n { type: \"text\", text: title, weight: \"bold\", size: \"lg\" },\n { type: \"separator\", margin: \"md\" },\n ];\n\n if (body) {\n contents.push({\n type: \"text\",\n text: body,\n wrap: true,\n margin: \"md\",\n });\n }\n\n return {\n type: \"bubble\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents,\n },\n };\n }\n\n private buildActionButtons(data: Record<string, unknown>): Record<string, unknown> {\n const prompt = String(data.prompt ?? \"選択してください\");\n const buttons = (data.buttons ?? []) as Array<Record<string, unknown>>;\n\n if (buttons.length === 0) {\n // Default yes/no\n buttons.push(\n { label: \"はい\", text: \"はい\", style: \"primary\" },\n { label: \"いいえ\", text: \"いいえ\", style: \"secondary\" },\n );\n }\n\n const buttonContents = buttons.map((btn) => ({\n type: \"button\",\n style: String(btn.style ?? \"primary\"),\n action: {\n type: \"message\",\n label: String(btn.label ?? \"\"),\n text: String(btn.text ?? btn.label ?? \"\"),\n },\n }));\n\n return {\n type: \"bubble\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: [\n { type: \"text\", text: prompt, weight: \"bold\", wrap: true },\n ],\n },\n footer: {\n type: \"box\",\n layout: \"vertical\",\n spacing: \"sm\",\n contents: buttonContents,\n },\n };\n }\n\n private buildReceipt(data: Record<string, unknown>): Record<string, unknown> {\n const title = String(data.title ?? \"明細\");\n const items = (data.items ?? []) as Array<Record<string, unknown>>;\n const total = data.total ? String(data.total) : null;\n\n const contents: Record<string, unknown>[] = [\n { type: \"text\", text: `💰 ${title}`, weight: \"bold\" },\n { type: \"separator\", margin: \"lg\" },\n ];\n\n for (const item of items) {\n contents.push({\n type: \"box\",\n layout: \"horizontal\",\n margin: \"md\",\n contents: [\n { type: \"text\", text: String(item.name ?? \"\"), flex: 0 },\n { type: \"text\", text: String(item.value ?? \"\"), align: \"end\" },\n ],\n });\n }\n\n if (total) {\n contents.push(\n { type: \"separator\", margin: \"lg\" },\n {\n type: \"box\",\n layout: \"horizontal\",\n margin: \"md\",\n contents: [\n { type: \"text\", text: \"合計\", weight: \"bold\" },\n { type: \"text\", text: total, weight: \"bold\", align: \"end\" },\n ],\n },\n );\n }\n\n return {\n type: \"bubble\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents,\n },\n };\n }\n\n private buildMorningSummary(data: Record<string, unknown>): Record<string, unknown> {\n const greeting = String(data.greeting ?? \"おはよう!\");\n const date = String(data.date ?? \"\");\n const weather = data.weather ? String(data.weather) : null;\n const advice = data.advice ? String(data.advice) : null;\n const schedule = (data.schedule ?? []) as string[];\n const headerColor = String(data.header_color ?? \"#1DB446\");\n\n const headerContents: Record<string, unknown>[] = [\n { type: \"text\", text: greeting, color: \"#ffffff\", weight: \"bold\", size: \"lg\" },\n ];\n if (date) {\n headerContents.push({ type: \"text\", text: date, color: \"#ffffff\", size: \"sm\" });\n }\n\n const bodyContents: Record<string, unknown>[] = [];\n\n if (weather) {\n bodyContents.push({ type: \"text\", text: weather, weight: \"bold\" });\n }\n if (advice) {\n bodyContents.push({ type: \"text\", text: advice, size: \"sm\", color: \"#666666\" });\n }\n\n if (schedule.length > 0) {\n bodyContents.push({ type: \"separator\", margin: \"md\" });\n for (const line of schedule) {\n bodyContents.push({ type: \"text\", text: line, margin: \"md\", wrap: true });\n }\n }\n\n return {\n type: \"bubble\",\n header: {\n type: \"box\",\n layout: \"vertical\",\n backgroundColor: headerColor,\n paddingAll: \"lg\",\n contents: headerContents,\n },\n body: {\n type: \"box\",\n layout: \"vertical\",\n paddingAll: \"lg\",\n contents: bodyContents.length > 0 ? bodyContents : [{ type: \"text\", text: \"良い一日を!\" }],\n },\n };\n }\n\n private buildHydration(data: Record<string, unknown>): Record<string, unknown> {\n const title = String(data.title ?? \"水飲んだ?\");\n const current = Number(data.current ?? 0);\n const goal = Number(data.goal ?? 8);\n const unit = String(data.unit ?? \"杯\");\n const buttonLabel = String(data.button_label ?? \"飲んだ!\");\n const buttonText = String(data.button_text ?? \"水飲んだ\");\n\n return {\n type: \"bubble\",\n size: \"kilo\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: [\n { type: \"text\", text: title, size: \"xl\" },\n { type: \"text\", text: `今日: ${current}${unit} / ${goal}${unit}`, color: \"#666666\" },\n ],\n },\n footer: {\n type: \"box\",\n layout: \"horizontal\",\n contents: [\n {\n type: \"button\",\n style: \"primary\",\n color: \"#00B9ED\",\n action: { type: \"message\", label: buttonLabel, text: buttonText },\n },\n ],\n },\n };\n }\n\n private buildCustom(data: Record<string, unknown>): Record<string, unknown> {\n // Carousel: array of bubble objects → horizontal swipeable cards\n const bubbles = data.bubbles as unknown[];\n if (Array.isArray(bubbles) && bubbles.length > 0) {\n return {\n type: \"carousel\",\n contents: bubbles,\n };\n }\n\n // If raw contents array is provided, use it directly as body contents\n const rawContents = data.contents as unknown[];\n if (Array.isArray(rawContents) && rawContents.length > 0) {\n return {\n type: \"bubble\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: rawContents,\n },\n };\n }\n\n // Fallback: auto-build a card from common fields (title, body, buttons, header_color)\n const title = data.title ? String(data.title) : null;\n const body = data.body ? String(data.body) : null;\n let buttons = Array.isArray(data.buttons) ? data.buttons as Array<Record<string, unknown>> : [];\n const headerColor = data.header_color ? String(data.header_color) : null;\n\n // Support flat button_label/button_text shorthand (like hydration template)\n if (buttons.length === 0 && data.button_label) {\n buttons = [{\n label: String(data.button_label),\n text: String(data.button_text ?? data.button_label),\n style: data.button_style ?? \"primary\",\n }];\n }\n\n if (!title && !body && buttons.length === 0) {\n throw new Error(\"custom template requires 'contents' array, or at least one of: title, body, buttons\");\n }\n\n const bodyContents: Record<string, unknown>[] = [];\n\n if (title) {\n bodyContents.push({ type: \"text\", text: title, weight: \"bold\", size: \"lg\" });\n }\n if (body) {\n if (title) bodyContents.push({ type: \"separator\", margin: \"md\" });\n bodyContents.push({ type: \"text\", text: body, wrap: true, margin: title ? \"md\" : undefined });\n }\n\n const bubble: Record<string, unknown> = {\n type: \"bubble\",\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: bodyContents.length > 0 ? bodyContents : [{ type: \"text\", text: \" \" }],\n },\n };\n\n // Add colored header if specified\n if (headerColor && title) {\n bubble.header = {\n type: \"box\",\n layout: \"vertical\",\n backgroundColor: headerColor,\n paddingAll: \"lg\",\n contents: [\n { type: \"text\", text: title, color: \"#ffffff\", weight: \"bold\", size: \"lg\" },\n ],\n };\n // Remove title from body since it's in the header now\n bodyContents.shift();\n }\n\n // Add buttons as footer\n if (buttons.length > 0) {\n bubble.footer = {\n type: \"box\",\n layout: \"vertical\",\n spacing: \"sm\",\n contents: buttons.map((btn) => ({\n type: \"button\",\n style: String(btn.style ?? \"primary\"),\n action: {\n type: \"message\",\n label: String(btn.label ?? \"\"),\n text: String(btn.text ?? btn.label ?? \"\"),\n },\n })),\n };\n }\n\n return bubble;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"flex.mjs","names":[],"sources":["../../../src/agent/tools/flex.ts"],"sourcesContent":["import { Tool } from \"./base.js\";\n\n/**\n * Tool for building LINE Flex Messages from structured data.\n *\n * The LLM calls this tool with a template name and data object,\n * and the tool returns valid Flex JSON that line.ts parseMessage()\n * will detect and send as a Flex Message.\n */\nexport class FlexTool extends Tool {\n readonly name = \"flex_message\";\n readonly description =\n \"Build a LINE Flex Message from a template. Returns JSON that will be rendered as a rich card in LINE. Use this instead of outputting raw JSON.\";\n readonly parameters = {\n properties: {\n template: {\n type: \"string\",\n description:\n \"Template name. Available: fortune, info_card, action_buttons, receipt, morning_summary, hydration, custom.\",\n },\n data: {\n type: \"object\",\n description: \"Template-specific data. See each template for fields.\",\n properties: {\n // fortune\n sign: {\n type: \"string\",\n description: \"Zodiac sign with emoji (e.g. '♍ 乙女座')\",\n },\n stars: { type: \"integer\", description: \"1-5 star rating\" },\n message: { type: \"string\", description: \"Fortune message\" },\n lucky_color: { type: \"string\", description: \"Lucky color name\" },\n lucky_item: { type: \"string\", description: \"Lucky item name\" },\n // info_card\n title: { type: \"string\", description: \"Card title\" },\n body: { type: \"string\", description: \"Card body text\" },\n // action_buttons\n prompt: { type: \"string\", description: \"Question or prompt text\" },\n buttons: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\" },\n text: { type: \"string\" },\n style: {\n type: \"string\",\n enum: [\"primary\", \"secondary\", \"link\"],\n },\n },\n },\n description: \"Button definitions\",\n },\n // receipt\n items: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n value: { type: \"string\" },\n },\n },\n description: \"Line items\",\n },\n total: { type: \"string\", description: \"Total amount\" },\n // morning_summary\n greeting: {\n type: \"string\",\n description: \"Greeting text (e.g. 'おはよう!')\",\n },\n date: {\n type: \"string\",\n description: \"Date string (e.g. '2月13日 木曜日')\",\n },\n weather: {\n type: \"string\",\n description: \"Weather info (e.g. '東京 12°C 曇り')\",\n },\n advice: {\n type: \"string\",\n description: \"Short advice (e.g. 'コートでOK')\",\n },\n schedule: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Schedule/reminder lines\",\n },\n header_color: {\n type: \"string\",\n description: \"Header background color hex (default: #1DB446)\",\n },\n // hydration\n current: {\n type: \"integer\",\n description: \"Current count (e.g. glasses drunk)\",\n },\n goal: { type: \"integer\", description: \"Goal count\" },\n unit: { type: \"string\", description: \"Unit label (default: 杯)\" },\n button_label: {\n type: \"string\",\n description: \"Button label (default: '飲んだ!')\",\n },\n button_text: {\n type: \"string\",\n description: \"Button message text (default: '水飲んだ')\",\n },\n // custom\n contents: {\n type: \"array\",\n description: \"Raw Flex body contents array for custom template\",\n },\n bubbles: {\n type: \"array\",\n items: { type: \"object\" },\n description:\n \"Array of bubble objects for a carousel (horizontal swipeable cards). Each item should be a complete bubble with type, body, etc.\",\n },\n },\n },\n },\n required: [\"template\", \"data\"],\n type: \"object\",\n };\n\n async execute(args: Record<string, unknown>): Promise<string> {\n const template = String(args.template);\n const data = (args.data ?? {}) as Record<string, unknown>;\n\n try {\n let flex: Record<string, unknown>;\n\n switch (template) {\n case \"fortune\": {\n flex = this.buildFortune(data);\n break;\n }\n case \"info_card\": {\n flex = this.buildInfoCard(data);\n break;\n }\n case \"action_buttons\": {\n flex = this.buildActionButtons(data);\n break;\n }\n case \"receipt\": {\n flex = this.buildReceipt(data);\n break;\n }\n case \"morning_summary\": {\n flex = this.buildMorningSummary(data);\n break;\n }\n case \"hydration\": {\n flex = this.buildHydration(data);\n break;\n }\n case \"custom\": {\n flex = this.buildCustom(data);\n break;\n }\n default: {\n return `Error: unknown template '${template}'. Use: fortune, info_card, action_buttons, receipt, morning_summary, hydration, custom.`;\n }\n }\n\n const json = JSON.stringify(flex);\n return `${json}\\n\\n(Card sent automatically. Do NOT repeat the JSON. Just respond naturally.)`;\n } catch (error) {\n return `Error building flex message: ${error instanceof Error ? error.message : error}`;\n }\n }\n\n private buildFortune(data: Record<string, unknown>): Record<string, unknown> {\n const sign = String(data.sign ?? \"♈ 牡羊座\");\n const stars = Math.max(1, Math.min(5, Number(data.stars ?? 3)));\n const message = String(data.message ?? \"\");\n const luckyColor = data.lucky_color ? String(data.lucky_color) : null;\n const luckyItem = data.lucky_item ? String(data.lucky_item) : null;\n\n const starText = \"★\".repeat(stars) + \"☆\".repeat(5 - stars);\n\n const contents: Record<string, unknown>[] = [\n { size: \"xl\", text: sign, type: \"text\", weight: \"bold\" },\n { color: \"#666666\", size: \"sm\", text: \"今日の運勢\", type: \"text\" },\n { margin: \"md\", size: \"xxl\", text: starText, type: \"text\" },\n ];\n\n if (message) {\n contents.push({\n margin: \"sm\",\n text: message,\n type: \"text\",\n wrap: true,\n });\n }\n\n if (luckyColor || luckyItem) {\n contents.push({ margin: \"md\", type: \"separator\" });\n }\n\n if (luckyColor) {\n contents.push({\n contents: [\n {\n type: \"text\",\n text: \"ラッキーカラー\",\n size: \"sm\",\n color: \"#228B22\",\n flex: 0,\n },\n { type: \"text\", text: luckyColor, size: \"sm\", align: \"end\" },\n ],\n layout: \"horizontal\",\n margin: \"md\",\n type: \"box\",\n });\n }\n\n if (luckyItem) {\n contents.push({\n contents: [\n {\n type: \"text\",\n text: \"ラッキーアイテム\",\n size: \"sm\",\n color: \"#228B22\",\n flex: 0,\n },\n { type: \"text\", text: luckyItem, size: \"sm\", align: \"end\" },\n ],\n layout: \"horizontal\",\n margin: luckyColor ? \"sm\" : \"md\",\n type: \"box\",\n });\n }\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n paddingAll: \"lg\",\n contents,\n },\n size: \"kilo\",\n type: \"bubble\",\n };\n }\n\n private buildInfoCard(\n data: Record<string, unknown>\n ): Record<string, unknown> {\n const title = String(data.title ?? \"お知らせ\");\n const body = String(data.body ?? \"\");\n\n const contents: Record<string, unknown>[] = [\n { size: \"lg\", text: title, type: \"text\", weight: \"bold\" },\n { margin: \"md\", type: \"separator\" },\n ];\n\n if (body) {\n contents.push({\n margin: \"md\",\n text: body,\n type: \"text\",\n wrap: true,\n });\n }\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents,\n },\n type: \"bubble\",\n };\n }\n\n private buildActionButtons(\n data: Record<string, unknown>\n ): Record<string, unknown> {\n const prompt = String(data.prompt ?? \"選択してください\");\n const buttons = (data.buttons ?? []) as Record<string, unknown>[];\n\n if (buttons.length === 0) {\n // Default yes/no\n buttons.push(\n { label: \"はい\", style: \"primary\", text: \"はい\" },\n { label: \"いいえ\", style: \"secondary\", text: \"いいえ\" }\n );\n }\n\n const buttonContents = buttons.map((btn) => ({\n action: {\n type: \"message\",\n label: String(btn.label ?? \"\"),\n text: String(btn.text ?? btn.label ?? \"\"),\n },\n style: String(btn.style ?? \"primary\"),\n type: \"button\",\n }));\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: [{ type: \"text\", text: prompt, weight: \"bold\", wrap: true }],\n },\n footer: {\n type: \"box\",\n layout: \"vertical\",\n spacing: \"sm\",\n contents: buttonContents,\n },\n type: \"bubble\",\n };\n }\n\n private buildReceipt(data: Record<string, unknown>): Record<string, unknown> {\n const title = String(data.title ?? \"明細\");\n const items = (data.items ?? []) as Record<string, unknown>[];\n const total = data.total ? String(data.total) : null;\n\n const contents: Record<string, unknown>[] = [\n { text: `💰 ${title}`, type: \"text\", weight: \"bold\" },\n { margin: \"lg\", type: \"separator\" },\n ];\n\n for (const item of items) {\n contents.push({\n contents: [\n { type: \"text\", text: String(item.name ?? \"\"), flex: 0 },\n { type: \"text\", text: String(item.value ?? \"\"), align: \"end\" },\n ],\n layout: \"horizontal\",\n margin: \"md\",\n type: \"box\",\n });\n }\n\n if (total) {\n contents.push(\n { margin: \"lg\", type: \"separator\" },\n {\n contents: [\n { type: \"text\", text: \"合計\", weight: \"bold\" },\n { type: \"text\", text: total, weight: \"bold\", align: \"end\" },\n ],\n layout: \"horizontal\",\n margin: \"md\",\n type: \"box\",\n }\n );\n }\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents,\n },\n type: \"bubble\",\n };\n }\n\n private buildMorningSummary(\n data: Record<string, unknown>\n ): Record<string, unknown> {\n const greeting = String(data.greeting ?? \"おはよう!\");\n const date = String(data.date ?? \"\");\n const weather = data.weather ? String(data.weather) : null;\n const advice = data.advice ? String(data.advice) : null;\n const schedule = (data.schedule ?? []) as string[];\n const headerColor = String(data.header_color ?? \"#1DB446\");\n\n const headerContents: Record<string, unknown>[] = [\n {\n color: \"#ffffff\",\n size: \"lg\",\n text: greeting,\n type: \"text\",\n weight: \"bold\",\n },\n ];\n if (date) {\n headerContents.push({\n color: \"#ffffff\",\n size: \"sm\",\n text: date,\n type: \"text\",\n });\n }\n\n const bodyContents: Record<string, unknown>[] = [];\n\n if (weather) {\n bodyContents.push({ text: weather, type: \"text\", weight: \"bold\" });\n }\n if (advice) {\n bodyContents.push({\n color: \"#666666\",\n size: \"sm\",\n text: advice,\n type: \"text\",\n });\n }\n\n if (schedule.length > 0) {\n bodyContents.push({ margin: \"md\", type: \"separator\" });\n for (const line of schedule) {\n bodyContents.push({\n margin: \"md\",\n text: line,\n type: \"text\",\n wrap: true,\n });\n }\n }\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n paddingAll: \"lg\",\n contents:\n bodyContents.length > 0\n ? bodyContents\n : [{ type: \"text\", text: \"良い一日を!\" }],\n },\n header: {\n type: \"box\",\n layout: \"vertical\",\n backgroundColor: headerColor,\n paddingAll: \"lg\",\n contents: headerContents,\n },\n type: \"bubble\",\n };\n }\n\n private buildHydration(\n data: Record<string, unknown>\n ): Record<string, unknown> {\n const title = String(data.title ?? \"水飲んだ?\");\n const current = Number(data.current ?? 0);\n const goal = Number(data.goal ?? 8);\n const unit = String(data.unit ?? \"杯\");\n const buttonLabel = String(data.button_label ?? \"飲んだ!\");\n const buttonText = String(data.button_text ?? \"水飲んだ\");\n\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: [\n { type: \"text\", text: title, size: \"xl\" },\n {\n type: \"text\",\n text: `今日: ${current}${unit} / ${goal}${unit}`,\n color: \"#666666\",\n },\n ],\n },\n footer: {\n type: \"box\",\n layout: \"horizontal\",\n contents: [\n {\n type: \"button\",\n style: \"primary\",\n color: \"#00B9ED\",\n action: { type: \"message\", label: buttonLabel, text: buttonText },\n },\n ],\n },\n size: \"kilo\",\n type: \"bubble\",\n };\n }\n\n private buildCustom(data: Record<string, unknown>): Record<string, unknown> {\n // Carousel: array of bubble objects → horizontal swipeable cards\n const bubbles = data.bubbles as unknown[];\n if (Array.isArray(bubbles) && bubbles.length > 0) {\n return {\n contents: bubbles,\n type: \"carousel\",\n };\n }\n\n // If raw contents array is provided, use it directly as body contents\n const rawContents = data.contents as unknown[];\n if (Array.isArray(rawContents) && rawContents.length > 0) {\n return {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents: rawContents,\n },\n type: \"bubble\",\n };\n }\n\n // Fallback: auto-build a card from common fields (title, body, buttons, header_color)\n const title = data.title ? String(data.title) : null;\n const body = data.body ? String(data.body) : null;\n let buttons = Array.isArray(data.buttons)\n ? (data.buttons as Record<string, unknown>[])\n : [];\n const headerColor = data.header_color ? String(data.header_color) : null;\n\n // Support flat button_label/button_text shorthand (like hydration template)\n if (buttons.length === 0 && data.button_label) {\n buttons = [\n {\n label: String(data.button_label),\n style: data.button_style ?? \"primary\",\n text: String(data.button_text ?? data.button_label),\n },\n ];\n }\n\n if (!title && !body && buttons.length === 0) {\n throw new Error(\n \"custom template requires 'contents' array, or at least one of: title, body, buttons\"\n );\n }\n\n const bodyContents: Record<string, unknown>[] = [];\n\n if (title) {\n bodyContents.push({\n size: \"lg\",\n text: title,\n type: \"text\",\n weight: \"bold\",\n });\n }\n if (body) {\n if (title) {\n bodyContents.push({ type: \"separator\", margin: \"md\" });\n }\n bodyContents.push({\n margin: title ? \"md\" : undefined,\n text: body,\n type: \"text\",\n wrap: true,\n });\n }\n\n const bubble: Record<string, unknown> = {\n body: {\n type: \"box\",\n layout: \"vertical\",\n contents:\n bodyContents.length > 0\n ? bodyContents\n : [{ type: \"text\", text: \" \" }],\n },\n type: \"bubble\",\n };\n\n // Add colored header if specified\n if (headerColor && title) {\n bubble.header = {\n backgroundColor: headerColor,\n contents: [\n {\n type: \"text\",\n text: title,\n color: \"#ffffff\",\n weight: \"bold\",\n size: \"lg\",\n },\n ],\n layout: \"vertical\",\n paddingAll: \"lg\",\n type: \"box\",\n };\n // Remove title from body since it's in the header now\n bodyContents.shift();\n }\n\n // Add buttons as footer\n if (buttons.length > 0) {\n bubble.footer = {\n contents: buttons.map((btn) => ({\n type: \"button\",\n style: String(btn.style ?? \"primary\"),\n action: {\n type: \"message\",\n label: String(btn.label ?? \"\"),\n text: String(btn.text ?? btn.label ?? \"\"),\n },\n })),\n layout: \"vertical\",\n spacing: \"sm\",\n type: \"box\",\n };\n }\n\n return bubble;\n }\n}\n"],"mappings":";;;;;;;;;;AASA,IAAa,WAAb,cAA8B,KAAK;CACjC,AAAS,OAAO;CAChB,AAAS,cACP;CACF,AAAS,aAAa;EACpB,YAAY;GACV,UAAU;IACR,MAAM;IACN,aACE;IACH;GACD,MAAM;IACJ,MAAM;IACN,aAAa;IACb,YAAY;KAEV,MAAM;MACJ,MAAM;MACN,aAAa;MACd;KACD,OAAO;MAAE,MAAM;MAAW,aAAa;MAAmB;KAC1D,SAAS;MAAE,MAAM;MAAU,aAAa;MAAmB;KAC3D,aAAa;MAAE,MAAM;MAAU,aAAa;MAAoB;KAChE,YAAY;MAAE,MAAM;MAAU,aAAa;MAAmB;KAE9D,OAAO;MAAE,MAAM;MAAU,aAAa;MAAc;KACpD,MAAM;MAAE,MAAM;MAAU,aAAa;MAAkB;KAEvD,QAAQ;MAAE,MAAM;MAAU,aAAa;MAA2B;KAClE,SAAS;MACP,MAAM;MACN,OAAO;OACL,MAAM;OACN,YAAY;QACV,OAAO,EAAE,MAAM,UAAU;QACzB,MAAM,EAAE,MAAM,UAAU;QACxB,OAAO;SACL,MAAM;SACN,MAAM;UAAC;UAAW;UAAa;UAAO;SACvC;QACF;OACF;MACD,aAAa;MACd;KAED,OAAO;MACL,MAAM;MACN,OAAO;OACL,MAAM;OACN,YAAY;QACV,MAAM,EAAE,MAAM,UAAU;QACxB,OAAO,EAAE,MAAM,UAAU;QAC1B;OACF;MACD,aAAa;MACd;KACD,OAAO;MAAE,MAAM;MAAU,aAAa;MAAgB;KAEtD,UAAU;MACR,MAAM;MACN,aAAa;MACd;KACD,MAAM;MACJ,MAAM;MACN,aAAa;MACd;KACD,SAAS;MACP,MAAM;MACN,aAAa;MACd;KACD,QAAQ;MACN,MAAM;MACN,aAAa;MACd;KACD,UAAU;MACR,MAAM;MACN,OAAO,EAAE,MAAM,UAAU;MACzB,aAAa;MACd;KACD,cAAc;MACZ,MAAM;MACN,aAAa;MACd;KAED,SAAS;MACP,MAAM;MACN,aAAa;MACd;KACD,MAAM;MAAE,MAAM;MAAW,aAAa;MAAc;KACpD,MAAM;MAAE,MAAM;MAAU,aAAa;MAA2B;KAChE,cAAc;MACZ,MAAM;MACN,aAAa;MACd;KACD,aAAa;MACX,MAAM;MACN,aAAa;MACd;KAED,UAAU;MACR,MAAM;MACN,aAAa;MACd;KACD,SAAS;MACP,MAAM;MACN,OAAO,EAAE,MAAM,UAAU;MACzB,aACE;MACH;KACF;IACF;GACF;EACD,UAAU,CAAC,YAAY,OAAO;EAC9B,MAAM;EACP;CAED,MAAM,QAAQ,MAAgD;EAC5D,MAAM,WAAW,OAAO,KAAK,SAAS;EACtC,MAAM,OAAQ,KAAK,QAAQ,EAAE;AAE7B,MAAI;GACF,IAAI;AAEJ,WAAQ,UAAR;IACE,KAAK;AACH,YAAO,KAAK,aAAa,KAAK;AAC9B;IAEF,KAAK;AACH,YAAO,KAAK,cAAc,KAAK;AAC/B;IAEF,KAAK;AACH,YAAO,KAAK,mBAAmB,KAAK;AACpC;IAEF,KAAK;AACH,YAAO,KAAK,aAAa,KAAK;AAC9B;IAEF,KAAK;AACH,YAAO,KAAK,oBAAoB,KAAK;AACrC;IAEF,KAAK;AACH,YAAO,KAAK,eAAe,KAAK;AAChC;IAEF,KAAK;AACH,YAAO,KAAK,YAAY,KAAK;AAC7B;IAEF,QACE,QAAO,4BAA4B,SAAS;;AAKhD,UAAO,GADM,KAAK,UAAU,KAAK,CAClB;WACR,OAAO;AACd,UAAO,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU;;;CAIpF,AAAQ,aAAa,MAAwD;EAC3E,MAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ;EACzC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,KAAK,SAAS,EAAE,CAAC,CAAC;EAC/D,MAAM,UAAU,OAAO,KAAK,WAAW,GAAG;EAC1C,MAAM,aAAa,KAAK,cAAc,OAAO,KAAK,YAAY,GAAG;EACjE,MAAM,YAAY,KAAK,aAAa,OAAO,KAAK,WAAW,GAAG;EAE9D,MAAM,WAAW,IAAI,OAAO,MAAM,GAAG,IAAI,OAAO,IAAI,MAAM;EAE1D,MAAM,WAAsC;GAC1C;IAAE,MAAM;IAAM,MAAM;IAAM,MAAM;IAAQ,QAAQ;IAAQ;GACxD;IAAE,OAAO;IAAW,MAAM;IAAM,MAAM;IAAS,MAAM;IAAQ;GAC7D;IAAE,QAAQ;IAAM,MAAM;IAAO,MAAM;IAAU,MAAM;IAAQ;GAC5D;AAED,MAAI,QACF,UAAS,KAAK;GACZ,QAAQ;GACR,MAAM;GACN,MAAM;GACN,MAAM;GACP,CAAC;AAGJ,MAAI,cAAc,UAChB,UAAS,KAAK;GAAE,QAAQ;GAAM,MAAM;GAAa,CAAC;AAGpD,MAAI,WACF,UAAS,KAAK;GACZ,UAAU,CACR;IACE,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACP,EACD;IAAE,MAAM;IAAQ,MAAM;IAAY,MAAM;IAAM,OAAO;IAAO,CAC7D;GACD,QAAQ;GACR,QAAQ;GACR,MAAM;GACP,CAAC;AAGJ,MAAI,UACF,UAAS,KAAK;GACZ,UAAU,CACR;IACE,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACP,EACD;IAAE,MAAM;IAAQ,MAAM;IAAW,MAAM;IAAM,OAAO;IAAO,CAC5D;GACD,QAAQ;GACR,QAAQ,aAAa,OAAO;GAC5B,MAAM;GACP,CAAC;AAGJ,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,YAAY;IACZ;IACD;GACD,MAAM;GACN,MAAM;GACP;;CAGH,AAAQ,cACN,MACyB;EACzB,MAAM,QAAQ,OAAO,KAAK,SAAS,OAAO;EAC1C,MAAM,OAAO,OAAO,KAAK,QAAQ,GAAG;EAEpC,MAAM,WAAsC,CAC1C;GAAE,MAAM;GAAM,MAAM;GAAO,MAAM;GAAQ,QAAQ;GAAQ,EACzD;GAAE,QAAQ;GAAM,MAAM;GAAa,CACpC;AAED,MAAI,KACF,UAAS,KAAK;GACZ,QAAQ;GACR,MAAM;GACN,MAAM;GACN,MAAM;GACP,CAAC;AAGJ,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR;IACD;GACD,MAAM;GACP;;CAGH,AAAQ,mBACN,MACyB;EACzB,MAAM,SAAS,OAAO,KAAK,UAAU,WAAW;EAChD,MAAM,UAAW,KAAK,WAAW,EAAE;AAEnC,MAAI,QAAQ,WAAW,EAErB,SAAQ,KACN;GAAE,OAAO;GAAM,OAAO;GAAW,MAAM;GAAM,EAC7C;GAAE,OAAO;GAAO,OAAO;GAAa,MAAM;GAAO,CAClD;EAGH,MAAM,iBAAiB,QAAQ,KAAK,SAAS;GAC3C,QAAQ;IACN,MAAM;IACN,OAAO,OAAO,IAAI,SAAS,GAAG;IAC9B,MAAM,OAAO,IAAI,QAAQ,IAAI,SAAS,GAAG;IAC1C;GACD,OAAO,OAAO,IAAI,SAAS,UAAU;GACrC,MAAM;GACP,EAAE;AAEH,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,UAAU,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAQ,QAAQ;KAAQ,MAAM;KAAM,CAAC;IACvE;GACD,QAAQ;IACN,MAAM;IACN,QAAQ;IACR,SAAS;IACT,UAAU;IACX;GACD,MAAM;GACP;;CAGH,AAAQ,aAAa,MAAwD;EAC3E,MAAM,QAAQ,OAAO,KAAK,SAAS,KAAK;EACxC,MAAM,QAAS,KAAK,SAAS,EAAE;EAC/B,MAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,MAAM,GAAG;EAEhD,MAAM,WAAsC,CAC1C;GAAE,MAAM,MAAM;GAAS,MAAM;GAAQ,QAAQ;GAAQ,EACrD;GAAE,QAAQ;GAAM,MAAM;GAAa,CACpC;AAED,OAAK,MAAM,QAAQ,MACjB,UAAS,KAAK;GACZ,UAAU,CACR;IAAE,MAAM;IAAQ,MAAM,OAAO,KAAK,QAAQ,GAAG;IAAE,MAAM;IAAG,EACxD;IAAE,MAAM;IAAQ,MAAM,OAAO,KAAK,SAAS,GAAG;IAAE,OAAO;IAAO,CAC/D;GACD,QAAQ;GACR,QAAQ;GACR,MAAM;GACP,CAAC;AAGJ,MAAI,MACF,UAAS,KACP;GAAE,QAAQ;GAAM,MAAM;GAAa,EACnC;GACE,UAAU,CACR;IAAE,MAAM;IAAQ,MAAM;IAAM,QAAQ;IAAQ,EAC5C;IAAE,MAAM;IAAQ,MAAM;IAAO,QAAQ;IAAQ,OAAO;IAAO,CAC5D;GACD,QAAQ;GACR,QAAQ;GACR,MAAM;GACP,CACF;AAGH,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR;IACD;GACD,MAAM;GACP;;CAGH,AAAQ,oBACN,MACyB;EACzB,MAAM,WAAW,OAAO,KAAK,YAAY,QAAQ;EACjD,MAAM,OAAO,OAAO,KAAK,QAAQ,GAAG;EACpC,MAAM,UAAU,KAAK,UAAU,OAAO,KAAK,QAAQ,GAAG;EACtD,MAAM,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,GAAG;EACnD,MAAM,WAAY,KAAK,YAAY,EAAE;EACrC,MAAM,cAAc,OAAO,KAAK,gBAAgB,UAAU;EAE1D,MAAM,iBAA4C,CAChD;GACE,OAAO;GACP,MAAM;GACN,MAAM;GACN,MAAM;GACN,QAAQ;GACT,CACF;AACD,MAAI,KACF,gBAAe,KAAK;GAClB,OAAO;GACP,MAAM;GACN,MAAM;GACN,MAAM;GACP,CAAC;EAGJ,MAAM,eAA0C,EAAE;AAElD,MAAI,QACF,cAAa,KAAK;GAAE,MAAM;GAAS,MAAM;GAAQ,QAAQ;GAAQ,CAAC;AAEpE,MAAI,OACF,cAAa,KAAK;GAChB,OAAO;GACP,MAAM;GACN,MAAM;GACN,MAAM;GACP,CAAC;AAGJ,MAAI,SAAS,SAAS,GAAG;AACvB,gBAAa,KAAK;IAAE,QAAQ;IAAM,MAAM;IAAa,CAAC;AACtD,QAAK,MAAM,QAAQ,SACjB,cAAa,KAAK;IAChB,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;IACP,CAAC;;AAIN,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,YAAY;IACZ,UACE,aAAa,SAAS,IAClB,eACA,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAU,CAAC;IACzC;GACD,QAAQ;IACN,MAAM;IACN,QAAQ;IACR,iBAAiB;IACjB,YAAY;IACZ,UAAU;IACX;GACD,MAAM;GACP;;CAGH,AAAQ,eACN,MACyB;EACzB,MAAM,QAAQ,OAAO,KAAK,SAAS,QAAQ;EAC3C,MAAM,UAAU,OAAO,KAAK,WAAW,EAAE;EACzC,MAAM,OAAO,OAAO,KAAK,QAAQ,EAAE;EACnC,MAAM,OAAO,OAAO,KAAK,QAAQ,IAAI;EACrC,MAAM,cAAc,OAAO,KAAK,gBAAgB,OAAO;EACvD,MAAM,aAAa,OAAO,KAAK,eAAe,OAAO;AAErD,SAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,UAAU,CACR;KAAE,MAAM;KAAQ,MAAM;KAAO,MAAM;KAAM,EACzC;KACE,MAAM;KACN,MAAM,OAAO,UAAU,KAAK,KAAK,OAAO;KACxC,OAAO;KACR,CACF;IACF;GACD,QAAQ;IACN,MAAM;IACN,QAAQ;IACR,UAAU,CACR;KACE,MAAM;KACN,OAAO;KACP,OAAO;KACP,QAAQ;MAAE,MAAM;MAAW,OAAO;MAAa,MAAM;MAAY;KAClE,CACF;IACF;GACD,MAAM;GACN,MAAM;GACP;;CAGH,AAAQ,YAAY,MAAwD;EAE1E,MAAM,UAAU,KAAK;AACrB,MAAI,MAAM,QAAQ,QAAQ,IAAI,QAAQ,SAAS,EAC7C,QAAO;GACL,UAAU;GACV,MAAM;GACP;EAIH,MAAM,cAAc,KAAK;AACzB,MAAI,MAAM,QAAQ,YAAY,IAAI,YAAY,SAAS,EACrD,QAAO;GACL,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,UAAU;IACX;GACD,MAAM;GACP;EAIH,MAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,MAAM,GAAG;EAChD,MAAM,OAAO,KAAK,OAAO,OAAO,KAAK,KAAK,GAAG;EAC7C,IAAI,UAAU,MAAM,QAAQ,KAAK,QAAQ,GACpC,KAAK,UACN,EAAE;EACN,MAAM,cAAc,KAAK,eAAe,OAAO,KAAK,aAAa,GAAG;AAGpE,MAAI,QAAQ,WAAW,KAAK,KAAK,aAC/B,WAAU,CACR;GACE,OAAO,OAAO,KAAK,aAAa;GAChC,OAAO,KAAK,gBAAgB;GAC5B,MAAM,OAAO,KAAK,eAAe,KAAK,aAAa;GACpD,CACF;AAGH,MAAI,CAAC,SAAS,CAAC,QAAQ,QAAQ,WAAW,EACxC,OAAM,IAAI,MACR,sFACD;EAGH,MAAM,eAA0C,EAAE;AAElD,MAAI,MACF,cAAa,KAAK;GAChB,MAAM;GACN,MAAM;GACN,MAAM;GACN,QAAQ;GACT,CAAC;AAEJ,MAAI,MAAM;AACR,OAAI,MACF,cAAa,KAAK;IAAE,MAAM;IAAa,QAAQ;IAAM,CAAC;AAExD,gBAAa,KAAK;IAChB,QAAQ,QAAQ,OAAO;IACvB,MAAM;IACN,MAAM;IACN,MAAM;IACP,CAAC;;EAGJ,MAAM,SAAkC;GACtC,MAAM;IACJ,MAAM;IACN,QAAQ;IACR,UACE,aAAa,SAAS,IAClB,eACA,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAK,CAAC;IACpC;GACD,MAAM;GACP;AAGD,MAAI,eAAe,OAAO;AACxB,UAAO,SAAS;IACd,iBAAiB;IACjB,UAAU,CACR;KACE,MAAM;KACN,MAAM;KACN,OAAO;KACP,QAAQ;KACR,MAAM;KACP,CACF;IACD,QAAQ;IACR,YAAY;IACZ,MAAM;IACP;AAED,gBAAa,OAAO;;AAItB,MAAI,QAAQ,SAAS,EACnB,QAAO,SAAS;GACd,UAAU,QAAQ,KAAK,SAAS;IAC9B,MAAM;IACN,OAAO,OAAO,IAAI,SAAS,UAAU;IACrC,QAAQ;KACN,MAAM;KACN,OAAO,OAAO,IAAI,SAAS,GAAG;KAC9B,MAAM,OAAO,IAAI,QAAQ,IAAI,SAAS,GAAG;KAC1C;IACF,EAAE;GACH,QAAQ;GACR,SAAS;GACT,MAAM;GACP;AAGH,SAAO"}