@tomako/tools-runtime 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. package/README.md +12 -0
  2. package/package.json +629 -0
  3. package/src/assets/icons/brands/social/bluesky-icon.tsx +9 -0
  4. package/src/assets/icons/brands/social/facebook-icon.tsx +9 -0
  5. package/src/assets/icons/brands/social/index.ts +8 -0
  6. package/src/assets/icons/brands/social/instagram-icon.tsx +9 -0
  7. package/src/assets/icons/brands/social/linkedin-icon.tsx +9 -0
  8. package/src/assets/icons/brands/social/threads-icon.tsx +9 -0
  9. package/src/assets/icons/brands/social/tiktok-icon.tsx +10 -0
  10. package/src/assets/icons/brands/social/x-icon.tsx +9 -0
  11. package/src/assets/icons/brands/social/youtube-icon.tsx +9 -0
  12. package/src/assets/icons/social-profile/facebook-icon.tsx +12 -0
  13. package/src/assets/icons/social-profile/index.ts +29 -0
  14. package/src/assets/icons/social-profile/instagram-icon.tsx +18 -0
  15. package/src/assets/icons/social-profile/linkedin-icon.tsx +12 -0
  16. package/src/assets/icons/social-profile/tiktok-icon.tsx +12 -0
  17. package/src/assets/icons/social-profile/x-icon.tsx +13 -0
  18. package/src/assets/icons/social-profile/youtube-icon.tsx +12 -0
  19. package/src/components/tools/engine/form-builder.tsx +219 -0
  20. package/src/components/tools/engine/package-widget-loader.tsx +38 -0
  21. package/src/components/tools/engine/package-widget-runtime.tsx +409 -0
  22. package/src/components/tools/engine/package-widget.tsx +77 -0
  23. package/src/components/tools/engine/result-view.tsx +596 -0
  24. package/src/components/tools/engine/use-legacy-llm-task.ts +64 -0
  25. package/src/components/tools/engine/use-tool-task.ts +195 -0
  26. package/src/components/tools/market-forecast-report.tsx +1150 -0
  27. package/src/components/tools/registry.ts +13 -0
  28. package/src/components/tools/workspace/index.ts +39 -0
  29. package/src/components/tools/workspace/tool-action-bar.tsx +99 -0
  30. package/src/components/tools/workspace/tool-empty-panel.tsx +32 -0
  31. package/src/components/tools/workspace/tool-error-panel.tsx +40 -0
  32. package/src/components/tools/workspace/tool-field.tsx +124 -0
  33. package/src/components/tools/workspace/tool-file-upload.tsx +112 -0
  34. package/src/components/tools/workspace/tool-form-section.tsx +21 -0
  35. package/src/components/tools/workspace/tool-form-shell.tsx +36 -0
  36. package/src/components/tools/workspace/tool-loading-panel.tsx +269 -0
  37. package/src/components/tools/workspace/tool-option-row.tsx +97 -0
  38. package/src/components/tools/workspace/tool-preview-panel.tsx +31 -0
  39. package/src/components/tools/workspace/tool-result-actions.tsx +67 -0
  40. package/src/components/tools/workspace/tool-result-file-actions.ts +31 -0
  41. package/src/components/tools/workspace/tool-result-header.tsx +39 -0
  42. package/src/components/tools/workspace/tool-status.tsx +13 -0
  43. package/src/components/tools/workspace/tool-workspace-layout.tsx +226 -0
  44. package/src/constants/LKS.ts +29 -0
  45. package/src/constants/related-tools.ts +18 -0
  46. package/src/constants/social-profile-kit.ts +284 -0
  47. package/src/constants/tool-assets.ts +7 -0
  48. package/src/env.d.ts +3 -0
  49. package/src/features/tools/_templates/standard-tool.container.tsx +90 -0
  50. package/src/features/tools/app-icon-resizer/app-icon-resizer.container.tsx +11 -0
  51. package/src/features/tools/app-icon-resizer/app-icon-resizer.spec.ts +15 -0
  52. package/src/features/tools/app-icon-resizer/widget/app-icon-resizer.tsx +444 -0
  53. package/src/features/tools/app-icon-resizer/widget/constants.ts +19 -0
  54. package/src/features/tools/app-icon-resizer/widget/helpers.ts +314 -0
  55. package/src/features/tools/app-icon-resizer/widget/index.ts +7 -0
  56. package/src/features/tools/app-icon-resizer/widget/platform-icons.tsx +59 -0
  57. package/src/features/tools/app-icon-resizer/widget/preview-dialogs.tsx +139 -0
  58. package/src/features/tools/app-icon-resizer/widget/result-shell.tsx +165 -0
  59. package/src/features/tools/app-icon-resizer/widget/types.ts +36 -0
  60. package/src/features/tools/app-store-screenshot-generator/app-store-screenshot-generator.container.tsx +108 -0
  61. package/src/features/tools/app-store-screenshot-generator/app-store-screenshot-generator.spec.ts +14 -0
  62. package/src/features/tools/app-store-screenshot-generator/config.ts +3 -0
  63. package/src/features/tools/app-store-screenshot-generator/widget/app-store-screenshot-generator.tsx +1250 -0
  64. package/src/features/tools/app-store-screenshot-generator/widget/asset-slots.ts +76 -0
  65. package/src/features/tools/app-store-screenshot-generator/widget/constants.ts +43 -0
  66. package/src/features/tools/app-store-screenshot-generator/widget/form-controls.tsx +214 -0
  67. package/src/features/tools/app-store-screenshot-generator/widget/generation.ts +528 -0
  68. package/src/features/tools/app-store-screenshot-generator/widget/index.ts +7 -0
  69. package/src/features/tools/app-store-screenshot-generator/widget/input-media.ts +175 -0
  70. package/src/features/tools/app-store-screenshot-generator/widget/types.ts +60 -0
  71. package/src/features/tools/app-store-screenshot-generator/widget/zip.ts +119 -0
  72. package/src/features/tools/build-in-public-story-generator/build-in-public-story-generator.container.tsx +135 -0
  73. package/src/features/tools/build-in-public-story-generator/build-in-public-story-generator.spec.ts +15 -0
  74. package/src/features/tools/build-in-public-story-generator/widget/build-in-public-story-generator.tsx +314 -0
  75. package/src/features/tools/build-in-public-story-generator/widget/constants.ts +3 -0
  76. package/src/features/tools/build-in-public-story-generator/widget/helpers.ts +25 -0
  77. package/src/features/tools/build-in-public-story-generator/widget/index.ts +7 -0
  78. package/src/features/tools/build-in-public-story-generator/widget/preview-panels.tsx +58 -0
  79. package/src/features/tools/build-in-public-story-generator/widget/result-shell.tsx +164 -0
  80. package/src/features/tools/build-in-public-story-generator/widget/types.ts +6 -0
  81. package/src/features/tools/cold-start-channel-selector/cold-start-channel-selector.container.tsx +30 -0
  82. package/src/features/tools/cold-start-channel-selector/cold-start-channel-selector.spec.ts +15 -0
  83. package/src/features/tools/cold-start-channel-selector/widget/cold-start-channel-selector.tsx +417 -0
  84. package/src/features/tools/cold-start-channel-selector/widget/constants.ts +46 -0
  85. package/src/features/tools/cold-start-channel-selector/widget/form-controls.tsx +41 -0
  86. package/src/features/tools/cold-start-channel-selector/widget/helpers.ts +75 -0
  87. package/src/features/tools/cold-start-channel-selector/widget/index.ts +7 -0
  88. package/src/features/tools/cold-start-channel-selector/widget/preview-panels.tsx +250 -0
  89. package/src/features/tools/cold-start-channel-selector/widget/result-shell.tsx +199 -0
  90. package/src/features/tools/cold-start-channel-selector/widget/types.ts +21 -0
  91. package/src/features/tools/commercial-bp-generator/commercial-bp-generator.container.tsx +102 -0
  92. package/src/features/tools/commercial-bp-generator/commercial-bp-generator.spec.ts +14 -0
  93. package/src/features/tools/commercial-bp-generator/widget/commercial-bp-generator.tsx +676 -0
  94. package/src/features/tools/commercial-bp-generator/widget/constants.ts +32 -0
  95. package/src/features/tools/commercial-bp-generator/widget/helpers.ts +147 -0
  96. package/src/features/tools/commercial-bp-generator/widget/index.ts +7 -0
  97. package/src/features/tools/commercial-bp-generator/widget/result-shell.tsx +271 -0
  98. package/src/features/tools/commercial-bp-generator/widget/style-option.tsx +54 -0
  99. package/src/features/tools/commercial-bp-generator/widget/types.ts +33 -0
  100. package/src/features/tools/community-feedback-inbox/community-feedback-inbox.container.tsx +126 -0
  101. package/src/features/tools/community-feedback-inbox/community-feedback-inbox.spec.ts +15 -0
  102. package/src/features/tools/community-feedback-inbox/widget/community-feedback-inbox.tsx +271 -0
  103. package/src/features/tools/community-feedback-inbox/widget/constants.ts +3 -0
  104. package/src/features/tools/community-feedback-inbox/widget/helpers.ts +28 -0
  105. package/src/features/tools/community-feedback-inbox/widget/index.ts +7 -0
  106. package/src/features/tools/community-feedback-inbox/widget/preview-panels.tsx +92 -0
  107. package/src/features/tools/community-feedback-inbox/widget/result-shell.tsx +266 -0
  108. package/src/features/tools/community-feedback-inbox/widget/types.ts +6 -0
  109. package/src/features/tools/community-pain-point-extractor/community-pain-point-extractor.container.tsx +124 -0
  110. package/src/features/tools/community-pain-point-extractor/community-pain-point-extractor.spec.ts +15 -0
  111. package/src/features/tools/community-pain-point-extractor/widget/community-pain-point-extractor.tsx +404 -0
  112. package/src/features/tools/community-pain-point-extractor/widget/constants.ts +41 -0
  113. package/src/features/tools/community-pain-point-extractor/widget/helpers.ts +76 -0
  114. package/src/features/tools/community-pain-point-extractor/widget/index.ts +8 -0
  115. package/src/features/tools/community-pain-point-extractor/widget/progress-panels.tsx +251 -0
  116. package/src/features/tools/community-pain-point-extractor/widget/result-shell.tsx +478 -0
  117. package/src/features/tools/community-pain-point-extractor/widget/types.ts +33 -0
  118. package/src/features/tools/community-post-risk-checker/community-post-risk-checker.package.ts +792 -0
  119. package/src/features/tools/competitor-analysis/competitor-analysis.container.tsx +136 -0
  120. package/src/features/tools/competitor-analysis/competitor-analysis.spec.ts +15 -0
  121. package/src/features/tools/competitor-analysis/widget/competitor-analysis.tsx +241 -0
  122. package/src/features/tools/competitor-analysis/widget/constants.ts +9 -0
  123. package/src/features/tools/competitor-analysis/widget/index.ts +7 -0
  124. package/src/features/tools/competitor-analysis/widget/preview-panels.tsx +60 -0
  125. package/src/features/tools/competitor-analysis/widget/result-shell.tsx +418 -0
  126. package/src/features/tools/competitor-analysis/widget/types.ts +13 -0
  127. package/src/features/tools/disclaimer-generator/disclaimer-generator.package.ts +339 -0
  128. package/src/features/tools/email-template-generator/email-template-generator.container.tsx +224 -0
  129. package/src/features/tools/email-template-generator/email-template-generator.spec.ts +14 -0
  130. package/src/features/tools/email-template-generator/widget/email-template-generator.tsx +358 -0
  131. package/src/features/tools/email-template-generator/widget/helpers.ts +39 -0
  132. package/src/features/tools/email-template-generator/widget/index.ts +7 -0
  133. package/src/features/tools/email-template-generator/widget/preview-panel.tsx +311 -0
  134. package/src/features/tools/email-template-generator/widget/result-text-block.tsx +7 -0
  135. package/src/features/tools/email-template-generator/widget/types.ts +24 -0
  136. package/src/features/tools/gtm-readiness-checklist/gtm-readiness-checklist.container.tsx +75 -0
  137. package/src/features/tools/gtm-readiness-checklist/gtm-readiness-checklist.spec.ts +15 -0
  138. package/src/features/tools/gtm-readiness-checklist/widget/gtm-readiness-checklist.tsx +122 -0
  139. package/src/features/tools/gtm-readiness-checklist/widget/index.ts +7 -0
  140. package/src/features/tools/investor-matching-planner/investor-matching-planner.package.ts +869 -0
  141. package/src/features/tools/koko-codex-assistant/koko-codex-assistant.container.tsx +151 -0
  142. package/src/features/tools/koko-codex-assistant/koko-codex-assistant.spec.ts +14 -0
  143. package/src/features/tools/koko-codex-assistant/widget/index.ts +7 -0
  144. package/src/features/tools/koko-codex-assistant/widget/koko-codex-assistant-download.tsx +192 -0
  145. package/src/features/tools/logo-generator/logo-generator.container.tsx +112 -0
  146. package/src/features/tools/logo-generator/logo-generator.spec.ts +15 -0
  147. package/src/features/tools/logo-generator/widget/index.ts +7 -0
  148. package/src/features/tools/logo-generator/widget/logo-generator.tsx +1244 -0
  149. package/src/features/tools/market-forecast-report/market-forecast-report.container.tsx +73 -0
  150. package/src/features/tools/market-forecast-report/market-forecast-report.spec.ts +15 -0
  151. package/src/features/tools/million-user-growth-test/million-user-growth-test.container.tsx +123 -0
  152. package/src/features/tools/million-user-growth-test/million-user-growth-test.spec.ts +14 -0
  153. package/src/features/tools/million-user-growth-test/widget/index.ts +7 -0
  154. package/src/features/tools/million-user-growth-test/widget/million-user-growth-test.tsx +433 -0
  155. package/src/features/tools/module-loader.ts +107 -0
  156. package/src/features/tools/og-image-generator/og-image-generator.container.tsx +86 -0
  157. package/src/features/tools/og-image-generator/og-image-generator.spec.ts +14 -0
  158. package/src/features/tools/og-image-generator/widget/constants.ts +38 -0
  159. package/src/features/tools/og-image-generator/widget/form-fields.tsx +240 -0
  160. package/src/features/tools/og-image-generator/widget/index.ts +7 -0
  161. package/src/features/tools/og-image-generator/widget/og-image-generator.tsx +742 -0
  162. package/src/features/tools/og-image-generator/widget/preview-panel.tsx +305 -0
  163. package/src/features/tools/og-image-generator/widget/types.ts +1 -0
  164. package/src/features/tools/package/direct-models.ts +20 -0
  165. package/src/features/tools/package/form.ts +38 -0
  166. package/src/features/tools/package/l10n.ts +22 -0
  167. package/src/features/tools/package/package-container.tsx +285 -0
  168. package/src/features/tools/package/package-loaders.ts +22 -0
  169. package/src/features/tools/package/package-registry.ts +36 -0
  170. package/src/features/tools/package/result-markdown.ts +142 -0
  171. package/src/features/tools/package/schema.ts +379 -0
  172. package/src/features/tools/package/to-tool-module.ts +20 -0
  173. package/src/features/tools/package/to-tool-spec.ts +52 -0
  174. package/src/features/tools/package/types.ts +381 -0
  175. package/src/features/tools/pitch-deck-generator/pitch-deck-generator.container.tsx +175 -0
  176. package/src/features/tools/pitch-deck-generator/pitch-deck-generator.spec.ts +14 -0
  177. package/src/features/tools/pitch-deck-generator/pitch-deck-library-data.ts +476 -0
  178. package/src/features/tools/pitch-deck-generator/pitch-deck-library.tsx +159 -0
  179. package/src/features/tools/pitch-deck-generator/widget/ceremony-line.tsx +27 -0
  180. package/src/features/tools/pitch-deck-generator/widget/constants.ts +27 -0
  181. package/src/features/tools/pitch-deck-generator/widget/index.ts +7 -0
  182. package/src/features/tools/pitch-deck-generator/widget/pitch-deck-generator.tsx +763 -0
  183. package/src/features/tools/pitch-deck-generator/widget/result-helpers.ts +102 -0
  184. package/src/features/tools/pitch-deck-generator/widget/result-shell.tsx +263 -0
  185. package/src/features/tools/pitch-deck-generator/widget/slide-frame.tsx +106 -0
  186. package/src/features/tools/pitch-deck-generator/widget/slide-lightbox.tsx +149 -0
  187. package/src/features/tools/pitch-deck-generator/widget/style-option.tsx +54 -0
  188. package/src/features/tools/pitch-deck-generator/widget/types.ts +44 -0
  189. package/src/features/tools/product-agreement-generator/product-agreement-generator.container.tsx +137 -0
  190. package/src/features/tools/product-agreement-generator/product-agreement-generator.spec.ts +14 -0
  191. package/src/features/tools/product-agreement-generator/widget/constants.ts +27 -0
  192. package/src/features/tools/product-agreement-generator/widget/form-controls.tsx +218 -0
  193. package/src/features/tools/product-agreement-generator/widget/helpers.ts +68 -0
  194. package/src/features/tools/product-agreement-generator/widget/index.ts +7 -0
  195. package/src/features/tools/product-agreement-generator/widget/product-agreement-generator.tsx +671 -0
  196. package/src/features/tools/product-agreement-generator/widget/result-shell.tsx +473 -0
  197. package/src/features/tools/product-agreement-generator/widget/types.ts +89 -0
  198. package/src/features/tools/product-hunt-launch-planner/product-hunt-launch-planner.container.tsx +122 -0
  199. package/src/features/tools/product-hunt-launch-planner/product-hunt-launch-planner.spec.ts +15 -0
  200. package/src/features/tools/product-hunt-launch-planner/widget/constants.ts +5 -0
  201. package/src/features/tools/product-hunt-launch-planner/widget/helpers.ts +44 -0
  202. package/src/features/tools/product-hunt-launch-planner/widget/index.ts +7 -0
  203. package/src/features/tools/product-hunt-launch-planner/widget/preview-panel.tsx +143 -0
  204. package/src/features/tools/product-hunt-launch-planner/widget/product-hunt-launch-planner.tsx +504 -0
  205. package/src/features/tools/product-hunt-launch-planner/widget/result-shell.tsx +176 -0
  206. package/src/features/tools/product-hunt-launch-planner/widget/types.ts +20 -0
  207. package/src/features/tools/product-name-generator/product-name-generator.container.tsx +14 -0
  208. package/src/features/tools/product-name-generator/product-name-generator.spec.ts +15 -0
  209. package/src/features/tools/product-name-generator/widget/candidate-card.tsx +273 -0
  210. package/src/features/tools/product-name-generator/widget/constants.ts +21 -0
  211. package/src/features/tools/product-name-generator/widget/form-controls.tsx +136 -0
  212. package/src/features/tools/product-name-generator/widget/helpers.ts +41 -0
  213. package/src/features/tools/product-name-generator/widget/index.ts +7 -0
  214. package/src/features/tools/product-name-generator/widget/product-name-generator.tsx +776 -0
  215. package/src/features/tools/product-name-generator/widget/types.ts +36 -0
  216. package/src/features/tools/product-positioning-analyzer/product-positioning-analyzer.package.ts +801 -0
  217. package/src/features/tools/product-poster-generator/product-poster-generator.container.tsx +14 -0
  218. package/src/features/tools/product-poster-generator/product-poster-generator.spec.ts +15 -0
  219. package/src/features/tools/product-poster-generator/widget/constants.ts +125 -0
  220. package/src/features/tools/product-poster-generator/widget/form-controls.tsx +204 -0
  221. package/src/features/tools/product-poster-generator/widget/helpers.ts +155 -0
  222. package/src/features/tools/product-poster-generator/widget/index.ts +7 -0
  223. package/src/features/tools/product-poster-generator/widget/product-poster-generator.tsx +663 -0
  224. package/src/features/tools/product-poster-generator/widget/result-shell.tsx +12 -0
  225. package/src/features/tools/product-poster-generator/widget/types.ts +83 -0
  226. package/src/features/tools/product-ui-generator/product-ui-generator.container.tsx +116 -0
  227. package/src/features/tools/product-ui-generator/product-ui-generator.spec.ts +14 -0
  228. package/src/features/tools/product-ui-generator/widget/constants.ts +18 -0
  229. package/src/features/tools/product-ui-generator/widget/helpers.ts +11 -0
  230. package/src/features/tools/product-ui-generator/widget/index.ts +7 -0
  231. package/src/features/tools/product-ui-generator/widget/preview-panels.tsx +73 -0
  232. package/src/features/tools/product-ui-generator/widget/product-ui-generator.tsx +304 -0
  233. package/src/features/tools/product-ui-generator/widget/result-shell.tsx +118 -0
  234. package/src/features/tools/product-ui-generator/widget/types.ts +9 -0
  235. package/src/features/tools/reddit-pain-point-finder/reddit-pain-point-finder.container.tsx +113 -0
  236. package/src/features/tools/reddit-pain-point-finder/reddit-pain-point-finder.spec.ts +15 -0
  237. package/src/features/tools/reddit-pain-point-finder/widget/constants.ts +5 -0
  238. package/src/features/tools/reddit-pain-point-finder/widget/index.ts +7 -0
  239. package/src/features/tools/reddit-pain-point-finder/widget/preview-panels.tsx +73 -0
  240. package/src/features/tools/reddit-pain-point-finder/widget/reddit-pain-point-finder.tsx +281 -0
  241. package/src/features/tools/reddit-pain-point-finder/widget/result-shell.tsx +203 -0
  242. package/src/features/tools/reddit-pain-point-finder/widget/types.ts +15 -0
  243. package/src/features/tools/registry.ts +288 -0
  244. package/src/features/tools/runtime-registry.ts +186 -0
  245. package/src/features/tools/shared/create-guide-stack-container.tsx +176 -0
  246. package/src/features/tools/shared/create-standard-landing-container.tsx +163 -0
  247. package/src/features/tools/shared/tool-content-sections.tsx +659 -0
  248. package/src/features/tools/shared/tool-cta.tsx +66 -0
  249. package/src/features/tools/shared/tool-draft-view.tsx +53 -0
  250. package/src/features/tools/shared/tool-guide-section.tsx +191 -0
  251. package/src/features/tools/shared/tool-handoff.tsx +38 -0
  252. package/src/features/tools/shared/tool-mcp-badge.tsx +23 -0
  253. package/src/features/tools/shared/tool-message-translator.ts +37 -0
  254. package/src/features/tools/shared/tool-page-shell.tsx +348 -0
  255. package/src/features/tools/shared/tool-standard-generation-steps.tsx +52 -0
  256. package/src/features/tools/shared/tool-standard-landing-sections.tsx +447 -0
  257. package/src/features/tools/shared/tool-ui-registry.ts +237 -0
  258. package/src/features/tools/shared/tool-widget-slot.tsx +29 -0
  259. package/src/features/tools/slogan-generator/slogan-generator.package.ts +641 -0
  260. package/src/features/tools/social-listening-research-report/social-listening-research-report.container.tsx +124 -0
  261. package/src/features/tools/social-listening-research-report/social-listening-research-report.spec.ts +15 -0
  262. package/src/features/tools/social-listening-research-report/widget/constants.ts +4 -0
  263. package/src/features/tools/social-listening-research-report/widget/index.ts +7 -0
  264. package/src/features/tools/social-listening-research-report/widget/preview-panels.tsx +73 -0
  265. package/src/features/tools/social-listening-research-report/widget/result-shell.tsx +216 -0
  266. package/src/features/tools/social-listening-research-report/widget/social-listening-research-report.tsx +303 -0
  267. package/src/features/tools/social-listening-research-report/widget/types.ts +15 -0
  268. package/src/features/tools/social-platform-asset-adapter/social-platform-asset-adapter.container.tsx +123 -0
  269. package/src/features/tools/social-platform-asset-adapter/social-platform-asset-adapter.spec.ts +15 -0
  270. package/src/features/tools/social-platform-asset-adapter/widget/constants.ts +43 -0
  271. package/src/features/tools/social-platform-asset-adapter/widget/helpers.ts +249 -0
  272. package/src/features/tools/social-platform-asset-adapter/widget/index.ts +7 -0
  273. package/src/features/tools/social-platform-asset-adapter/widget/result-shell.tsx +350 -0
  274. package/src/features/tools/social-platform-asset-adapter/widget/section-heading.tsx +18 -0
  275. package/src/features/tools/social-platform-asset-adapter/widget/social-platform-asset-adapter.tsx +641 -0
  276. package/src/features/tools/social-platform-asset-adapter/widget/types.ts +40 -0
  277. package/src/features/tools/social-profile-kit/social-profile-kit.container.tsx +177 -0
  278. package/src/features/tools/social-profile-kit/social-profile-kit.spec.ts +15 -0
  279. package/src/features/tools/social-profile-kit/widget/context-editor.tsx +171 -0
  280. package/src/features/tools/social-profile-kit/widget/generation-runtime.ts +281 -0
  281. package/src/features/tools/social-profile-kit/widget/index.ts +7 -0
  282. package/src/features/tools/social-profile-kit/widget/input-panel.tsx +294 -0
  283. package/src/features/tools/social-profile-kit/widget/platform-dock.tsx +115 -0
  284. package/src/features/tools/social-profile-kit/widget/profile-canvas.tsx +318 -0
  285. package/src/features/tools/social-profile-kit/widget/profile-preview/bluesky-preview.tsx +188 -0
  286. package/src/features/tools/social-profile-kit/widget/profile-preview/facebook-preview.tsx +168 -0
  287. package/src/features/tools/social-profile-kit/widget/profile-preview/index.ts +1 -0
  288. package/src/features/tools/social-profile-kit/widget/profile-preview/instagram-preview.tsx +278 -0
  289. package/src/features/tools/social-profile-kit/widget/profile-preview/linkedin-preview.tsx +358 -0
  290. package/src/features/tools/social-profile-kit/widget/profile-preview/profile-preview.tsx +348 -0
  291. package/src/features/tools/social-profile-kit/widget/profile-preview/shared.tsx +391 -0
  292. package/src/features/tools/social-profile-kit/widget/profile-preview/threads-preview.tsx +148 -0
  293. package/src/features/tools/social-profile-kit/widget/profile-preview/tiktok-preview.tsx +319 -0
  294. package/src/features/tools/social-profile-kit/widget/profile-preview/x-preview.tsx +341 -0
  295. package/src/features/tools/social-profile-kit/widget/profile-preview/youtube-preview.tsx +297 -0
  296. package/src/features/tools/social-profile-kit/widget/social-profile-kit-generator.tsx +1059 -0
  297. package/src/features/tools/social-profile-kit/widget/types.ts +104 -0
  298. package/src/features/tools/spec-registry.ts +158 -0
  299. package/src/features/tools/startup-idea-research/startup-idea-research.container.tsx +111 -0
  300. package/src/features/tools/startup-idea-research/startup-idea-research.spec.ts +15 -0
  301. package/src/features/tools/startup-idea-research/widget/constants.ts +11 -0
  302. package/src/features/tools/startup-idea-research/widget/index.ts +7 -0
  303. package/src/features/tools/startup-idea-research/widget/preview-panels.tsx +67 -0
  304. package/src/features/tools/startup-idea-research/widget/result-shell.tsx +323 -0
  305. package/src/features/tools/startup-idea-research/widget/startup-idea-research.tsx +272 -0
  306. package/src/features/tools/startup-idea-research/widget/types.ts +21 -0
  307. package/src/features/tools/tarot-reading/tarot-reading.container.tsx +412 -0
  308. package/src/features/tools/tarot-reading/tarot-reading.spec.ts +15 -0
  309. package/src/features/tools/tarot-reading/widget/cards.tsx +152 -0
  310. package/src/features/tools/tarot-reading/widget/constants.ts +69 -0
  311. package/src/features/tools/tarot-reading/widget/deck-view.tsx +86 -0
  312. package/src/features/tools/tarot-reading/widget/deck.ts +86 -0
  313. package/src/features/tools/tarot-reading/widget/index.ts +7 -0
  314. package/src/features/tools/tarot-reading/widget/landing-view.tsx +209 -0
  315. package/src/features/tools/tarot-reading/widget/reading-copy.tsx +138 -0
  316. package/src/features/tools/tarot-reading/widget/reading-view.tsx +189 -0
  317. package/src/features/tools/tarot-reading/widget/reveal-view.tsx +50 -0
  318. package/src/features/tools/tarot-reading/widget/ritual-view.tsx +276 -0
  319. package/src/features/tools/tarot-reading/widget/tarot-reading.tsx +262 -0
  320. package/src/features/tools/tarot-reading/widget/types.ts +22 -0
  321. package/src/features/tools/twitter-gif-downloader/twitter-gif-downloader.container.tsx +114 -0
  322. package/src/features/tools/twitter-gif-downloader/twitter-gif-downloader.spec.ts +14 -0
  323. package/src/features/tools/twitter-gif-downloader/widget/index.ts +7 -0
  324. package/src/features/tools/twitter-gif-downloader/widget/twitter-gif-downloader.tsx +351 -0
  325. package/src/features/tools/types.ts +68 -0
  326. package/src/features/tools/user-interview-guide-generator/user-interview-guide-generator.package.ts +774 -0
  327. package/src/features/tools/user-interview-insight-report-generator/user-interview-insight-report-generator.container.tsx +23 -0
  328. package/src/features/tools/user-interview-insight-report-generator/user-interview-insight-report-generator.spec.ts +14 -0
  329. package/src/features/tools/user-interview-insight-report-generator/widget/constants.ts +8 -0
  330. package/src/features/tools/user-interview-insight-report-generator/widget/helpers.ts +4 -0
  331. package/src/features/tools/user-interview-insight-report-generator/widget/index.ts +7 -0
  332. package/src/features/tools/user-interview-insight-report-generator/widget/preview-panels.tsx +55 -0
  333. package/src/features/tools/user-interview-insight-report-generator/widget/result-shell.tsx +122 -0
  334. package/src/features/tools/user-interview-insight-report-generator/widget/types.ts +16 -0
  335. package/src/features/tools/user-interview-insight-report-generator/widget/user-interview-insight-report-generator.tsx +293 -0
  336. package/src/features/tools/user-interview-record-generator/user-interview-record-generator.container.tsx +18 -0
  337. package/src/features/tools/user-interview-record-generator/user-interview-record-generator.spec.ts +14 -0
  338. package/src/features/tools/user-interview-record-generator/widget/constants.ts +9 -0
  339. package/src/features/tools/user-interview-record-generator/widget/helpers.ts +4 -0
  340. package/src/features/tools/user-interview-record-generator/widget/index.ts +7 -0
  341. package/src/features/tools/user-interview-record-generator/widget/preview-panels.tsx +48 -0
  342. package/src/features/tools/user-interview-record-generator/widget/result-shell.tsx +128 -0
  343. package/src/features/tools/user-interview-record-generator/widget/types.ts +16 -0
  344. package/src/features/tools/user-interview-record-generator/widget/user-interview-record-generator.tsx +305 -0
  345. package/src/features/tools/utm-builder/utm-builder.package.ts +846 -0
  346. package/src/features/tools/widget-registry.ts +73 -0
  347. package/src/generated/mcp-tools-registry.json +17 -0
  348. package/src/host/client-proxy.test.ts +33 -0
  349. package/src/host/client.ts +678 -0
  350. package/src/host/server.ts +119 -0
  351. package/src/i18n/client.ts +11 -0
  352. package/src/i18n/locale-fallback.ts +38 -0
  353. package/src/i18n/locale.ts +18 -0
  354. package/src/i18n/messages/en/page/tools.ts +124 -0
  355. package/src/i18n/messages/en/tools/app-icon-resizer.ts +244 -0
  356. package/src/i18n/messages/en/tools/app-store-screenshot-generator.ts +145 -0
  357. package/src/i18n/messages/en/tools/build-in-public-story-generator.ts +229 -0
  358. package/src/i18n/messages/en/tools/cold-start-channel-selector.ts +423 -0
  359. package/src/i18n/messages/en/tools/commercial-bp-generator.ts +304 -0
  360. package/src/i18n/messages/en/tools/community-feedback-inbox.ts +218 -0
  361. package/src/i18n/messages/en/tools/community-pain-point-extractor.ts +230 -0
  362. package/src/i18n/messages/en/tools/community-post-risk-checker.ts +209 -0
  363. package/src/i18n/messages/en/tools/competitor-analysis.ts +197 -0
  364. package/src/i18n/messages/en/tools/email-template-generator.ts +302 -0
  365. package/src/i18n/messages/en/tools/engine.ts +69 -0
  366. package/src/i18n/messages/en/tools/gtm-readiness-checklist.ts +166 -0
  367. package/src/i18n/messages/en/tools/index.ts +73 -0
  368. package/src/i18n/messages/en/tools/koko-codex-assistant.ts +171 -0
  369. package/src/i18n/messages/en/tools/logo-generator.ts +173 -0
  370. package/src/i18n/messages/en/tools/market-forecast-report.ts +228 -0
  371. package/src/i18n/messages/en/tools/million-user-growth-test.ts +386 -0
  372. package/src/i18n/messages/en/tools/og-image-generator.ts +172 -0
  373. package/src/i18n/messages/en/tools/pitch-deck-generator.ts +358 -0
  374. package/src/i18n/messages/en/tools/product-agreement-generator.ts +411 -0
  375. package/src/i18n/messages/en/tools/product-hunt-launch-planner.ts +272 -0
  376. package/src/i18n/messages/en/tools/product-name-generator.ts +383 -0
  377. package/src/i18n/messages/en/tools/product-poster-generator.ts +294 -0
  378. package/src/i18n/messages/en/tools/product-ui-generator.ts +234 -0
  379. package/src/i18n/messages/en/tools/reddit-pain-point-finder.ts +163 -0
  380. package/src/i18n/messages/en/tools/shared.ts +24 -0
  381. package/src/i18n/messages/en/tools/social-listening-research-report.ts +185 -0
  382. package/src/i18n/messages/en/tools/social-media-profile-generator.ts +22 -0
  383. package/src/i18n/messages/en/tools/social-platform-asset-adapter.ts +287 -0
  384. package/src/i18n/messages/en/tools/social-profile-kit.ts +150 -0
  385. package/src/i18n/messages/en/tools/startup-idea-research.ts +170 -0
  386. package/src/i18n/messages/en/tools/tarot-reading.ts +230 -0
  387. package/src/i18n/messages/en/tools/twitter-gif-downloader.ts +145 -0
  388. package/src/i18n/messages/en/tools/user-interview-insight-report-generator.ts +242 -0
  389. package/src/i18n/messages/en/tools/user-interview-record-generator.ts +244 -0
  390. package/src/i18n/messages/en/tools-ui.ts +704 -0
  391. package/src/i18n/messages/zh/page/tools.ts +124 -0
  392. package/src/i18n/messages/zh/tools/app-icon-resizer.ts +242 -0
  393. package/src/i18n/messages/zh/tools/app-store-screenshot-generator.ts +145 -0
  394. package/src/i18n/messages/zh/tools/build-in-public-story-generator.ts +230 -0
  395. package/src/i18n/messages/zh/tools/cold-start-channel-selector.ts +422 -0
  396. package/src/i18n/messages/zh/tools/commercial-bp-generator.ts +302 -0
  397. package/src/i18n/messages/zh/tools/community-feedback-inbox.ts +217 -0
  398. package/src/i18n/messages/zh/tools/community-pain-point-extractor.ts +230 -0
  399. package/src/i18n/messages/zh/tools/community-post-risk-checker.ts +200 -0
  400. package/src/i18n/messages/zh/tools/competitor-analysis.ts +192 -0
  401. package/src/i18n/messages/zh/tools/email-template-generator.ts +302 -0
  402. package/src/i18n/messages/zh/tools/engine.ts +68 -0
  403. package/src/i18n/messages/zh/tools/gtm-readiness-checklist.ts +166 -0
  404. package/src/i18n/messages/zh/tools/index.ts +73 -0
  405. package/src/i18n/messages/zh/tools/koko-codex-assistant.ts +170 -0
  406. package/src/i18n/messages/zh/tools/logo-generator.ts +172 -0
  407. package/src/i18n/messages/zh/tools/market-forecast-report.ts +228 -0
  408. package/src/i18n/messages/zh/tools/million-user-growth-test.ts +385 -0
  409. package/src/i18n/messages/zh/tools/og-image-generator.ts +173 -0
  410. package/src/i18n/messages/zh/tools/pitch-deck-generator.ts +358 -0
  411. package/src/i18n/messages/zh/tools/product-agreement-generator.ts +401 -0
  412. package/src/i18n/messages/zh/tools/product-hunt-launch-planner.ts +267 -0
  413. package/src/i18n/messages/zh/tools/product-name-generator.ts +383 -0
  414. package/src/i18n/messages/zh/tools/product-poster-generator.ts +282 -0
  415. package/src/i18n/messages/zh/tools/product-ui-generator.ts +234 -0
  416. package/src/i18n/messages/zh/tools/reddit-pain-point-finder.ts +162 -0
  417. package/src/i18n/messages/zh/tools/shared.ts +24 -0
  418. package/src/i18n/messages/zh/tools/social-listening-research-report.ts +181 -0
  419. package/src/i18n/messages/zh/tools/social-media-profile-generator.ts +22 -0
  420. package/src/i18n/messages/zh/tools/social-platform-asset-adapter.ts +284 -0
  421. package/src/i18n/messages/zh/tools/social-profile-kit.ts +150 -0
  422. package/src/i18n/messages/zh/tools/startup-idea-research.ts +165 -0
  423. package/src/i18n/messages/zh/tools/tarot-reading.ts +228 -0
  424. package/src/i18n/messages/zh/tools/twitter-gif-downloader.ts +138 -0
  425. package/src/i18n/messages/zh/tools/user-interview-insight-report-generator.ts +224 -0
  426. package/src/i18n/messages/zh/tools/user-interview-record-generator.ts +226 -0
  427. package/src/i18n/messages/zh/tools-ui.ts +684 -0
  428. package/src/i18n/messages/zh-tw/page/tools.ts +115 -0
  429. package/src/i18n/messages/zh-tw/tools/app-icon-resizer.ts +242 -0
  430. package/src/i18n/messages/zh-tw/tools/app-store-screenshot-generator.ts +145 -0
  431. package/src/i18n/messages/zh-tw/tools/build-in-public-story-generator.ts +230 -0
  432. package/src/i18n/messages/zh-tw/tools/cold-start-channel-selector.ts +440 -0
  433. package/src/i18n/messages/zh-tw/tools/commercial-bp-generator.ts +302 -0
  434. package/src/i18n/messages/zh-tw/tools/community-feedback-inbox.ts +217 -0
  435. package/src/i18n/messages/zh-tw/tools/community-pain-point-extractor.ts +230 -0
  436. package/src/i18n/messages/zh-tw/tools/community-post-risk-checker.ts +200 -0
  437. package/src/i18n/messages/zh-tw/tools/competitor-analysis.ts +192 -0
  438. package/src/i18n/messages/zh-tw/tools/email-template-generator.ts +302 -0
  439. package/src/i18n/messages/zh-tw/tools/engine.ts +68 -0
  440. package/src/i18n/messages/zh-tw/tools/gtm-readiness-checklist.ts +166 -0
  441. package/src/i18n/messages/zh-tw/tools/index.ts +73 -0
  442. package/src/i18n/messages/zh-tw/tools/koko-codex-assistant.ts +170 -0
  443. package/src/i18n/messages/zh-tw/tools/logo-generator.ts +71 -0
  444. package/src/i18n/messages/zh-tw/tools/market-forecast-report.ts +228 -0
  445. package/src/i18n/messages/zh-tw/tools/million-user-growth-test.ts +385 -0
  446. package/src/i18n/messages/zh-tw/tools/og-image-generator.ts +173 -0
  447. package/src/i18n/messages/zh-tw/tools/pitch-deck-generator.ts +358 -0
  448. package/src/i18n/messages/zh-tw/tools/product-agreement-generator.ts +401 -0
  449. package/src/i18n/messages/zh-tw/tools/product-hunt-launch-planner.ts +267 -0
  450. package/src/i18n/messages/zh-tw/tools/product-name-generator.ts +383 -0
  451. package/src/i18n/messages/zh-tw/tools/product-poster-generator.ts +282 -0
  452. package/src/i18n/messages/zh-tw/tools/product-ui-generator.ts +234 -0
  453. package/src/i18n/messages/zh-tw/tools/reddit-pain-point-finder.ts +162 -0
  454. package/src/i18n/messages/zh-tw/tools/shared.ts +24 -0
  455. package/src/i18n/messages/zh-tw/tools/social-listening-research-report.ts +181 -0
  456. package/src/i18n/messages/zh-tw/tools/social-media-profile-generator.ts +22 -0
  457. package/src/i18n/messages/zh-tw/tools/social-platform-asset-adapter.ts +284 -0
  458. package/src/i18n/messages/zh-tw/tools/social-profile-kit.ts +150 -0
  459. package/src/i18n/messages/zh-tw/tools/startup-idea-research.ts +165 -0
  460. package/src/i18n/messages/zh-tw/tools/tarot-reading.ts +228 -0
  461. package/src/i18n/messages/zh-tw/tools/twitter-gif-downloader.ts +138 -0
  462. package/src/i18n/messages/zh-tw/tools/user-interview-insight-report-generator.ts +224 -0
  463. package/src/i18n/messages/zh-tw/tools/user-interview-record-generator.ts +226 -0
  464. package/src/i18n/messages/zh-tw/tools-ui.ts +525 -0
  465. package/src/index.ts +15 -0
  466. package/src/lib/activity-task-handoff.ts +404 -0
  467. package/src/lib/api/errors.ts +39 -0
  468. package/src/lib/app-origin.ts +30 -0
  469. package/src/lib/fact-claim-contract.ts +68 -0
  470. package/src/lib/fake-delay.ts +3 -0
  471. package/src/lib/file/download.ts +10 -0
  472. package/src/lib/routing/locale-paths.ts +27 -0
  473. package/src/lib/seo-meta.ts +3 -0
  474. package/src/lib/tools/app-icon-resizer-schema.ts +191 -0
  475. package/src/lib/tools/app-store-screenshot-generator-schema.ts +185 -0
  476. package/src/lib/tools/build-in-public-story-generator-schema.ts +67 -0
  477. package/src/lib/tools/build-in-public-story-generator.format.ts +507 -0
  478. package/src/lib/tools/cold-start-channel-selector-schema.ts +147 -0
  479. package/src/lib/tools/commercial-bp-generator-schema.ts +222 -0
  480. package/src/lib/tools/community-feedback-inbox-schema.ts +125 -0
  481. package/src/lib/tools/community-feedback-inbox.format.ts +764 -0
  482. package/src/lib/tools/community-pain-point-extractor-schema.ts +166 -0
  483. package/src/lib/tools/community-post-risk-checker-schema.ts +99 -0
  484. package/src/lib/tools/community-post-risk-checker.format.ts +557 -0
  485. package/src/lib/tools/competitor-analysis-schema.ts +144 -0
  486. package/src/lib/tools/draft-preview-access.ts +3 -0
  487. package/src/lib/tools/draft-store.ts +69 -0
  488. package/src/lib/tools/email-template-generator-schema.ts +124 -0
  489. package/src/lib/tools/gtm-checklist-copy.ts +57 -0
  490. package/src/lib/tools/gtm-checklist-structure.ts +37 -0
  491. package/src/lib/tools/image-download.ts +68 -0
  492. package/src/lib/tools/input-quality.ts +97 -0
  493. package/src/lib/tools/logo-generator-schema.ts +224 -0
  494. package/src/lib/tools/market-forecast-report-schema.ts +299 -0
  495. package/src/lib/tools/mcp-registry.ts +16 -0
  496. package/src/lib/tools/mcp-types.ts +18 -0
  497. package/src/lib/tools/million-user-growth-test-schema.ts +49 -0
  498. package/src/lib/tools/million-user-growth-test.ts +181 -0
  499. package/src/lib/tools/og-image-generator-render.ts +448 -0
  500. package/src/lib/tools/og-image-generator-schema.ts +140 -0
  501. package/src/lib/tools/ops-catalog.ts +102 -0
  502. package/src/lib/tools/pitch-deck-generator-schema.ts +182 -0
  503. package/src/lib/tools/pitch-deck-package.ts +0 -0
  504. package/src/lib/tools/product-agreement-generator-schema.ts +168 -0
  505. package/src/lib/tools/product-hunt-launch-planner-schema.ts +136 -0
  506. package/src/lib/tools/product-hunt-launch-planner.format.ts +72 -0
  507. package/src/lib/tools/product-name-generator-schema.ts +563 -0
  508. package/src/lib/tools/product-poster-generator-schema.ts +215 -0
  509. package/src/lib/tools/product-ui-generator-schema.ts +157 -0
  510. package/src/lib/tools/reddit-pain-point-finder-schema.ts +88 -0
  511. package/src/lib/tools/resolve-tool-locale-copy.ts +75 -0
  512. package/src/lib/tools/slug.ts +60 -0
  513. package/src/lib/tools/social-listening-research-report-schema.ts +105 -0
  514. package/src/lib/tools/social-platform-asset-adapter-schema.ts +152 -0
  515. package/src/lib/tools/social-profile-kit.constants.ts +12 -0
  516. package/src/lib/tools/social-profile-kit.generation.ts +257 -0
  517. package/src/lib/tools/social-profile-kit.input.ts +290 -0
  518. package/src/lib/tools/social-profile-kit.manual.ts +481 -0
  519. package/src/lib/tools/social-profile-kit.package.ts +220 -0
  520. package/src/lib/tools/social-profile-kit.schema.ts +328 -0
  521. package/src/lib/tools/startup-idea-research-schema.ts +107 -0
  522. package/src/lib/tools/tarot-imagery.ts +89 -0
  523. package/src/lib/tools/tarot-reading.ts +1044 -0
  524. package/src/lib/tools/tool-message-keys.ts +18 -0
  525. package/src/lib/tools/types.ts +32 -0
  526. package/src/lib/tools/user-interview.format.ts +147 -0
  527. package/src/lib/tools/user-interview.generation.ts +670 -0
  528. package/src/lib/tools/user-interview.schema.ts +192 -0
  529. package/src/lib/zip.ts +106 -0
  530. package/src/services/tools/handlers/gtm-readiness-checklist.ts +71 -0
  531. package/src/services/tools/handlers/types.ts +7 -0
