vibefast-cli 0.7.13 → 0.7.14

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 (93) hide show
  1. package/dist/commands/add.d.ts.map +1 -1
  2. package/dist/commands/add.js +27 -1
  3. package/dist/commands/add.js.map +1 -1
  4. package/package.json +1 -1
  5. package/recipes/audio-recorder/recipe.json +1 -1
  6. package/recipes/audio-recorder@latest.zip +0 -0
  7. package/recipes/charts/apps/native/src/app/{charts → (root)/(protected)/charts}/index.tsx +0 -3
  8. package/recipes/charts/apps/native/src/features/charts/app/preview.tsx +0 -3
  9. package/recipes/charts/apps/native/src/features/charts/components/area-chart.tsx +0 -3
  10. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +0 -3
  11. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +0 -3
  12. package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +0 -3
  13. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +0 -3
  14. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +0 -3
  15. package/recipes/charts/apps/native/src/features/charts/components/index.ts +0 -3
  16. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +0 -3
  17. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +0 -3
  18. package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +0 -3
  19. package/recipes/charts/apps/native/src/features/charts/components/stacked-area-chart.tsx +0 -3
  20. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +0 -3
  21. package/recipes/charts/apps/native/src/features/charts/data/mock-data.ts +0 -3
  22. package/recipes/charts/apps/native/src/features/charts/types/index.ts +0 -3
  23. package/recipes/charts/recipe.json +1 -1
  24. package/recipes/charts@latest.zip +0 -0
  25. package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +83 -0
  26. package/recipes/chatbot/apps/native/src/app/{chatbot → (root)/(protected)/chatbot}/index.tsx +0 -1
  27. package/recipes/chatbot/apps/native/src/features/chatbot/app/index.tsx +56 -60
  28. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +0 -1
  29. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-input-bar.tsx +0 -1
  30. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +0 -1
  31. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +3 -26
  32. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +0 -1
  33. package/recipes/chatbot/apps/native/src/features/chatbot/components/image-preview-list.tsx +0 -1
  34. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +0 -1
  35. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/index.ts +0 -1
  36. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +0 -1
  37. package/recipes/chatbot/apps/native/src/features/chatbot/components/message-error-boundary.tsx +0 -1
  38. package/recipes/chatbot/apps/native/src/features/chatbot/components/message-list.tsx +10 -14
  39. package/recipes/chatbot/apps/native/src/features/chatbot/components/model-selector.tsx +0 -1
  40. package/recipes/chatbot/apps/native/src/features/chatbot/components/report-content-modal.tsx +0 -1
  41. package/recipes/chatbot/apps/native/src/features/chatbot/components/suggested-messages.tsx +0 -1
  42. package/recipes/chatbot/apps/native/src/features/chatbot/constants/models.ts +0 -1
  43. package/recipes/chatbot/apps/native/src/features/chatbot/constants/report-reasons.ts +0 -1
  44. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +0 -1
  45. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-config.ts +0 -1
  46. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +0 -1
  47. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +0 -1
  48. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-conversation.ts +0 -1
  49. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-image-picker.ts +0 -1
  50. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +0 -1
  51. package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +0 -1
  52. package/recipes/chatbot/apps/native/src/features/chatbot/models/index.ts +0 -1
  53. package/recipes/chatbot/apps/native/src/features/chatbot/models/models.ts +0 -1
  54. package/recipes/chatbot/apps/native/src/features/chatbot/models/providers.ts +0 -1
  55. package/recipes/chatbot/apps/native/src/features/chatbot/models/types.ts +0 -1
  56. package/recipes/chatbot/apps/native/src/features/chatbot/services/file-uploader.ts +0 -1
  57. package/recipes/chatbot/apps/native/src/features/chatbot/services/message-handler-service.ts +0 -1
  58. package/recipes/chatbot/apps/native/src/features/chatbot/types/index.ts +5 -3
  59. package/recipes/chatbot/apps/native/src/features/chatbot/utils/chat-telemetry.ts +0 -1
  60. package/recipes/chatbot/packages/backend/convex/agents.ts +3 -4
  61. package/recipes/chatbot/packages/backend/convex/chatbot/content.ts +35 -0
  62. package/recipes/chatbot/packages/backend/convex/chatbot/sessions.ts +52 -0
  63. package/recipes/chatbot/packages/backend/convex/chatbot/streaming.ts +422 -0
  64. package/recipes/chatbot/packages/backend/convex/chatbot/telemetry.ts +56 -0
  65. package/recipes/chatbot/packages/backend/convex/chatbot/tools.ts +128 -0
  66. package/recipes/chatbot/packages/backend/convex/chatbotAgent.ts +6 -651
  67. package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -714
  68. package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +12 -7
  69. package/recipes/chatbot/recipe.json +6 -1
  70. package/recipes/chatbot@latest.zip +0 -0
  71. package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +34 -0
  72. package/recipes/image-generator/packages/backend/convex/{imageGeneratorFunctions.ts → imageGenerator.ts} +1 -1
  73. package/recipes/image-generator/recipe.json +5 -1
  74. package/recipes/image-generator@latest.zip +0 -0
  75. package/recipes/payments/apps/native/src/api-client/payments.ts +44 -0
  76. package/recipes/payments/packages/backend/convex/payments/index.ts +13 -0
  77. package/recipes/payments/packages/backend/convex/payments.ts +119 -0
  78. package/recipes/payments/recipe.json +15 -2
  79. package/recipes/payments@latest.zip +0 -0
  80. package/recipes/quiz/recipe.json +1 -1
  81. package/recipes/quiz@latest.zip +0 -0
  82. package/recipes/tracker-app/recipe.json +1 -1
  83. package/recipes/tracker-app@latest.zip +0 -0
  84. package/recipes/voice-bot/recipe.json +1 -1
  85. package/recipes/voice-bot@latest.zip +0 -0
  86. package/src/commands/add.ts +39 -1
  87. package/tmp-npm-cache/_update-notifier-last-checked +0 -0
  88. /package/recipes/audio-recorder/apps/native/src/app/{audio-recorder → (root)/(protected)/audio-recorder}/index.tsx +0 -0
  89. /package/recipes/image-generator/apps/native/src/app/{image-generator → (root)/(protected)/image-generator}/gallery.tsx +0 -0
  90. /package/recipes/image-generator/apps/native/src/app/{image-generator → (root)/(protected)/image-generator}/index.tsx +0 -0
  91. /package/recipes/quiz/apps/native/src/app/{quiz → (root)/(protected)/quiz}/index.tsx +0 -0
  92. /package/recipes/tracker-app/apps/native/src/app/{tracker-app → (root)/(protected)/tracker-app}/index.tsx +0 -0
  93. /package/recipes/voice-bot/apps/native/src/app/{voice-bot → (root)/(protected)/voice-bot}/index.tsx +0 -0
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import { createTool } from '@convex-dev/agent';
2
3
  import { z } from 'zod';
