@tomako/tools-runtime 0.1.5 → 0.1.7

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 (47) hide show
  1. package/package.json +2 -1
  2. package/src/components/tools/engine/package-widget-runtime.tsx +5 -1
  3. package/src/components/tools/engine/task-recovery.test.ts +65 -0
  4. package/src/components/tools/engine/task-recovery.ts +109 -0
  5. package/src/components/tools/engine/use-legacy-llm-task.ts +16 -3
  6. package/src/components/tools/engine/use-tool-task.ts +77 -53
  7. package/src/features/tools/app-store-screenshot-generator/widget/app-store-screenshot-generator.tsx +88 -16
  8. package/src/features/tools/app-store-screenshot-generator/widget/asset-slots.test.ts +52 -0
  9. package/src/features/tools/app-store-screenshot-generator/widget/asset-slots.ts +3 -2
  10. package/src/features/tools/app-store-screenshot-generator/widget/generation.test.ts +126 -0
  11. package/src/features/tools/app-store-screenshot-generator/widget/generation.ts +52 -14
  12. package/src/features/tools/app-store-screenshot-generator/widget/input-media.test.ts +81 -0
  13. package/src/features/tools/app-store-screenshot-generator/widget/input-media.ts +20 -8
  14. package/src/features/tools/cold-start-channel-selector/widget/cold-start-channel-selector.tsx +45 -16
  15. package/src/features/tools/competitor-analysis/competitor-analysis.container.tsx +26 -20
  16. package/src/features/tools/competitor-analysis/widget/competitor-analysis.tsx +47 -16
  17. package/src/features/tools/disclaimer-generator/disclaimer-generator.package.ts +3 -3
  18. package/src/features/tools/email-template-generator/widget/email-template-generator.tsx +37 -4
  19. package/src/features/tools/package/to-tool-module.ts +15 -0
  20. package/src/features/tools/product-name-generator/widget/product-name-generator.tsx +60 -27
  21. package/src/features/tools/product-poster-generator/widget/constants.ts +3 -1
  22. package/src/features/tools/product-poster-generator/widget/helpers.test.ts +51 -0
  23. package/src/features/tools/product-poster-generator/widget/helpers.ts +27 -0
  24. package/src/features/tools/product-poster-generator/widget/product-poster-generator.tsx +112 -12
  25. package/src/features/tools/slogan-generator/slogan-generator.package.ts +28 -28
  26. package/src/i18n/messages/en/tools/app-icon-resizer.ts +1 -1
  27. package/src/i18n/messages/en/tools/app-store-screenshot-generator.ts +2 -2
  28. package/src/i18n/messages/en/tools/cold-start-channel-selector.ts +4 -4
  29. package/src/i18n/messages/en/tools/competitor-analysis.ts +9 -8
  30. package/src/i18n/messages/en/tools/email-template-generator.ts +10 -10
  31. package/src/i18n/messages/en/tools/product-poster-generator.ts +1 -0
  32. package/src/i18n/messages/zh/tools/app-store-screenshot-generator.ts +3 -3
  33. package/src/i18n/messages/zh/tools/cold-start-channel-selector.ts +2 -2
  34. package/src/i18n/messages/zh/tools/competitor-analysis.ts +10 -9
  35. package/src/i18n/messages/zh/tools/email-template-generator.ts +11 -11
  36. package/src/i18n/messages/zh/tools/product-poster-generator.ts +1 -0
  37. package/src/i18n/messages/zh-tw/tools/app-store-screenshot-generator.ts +44 -44
  38. package/src/i18n/messages/zh-tw/tools/cold-start-channel-selector.ts +105 -105
  39. package/src/i18n/messages/zh-tw/tools/competitor-analysis.ts +41 -40
  40. package/src/i18n/messages/zh-tw/tools/email-template-generator.ts +111 -111
  41. package/src/i18n/messages/zh-tw/tools/product-name-generator.ts +92 -92
  42. package/src/i18n/messages/zh-tw/tools/product-poster-generator.ts +74 -73
  43. package/src/i18n/messages/zh-tw/tools/twitter-gif-downloader.ts +47 -47
  44. package/src/lib/tools/cold-start-channel-selector-schema.test.ts +39 -0
  45. package/src/lib/tools/cold-start-channel-selector-schema.ts +8 -4
  46. package/src/lib/tools/competitor-analysis-schema.test.ts +69 -0
  47. package/src/lib/tools/competitor-analysis-schema.ts +53 -5