@@ -0,0 +1,507 @@
1
+ import type {
2
+ BuildInPublicChannel,
3
+ BuildInPublicStoryBrief,
4
+ BuildInPublicStoryResult,
5
+ } from "./build-in-public-story-generator-schema";
6
+
7
+ type CopyPack = {
8
+ stage: Record<BuildInPublicStoryBrief["stage"], string>;
9
+ channel: Record<BuildInPublicChannel, string>;
10
+ channelFit: Record<BuildInPublicChannel, string>;
11
+ risk: {
12
+ promo: string;
13
+ noMetrics: string;
14
+ roadmap: string;
15
+ customer: string;
16
+ proof: string;
17
+ };
18
+ gaps: {
19
+ metrics: string;
20
+ gtm: string;
21
+ uncertainty: string;
22
+ ask: string;
23
+ baseline: string;
24
+ };
25
+ review: string[];
26
+ community: string[];
27
+ };
28
+
29
+ const copy: Record<BuildInPublicStoryBrief["language"], CopyPack> = {
30
+ zh: {
31
+ stage: {
32
+ idea: "想法验证",
33
+ prototype: "原型验证",
34
+ beta: "Beta 测试",
35
+ launched: "已发布早期版本",
36
+ postLaunch: "发布后学习",
37
+ },
38
+ channel: {
39
+ indieHackers: "Indie Hackers 长帖",
40
+ reddit: "Reddit 讨论帖",
41
+ xThread: "X build-in-public thread",
42
+ linkedin: "LinkedIn 进展帖",
43
+ },
44
+ channelFit: {
45
+ indieHackers: "适合讲清背景、假设、数据和本周想请 founder 反馈的问题。",
46
+ reddit: "适合把宣传降到最低,把具体问题放在前面,让讨论围绕判断而不是产品本身。",
47
+ xThread: "适合拆成阶段、行动、信号和疑问,保持每条都能单独读懂。",
48
+ linkedin: "适合给专业网络展示学习过程和决策质量,但不要写成公司新闻稿。",
49
+ },
50
+ risk: {
51
+ promo: "草案里可能有营销感过强的词,发布前要改成事实、信号和问题。",
52
+ noMetrics: "缺少指标或具体反馈时,帖子容易像观点而不是公开学习记录。",
53
+ roadmap: "路线图、客户信息或未发布能力需要模糊处理,避免过度公开。",
54
+ customer: "如果提到客户、用户或社区反馈,必须匿名化并避免可识别细节。",
55
+ proof: "GTM 结论需要保留为假设,不要写成已经被市场验证的事实。",
56
+ },
57
+ gaps: {
58
+ metrics: "补一个最小信号:访问、注册、回复、等待名单、访谈数、转化率或定性原话。",
59
+ gtm: "补 Tomako 生成的 GTM 策略:优先渠道、目标用户、核心假设或暂不做的渠道。",
60
+ uncertainty: "补一个仍不确定的判断,社区才有空间参与讨论。",
61
+ ask: "把反馈问题改得更具体,例如二选一、排序、反例或判断标准。",
62
+ baseline: "补上当前阶段和上周/上次基线,读者才知道这周进展意味着什么。",
63
+ },
64
+ review: [
65
+ "每个结论都能指向一个输入、指标、用户反馈或明确假设。",
66
+ "删除“革命性、颠覆、爆发、增长飞轮”等没有证据支撑的词。",
67
+ "保留至少一个失败、犹豫或不确定点。",
68
+ "不要公开客户姓名、收入细节、敏感路线图或团队内部冲突。",
69
+ "结尾只问一个清楚问题,不塞注册链接或强 CTA。",
70
+ ],
71
+ community: [
72
+ "先交代阶段,不把早期信号包装成成功案例。",
73
+ "把 Tomako 的建议写成假设来源,而不是替你背书的权威结论。",
74
+ "用数据或原话解释“有效”,用待验证问题解释“不确定”。",
75
+ "请社区反馈判断,而不是请社区帮忙推广。",
76
+ ],
77
+ },
78
+ en: {
79
+ stage: {
80
+ idea: "idea validation",
81
+ prototype: "prototype validation",
82
+ beta: "beta testing",
83
+ launched: "early launch",
84
+ postLaunch: "post-launch learning",
85
+ },
86
+ channel: {
87
+ indieHackers: "Indie Hackers long post",
88
+ reddit: "Reddit discussion post",
89
+ xThread: "X build-in-public thread",
90
+ linkedin: "LinkedIn progress post",
91
+ },
92
+ channelFit: {
93
+ indieHackers: "Best for context, assumptions, evidence, and a clear founder feedback ask.",
94
+ reddit: "Best when the promotion is reduced and the question leads the discussion.",
95
+ xThread: "Best as a compact sequence of stage, action, signal, uncertainty, and ask.",
96
+ linkedin: "Best for showing learning quality to a professional network without turning it into a press release.",
97
+ },
98
+ risk: {
99
+ promo: "Some wording may feel too promotional. Rewrite it as facts, signals, and questions before posting.",
100
+ noMetrics: "Without metrics or concrete feedback, the story can read like opinion instead of public learning.",
101
+ roadmap: "Roadmap, customer details, and unreleased capabilities should be blurred before posting.",
102
+ customer: "If you mention customers, users, or community feedback, anonymize anything identifiable.",
103
+ proof: "Keep GTM conclusions framed as hypotheses unless the market has actually validated them.",
104
+ },
105
+ gaps: {
106
+ metrics: "Add one minimum signal: visits, signups, replies, waitlist adds, interviews, conversion rate, or a user quote.",
107
+ gtm: "Add the GTM strategy Tomako generated: priority channel, target user, core assumption, or channels you are not prioritizing.",
108
+ uncertainty: "Add one unresolved decision so the community has something meaningful to respond to.",
109
+ ask: "Make the feedback ask sharper: a choice, a ranking, a counterexample, or a decision criterion.",
110
+ baseline: "Add the current stage and previous baseline so readers can interpret this week's progress.",
111
+ },
112
+ review: [
113
+ "Every claim points to an input, metric, user quote, or explicit assumption.",
114
+ "Remove words like revolutionary, game-changing, explosive, or flywheel unless you have proof.",
115
+ "Keep at least one failure, hesitation, or open question.",
116
+ "Do not reveal customer names, sensitive revenue details, private roadmap, or internal conflict.",
117
+ "End with one clear question, not a signup link or heavy CTA.",
118
+ ],
119
+ community: [
120
+ "Name the stage first; do not package early signals as a success story.",
121
+ "Frame Tomako's strategy as an input to your hypothesis, not as authority.",
122
+ "Use data or quotes for what worked, and open questions for what is uncertain.",
123
+ "Ask the community for judgment, not promotion.",
124
+ ],
125
+ },
126
+ };
127
+
128
+ const promoPattern =
129
+ /\b(revolutionary|game[-\s]?changing|explode|viral|dominate|crush|颠覆|革命性|爆发|碾压|增长飞轮)\b/i;
130
+
131
+ function hasMeaningful(value?: string) {
132
+ return Boolean(value?.trim() && value.trim().length >= 18);
133
+ }
134
+
135
+ function firstSentence(value: string) {
136
+ const trimmed = value.trim().replace(/\s+/g, " ");
137
+ const match = trimmed.match(/^(.{28,160}?[。.!?])\s/);
138
+ return match?.[1] ?? trimmed.slice(0, 160);
139
+ }
140
+
141
+ function buildScore(brief: BuildInPublicStoryBrief) {
142
+ let score = 50;
143
+ if (hasMeaningful(brief.metrics)) score += 14;
144
+ if (hasMeaningful(brief.gtmStrategy)) score += 12;
145
+ if (hasMeaningful(brief.uncertainty)) score += 10;
146
+ if (brief.feedbackAsk.trim().length >= 36) score += 8;
147
+ if (brief.thisWeek.trim().length >= 120) score += 6;
148
+ if (promoPattern.test(`${brief.productContext} ${brief.thisWeek}`)) score -= 12;
149
+ if (brief.publicBoundary !== "open") score += 4;
150
+ return Math.max(28, Math.min(94, score));
151
+ }
152
+
153
+ function getPrimaryRisk(brief: BuildInPublicStoryBrief) {
154
+ const c = copy[brief.language];
155
+ if (promoPattern.test(`${brief.productContext} ${brief.thisWeek}`)) return c.risk.promo;
156
+ if (!hasMeaningful(brief.metrics)) return c.risk.noMetrics;
157
+ if (brief.publicBoundary === "avoidRoadmap") return c.risk.roadmap;
158
+ if (brief.publicBoundary === "customerSafe") return c.risk.customer;
159
+ return c.risk.proof;
160
+ }
161
+
162
+ function getStoryAngle(brief: BuildInPublicStoryBrief) {
163
+ const c = copy[brief.language];
164
+ const name = brief.productName.trim();
165
+ const stage = c.stage[brief.stage];
166
+ if (brief.language === "zh") {
167
+ return `${name} 处于${stage}阶段:这周不是讲成功,而是公开一个 GTM 假设、一个真实信号和一个仍没想清楚的问题。`;
168
+ }
169
+ return `${name} is in ${stage}: this is not a success story, but a public note about one GTM assumption, one real signal, and one unresolved question.`;
170
+ }
171
+
172
+ function getRecommendedLead(brief: BuildInPublicStoryBrief) {
173
+ const c = copy[brief.language];
174
+ const stage = c.stage[brief.stage];
175
+ if (brief.language === "zh") {
176
+ return `先说“我们还在${stage},这不是成功复盘”,再进入假设、动作、信号和请教问题。`;
177
+ }
178
+ return `Lead with: "We are still in ${stage}, so this is not a success story," then move into the assumption, action, signal, and feedback ask.`;
179
+ }
180
+
181
+ function buildMissingInfo(brief: BuildInPublicStoryBrief) {
182
+ const c = copy[brief.language];
183
+ const missing = [c.gaps.baseline];
184
+ if (!hasMeaningful(brief.metrics)) missing.push(c.gaps.metrics);
185
+ if (!hasMeaningful(brief.gtmStrategy)) missing.push(c.gaps.gtm);
186
+ if (!hasMeaningful(brief.uncertainty)) missing.push(c.gaps.uncertainty);
187
+ if (brief.feedbackAsk.trim().length < 36) missing.push(c.gaps.ask);
188
+ return Array.from(new Set(missing));
189
+ }
190
+
191
+ function buildEvidenceGaps(brief: BuildInPublicStoryBrief) {
192
+ const c = copy[brief.language];
193
+ const gaps = [];
194
+ if (!hasMeaningful(brief.metrics)) gaps.push(c.gaps.metrics);
195
+ if (!hasMeaningful(brief.gtmStrategy)) gaps.push(c.gaps.gtm);
196
+ if (!hasMeaningful(brief.uncertainty)) gaps.push(c.gaps.uncertainty);
197
+ return gaps.length > 0 ? gaps : [brief.language === "zh" ? "证据结构基本完整,发布前只需复核敏感信息。" : "The evidence structure is usable. Review sensitive details before posting."];
198
+ }
199
+
200
+ function boundaryLine(brief: BuildInPublicStoryBrief) {
201
+ if (brief.language === "zh") {
202
+ const map = {
203
+ open: "公开边界:可以直接写真实阶段和非敏感指标。",
204
+ blurMetrics: "公开边界:指标建议写成区间或相对变化,不写绝对值。",
205
+ avoidRoadmap: "公开边界:不要透露未发布路线图,只写当前实验。",
206
+ customerSafe: "公开边界:客户、用户和社区反馈必须匿名化。",
207
+ } as const;
208
+ return map[brief.publicBoundary];
209
+ }
210
+ const map = {
211
+ open: "Public boundary: stage and non-sensitive metrics can be shared directly.",
212
+ blurMetrics: "Public boundary: use ranges or relative movement instead of exact numbers.",
213
+ avoidRoadmap: "Public boundary: avoid unreleased roadmap details; write only about the current experiment.",
214
+ customerSafe: "Public boundary: anonymize customer, user, and community feedback.",
215
+ } as const;
216
+ return map[brief.publicBoundary];
217
+ }
218
+
219
+ function cleanAsk(brief: BuildInPublicStoryBrief) {
220
+ const ask = brief.feedbackAsk.trim();
221
+ if (brief.language === "zh") {
222
+ return ask.endsWith("?") || ask.endsWith("?") ? ask : `${ask}?`;
223
+ }
224
+ return ask.endsWith("?") ? ask : `${ask}?`;
225
+ }
226
+
227
+ function buildDrafts(brief: BuildInPublicStoryBrief): BuildInPublicStoryResult["drafts"] {
228
+ const c = copy[brief.language];
229
+ const name = brief.productName.trim();
230
+ const stage = c.stage[brief.stage];
231
+ const context = firstSentence(brief.productContext);
232
+ const week = brief.thisWeek.trim();
233
+ const gtmStrategy = brief.gtmStrategy ?? "";
234
+ const metricsInput = brief.metrics ?? "";
235
+ const uncertaintyInput = brief.uncertainty ?? "";
236
+ const gtm = hasMeaningful(gtmStrategy)
237
+ ? gtmStrategy.trim()
238
+ : brief.language === "zh"
239
+ ? "Tomako 给出的 GTM 策略还需要补充到帖子里。"
240
+ : "The GTM strategy from Tomako still needs to be added to the post.";
241
+ const metrics = hasMeaningful(metricsInput)
242
+ ? metricsInput.trim()
243
+ : brief.language === "zh"
244
+ ? "这周还没有足够干净的指标,所以我先把它当成定性观察。"
245
+ : "I do not have a clean metric yet, so I am treating this as a qualitative signal.";
246
+ const uncertainty = hasMeaningful(uncertaintyInput)
247
+ ? uncertaintyInput.trim()
248
+ : brief.language === "zh"
249
+ ? "不确定点是:这个信号到底说明渠道有效,还是只是我们表达更清楚。"
250
+ : "The unresolved part: I cannot tell whether the channel worked or whether the message simply became clearer.";
251
+ const ask = cleanAsk(brief);
252
+ const boundary = boundaryLine(brief);
253
+
254
+ if (brief.language === "zh") {
255
+ return [
256
+ {
257
+ channel: "indieHackers",
258
+ title: `${name} 的 build-in-public 记录:${stage}阶段的一次 GTM 假设测试`,
259
+ fitNote: c.channelFit.indieHackers,
260
+ body: [
261
+ `我们现在还在${stage}阶段,所以这不是成功复盘,更像一份公开学习记录。`,
262
+ ``,
263
+ `产品背景:${context}`,
264
+ ``,
265
+ `这周我们做了什么:${week}`,
266
+ ``,
267
+ `Tomako 生成的 GTM 假设:${gtm}`,
268
+ ``,
269
+ `目前看到的信号:${metrics}`,
270
+ ``,
271
+ `有效的地方:这次至少让我们把目标用户、渠道和反馈问题写得更具体。`,
272
+ ``,
273
+ `不确定的地方:${uncertainty}`,
274
+ ``,
275
+ `${boundary}`,
276
+ ``,
277
+ `这周想请大家帮忙判断一个问题:${ask}`,
278
+ ].join("\n"),
279
+ },
280
+ {
281
+ channel: "reddit",
282
+ title: `早期产品做 build in public 时,怎么判断这类 GTM 信号有没有意义?`,
283
+ fitNote: c.channelFit.reddit,
284
+ body: [
285
+ `我在做 ${name},目前处于${stage}阶段。先说清楚:这不是推广帖,我更想请教判断方法。`,
286
+ ``,
287
+ `背景:${context}`,
288
+ ``,
289
+ `这周的动作:${week}`,
290
+ ``,
291
+ `我们用 Tomako 梳理出的 GTM 假设是:${gtm}`,
292
+ ``,
293
+ `看到的信号:${metrics}`,
294
+ ``,
295
+ `我不确定的是:${uncertainty}`,
296
+ ``,
297
+ `如果你也做过早期发布或社区反馈,你会怎么解读这个信号?${ask}`,
298
+ ``,
299
+ `${boundary}`,
300
+ ].join("\n"),
301
+ },
302
+ {
303
+ channel: "xThread",
304
+ title: `${name}: build-in-public thread`,
305
+ fitNote: c.channelFit.xThread,
306
+ body: [
307
+ `1/ ${name} 现在还在${stage}阶段。这不是成功故事,只是把本周 GTM 学习公开记下来。`,
308
+ ``,
309
+ `2/ 产品背景:${context}`,
310
+ ``,
311
+ `3/ 这周做的事:${week}`,
312
+ ``,
313
+ `4/ Tomako 给出的 GTM 假设:${gtm}`,
314
+ ``,
315
+ `5/ 目前信号:${metrics}`,
316
+ ``,
317
+ `6/ 我们不确定:${uncertainty}`,
318
+ ``,
319
+ `7/ 想请大家反馈:${ask}`,
320
+ ``,
321
+ `8/ ${boundary}`,
322
+ ].join("\n"),
323
+ },
324
+ {
325
+ channel: "linkedin",
326
+ title: `${name} 本周 GTM 学习记录`,
327
+ fitNote: c.channelFit.linkedin,
328
+ body: [
329
+ `这周我们没有得到一个“增长答案”,但得到了一份更清楚的问题。`,
330
+ ``,
331
+ `${name} 仍处在${stage}阶段。产品背景是:${context}`,
332
+ ``,
333
+ `我们用 Tomako 把 GTM 策略拆成一个可验证假设:${gtm}`,
334
+ ``,
335
+ `本周执行:${week}`,
336
+ ``,
337
+ `信号:${metrics}`,
338
+ ``,
339
+ `还不确定:${uncertainty}`,
340
+ ``,
341
+ `我现在最想请教的是:${ask}`,
342
+ ``,
343
+ `${boundary}`,
344
+ ].join("\n"),
345
+ },
346
+ ];
347
+ }
348
+
349
+ return [
350
+ {
351
+ channel: "indieHackers",
352
+ title: `${name} build-in-public note: a GTM assumption test in ${stage}`,
353
+ fitNote: c.channelFit.indieHackers,
354
+ body: [
355
+ `We are still in ${stage}, so this is not a success story. It is a public learning note.`,
356
+ ``,
357
+ `Product context: ${context}`,
358
+ ``,
359
+ `What we did this week: ${week}`,
360
+ ``,
361
+ `The GTM hypothesis Tomako helped us shape: ${gtm}`,
362
+ ``,
363
+ `Signal so far: ${metrics}`,
364
+ ``,
365
+ `What worked: the process forced us to state the target user, channel, and feedback ask more clearly.`,
366
+ ``,
367
+ `What is still uncertain: ${uncertainty}`,
368
+ ``,
369
+ `${boundary}`,
370
+ ``,
371
+ `This week I would love feedback on one question: ${ask}`,
372
+ ].join("\n"),
373
+ },
374
+ {
375
+ channel: "reddit",
376
+ title: `How would you interpret this early build-in-public GTM signal?`,
377
+ fitNote: c.channelFit.reddit,
378
+ body: [
379
+ `I am working on ${name}, currently in ${stage}. To be clear, this is not meant as a promo post. I am looking for help interpreting the signal.`,
380
+ ``,
381
+ `Context: ${context}`,
382
+ ``,
383
+ `This week's action: ${week}`,
384
+ ``,
385
+ `The GTM hypothesis we shaped with Tomako: ${gtm}`,
386
+ ``,
387
+ `Signal: ${metrics}`,
388
+ ``,
389
+ `What I cannot tell yet: ${uncertainty}`,
390
+ ``,
391
+ `For people who have launched early products or asked for community feedback, how would you read this? ${ask}`,
392
+ ``,
393
+ `${boundary}`,
394
+ ].join("\n"),
395
+ },
396
+ {
397
+ channel: "xThread",
398
+ title: `${name}: build-in-public thread`,
399
+ fitNote: c.channelFit.xThread,
400
+ body: [
401
+ `1/ ${name} is still in ${stage}. This is not a success story, just a public GTM learning note from this week.`,
402
+ ``,
403
+ `2/ Product context: ${context}`,
404
+ ``,
405
+ `3/ What we did: ${week}`,
406
+ ``,
407
+ `4/ GTM hypothesis from Tomako: ${gtm}`,
408
+ ``,
409
+ `5/ Signal so far: ${metrics}`,
410
+ ``,
411
+ `6/ Still uncertain: ${uncertainty}`,
412
+ ``,
413
+ `7/ Feedback I want: ${ask}`,
414
+ ``,
415
+ `8/ ${boundary}`,
416
+ ].join("\n"),
417
+ },
418
+ {
419
+ channel: "linkedin",
420
+ title: `${name}: this week's GTM learning note`,
421
+ fitNote: c.channelFit.linkedin,
422
+ body: [
423
+ `This week did not give us a growth answer. It gave us a clearer question.`,
424
+ ``,
425
+ `${name} is still in ${stage}. Product context: ${context}`,
426
+ ``,
427
+ `We used Tomako to turn our GTM strategy into a testable hypothesis: ${gtm}`,
428
+ ``,
429
+ `Execution this week: ${week}`,
430
+ ``,
431
+ `Signal: ${metrics}`,
432
+ ``,
433
+ `Still uncertain: ${uncertainty}`,
434
+ ``,
435
+ `The question I would like feedback on: ${ask}`,
436
+ ``,
437
+ `${boundary}`,
438
+ ].join("\n"),
439
+ },
440
+ ];
441
+ }
442
+
443
+ export function createBuildInPublicStory(
444
+ brief: BuildInPublicStoryBrief,
445
+ ): BuildInPublicStoryResult {
446
+ const c = copy[brief.language];
447
+ const issues = [getPrimaryRisk(brief)];
448
+ if (brief.publicBoundary !== "open") issues.push(boundaryLine(brief));
449
+ if (promoPattern.test(`${brief.productContext} ${brief.thisWeek}`)) {
450
+ issues.push(c.risk.promo);
451
+ }
452
+
453
+ return {
454
+ summary: {
455
+ transparencyScore: buildScore(brief),
456
+ storyAngle: getStoryAngle(brief),
457
+ primaryRisk: getPrimaryRisk(brief),
458
+ recommendedLead: getRecommendedLead(brief),
459
+ },
460
+ drafts: buildDrafts(brief),
461
+ checks: {
462
+ authenticityIssues: Array.from(new Set(issues)),
463
+ evidenceGaps: buildEvidenceGaps(brief),
464
+ communityFit: c.community,
465
+ missingInfo: buildMissingInfo(brief),
466
+ reviewChecklist: c.review,
467
+ },
468
+ };
469
+ }
470
+
471
+ export function stringifyBuildInPublicStory(result: BuildInPublicStoryResult) {
472
+ const lines = [
473
+ "# Build-in-Public Story Drafts",
474
+ "",
475
+ `Transparency score: ${result.summary.transparencyScore}/100`,
476
+ `Story angle: ${result.summary.storyAngle}`,
477
+ `Primary risk: ${result.summary.primaryRisk}`,
478
+ `Recommended lead: ${result.summary.recommendedLead}`,
479
+ "",
480
+ "## Drafts",
481
+ ...result.drafts.flatMap((draft) => [
482
+ "",
483
+ `### ${draft.title}`,
484
+ `Channel: ${draft.channel}`,
485
+ `Fit note: ${draft.fitNote}`,
486
+ "",
487
+ draft.body,
488
+ ]),
489
+ "",
490
+ "## Authenticity issues",
491
+ ...result.checks.authenticityIssues.map((item) => `- ${item}`),
492
+ "",
493
+ "## Evidence gaps",
494
+ ...result.checks.evidenceGaps.map((item) => `- ${item}`),
495
+ "",
496
+ "## Community fit",
497
+ ...result.checks.communityFit.map((item) => `- ${item}`),
498
+ "",
499
+ "## Missing info",
500
+ ...result.checks.missingInfo.map((item) => `- ${item}`),
501
+ "",
502
+ "## Review checklist",
503
+ ...result.checks.reviewChecklist.map((item) => `- [ ] ${item}`),
504
+ ];
505
+
506
+ return lines.join("\n");
507
+ }
@@ -0,0 +1,147 @@
1
+ import { z } from "zod";
2
+
3
+ export const COLD_START_CHANNEL_SELECTOR_RESULT_TYPE = "cold_start_channel_selection";
4
+ export const COLD_START_CHANNEL_SELECTOR_SCENE = "cold_start_channel_selector";
5
+ export const COLD_START_CHANNEL_SELECTOR_PROMPT_VERSION = "cold-start-channel-selector.v1";
6
+
7
+ const emptyToUndefined = (value: unknown) =>
8
+ typeof value === "string" && value.trim() === "" ? undefined : value;
9
+
10
+ const urlField = z
11
+ .preprocess(
12
+ emptyToUndefined,
13
+ z
14
+ .string()
15
+ .trim()
16
+ .url()
17
+ .transform((value) => value.replace(/\/$/, ""))
18
+ .optional(),
19
+ );
20
+
21
+ const optionalShortText = (max = 240) =>
22
+ z.preprocess(emptyToUndefined, z.string().trim().min(2).max(max).optional());
23
+
24
+ export const coldStartChannelSelectorInputSchema = z
25
+ .object({
26
+ productUrl: urlField,
27
+ productDescription: optionalShortText(900),
28
+ productForm: z.enum([
29
+ "web_app",
30
+ "mobile_app",
31
+ "browser_extension",
32
+ "api_devtool",
33
+ "open_source",
34
+ "content_product",
35
+ "other",
36
+ "unknown",
37
+ ]),
38
+ targetMarket: z.enum([
39
+ "global",
40
+ "china",
41
+ "north_america",
42
+ "europe",
43
+ "japan_korea",
44
+ "southeast_asia",
45
+ "other",
46
+ "unknown",
47
+ ]),
48
+ stage: z.enum(["idea", "prototype", "private_beta", "launched", "early_traction"]),
49
+ weeklyHours: z.enum(["under_3", "3_7", "8_15", "16_plus"]),
50
+ budget: z.enum(["none", "under_500", "500_2000", "2000_plus"]),
51
+ targetAudience: optionalShortText(240),
52
+ existingAssets: optionalShortText(360),
53
+ triedChannels: optionalShortText(360),
54
+ constraints: optionalShortText(360),
55
+ })
56
+ .superRefine((value, ctx) => {
57
+ if (!value.productUrl && !value.productDescription) {
58
+ ctx.addIssue({
59
+ code: z.ZodIssueCode.custom,
60
+ path: ["productUrl"],
61
+ message: "product_url_or_description_required",
62
+ });
63
+ }
64
+
65
+ const weakDescription = value.productDescription
66
+ ? value.productDescription.replace(/[\s\d\W_]/g, "")
67
+ : "";
68
+ if (!value.productUrl && weakDescription.length < 12) {
69
+ ctx.addIssue({
70
+ code: z.ZodIssueCode.custom,
71
+ path: ["productDescription"],
72
+ message: "product_description_too_weak",
73
+ });
74
+ }
75
+ });
76
+
77
+ export type ColdStartChannelSelectorInput = z.infer<
78
+ typeof coldStartChannelSelectorInputSchema
79
+ >;
80
+
81
+ const confidence = z.enum(["low", "medium", "high"]).catch("low");
82
+ const priority = z.enum(["first", "second", "third", "later"]).catch("later");
83
+
84
+ const sourceSchema = z.object({
85
+ label: z.string(),
86
+ url: z.string().optional(),
87
+ });
88
+
89
+ export const coldStartChannelSelectorResultSchema = z.object({
90
+ summary: z.string().min(10),
91
+ productSnapshot: z.object({
92
+ name: z.string().optional(),
93
+ url: z.string().optional(),
94
+ category: z.string().optional(),
95
+ audience: z.string().optional(),
96
+ market: z.string().optional(),
97
+ stage: z.string().optional(),
98
+ constraints: z.array(z.string()).default([]),
99
+ }),
100
+ priorityChannels: z
101
+ .array(
102
+ z.object({
103
+ name: z.string(),
104
+ priority,
105
+ score: z.number().min(0).max(100).catch(50),
106
+ fitReason: z.string(),
107
+ whyNow: z.string(),
108
+ firstAction: z.string(),
109
+ requiredAssets: z.array(z.string()).default([]),
110
+ validationMetrics: z.array(z.string()).default([]),
111
+ risks: z.array(z.string()).default([]),
112
+ confidence,
113
+ }),
114
+ )
115
+ .min(1),
116
+ avoidForNow: z
117
+ .array(
118
+ z.object({
119
+ name: z.string(),
120
+ reason: z.string(),
121
+ revisitWhen: z.string().optional(),
122
+ }),
123
+ )
124
+ .default([]),
125
+ executionPlan: z
126
+ .array(
127
+ z.object({
128
+ day: z.string(),
129
+ focus: z.string(),
130
+ actions: z.array(z.string()).default([]),
131
+ expectedSignal: z.string(),
132
+ }),
133
+ )
134
+ .default([]),
135
+ missingInfo: z.array(z.string()).default([]),
136
+ sources: z.array(sourceSchema).default([]),
137
+ confidence,
138
+ boundaryNote: z.string(),
139
+ promptVersion: z.string().default(COLD_START_CHANNEL_SELECTOR_PROMPT_VERSION),
140
+ generatedAt: z.string().optional(),
141
+ });
142
+
143
+ export type ColdStartChannelSelectorResult = z.infer<
144
+ typeof coldStartChannelSelectorResultSchema
145
+ >;
146
+ export type ColdStartChannelConfidence = z.infer<typeof confidence>;
147
+ export type ColdStartChannelPriority = z.infer<typeof priority>;