3
4
 
@@ -65,13 +66,16 @@ export const knowledgeRetrievalTool = createTool({
65
66
  after: args.chunkContext?.after ?? 1,
66
67
  };
67
68
 
68
- const result = (await ctx.runAction(api.ragKnowledge.askKnowledge, {
69
- prompt,
70
- globalNamespace: args.scope === 'global',
71
- limit: args.limit,
72
- chunkContext,
73
- filter,
74
- })) as {
69
+ const result = (await (ctx as any).runAction(
70
+ (api as any).ragKnowledge.askKnowledge,
71
+ {
72
+ prompt,
73
+ globalNamespace: args.scope === 'global',
74
+ limit: args.limit,
75
+ chunkContext,
76
+ filter,
77
+ } as any,
78
+ )) as {
75
79
  answer: string;
76
80
  files?: { filename: string; url: string | null }[];
77
81
  };
@@ -90,3 +94,4 @@ export const knowledgeRetrievalTool = createTool({
90
94
  return `${result.answer}\n\n**References**\n${references}`;
91
95
  },
92
96
  });
97
+ // @ts-nocheck
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatbot",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI-powered chat assistant",
5
5
  "copy": [
6
6
  {
@@ -11,6 +11,10 @@
11
11
  "from": "apps/native/src/features/chatbot",
12
12
  "to": "apps/native/src/features/chatbot"
13
13
  },
14
+ {
15
+ "from": "apps/native/src/api-client/chatbot.ts",
16
+ "to": "apps/native/src/api-client/chatbot.ts"
17
+ },
14
18
  {
15
19
  "from": "packages/backend/convex/chatbot",
16
20
  "to": "packages/backend/convex/chatbot"
@@ -69,6 +73,7 @@
69
73
  "expo-clipboard",
70
74
  "markdown-it",
71
75
  "react-native-markdown-display",
76
+ "react-native-syntax-highlighter",
72
77
  "react-syntax-highlighter",
73
78
  "react-native-reanimated",
74
79
  "react-native-safe-area-context"
Binary file
@@ -0,0 +1,34 @@
1
+ import { api } from '@vibefast/backend/_generated/api';
2
+ import { useAction } from 'convex/react';
3
+
4
+ /**
5
+ * Image Generator API Gateway
6
+ *
7
+ * This gateway provides typed wrappers around Convex image generation functions.
8
+ * It handles AI-powered image generation backed by the AI SDK providers.
9
+ *
10
+ * Usage:
11
+ * - Import this gateway in feature code: `import { imageGeneratorApi } from '@/platform/api/image-generator'`
12
+ * - Never import from `@vibefast/backend/_generated/api` directly in feature code
13
+ */
14
+ export const imageGeneratorApi = {
15
+ /**
16
+ * Generate an image based on user prompt and provider selection
17
+ *
18
+ * @returns Promise with image data URI, mime type, and metadata
19
+ */
20
+ useGenerateImage() {
21
+ const action = useAction(api['imageGeneration/index'].generateImageAction);
22
+
23
+ return (args: GenerateImageArgs) =>
24
+ action(args as Parameters<typeof action>[0]);
25
+ },
26
+ };
27
+
28
+ export type ImageGeneratorApi = typeof imageGeneratorApi;
29
+
30
+ export type GenerateImageArgs = {
31
+ prompt: string;
32
+ provider: string;
33
+ model: string;
34
+ };
@@ -63,7 +63,7 @@ const generateWithOpenAI = async (prompt: string, model: string) => {
63
63
  throw new Error('OpenAI image generation did not return any image data.');
64
64
  }
65
65
 
66
- const mimeType = imageResult.mimeType ?? 'image/png';
66
+ const mimeType = (imageResult as any).mimeType ?? 'image/png';
67
67
  const base64Data =
68
68
  imageResult.base64 ??
69
69
  (imageResult.uint8Array
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "image-generator",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI-powered image generation",
5
5
  "copy": [
6
6
  {
@@ -11,6 +11,10 @@
11
11
  "from": "apps/native/src/features/image-generator",
12
12
  "to": "apps/native/src/features/image-generator"
13
13
  },
14
+ {
15
+ "from": "apps/native/src/api-client/image-generator.ts",
16
+ "to": "apps/native/src/api-client/image-generator.ts"
17
+ },
14
18
  {
15
19
  "from": "packages/backend/convex/imageGeneration/index.ts",
16
20
  "to": "packages/backend/convex/imageGeneration/index.ts"
Binary file
@@ -0,0 +1,44 @@
1
+ import { api } from '@vibefast/backend/_generated/api';
2
+ import { useMutation, useQuery } from 'convex/react';
3
+
4
+ /**
5
+ * Payments API Gateway
6
+ *
7
+ * This gateway provides typed wrappers around Convex payment functions.
8
+ * It handles RevenueCat purchases, credit management, and purchase history.
9
+ *
10
+ * Usage:
11
+ * - Import this gateway in feature code: `import { paymentsApi } from '@/platform/api/payments'`
12
+ * - Never import from `@vibefast/backend/_generated/api` directly in feature code
13
+ */
14
+ export const paymentsApi = {
15
+ /**
16
+ * Record a consumable purchase (like credits) in the database
17
+ */
18
+ useRecordConsumablePurchase() {
19
+ return useMutation(api['payments/index'].recordConsumablePurchase);
20
+ },
21
+
22
+ /**
23
+ * Get user's current credit balance
24
+ */
25
+ useGetUserCredits() {
26
+ return useQuery(api['payments/index'].getUserCredits);
27
+ },
28
+
29
+ /**
30
+ * Get user's purchase history with pagination
31
+ */
32
+ useGetPurchaseHistory(
33
+ paginationOpts: { numItems: number; cursor: string | null } = {
34
+ numItems: 50,
35
+ cursor: null,
36
+ },
37
+ ) {
38
+ return useQuery(api['payments/index'].getPurchaseHistory, {
39
+ paginationOpts,
40
+ });
41
+ },
42
+ };
43
+
44
+ export type PaymentsApi = typeof paymentsApi;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Payments Domain Aggregator
3
+ *
4
+ * Single entry point for all payment-related Convex functions.
5
+ * Re-exports functions from payments.ts to decouple
6
+ * frontend from internal file structure.
7
+ */
8
+
9
+ export {
10
+ getPurchaseHistory,
11
+ getUserCredits,
12
+ recordConsumablePurchase,
13
+ } from '../payments';
@@ -0,0 +1,119 @@
1
+ import { getAuthUserId } from '@convex-dev/auth/server';
2
+ import { v } from 'convex/values';
3
+
4
+ import { mutation, query } from './_generated/server';
5
+
6
+ /**
7
+ * Record a consumable purchase (like credits) in the database
8
+ */
9
+ export const recordConsumablePurchase = mutation({
10
+ args: {
11
+ productId: v.string(),
12
+ quantity: v.number(),
13
+ },
14
+ returns: v.object({
15
+ success: v.boolean(),
16
+ newCredits: v.number(),
17
+ totalCredits: v.number(),
18
+ }),
19
+ handler: async (ctx, args) => {
20
+ const userId = await getAuthUserId(ctx);
21
+ if (!userId) {
22
+ throw new Error('Not authenticated');
23
+ }
24
+ // Get current user to check existing credits
25
+ const user = await ctx.db.get(userId);
26
+ if (!user) {
27
+ throw new Error('User not found');
28
+ }
29
+
30
+ // Calculate new credits based on product
31
+ let creditsToAdd = args.quantity;
32
+
33
+ // You can customize credit amounts based on productId
34
+ if (args.productId.includes('premium')) {
35
+ creditsToAdd = args.quantity * 2; // Premium products give 2x credits
36
+ }
37
+
38
+ // Update user credits - safely access credits field
39
+ const currentCredits = (user as any).credits || 0;
40
+ const newTotalCredits = currentCredits + creditsToAdd;
41
+
42
+ await ctx.db.patch(userId, {
43
+ credits: newTotalCredits,
44
+ });
45
+
46
+ // Log the purchase
47
+ await ctx.db.insert('purchases', {
48
+ userId,
49
+ productId: args.productId,
50
+ quantity: args.quantity,
51
+ creditsAdded: creditsToAdd,
52
+ purchaseDate: Date.now(),
53
+ });
54
+
55
+ return {
56
+ success: true,
57
+ newCredits: creditsToAdd,
58
+ totalCredits: newTotalCredits,
59
+ };
60
+ },
61
+ });
62
+
63
+ /**
64
+ * Get user's current credit balance
65
+ */
66
+ export const getUserCredits = query({
67
+ args: {},
68
+ returns: v.union(v.number(), v.null()),
69
+ handler: async (ctx) => {
70
+ const userId = await getAuthUserId(ctx);
71
+ if (!userId) {
72
+ throw new Error('Not authenticated');
73
+ }
74
+ const user = await ctx.db.get(userId);
75
+
76
+ return (user as any)?.credits || 0;
77
+ },
78
+ });
79
+
80
+ /**
81
+ * Get user's purchase history with pagination
82
+ */
83
+ export const getPurchaseHistory = query({
84
+ args: {
85
+ paginationOpts: v.optional(
86
+ v.object({
87
+ numItems: v.number(),
88
+ cursor: v.union(v.string(), v.null()),
89
+ }),
90
+ ),
91
+ },
92
+ returns: v.object({
93
+ page: v.array(
94
+ v.object({
95
+ _id: v.id('purchases'),
96
+ _creationTime: v.number(),
97
+ productId: v.string(),
98
+ quantity: v.number(),
99
+ creditsAdded: v.number(),
100
+ purchaseDate: v.number(),
101
+ }),
102
+ ),
103
+ isDone: v.boolean(),
104
+ continueCursor: v.string(),
105
+ pageStatus: v.optional(v.union(v.string(), v.null())),
106
+ splitCursor: v.optional(v.union(v.string(), v.null())),
107
+ }),
108
+ handler: async (ctx, args) => {
109
+ const userId = await getAuthUserId(ctx);
110
+ if (!userId) {
111
+ throw new Error('Not authenticated');
112
+ }
113
+ return await ctx.db
114
+ .query('purchases')
115
+ .withIndex('by_userId', (q) => q.eq('userId', userId))
116
+ .order('desc')
117
+ .paginate(args.paginationOpts ?? { numItems: 50, cursor: null });
118
+ },
119
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payments",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "In-app purchases and subscriptions with RevenueCat",
5
5
  "copy": [
6
6
  {
@@ -10,6 +10,18 @@
10
10
  {
11
11
  "from": "apps/native/src/features/payments",
12
12
  "to": "apps/native/src/features/payments"
13
+ },
14
+ {
15
+ "from": "apps/native/src/api-client/payments.ts",
16
+ "to": "apps/native/src/api-client/payments.ts"
17
+ },
18
+ {
19
+ "from": "packages/backend/convex/payments",
20
+ "to": "packages/backend/convex/payments"
21
+ },
22
+ {
23
+ "from": "packages/backend/convex/payments.ts",
24
+ "to": "packages/backend/convex/payments.ts"
13
25
  }
14
26
  ],
15
27
  "nav": {
@@ -21,7 +33,8 @@
21
33
  "target": "native",
22
34
  "dependencies": {
23
35
  "expo": [
24
- "react-native-purchases"
36
+ "react-native-purchases",
37
+ "react-native-purchases-ui"
25
38
  ]
26
39
  },
27
40
  "env": [
Binary file
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quiz",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Interactive quiz feature",
5
5
  "copy": [
6
6
  {
Binary file
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tracker-app",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Track habits and activities",
5
5
  "copy": [
6
6
  {
Binary file
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voice-bot",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Real-time voice conversations with AI",
5
5
  "copy": [
6
6
  {
Binary file
@@ -22,7 +22,8 @@ import {
22
22
  ENV_CONSTANTS_END,
23
23
  ENV_CONSTANTS_START,
24
24
  } from '../core/codemod.js';
25
- import { join, resolve } from 'path';
25
+ import { join, resolve, dirname } from 'path';
26
+ import { copyFile, mkdir } from 'fs/promises';
26
27
  import { ensureWithinBase } from '../core/pathGuard.js';
27
28
  import { extractZipSafe } from '../core/archive.js';
28
29
  import { hashFiles } from '../core/hash.js';
@@ -259,6 +260,41 @@ function groupEnvVars(env: RecipeManifest['env'] | undefined, cwd: string): EnvG
259
260
  return [...groups.values()];
260
261
  }
261
262
 
263
+ async function ensureEnvFileFromExample(
264
+ group: EnvGroup,
265
+ options: any,
266
+ ): Promise<boolean> {
267
+ if (await exists(group.path)) {
268
+ return false;
269
+ }
270
+
271
+ const exampleCandidates = [
272
+ `${group.path}.example`,
273
+ join(dirname(group.path), '.env.example'),
274
+ ];
275
+ const examplePath = (await Promise.all(
276
+ exampleCandidates.map(async (candidate) => ((await exists(candidate)) ? candidate : null)),
277
+ )).find(Boolean);
278
+
279
+ if (!examplePath) {
280
+ return false;
281
+ }
282
+
283
+ const exampleLabel = examplePath.startsWith(dirname(group.path))
284
+ ? examplePath.slice(dirname(group.path).length + 1)
285
+ : examplePath;
286
+
287
+ if (options?.dryRun) {
288
+ log.info(`[DRY RUN] Would create ${group.relativePath} from ${exampleLabel}`);
289
+ return true;
290
+ }
291
+
292
+ await mkdir(dirname(group.path), { recursive: true });
293
+ await copyFile(examplePath, group.path);
294
+ log.info(`Created ${group.relativePath} from ${exampleLabel}`);
295
+ return true;
296
+ }
297
+
262
298
  async function ensureEnvVarsForGroups(
263
299
  envGroups: EnvGroup[],
264
300
  options: any,
@@ -266,6 +302,8 @@ async function ensureEnvVarsForGroups(
266
302
  const summary: Array<{ relativePath: string; added: string[] }> = [];
267
303
 
268
304
  for (const group of envGroups) {
305
+ await ensureEnvFileFromExample(group, options);
306
+
269
307
  const vars: CoreEnvVar[] = group.vars.map(envVar => ({
270
308
  key: envVar.key,
271
309
  value: envVar.value ?? envVar.example ?? '',
File without changes