vibebusiness 1.2.65 → 1.2.68

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 (56) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +19 -19
  3. package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
  4. package/.next/standalone/.next/build-manifest.json +2 -2
  5. package/.next/standalone/.next/prerender-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  8. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  9. package/.next/standalone/.next/server/app/api/investor-updates/generate/route.js +1 -1
  10. package/.next/standalone/.next/server/app/api/investor-updates/generate/route.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js +1 -1
  12. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/goals/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/hypotheses/[id]/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/hypotheses/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/ideas/[id]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/roadmap/[id]/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/roadmap/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/settings.html +1 -1
  24. package/.next/standalone/.next/server/app/settings.rsc +1 -1
  25. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/social.html +1 -1
  27. package/.next/standalone/.next/server/app/social.rsc +1 -1
  28. package/.next/standalone/.next/server/app/updates/[id]/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/updates/new/page.js +1 -1
  30. package/.next/standalone/.next/server/app/updates/new/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/updates/new.html +1 -1
  32. package/.next/standalone/.next/server/app/updates/new.rsc +2 -2
  33. package/.next/standalone/.next/server/app/updates/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app-paths-manifest.json +13 -13
  35. package/.next/standalone/.next/server/chunks/{7599.js → 3794.js} +33 -25
  36. package/.next/standalone/.next/server/pages/404.html +1 -1
  37. package/.next/standalone/.next/server/pages/500.html +1 -1
  38. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  39. package/.next/standalone/data/business-context.json +1 -1
  40. package/.next/standalone/data/goals.json +93 -12
  41. package/.next/standalone/data/ideas.json +58 -17
  42. package/.next/standalone/data/implementations.json +53 -0
  43. package/.next/standalone/data/social.json +49 -1
  44. package/.next/standalone/package.json +1 -1
  45. package/.next/standalone/scripts/investor-update.ts +249 -12
  46. package/.next/standalone/scripts/skills/social-media.ts +239 -34
  47. package/.next/static/chunks/app/updates/new/page-dcc67ffca587dcc2.js +1 -0
  48. package/dist/scripts/heartbeat.js +205 -30
  49. package/dist/scripts/social-routine.js +205 -30
  50. package/package.json +1 -1
  51. package/.next/standalone/.next/server/chunks/1685.js +0 -6
  52. package/.next/standalone/.next/server/chunks/7564.js +0 -81
  53. package/.next/standalone/scripts/skills/investor-update.ts +0 -476
  54. package/.next/static/chunks/app/updates/new/page-c518fba0d9ffae98.js +0 -1
  55. /package/.next/static/{yXi8K8u58qskYid0oHU5f → Gsf15cMKd-7htpbN5eZHd}/_buildManifest.js +0 -0
  56. /package/.next/static/{yXi8K8u58qskYid0oHU5f → Gsf15cMKd-7htpbN5eZHd}/_ssgManifest.js +0 -0