@@ -118,8 +118,12 @@ const positioningSchema = z
118
118
  .default({ strengths: [], weaknesses: [], opportunities: [] });
119
119
 
120
120
  const sourceSchema = z.object({
121
- label: z.string(),
122
- url: z.string().optional(),
121
+ label: z.string().trim().min(1),
122
+ url: z
123
+ .string()
124
+ .trim()
125
+ .url()
126
+ .refine((value) => /^https?:\/\//i.test(value), "source url must use http or https"),
123
127
  });
124
128
 
125
129
  export const competitorAnalysisResultSchema = z.object({
@@ -129,14 +133,58 @@ export const competitorAnalysisResultSchema = z.object({
129
133
  team: teamSchema,
130
134
  funding: fundingSchema,
131
135
  positioning: positioningSchema,
132
- highlights: z.array(z.string()).default([]),
133
- sources: z.array(sourceSchema).default([]),
136
+ highlights: z.array(z.string().trim().min(1)).default([]),
137
+ sources: z.array(sourceSchema).min(1),
134
138
  confidence,
135
- summary: z.string(),
139
+ summary: z.string().trim().min(1),
136
140
  disclaimer: z.string().default(""),
137
141
  promptVersion: z.string().default(COMPETITOR_ANALYSIS_PROMPT_VERSION),
138
142
  generatedAt: z.string().optional(),
139
143
  sourceUrl: z.string().optional(),
144
+ }).superRefine((result, context) => {
145
+ const hasText = (value: string | undefined) => Boolean(value?.trim());
146
+ const hasCompetitorIdentity =
147
+ hasText(result.overview.name) &&
148
+ [result.overview.description, result.overview.tagline, result.overview.category].some(hasText);
149
+ if (!hasCompetitorIdentity) {
150
+ context.addIssue({
151
+ code: "custom",
152
+ path: ["overview"],
153
+ message: "overview must identify the competitor and describe its product or category",
154
+ });
155
+ }
156
+
157
+ const hasAnalysisFinding =
158
+ result.highlights.some(hasText) ||
159
+ [
160
+ result.traffic.summary,
161
+ result.traffic.monthlyVisitsEstimate,
162
+ result.businessScale.summary,
163
+ result.businessScale.pricingModel,
164
+ result.team.summary,
165
+ result.team.teamSize,
166
+ result.funding.summary,
167
+ result.funding.totalRaised,
168
+ ].some(hasText) ||
169
+ result.traffic.trendSeries.length > 0 ||
170
+ result.traffic.channels.length > 0 ||
171
+ result.traffic.geographies.length > 0 ||
172
+ result.businessScale.customerSegments.length > 0 ||
173
+ result.businessScale.notableCustomers.length > 0 ||
174
+ result.team.founders.length > 0 ||
175
+ result.team.keyPeople.length > 0 ||
176
+ Boolean(result.funding.lastRound) ||
177
+ result.funding.investors.length > 0 ||
178
+ result.positioning.strengths.length > 0 ||
179
+ result.positioning.weaknesses.length > 0 ||
180
+ result.positioning.opportunities.length > 0;
181
+ if (!hasAnalysisFinding) {
182
+ context.addIssue({
183
+ code: "custom",
184
+ path: ["highlights"],
185
+ message: "result must include at least one concrete analysis finding",
186
+ });
187
+ }
140
188
  });
141
189
 
142
190
  export type CompetitorAnalysisResult = z.infer<typeof competitorAnalysisResultSchema>;