@@ -1,476 +0,0 @@
1
- /**
2
- * Investor Update Skill — AI-Powered Investor Reports
3
- *
4
- * Generates investor updates with AI narrative from VibeBusiness data or git history.
5
- * Stores update history in data/investor-updates.json for period-over-period comparison.
6
- *
7
- * Task prefixes handled:
8
- * investor-update-monthly → Generate monthly update (last 30 days)
9
- * investor-update-quarterly → Generate quarterly update (last 90 days)
10
- * investor-update-custom → Generate custom date range update
11
- *
12
- * Usage:
13
- * import { isInvestorUpdateTask, executeInvestorUpdateTask } from './skills/investor-update';
14
- *
15
- * if (isInvestorUpdateTask(taskId)) {
16
- * const result = await executeInvestorUpdateTask(taskId, description);
17
- * }
18
- */
19
-
20
- import * as fs from 'fs';
21
- import * as path from 'path';
22
- import { execSync } from 'child_process';
23
- import { invokeAI } from '../lib/ai-provider';
24
- import { PROJECT_DIR } from '../lib/paths';
25
-
26
- // ─── Types ───────────────────────────────────────────────────────────────────
27
-
28
- interface InvestorUpdate {
29
- id: string;
30
- created_at: string;
31
- period_start: string;
32
- period_end: string;
33
- project: string;
34
-
35
- epics_completed: Array<{
36
- epic_id: string;
37
- title: string;
38
- impact: string;
39
- ideas_shipped: number;
40
- }>;
41
-
42
- goals: Array<{
43
- goal_id: string;
44
- title: string;
45
- previous_value: number;
46
- current_value: number;
47
- growth_pct: string;
48
- status: 'on_track' | 'at_risk' | 'behind' | 'achieved';
49
- }>;
50
-
51
- roadmap_epics: Array<{
52
- epic_id: string;
53
- title: string;
54
- target_date?: string;
55
- expected_impact: string;
56
- }>;
57
-
58
- insights: string[];
59
- asks: string[];
60
-
61
- narrative: {
62
- executive_summary: string;
63
- accomplishments_story: string;
64
- challenges_and_plans: string;
65
- asks_rationale: string;
66
- };
67
-
68
- markdown: string;
69
- status: 'draft' | 'published';
70
- }
71
-
72
- interface UpdatesStore {
73
- updates: InvestorUpdate[];
74
- }
75
-
76
- // ─── Constants ───────────────────────────────────────────────────────────────
77
-
78
- const UPDATES_FILE = path.join(PROJECT_DIR, 'data/investor-updates.json');
79
- const INVESTOR_UPDATE_SCRIPT = path.join(PROJECT_DIR, 'scripts/investor-update.ts');
80
-
81
- const UPDATE_PREFIXES = [
82
- 'investor-update-monthly',
83
- 'investor-update-quarterly',
84
- 'investor-update-custom',
85
- ] as const;
86
-
87
- // ─── Utilities ───────────────────────────────────────────────────────────────
88
-
89
- function readJsonSafe<T>(filePath: string, fallback: T): T {
90
- try {
91
- if (!fs.existsSync(filePath)) return fallback;
92
- return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
93
- } catch {
94
- return fallback;
95
- }
96
- }
97
-
98
- function writeJsonSafe<T>(filePath: string, data: T): void {
99
- const dir = path.dirname(filePath);
100
- if (!fs.existsSync(dir)) {
101
- fs.mkdirSync(dir, { recursive: true });
102
- }
103
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
104
- }
105
-
106
- function formatDate(date: Date): string {
107
- return date.toISOString().split('T')[0];
108
- }
109
-
110
- function generateUpdateId(): string {
111
- return `update-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
112
- }
113
-
114
- // ─── Task Matching ───────────────────────────────────────────────────────────
115
-
116
- export function isInvestorUpdateTask(taskId: string): boolean {
117
- return UPDATE_PREFIXES.some((prefix) => taskId.startsWith(prefix));
118
- }
119
-
120
- // ─── Core Generation ─────────────────────────────────────────────────────────
121
-
122
- interface GenerationOptions {
123
- since: Date;
124
- until: Date;
125
- repo: string;
126
- includeAI: boolean;
127
- }
128
-
129
- function generateRawUpdate(options: GenerationOptions): string {
130
- const { since, until, repo } = options;
131
-
132
- // Call the Phase 1 script to generate raw markdown
133
- const sinceStr = formatDate(since);
134
- const untilStr = formatDate(until);
135
-
136
- const output = execSync(
137
- `npx tsx "${INVESTOR_UPDATE_SCRIPT}" --since="${sinceStr}" --until="${untilStr}" --repo="${repo}"`,
138
- {
139
- cwd: PROJECT_DIR,
140
- encoding: 'utf-8',
141
- maxBuffer: 10 * 1024 * 1024, // 10MB
142
- }
143
- );
144
-
145
- // Extract markdown from output (after the separator lines)
146
- const lines = output.split('\n');
147
- const separatorIndex = lines.findIndex((line) => line.includes('────────'));
148
- if (separatorIndex === -1) return output;
149
-
150
- const markdownLines = lines.slice(separatorIndex + 1);
151
- const endSeparatorIndex = markdownLines.findIndex((line) => line.includes('────────'));
152
- if (endSeparatorIndex === -1) return markdownLines.join('\n');
153
-
154
- return markdownLines.slice(0, endSeparatorIndex).join('\n').trim();
155
- }
156
-
157
- async function generateAINarrative(rawMarkdown: string, previousUpdate?: InvestorUpdate): Promise<{
158
- executive_summary: string;
159
- accomplishments_story: string;
160
- challenges_and_plans: string;
161
- asks_rationale: string;
162
- }> {
163
- let prompt = `You are a seasoned investor relations advisor. Transform this data-driven investor update into a compelling narrative.
164
-
165
- # Raw Update Data
166
-
167
- ${rawMarkdown}
168
-
169
- ${previousUpdate ? `# Previous Period Context (for comparison)\n\nLast update period: ${previousUpdate.period_start} to ${previousUpdate.period_end}\nLast update summary: ${previousUpdate.narrative.executive_summary}\n\n` : ''}
170
-
171
- # Your Task
172
-
173
- Generate the following sections in a confident, achievement-focused tone:
174
-
175
- 1. **Executive Summary** (2-3 sentences)
176
- - Open with the most impressive metric or milestone
177
- - Frame momentum: "up and to the right" or "pivoting based on data"
178
- ${previousUpdate ? '- Compare to previous period if there\'s meaningful change' : ''}
179
-
180
- 2. **Accomplishments Story** (3-4 paragraphs)
181
- - Turn bullet points into a narrative arc
182
- - Highlight strategic wins, not just feature lists
183
- - Quantify impact where possible (users, revenue, time saved)
184
- - Connect accomplishments to business goals
185
-
186
- 3. **Challenges and Plans** (2-3 paragraphs)
187
- - Frame challenges as "what we're learning" not "what's broken"
188
- - Show you have a plan to address each challenge
189
- - Demonstrate strategic thinking about resource allocation
190
-
191
- 4. **Asks Rationale** (1-2 paragraphs)
192
- - Explain what you need and WHY it will accelerate growth
193
- - Make it easy for investors to help (specific intros, feedback requests)
194
- - Show you've thought through how their help connects to outcomes
195
-
196
- # Output Format
197
-
198
- Return ONLY valid JSON with this structure:
199
- {
200
- "executive_summary": "...",
201
- "accomplishments_story": "...",
202
- "challenges_and_plans": "...",
203
- "asks_rationale": "..."
204
- }
205
-
206
- No markdown fencing, no extra commentary. Just the JSON object.`;
207
-
208
- const result = await invokeAI({
209
- prompt,
210
- timeoutMs: 120_000, // 2 minutes
211
- expectJson: true,
212
- });
213
-
214
- if (result.error) {
215
- throw new Error(`AI narrative generation failed: ${result.error}`);
216
- }
217
-
218
- try {
219
- return JSON.parse(result.output);
220
- } catch (error) {
221
- throw new Error(`Failed to parse AI narrative JSON: ${result.output.slice(0, 200)}`);
222
- }
223
- }
224
-
225
- function extractStructuredData(rawMarkdown: string): {
226
- epics_completed: InvestorUpdate['epics_completed'];
227
- goals: InvestorUpdate['goals'];
228
- roadmap_epics: InvestorUpdate['roadmap_epics'];
229
- insights: string[];
230
- } {
231
- // Simple extraction from markdown sections
232
- // In a real implementation, this would parse the markdown more thoroughly
233
- const epics_completed: InvestorUpdate['epics_completed'] = [];
234
- const goals: InvestorUpdate['goals'] = [];
235
- const roadmap_epics: InvestorUpdate['roadmap_epics'] = [];
236
- const insights: string[] = [];
237
-
238
- const lines = rawMarkdown.split('\n');
239
-
240
- let inEpicsSection = false;
241
- let inGoalsSection = false;
242
- let inRoadmapSection = false;
243
- let inInsightsSection = false;
244
-
245
- for (const line of lines) {
246
- // Section detection
247
- if (line.includes('## 🚀 Key Accomplishments')) {
248
- inEpicsSection = true;
249
- inGoalsSection = false;
250
- inRoadmapSection = false;
251
- inInsightsSection = false;
252
- } else if (line.includes('### Business Growth')) {
253
- inGoalsSection = true;
254
- inEpicsSection = false;
255
- } else if (line.includes('## 🗺️ Next 30 Days Roadmap')) {
256
- inRoadmapSection = true;
257
- inEpicsSection = false;
258
- inGoalsSection = false;
259
- inInsightsSection = false;
260
- } else if (line.includes('## 💡 Strategic Insights')) {
261
- inInsightsSection = true;
262
- inRoadmapSection = false;
263
- } else if (line.includes('## 📊 Momentum Indicators')) {
264
- inInsightsSection = false;
265
- }
266
-
267
- // Extract insights
268
- if (inInsightsSection && line.startsWith('- ')) {
269
- insights.push(line.slice(2).trim());
270
- }
271
- }
272
-
273
- return { epics_completed, goals, roadmap_epics, insights };
274
- }
275
-
276
- function enhanceMarkdownWithNarrative(rawMarkdown: string, narrative: InvestorUpdate['narrative']): string {
277
- // Insert narrative sections into the raw markdown
278
- const sections = rawMarkdown.split('\n## ');
279
-
280
- let enhanced = `${sections[0]}\n\n## 📝 Executive Summary\n\n${narrative.executive_summary}\n\n## `;
281
-
282
- // Insert accomplishments story after Key Accomplishments section
283
- for (let i = 1; i < sections.length; i++) {
284
- const section = sections[i];
285
-
286
- if (section.startsWith('🚀 Key Accomplishments')) {
287
- enhanced += `${section}\n\n### Strategic Context\n\n${narrative.accomplishments_story}\n\n## `;
288
- } else if (section.startsWith('🗺️ Next 30 Days Roadmap')) {
289
- enhanced += `${section}\n\n### Strategic Approach\n\n${narrative.challenges_and_plans}\n\n## `;
290
- } else {
291
- enhanced += `${section}\n\n## `;
292
- }
293
- }
294
-
295
- // Replace the asks section (use [\s\S] instead of . with s flag for better compatibility)
296
- enhanced = enhanced.replace(
297
- /\*\*What We Need:\*\*\n- \[Your ask here[\s\S]*?\]\n- \[Your ask here[\s\S]*?\]/g,
298
- `**What We Need:**\n\n${narrative.asks_rationale}`
299
- );
300
-
301
- return enhanced.trim();
302
- }
303
-
304
- // ─── Period Comparison ───────────────────────────────────────────────────────
305
-
306
- function getPreviousUpdate(period_start: string): InvestorUpdate | undefined {
307
- const store = readJsonSafe<UpdatesStore>(UPDATES_FILE, { updates: [] });
308
-
309
- // Find the most recent update that ended before this period started
310
- const previous = store.updates
311
- .filter((u) => u.period_end < period_start && u.status === 'published')
312
- .sort((a, b) => b.period_end.localeCompare(a.period_end))[0];
313
-
314
- return previous;
315
- }
316
-
317
- // ─── Storage ─────────────────────────────────────────────────────────────────
318
-
319
- function saveUpdate(update: InvestorUpdate): void {
320
- const store = readJsonSafe<UpdatesStore>(UPDATES_FILE, { updates: [] });
321
-
322
- // Remove any existing update with the same ID
323
- store.updates = store.updates.filter((u) => u.id !== update.id);
324
-
325
- // Add the new update
326
- store.updates.push(update);
327
-
328
- // Sort by period_end descending
329
- store.updates.sort((a, b) => b.period_end.localeCompare(a.period_end));
330
-
331
- writeJsonSafe(UPDATES_FILE, store);
332
- }
333
-
334
- // ─── Execution ───────────────────────────────────────────────────────────────
335
-
336
- export async function executeInvestorUpdateTask(
337
- taskId: string,
338
- _description: string
339
- ): Promise<{ success: boolean; output: string }> {
340
- try {
341
- // Determine date range based on task type
342
- const now = new Date();
343
- let since: Date;
344
- let until = now;
345
-
346
- if (taskId === 'investor-update-monthly') {
347
- since = new Date(now);
348
- since.setDate(now.getDate() - 30);
349
- } else if (taskId === 'investor-update-quarterly') {
350
- since = new Date(now);
351
- since.setDate(now.getDate() - 90);
352
- } else {
353
- // Default to monthly
354
- since = new Date(now);
355
- since.setDate(now.getDate() - 30);
356
- }
357
-
358
- const repo = PROJECT_DIR;
359
-
360
- console.log(`\n🚀 Generating investor update for ${formatDate(since)} to ${formatDate(until)}\n`);
361
-
362
- // Step 1: Generate raw markdown
363
- console.log('📊 Gathering data...');
364
- const rawMarkdown = generateRawUpdate({ since, until, repo, includeAI: true });
365
-
366
- // Step 2: Get previous update for comparison
367
- const previousUpdate = getPreviousUpdate(formatDate(since));
368
- if (previousUpdate) {
369
- console.log(`📈 Found previous update from ${previousUpdate.period_start} to ${previousUpdate.period_end}`);
370
- }
371
-
372
- // Step 3: Generate AI narrative
373
- console.log('🤖 Generating AI narrative...');
374
- const narrative = await generateAINarrative(rawMarkdown, previousUpdate);
375
-
376
- // Step 4: Extract structured data
377
- const { epics_completed, goals, roadmap_epics, insights } = extractStructuredData(rawMarkdown);
378
-
379
- // Step 5: Enhance markdown with narrative
380
- const enhancedMarkdown = enhanceMarkdownWithNarrative(rawMarkdown, narrative);
381
-
382
- // Step 6: Create update object
383
- const update: InvestorUpdate = {
384
- id: generateUpdateId(),
385
- created_at: new Date().toISOString(),
386
- period_start: formatDate(since),
387
- period_end: formatDate(until),
388
- project: repo.split('/').pop() || repo,
389
- epics_completed,
390
- goals,
391
- roadmap_epics,
392
- insights,
393
- asks: [], // Could be extracted from narrative
394
- narrative,
395
- markdown: enhancedMarkdown,
396
- status: 'draft',
397
- };
398
-
399
- // Step 7: Save to data/investor-updates.json
400
- saveUpdate(update);
401
- console.log(`\n✅ Update saved to ${UPDATES_FILE}`);
402
- console.log(`📝 Update ID: ${update.id}\n`);
403
-
404
- // Step 8: Write markdown file
405
- const outputPath = path.join(PROJECT_DIR, `investor-update-${formatDate(until)}.md`);
406
- fs.writeFileSync(outputPath, enhancedMarkdown, 'utf-8');
407
- console.log(`📄 Markdown saved to: ${outputPath}\n`);
408
-
409
- return {
410
- success: true,
411
- output: `Investor update generated successfully!\n\nUpdate ID: ${update.id}\nMarkdown: ${outputPath}\n\nTo publish: Update status to 'published' in ${UPDATES_FILE}`,
412
- };
413
- } catch (error) {
414
- return {
415
- success: false,
416
- output: `Failed to generate investor update: ${(error as Error).message}`,
417
- };
418
- }
419
- }
420
-
421
- // ─── Heartbeat Integration ───────────────────────────────────────────────────
422
-
423
- /**
424
- * Check if a monthly investor update is due.
425
- * Returns true if it's been >28 days since the last update.
426
- */
427
- export function isMonthlyUpdateDue(): boolean {
428
- const store = readJsonSafe<UpdatesStore>(UPDATES_FILE, { updates: [] });
429
-
430
- if (store.updates.length === 0) return true;
431
-
432
- const lastUpdate = store.updates
433
- .filter((u) => u.status === 'published')
434
- .sort((a, b) => b.period_end.localeCompare(a.period_end))[0];
435
-
436
- if (!lastUpdate) return true;
437
-
438
- const lastDate = new Date(lastUpdate.period_end);
439
- const now = new Date();
440
- const daysSince = (now.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24);
441
-
442
- return daysSince >= 28; // Allow slight variation from exactly 30 days
443
- }
444
-
445
- /**
446
- * Read update freshness for heartbeat reporting.
447
- */
448
- export function readUpdateFreshness(): {
449
- last_update_date: string | null;
450
- days_since_update: number | null;
451
- is_due: boolean;
452
- } {
453
- const store = readJsonSafe<UpdatesStore>(UPDATES_FILE, { updates: [] });
454
-
455
- if (store.updates.length === 0) {
456
- return { last_update_date: null, days_since_update: null, is_due: true };
457
- }
458
-
459
- const lastUpdate = store.updates
460
- .filter((u) => u.status === 'published')
461
- .sort((a, b) => b.period_end.localeCompare(a.period_end))[0];
462
-
463
- if (!lastUpdate) {
464
- return { last_update_date: null, days_since_update: null, is_due: true };
465
- }
466
-
467
- const lastDate = new Date(lastUpdate.period_end);
468
- const now = new Date();
469
- const daysSince = Math.floor((now.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24));
470
-
471
- return {
472
- last_update_date: lastUpdate.period_end,
473
- days_since_update: daysSince,
474
- is_due: daysSince >= 28,
475
- };
476
- }
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[940],{1554:function(e,t,s){Promise.resolve().then(s.bind(s,9525))},9205:function(e,t,s){"use strict";s.d(t,{Z:function(){return c}});var a=s(2265);let r=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),n=function(){for(var e=arguments.length,t=Array(e),s=0;s<e;s++)t[s]=arguments[s];return t.filter((e,t,s)=>!!e&&s.indexOf(e)===t).join(" ")};var l={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let i=(0,a.forwardRef)((e,t)=>{let{color:s="currentColor",size:r=24,strokeWidth:i=2,absoluteStrokeWidth:c,className:d="",children:o,iconNode:m,...h}=e;return(0,a.createElement)("svg",{ref:t,...l,width:r,height:r,stroke:s,strokeWidth:c?24*Number(i)/Number(r):i,className:n("lucide",d),...h},[...m.map(e=>{let[t,s]=e;return(0,a.createElement)(t,s)}),...Array.isArray(o)?o:[o]])}),c=(e,t)=>{let s=(0,a.forwardRef)((s,l)=>{let{className:c,...d}=s;return(0,a.createElement)(i,{ref:l,iconNode:t,className:n("lucide-".concat(r(e)),c),...d})});return s.displayName="".concat(e),s}},2660:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]])},505:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("Calendar",[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}]])},401:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]])},8867:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]])},2735:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]])},8736:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]])},2023:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(9205).Z)("Sparkles",[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",key:"4pj2yx"}],["path",{d:"M20 3v4",key:"1olli1"}],["path",{d:"M22 5h-4",key:"1gvqau"}],["path",{d:"M4 17v2",key:"vumght"}],["path",{d:"M5 18H3",key:"zchphs"}]])},7648:function(e,t,s){"use strict";s.d(t,{default:function(){return r.a}});var a=s(2972),r=s.n(a)},9376:function(e,t,s){"use strict";var a=s(5475);s.o(a,"usePathname")&&s.d(t,{usePathname:function(){return a.usePathname}}),s.o(a,"useRouter")&&s.d(t,{useRouter:function(){return a.useRouter}})},9525:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return u}});var a=s(7437),r=s(2265),n=s(2660),l=s(505),i=s(2023),c=s(8736),d=s(401),o=s(8867),m=s(2735),h=s(7648),x=s(9376);function u(){let e=(0,x.useRouter)(),[t,s]=(0,r.useState)(!1),[u,p]=(0,r.useState)("last_30"),[g,f]=(0,r.useState)(!0),[j,b]=(0,r.useState)(null),[y,w]=(0,r.useState)(!1),v=async()=>{s(!0);try{let e=await fetch("/api/investor-updates/generate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({dateRange:u,includeAI:g})});if(!e.ok)throw Error("Failed to generate update");let t=await e.json();b(t)}catch(e){console.error("Error generating update:",e),alert("Failed to generate update. Please try again.")}finally{s(!1)}},N=async()=>{j&&(await navigator.clipboard.writeText(j.markdown),w(!0),setTimeout(()=>w(!1),2e3))};return(0,a.jsxs)("div",{className:"min-h-screen bg-slate-50",children:[(0,a.jsx)("div",{className:"bg-white border-b border-slate-200 px-6 py-4",children:(0,a.jsx)("div",{className:"max-w-7xl mx-auto flex items-center justify-between",children:(0,a.jsxs)("div",{className:"flex items-center gap-4",children:[(0,a.jsx)(h.default,{href:"/updates",className:"text-slate-600 hover:text-slate-900 transition-colors",children:(0,a.jsx)(n.Z,{className:"w-5 h-5"})}),(0,a.jsxs)("div",{children:[(0,a.jsx)("h1",{className:"text-xl font-bold text-slate-900",children:"Generate Investor Update"}),(0,a.jsx)("p",{className:"text-sm text-slate-500",children:"Create a compelling monthly update with AI narrative"})]})]})})}),(0,a.jsx)("div",{className:"max-w-7xl mx-auto p-6",children:(0,a.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[(0,a.jsxs)("div",{className:"bg-white rounded-lg border border-slate-200 p-6",children:[(0,a.jsx)("h2",{className:"text-lg font-semibold text-slate-900 mb-4",children:"Configuration"}),(0,a.jsxs)("div",{className:"mb-6",children:[(0,a.jsxs)("label",{className:"block text-sm font-medium text-slate-700 mb-2",children:[(0,a.jsx)(l.Z,{className:"w-4 h-4 inline mr-1"}),"Time Period"]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,a.jsx)("input",{type:"radio",name:"dateRange",value:"last_30",checked:"last_30"===u,onChange:e=>p(e.target.value),className:"w-4 h-4 text-emerald-600"}),(0,a.jsx)("span",{className:"text-sm text-slate-700",children:"Last 30 Days (Monthly)"})]}),(0,a.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,a.jsx)("input",{type:"radio",name:"dateRange",value:"last_90",checked:"last_90"===u,onChange:e=>p(e.target.value),className:"w-4 h-4 text-emerald-600"}),(0,a.jsx)("span",{className:"text-sm text-slate-700",children:"Last 90 Days (Quarterly)"})]}),(0,a.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer opacity-50",children:[(0,a.jsx)("input",{type:"radio",name:"dateRange",value:"custom",disabled:!0,className:"w-4 h-4 text-emerald-600"}),(0,a.jsx)("span",{className:"text-sm text-slate-700",children:"Custom Range (Coming Soon)"})]})]})]}),(0,a.jsxs)("div",{className:"mb-6",children:[(0,a.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,a.jsx)("input",{type:"checkbox",checked:g,onChange:e=>f(e.target.checked),className:"w-4 h-4 text-emerald-600 rounded"}),(0,a.jsx)(i.Z,{className:"w-4 h-4 text-emerald-500"}),(0,a.jsx)("span",{className:"text-sm font-medium text-slate-700",children:"Include AI Narrative (Recommended)"})]}),(0,a.jsx)("p",{className:"text-xs text-slate-500 ml-6 mt-1",children:"Generates executive summary, strategic context, and asks rationale"})]}),(0,a.jsx)("button",{onClick:v,disabled:t,className:"w-full flex items-center justify-center gap-2 px-4 py-3 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors disabled:bg-slate-300 disabled:cursor-not-allowed",children:t?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("div",{className:"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"}),(0,a.jsx)("span",{children:"Generating..."})]}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.Z,{className:"w-4 h-4"}),(0,a.jsx)("span",{children:"Generate Update"})]})}),(0,a.jsxs)("div",{className:"mt-6 p-4 bg-blue-50 border border-blue-200 rounded-lg",children:[(0,a.jsx)("h3",{className:"text-sm font-semibold text-blue-900 mb-2",children:"What's included:"}),(0,a.jsxs)("ul",{className:"text-xs text-blue-700 space-y-1",children:[(0,a.jsx)("li",{children:"• Completed epics and shipped features"}),(0,a.jsx)("li",{children:"• Goal metrics with month-over-month growth"}),(0,a.jsx)("li",{children:"• Upcoming roadmap with strategic priorities"}),(0,a.jsx)("li",{children:"• Strategic insights from MEMORY.md"}),(0,a.jsx)("li",{children:"• AI-generated narrative (if enabled)"})]})]})]}),(0,a.jsxs)("div",{className:"bg-white rounded-lg border border-slate-200 p-6",children:[(0,a.jsx)("h2",{className:"text-lg font-semibold text-slate-900 mb-4",children:"Preview"}),j?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 mb-4",children:[(0,a.jsx)("button",{onClick:N,className:"flex items-center gap-1 px-3 py-2 text-sm bg-slate-100 hover:bg-slate-200 rounded-lg transition-colors",children:y?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(d.Z,{className:"w-4 h-4 text-emerald-600"}),(0,a.jsx)("span",{children:"Copied!"})]}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(o.Z,{className:"w-4 h-4"}),(0,a.jsx)("span",{children:"Copy Markdown"})]})}),(0,a.jsxs)("button",{onClick:()=>{if(!j)return;let e=new Blob([j.markdown],{type:"text/markdown"}),t=URL.createObjectURL(e),s=document.createElement("a");s.href=t,s.download="investor-update-".concat(new Date().toISOString().split("T")[0],".md"),s.click(),URL.revokeObjectURL(t)},className:"flex items-center gap-1 px-3 py-2 text-sm bg-slate-100 hover:bg-slate-200 rounded-lg transition-colors",children:[(0,a.jsx)(m.Z,{className:"w-4 h-4"}),(0,a.jsx)("span",{children:"Download"})]}),(0,a.jsxs)("button",{onClick:()=>{j&&e.push("/updates/".concat(j.id))},className:"flex items-center gap-1 px-3 py-2 text-sm bg-emerald-600 text-white hover:bg-emerald-700 rounded-lg transition-colors ml-auto",children:[(0,a.jsx)(c.Z,{className:"w-4 h-4"}),(0,a.jsx)("span",{children:"View Details"})]})]}),(0,a.jsx)("div",{className:"prose prose-sm max-w-none overflow-auto max-h-[600px] p-4 bg-slate-50 rounded-lg border border-slate-200",children:(0,a.jsx)("pre",{className:"whitespace-pre-wrap text-xs font-mono",children:j.markdown})})]}):(0,a.jsxs)("div",{className:"flex flex-col items-center justify-center h-64 text-center",children:[(0,a.jsx)(c.Z,{className:"w-12 h-12 text-slate-300 mb-4"}),(0,a.jsxs)("p",{className:"text-sm text-slate-500",children:["Configure your update and click Generate",(0,a.jsx)("br",{}),"to see a preview here"]})]})]})]})})]})}}},function(e){e.O(0,[972,971,117,744],function(){return e(e.s=1554)}),_N_E=e.O()}]);