@messenger-box/platform-server 10.0.3-alpha.95 → 10.0.3-alpha.97

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 (74) hide show
  1. package/lib/containers/containers.js +1 -4
  2. package/lib/containers/containers.js.map +1 -1
  3. package/lib/containers/context-services-from-container.js +1 -2
  4. package/lib/containers/context-services-from-container.js.map +1 -1
  5. package/lib/graphql/resolvers/channel.js +2 -10
  6. package/lib/graphql/resolvers/channel.js.map +1 -1
  7. package/lib/graphql/resolvers/index.js +1 -1
  8. package/lib/graphql/resolvers/index.js.map +1 -1
  9. package/lib/graphql/resolvers/post.js +3 -30
  10. package/lib/graphql/resolvers/post.js.map +1 -1
  11. package/lib/graphql/schema/channel.graphql +17 -2
  12. package/lib/graphql/schema/channel.graphql.js +1 -1
  13. package/lib/graphql/schema/index.js +2 -2
  14. package/lib/graphql/schema/index.js.map +1 -1
  15. package/lib/graphql/schema/post.graphql +16 -2
  16. package/lib/graphql/schema/post.graphql.js +1 -1
  17. package/lib/index.d.ts +1 -1
  18. package/lib/inngest/factory.js +2 -2
  19. package/lib/inngest/factory.js.map +1 -1
  20. package/lib/inngest/functions.d.ts +0 -96
  21. package/lib/inngest/functions.js +88 -815
  22. package/lib/inngest/functions.js.map +1 -1
  23. package/lib/module.d.ts +1 -1
  24. package/lib/module.js +8 -8
  25. package/lib/module.js.map +1 -1
  26. package/lib/plugins/index.d.ts +0 -1
  27. package/lib/preferences/permissions/inbox-permission-contribution.js +61 -22
  28. package/lib/preferences/permissions/inbox-permission-contribution.js.map +1 -1
  29. package/lib/preferences/permissions/inbox-roles-permission-overwrite.js +2 -2
  30. package/lib/preferences/permissions/inbox-roles-permission-overwrite.js.map +1 -1
  31. package/lib/services/channel-service.js +2 -2
  32. package/lib/services/channel-service.js.map +1 -1
  33. package/lib/services/index.d.ts +0 -1
  34. package/lib/services/post-service.d.ts +2 -3
  35. package/lib/services/post-service.js +9 -12
  36. package/lib/services/post-service.js.map +1 -1
  37. package/lib/services/proxy-services/index.d.ts +0 -1
  38. package/lib/store/models/index.d.ts +0 -1
  39. package/lib/store/repositories/channel-repository.js +1 -1
  40. package/lib/store/repositories/channel-repository.js.map +1 -1
  41. package/lib/store/repositories/index.d.ts +0 -1
  42. package/lib/store/repositories/post-repository.js +1 -1
  43. package/lib/store/repositories/post-repository.js.map +1 -1
  44. package/lib/store/repositories/post-thread-repository.js +1 -1
  45. package/lib/store/repositories/post-thread-repository.js.map +1 -1
  46. package/lib/store/repositories/reaction-repository.js +1 -1
  47. package/lib/store/repositories/reaction-repository.js.map +1 -1
  48. package/lib/templates/constants/SERVER_TYPES.ts.template +0 -3
  49. package/lib/templates/constants/WorkflowNamespace.ts.template +10 -0
  50. package/lib/templates/services/PostService.ts.template +8 -8
  51. package/package.json +6 -7
  52. package/lib/graphql/resolvers/ai-fragment.d.ts +0 -3
  53. package/lib/graphql/resolvers/ai-fragment.js +0 -276
  54. package/lib/graphql/resolvers/ai-fragment.js.map +0 -1
  55. package/lib/graphql/schema/ai-fragment.graphql +0 -311
  56. package/lib/graphql/schema/ai-fragment.graphql.js +0 -1
  57. package/lib/graphql/schema/ai-fragment.graphql.js.map +0 -1
  58. package/lib/plugins/ai-fragment-moleculer-service.d.ts +0 -29
  59. package/lib/plugins/ai-fragment-moleculer-service.js +0 -516
  60. package/lib/plugins/ai-fragment-moleculer-service.js.map +0 -1
  61. package/lib/services/ai-fragment-service.d.ts +0 -195
  62. package/lib/services/ai-fragment-service.js +0 -631
  63. package/lib/services/ai-fragment-service.js.map +0 -1
  64. package/lib/services/proxy-services/ai-fragment-microservice.d.ts +0 -23
  65. package/lib/services/proxy-services/ai-fragment-microservice.js +0 -75
  66. package/lib/services/proxy-services/ai-fragment-microservice.js.map +0 -1
  67. package/lib/store/models/ai-fragment.d.ts +0 -4
  68. package/lib/store/models/ai-fragment.js +0 -125
  69. package/lib/store/models/ai-fragment.js.map +0 -1
  70. package/lib/store/repositories/ai-fragment-repository.d.ts +0 -15
  71. package/lib/store/repositories/ai-fragment-repository.js +0 -69
  72. package/lib/store/repositories/ai-fragment-repository.js.map +0 -1
  73. package/lib/templates/repositories/AiFragmentRepository.ts.template +0 -4
  74. package/lib/templates/services/AiFragmentService.ts.template +0 -123
@@ -1,4 +1,4 @@
1
- import {SERVER_TYPES,RoomType,PostTypeEnum,AiAgentMessageRole,AiAgentMessageType}from'common/server';import {TaggedType}from'@common-stack/core';import {createAgent,createTool,createState,createNetwork,gemini,anthropic,openai}from'@inngest/agent-kit';import {Sandbox}from'@e2b/code-interpreter';import {z}from'zod';import {lastAssistantTextMessageContent,getSandbox,parseAgentOutput}from'./utils.js';import {CODING_PROMPT,FRAGMENT_TITLE_PROMPT,RESPONSE_PROMPT,VUE_CODING_PROMPT,VITE_REACT_CODING_PROMPT}from'./prompt.js';import {config}from'../config/env-config.js';// E2B Configuration constants
1
+ import {WorkflowNamespace,SERVER_TYPES,RoomType,AiAgentMessageRole,PostTypeEnum,AiAgentMessageType}from'common/server';import {TaggedType}from'@common-stack/core';import {createState,createAgent,createTool,createNetwork,gemini,anthropic,openai}from'@inngest/agent-kit';import {Sandbox}from'@e2b/code-interpreter';import {z}from'zod';import {lastAssistantTextMessageContent,getSandbox,parseAgentOutput}from'./utils.js';import {FRAGMENT_TITLE_PROMPT,RESPONSE_PROMPT,VUE_CODING_PROMPT,VITE_REACT_CODING_PROMPT,CODING_PROMPT}from'./prompt.js';import {config}from'../config/env-config.js';// E2B Configuration constants
2
2
  const templateID = config.E2B_TEMPLATE_ID; // Next.js template (default)
3
3
  const vueTemplateID = config.E2B_VUE_TEMPLATE_ID; // Vue template
4
4
  const viteReactTemplateID = config.E2B_VITE_REACT_TEMPLATE_ID; // Vite+React template
@@ -24,21 +24,6 @@ const getTemplateId = modelConfig => {
24
24
  }
25
25
  return templateID; // Default to Next.js template
26
26
  };
27
- // Helper function to normalize template names for database validation
28
- const normalizeTemplateName = template => {
29
- if (!template) return 'NEXTJS';
30
- switch (template.toLowerCase()) {
31
- case 'nextjs':
32
- return 'NEXTJS';
33
- case 'vue':
34
- return 'VUE';
35
- case 'vite-react':
36
- case 'vitereact':
37
- return 'VITE_REACT';
38
- default:
39
- return 'NEXTJS';
40
- }
41
- };
42
27
  // Helper to create model instance from modelConfig (provider/model/apiKey)
43
28
  const createModelInstance = modelConfig => {
44
29
  if (!modelConfig || !modelConfig.apiKey) {
@@ -74,9 +59,9 @@ const createModelInstance = modelConfig => {
74
59
  }
75
60
  };
76
61
  const createChannelWithProjectId = (inngest, container) => inngest.createFunction({
77
- id: 'create-channel-with-projectid'
62
+ id: WorkflowNamespace.MESSENGER_PLATFORM_CREATE_CHANNEL_FUNCTION
78
63
  }, {
79
- event: 'channel-with-project-id.create'
64
+ event: WorkflowNamespace.MESSENGER_PLATFORM_CREATE_CHANNEL_EVENT
80
65
  }, async ({
81
66
  event,
82
67
  step
@@ -88,17 +73,16 @@ const createChannelWithProjectId = (inngest, container) => inngest.createFunctio
88
73
  channelInput
89
74
  } = event.data || {};
90
75
  const {
91
- content,
92
76
  createdBy,
77
+ type,
78
+ title,
79
+ displayName,
80
+ topic,
81
+ description,
93
82
  orgName,
94
- organization,
95
83
  team,
96
- files,
97
- notificationParams,
98
84
  modelConfig,
99
- accountId,
100
- teamId,
101
- orgId
85
+ postData
102
86
  } = channelInput;
103
87
  // Validate that projectId is provided
104
88
  if (!projectId) {
@@ -111,7 +95,7 @@ const createChannelWithProjectId = (inngest, container) => inngest.createFunctio
111
95
  const existingList = await channelService.getAll({
112
96
  criteria: {
113
97
  projectId,
114
- type: RoomType.Aiassistant
98
+ type: type || RoomType.Aiassistant
115
99
  }
116
100
  });
117
101
  const existing = Array.isArray(existingList) ? existingList[0] : null;
@@ -119,15 +103,16 @@ const createChannelWithProjectId = (inngest, container) => inngest.createFunctio
119
103
  return existing;
120
104
  }
121
105
  const newChannel = await channelService.saveChannel({
122
- type: RoomType.Aiassistant,
123
- orgName: orgId,
124
- organization: orgId,
125
- creator: createdBy || accountId,
126
- title: 'AI Assistant',
127
- displayName: 'AI Assistant',
128
- topic: 'AI Assistant',
129
- team: teamId,
130
- description: 'AI Assistant',
106
+ ...channelInput,
107
+ type: type || RoomType.Aiassistant,
108
+ orgName,
109
+ organization: orgName,
110
+ creator: createdBy,
111
+ title: title || 'AI Assistant',
112
+ displayName: displayName || 'AI Assistant',
113
+ topic: topic || 'AI Assistant',
114
+ team: team,
115
+ description: description || 'AI Assistant',
131
116
  projectId,
132
117
  _id: undefined
133
118
  });
@@ -138,28 +123,36 @@ const createChannelWithProjectId = (inngest, container) => inngest.createFunctio
138
123
  if (!channelId) {
139
124
  throw new Error('Failed to resolve channel id for post creation');
140
125
  }
126
+ const {
127
+ content,
128
+ files,
129
+ props: propsData
130
+ } = postData;
131
+ const props = propsData || {
132
+ notificationParams: {},
133
+ template: modelConfig?.template || 'vite-react',
134
+ projectId: projectId,
135
+ role: AiAgentMessageRole.User,
136
+ fragment: {},
137
+ sendNotificationWithProjectId: false
138
+ };
141
139
  await step.sendEvent('emit-send-message', {
142
- name: 'channel.message.send',
140
+ name: WorkflowNamespace.MESSENGER_PLATFORM_CREATE_POST_EVENT,
143
141
  data: {
144
142
  channelId,
145
143
  content,
146
144
  createdBy,
147
145
  files,
148
- notificationParams,
149
- projectId,
150
- modelConfig,
151
- accountId,
152
- teamId,
153
- orgId
146
+ props
154
147
  }
155
148
  });
156
149
  }
157
150
  return channelData;
158
151
  });
159
152
  const sendMessageHandler = (inngest, container) => inngest.createFunction({
160
- id: 'channel-message-send'
153
+ id: WorkflowNamespace.MESSENGER_PLATFORM_CREATE_POST_FUNCTION
161
154
  }, {
162
- event: 'channel.message.send'
155
+ event: WorkflowNamespace.MESSENGER_PLATFORM_CREATE_POST_EVENT
163
156
  }, async ({
164
157
  event,
165
158
  step
@@ -167,717 +160,38 @@ const sendMessageHandler = (inngest, container) => inngest.createFunction({
167
160
  console.log('=== Send Message Handler FUNCTION STARTED ===');
168
161
  console.log('=== Send Message Handler Event data:', JSON.stringify(event.data, null, 2));
169
162
  const {
170
- projectId,
163
+ props,
171
164
  channelId,
172
165
  content,
173
166
  createdBy,
174
- files,
175
- notificationParams,
176
- modelConfig,
177
- accountId,
178
- teamId,
179
- orgId
167
+ files
180
168
  } = event.data || {};
181
- if (!channelId || !content || !createdBy || !accountId) {
169
+ if (!channelId || !content || !createdBy) {
182
170
  throw new Error('channelId, content and createdBy are required');
183
171
  }
184
172
  const messageData = await step.run('persist-message', async () => {
185
173
  const postService = container.getNamed(SERVER_TYPES.PostService, TaggedType.MICROSERVICE);
186
- container.get('PubSub');
187
174
  const postDoc = await postService.create({
188
175
  channel: channelId,
189
176
  message: content,
190
- editedBy: createdBy || accountId,
191
- author: createdBy || accountId,
192
- // Convert props to propsConfiguration structure
193
- props: {
194
- notificationParams: notificationParams || {},
195
- template: modelConfig?.template || 'vite-react',
196
- projectId: projectId,
197
- role: AiAgentMessageRole.USER,
198
- fragment: {},
199
- sendNotificationWithProjectId: false
200
- },
201
- type: PostTypeEnum.Simple,
177
+ editedBy: createdBy,
178
+ author: createdBy,
179
+ props: props || {},
180
+ type: PostTypeEnum.Aiassistant,
202
181
  files
203
182
  });
204
- // if (postDoc) {
205
- // pubsub.publish(`POST_CREATED.${projectId}`, postDoc);
206
- // }
207
183
  return await postDoc;
208
184
  });
209
185
  await step.run('publish-subscription-update', async () => {
210
186
  const pubsub = container.get('PubSub');
211
- pubsub.publish(`POST_CREATED.${projectId}`, messageData);
187
+ pubsub.publish(`POST_CREATED.${props.projectId}`, messageData);
212
188
  });
213
- // Prepare final model config with the template that was actually used
214
- // const finalModelConfig = await step.run('prepare-final-model-config', async () => {
215
- // let actualTemplate = modelConfig?.template || 'nextjs';
216
- // if (modelConfig) {
217
- // // Use provided modelConfig but ensure template is what was actually stored
218
- // const finalConfig = {
219
- // ...modelConfig,
220
- // template: actualTemplate, // Always use the immutable template from DB
221
- // };
222
- // console.log('Final modelConfig for code generation:', finalConfig);
223
- // return finalConfig;
224
- // }
225
- // return {
226
- // template: actualTemplate,
227
- // provider: 'gemini',
228
- // model: 'gemini-1.5-flash',
229
- // apiKey: '', // Will need to be provided via environment
230
- // };
231
- // });
232
- // Trigger code generation
233
- // await step.run('trigger-code-generation', async () => {
234
- // await inngest.send({
235
- // name: 'code-agent/run-code-creation',
236
- // data: {
237
- // value:messageData.message,
238
- // projectId,
239
- // messageId: messageData.id,
240
- // owner: messageData?.author || createdBy || accountId,
241
- // orgName: orgId,
242
- // modelConfig: finalModelConfig,
243
- // accountId,
244
- // teamId,
245
- // orgId,
246
- // channelId
247
- // },
248
- // });
249
- // });
250
- // Send event after result is available
251
- // await step.sendEvent('emit-ai-response-generate', {
252
- // name: 'ai.response.generate',
253
- // data: {
254
- // projectId,
255
- // post: result,
256
- // modelConfig,
257
- // },
258
- // });
259
189
  return messageData;
260
190
  });
261
- // Main code agent function - processes queries and generates code
262
- const codeAgentFunction = (inngest, container) => inngest.createFunction({
263
- id: 'code-agent'
264
- }, {
265
- event: 'code-agent/run-code-creation'
266
- }, async ({
267
- event,
268
- step
269
- }) => {
270
- console.log('=== CODE AGENT FUNCTION STARTED ===');
271
- console.log('Event data:', JSON.stringify(event.data, null, 2));
272
- const {
273
- sandboxId,
274
- sandboxUrl
275
- } = await step.run('create-sandbox-and-start-monitoring', async () => {
276
- const selectedTemplateId = getTemplateId(event.data.modelConfig);
277
- console.log(`Creating sandbox with template: ${selectedTemplateId} (requested: ${event.data.modelConfig?.template || 'nextjs'})`);
278
- const sandbox = await Sandbox.create(selectedTemplateId, {
279
- apiKey,
280
- domain,
281
- timeoutMs: 60_000 * 20
282
- });
283
- const sandboxUrl = `https://3000-${sandbox.sandboxId}.yarntra.ai`;
284
- // Start error monitoring immediately after sandbox creation
285
- // const container = await initializeContainer();
286
- const sandboxErrorService = container.get(SERVER_TYPES.SandboxErrorService);
287
- console.log(`Starting immediate error monitoring for sandbox ${sandbox.sandboxId}`);
288
- await sandboxErrorService.startErrorMonitoring(event.data.projectId, sandbox.sandboxId, sandboxUrl);
289
- return {
290
- sandboxId: sandbox.sandboxId,
291
- sandboxUrl
292
- };
293
- });
294
- // Only fetch previous messages if we don't have active fragment files
295
- const previousMessages = event.data.activeFragmentFiles ? [] // Skip fetching previous messages when we have active fragment files
296
- : await step.run('get-previous-messages', async () => {
297
- const postService = container.getNamed(SERVER_TYPES.PostService, TaggedType.MICROSERVICE);
298
- const result = await postService.getPreviousMessagesByProjectId(event.data.projectId, 5);
299
- // Handle error case - return empty array if getPreviousMessagesByProjectId returns an Error
300
- if (result instanceof Error) {
301
- console.warn('Failed to get previous messages:', result.message);
302
- return [];
303
- }
304
- return result;
305
- });
306
- const state = createState({
307
- summary: '',
308
- files: event.data.activeFragmentFiles || {},
309
- // Use active fragment files if provided
310
- canvasLayers: []
311
- }, {
312
- messages: previousMessages
313
- });
314
- // Get model configuration from event data
315
- const {
316
- modelConfig
317
- } = event.data;
318
- console.log('Model configuration received:', JSON.stringify(modelConfig, null, 2));
319
- // Create a new agent with the template-specific coding prompt
320
- const selectedCodingPrompt = getCodingPrompt(event.data.modelConfig);
321
- console.log(`Using coding prompt for template: ${event.data.modelConfig?.template || 'nextjs'}`);
322
- const codeAgent = createAgent({
323
- name: 'code-agent',
324
- description: 'An expert coding agent for page creation',
325
- system: selectedCodingPrompt,
326
- model: createModelInstance(modelConfig),
327
- tools: [createTool({
328
- name: 'terminal',
329
- description: 'Use the terminal to run commands',
330
- parameters: z.object({
331
- command: z.string()
332
- }),
333
- handler: async ({
334
- command
335
- }, {
336
- step
337
- }) => await step?.run('terminal', async () => {
338
- try {
339
- const sandbox = await getSandbox(sandboxId);
340
- const result = await sandbox.commands.run(command);
341
- return result.stdout;
342
- } catch (e) {
343
- return `Command failed: ${e}`;
344
- }
345
- })
346
- }), createTool({
347
- name: 'createOrUpdateFiles',
348
- description: 'Create or update files in the sandbox',
349
- parameters: z.object({
350
- files: z.union([z.array(z.object({
351
- path: z.string(),
352
- content: z.string()
353
- })), z.string() // Accept JSON string as fallback
354
- ])
355
- }),
356
- // handler: async ({ files }, { step, network }: Tool.Options<AgentState>) => {
357
- handler: async ({
358
- files
359
- }, {
360
- step,
361
- network
362
- }) => {
363
- const newFiles = await step?.run('createOrUpdateFiles', async () => {
364
- try {
365
- console.log('createOrUpdateFiles - Raw files parameter type:', typeof files);
366
- console.log('createOrUpdateFiles - Raw files parameter:', `${JSON.stringify(files).substring(0, 200)}...`);
367
- // Parse files if it's a JSON string (fallback for AI model behavior)
368
- let parsedFiles;
369
- if (typeof files === 'string') {
370
- try {
371
- // First try standard JSON parsing
372
- parsedFiles = JSON.parse(files);
373
- console.log('createOrUpdateFiles - Successfully parsed files from JSON string');
374
- } catch (parseError) {
375
- console.log('createOrUpdateFiles - Standard JSON parse failed, trying template literal fix');
376
- try {
377
- // AI is using template literals in JSON - need more sophisticated parsing
378
- console.log('createOrUpdateFiles - Attempting to fix template literals in JSON');
379
- // Try to evaluate the string as JavaScript to handle template literals
380
- // This is safe because we're in a sandboxed environment and only parsing our own AI's output
381
- const evalString = `(${files})`;
382
- console.log('createOrUpdateFiles - Evaluating as JavaScript array');
383
- parsedFiles = eval(evalString);
384
- console.log('createOrUpdateFiles - Successfully evaluated template literals');
385
- } catch (secondError) {
386
- console.error('createOrUpdateFiles - Both parsing attempts failed:');
387
- console.error('Original error:', parseError.message);
388
- console.error('Template literal fix error:', secondError.message);
389
- console.error('Raw string (first 500 chars):', files.substring(0, 500));
390
- return `Error: Failed to parse files JSON - ${parseError.message}`;
391
- }
392
- }
393
- } else if (Array.isArray(files)) {
394
- parsedFiles = files;
395
- console.log('createOrUpdateFiles - Using files array directly');
396
- } else {
397
- console.error('createOrUpdateFiles - Files parameter is neither string nor array:', typeof files);
398
- return `Error: Files parameter must be an array or JSON string, got ${typeof files}`;
399
- }
400
- // Validate that parsedFiles is an array
401
- if (!Array.isArray(parsedFiles)) {
402
- console.error('createOrUpdateFiles - Parsed files is not an array:', parsedFiles);
403
- return `Error: Files must be an array after parsing, got ${typeof parsedFiles}`;
404
- }
405
- console.log(`createOrUpdateFiles - Processing ${parsedFiles.length} files`);
406
- const updatedFiles = network.state.data.files || {};
407
- const sandbox = await getSandbox(sandboxId);
408
- for (const file of parsedFiles) {
409
- if (!file.path || file.content === undefined) {
410
- console.error('createOrUpdateFiles - Invalid file object (missing path or content):', file);
411
- continue;
412
- }
413
- console.log(`createOrUpdateFiles - Writing file: ${file.path}`);
414
- await sandbox.files.write(file.path, file.content);
415
- updatedFiles[file.path] = file.content;
416
- }
417
- console.log(`createOrUpdateFiles - Successfully updated ${parsedFiles.length} files`);
418
- return updatedFiles;
419
- } catch (e) {
420
- console.error('createOrUpdateFiles - Error:', e);
421
- console.error('createOrUpdateFiles - Error stack:', e?.stack);
422
- return `Error: ${e}`;
423
- }
424
- });
425
- if (typeof newFiles === 'object' && !Array.isArray(newFiles) && typeof newFiles !== 'string') {
426
- network.state.data.files = newFiles;
427
- }
428
- }
429
- }), createTool({
430
- name: 'readFiles',
431
- description: 'Read files from the sandbox',
432
- parameters: z.object({
433
- files: z.array(z.string())
434
- }),
435
- handler: async ({
436
- files
437
- }, {
438
- step
439
- }) => await step?.run('readFiles', async () => {
440
- try {
441
- const sandbox = await getSandbox(sandboxId);
442
- const contents = [];
443
- for (const file of files) {
444
- const content = await sandbox.files.read(file);
445
- contents.push({
446
- path: file,
447
- content
448
- });
449
- }
450
- return JSON.stringify(contents);
451
- } catch (e) {
452
- return `Error: ${e}`;
453
- }
454
- })
455
- })],
456
- lifecycle: {
457
- onResponse: async ({
458
- result,
459
- network
460
- }) => {
461
- const lastAssistantMessageText = lastAssistantTextMessageContent(result);
462
- if (lastAssistantMessageText && network) {
463
- if (lastAssistantMessageText.includes('<task_summary>')) {
464
- network.state.data.summary = lastAssistantMessageText;
465
- // Extract canvas layers if present
466
- const canvasLayersMatch = lastAssistantMessageText.match(/<canvas_layers>([\s\S]*?)<\/canvas_layers>/);
467
- if (canvasLayersMatch) {
468
- try {
469
- const layersJson = canvasLayersMatch[1].trim();
470
- network.state.data.canvasLayers = JSON.parse(layersJson);
471
- } catch (error) {
472
- console.error('Error parsing canvas layers:', error);
473
- network.state.data.canvasLayers = null;
474
- }
475
- }
476
- }
477
- }
478
- return result;
479
- }
480
- }
481
- });
482
- const network = createNetwork({
483
- name: 'coding-agent-network',
484
- agents: [codeAgent],
485
- maxIter: 15,
486
- defaultState: state,
487
- router: async ({
488
- network
489
- }) => {
490
- const {
491
- summary
492
- } = network.state.data;
493
- if (summary) {
494
- return;
495
- }
496
- return codeAgent;
497
- }
498
- });
499
- // Prepare the enhanced input message that includes activeFragmentFiles context
500
- let enhancedInput = event.data.value;
501
- // If we have activeFragmentFiles, include them in the message to the AI
502
- if (event.data.activeFragmentFiles && Object.keys(event.data.activeFragmentFiles).length > 0) {
503
- console.log('📂 Including activeFragmentFiles context for AI agent:');
504
- console.log('- File count:', Object.keys(event.data.activeFragmentFiles).length);
505
- console.log('- Files:', Object.keys(event.data.activeFragmentFiles));
506
- // Check if ViteVisualEditor exists and warn if it's missing for vite-react template
507
- const hasViteVisualEditor = 'src/components/ViteVisualEditor.tsx' in event.data.activeFragmentFiles;
508
- const isViteReact = event.data.modelConfig?.template === 'vite-react';
509
- if (isViteReact && !hasViteVisualEditor) {
510
- console.warn('⚠️ ViteVisualEditor.tsx missing from activeFragmentFiles for vite-react template');
511
- console.warn('AI may create stub component instead of importing existing one');
512
- }
513
- enhancedInput = `${event.data.value}
514
-
515
- ACTIVE FRAGMENT FILES CONTEXT:
516
- The current sandbox contains the following files that you MUST include in your createOrUpdateFiles call:
517
-
518
- ${Object.entries(event.data.activeFragmentFiles).map(([path, content]) => `FILE: ${path}\n${typeof content === 'string' ? content.substring(0, 500) + (content.length > 500 ? '...' : '') : '[Non-string content]'}`).join('\n\n')}
519
-
520
- CRITICAL INSTRUCTIONS FOR VISUAL CHANGES:
521
- - You MUST include ALL ${Object.keys(event.data.activeFragmentFiles).length} files from the active fragment files in your createOrUpdateFiles call
522
- - Apply the visual changes described above to the appropriate files
523
- - Preserve ALL existing files and their content except for the specific changes requested
524
- - Use the complete file context provided above as your current codebase state
525
- - DO NOT output only the changed file - output ALL files to rebuild the complete sandbox${isViteReact && !hasViteVisualEditor ? '\n- IMPORTANT: For vite-react template, you MUST import ViteVisualEditor from "./components/ViteVisualEditor" (it exists in the template), do NOT create a new component' : ''}`;
526
- }
527
- console.log('🤖 Running AI agent with enhanced input length:', enhancedInput.length);
528
- const result = await network.run(enhancedInput, {
529
- state
530
- });
531
- // Enhanced file validation with logging
532
- const hasFiles = result.state.data.files && Object.keys(result.state.data.files).length > 0;
533
- const hasSummary = result.state.data.summary && result.state.data.summary.trim().length > 0;
534
- const outputFileCount = Object.keys(result.state.data.files || {}).length;
535
- const inputFileCount = event.data.activeFragmentFiles ? Object.keys(event.data.activeFragmentFiles).length : 0;
536
- console.log('Agent result validation:', {
537
- hasFiles,
538
- outputFileCount,
539
- inputFileCount,
540
- fileCountMatch: inputFileCount > 0 ? outputFileCount === inputFileCount : true,
541
- hasSummary,
542
- summaryLength: result.state.data.summary?.length || 0,
543
- outputFiles: Object.keys(result.state.data.files || {}),
544
- inputFiles: event.data.activeFragmentFiles ? Object.keys(event.data.activeFragmentFiles) : []
545
- });
546
- // Warning if file counts don't match for visual changes
547
- if (event.data.activeFragmentFiles && inputFileCount > 0 && outputFileCount !== inputFileCount) {
548
- console.warn(`⚠️ File count mismatch! Expected ${inputFileCount} files, got ${outputFileCount} files`);
549
- console.warn('Missing files may cause incomplete sandbox rebuild');
550
- }
551
- const fragmentTitleGenerator = createAgent({
552
- name: 'fragment-title-generator',
553
- description: 'A fragment title generator',
554
- system: FRAGMENT_TITLE_PROMPT,
555
- model: createModelInstance(modelConfig)
556
- });
557
- const responseGenerator = createAgent({
558
- name: 'response-generator',
559
- description: 'A response generator',
560
- system: RESPONSE_PROMPT,
561
- model: createModelInstance(modelConfig)
562
- });
563
- // Run generators in parallel outside of steps (like lovable-clone)
564
- const {
565
- output: fragmentTitleOutput
566
- } = await fragmentTitleGenerator.run(result.state.data.summary || 'Generated Page');
567
- const {
568
- output: responseOutput
569
- } = await responseGenerator.run(result.state.data.summary || 'Code generated successfully');
570
- const agentError = !result.state.data.summary || Object.keys(result.state.data.files || {}).length === 0;
571
- // sandboxUrl is already available from the previous step
572
- // Save to database using handler
573
- const messageData = await step.run('save-result', async () => {
574
- const postService = container.getNamed(SERVER_TYPES.PostService, TaggedType.MICROSERVICE);
575
- // Normalize template name for database validation
576
- const normalizedModelConfig = {
577
- ...event.data.modelConfig,
578
- template: normalizeTemplateName(event.data.modelConfig?.template)
579
- };
580
- return await postService.saveCodeAgentResult({
581
- value: event.data.value,
582
- projectId: event.data.projectId,
583
- messageId: event.data.messageId,
584
- owner: event.data.owner,
585
- orgName: event.data.orgName,
586
- modelConfig: normalizedModelConfig
587
- }, sandboxUrl, parseAgentOutput(fragmentTitleOutput), parseAgentOutput(responseOutput), result.state.data.files || {}, result.state.data.summary || '', agentError, result.state.data.canvasLayers);
588
- });
589
- // Publish subscription update for real-time client updates
590
- await step.run('publish-subscription-update', async () => {
591
- // const responseData = {
592
- // projectId: event.data.projectId,
593
- // sandboxId: sandboxId,
594
- // sandboxUrl: sandboxUrl,
595
- // url: sandboxUrl, // Keep both for compatibility
596
- // title: parseAgentOutput(fragmentTitleOutput) || 'Generated Page',
597
- // files: result.state.data.files,
598
- // summary: result.state.data.summary,
599
- // isError: agentError,
600
- // messageId: agentError ? null : (messageData as any).id,
601
- // canvasLayers: result.state.data.canvasLayers,
602
- // template: normalizeTemplateName(event.data.modelConfig?.template),
603
- // timestamp: new Date().toISOString(),
604
- // };
605
- const pubsub = container.get('PubSub');
606
- // const post = event.data.post;
607
- // const postData = {
608
- // ...messageData,
609
- // props: {
610
- // ...messageData.props,
611
- // fragment: responseData,
612
- // },
613
- // };
614
- console.log('=== Publish to subscription Post Data:', JSON.stringify(messageData, null, 2));
615
- pubsub.publish(`POST_CREATED.${event.data.projectId}`, messageData);
616
- });
617
- // Error monitoring was already started immediately after sandbox creation
618
- // No need to start it again here
619
- return {
620
- projectId: event.data.projectId,
621
- sandboxId: sandboxId,
622
- sandboxUrl: sandboxUrl,
623
- url: sandboxUrl,
624
- // Keep both for compatibility
625
- title: parseAgentOutput(fragmentTitleOutput) || 'Generated Page',
626
- files: result.state.data.files,
627
- summary: result.state.data.summary,
628
- isError: agentError,
629
- canvasLayers: result.state.data.canvasLayers,
630
- template: normalizeTemplateName(event.data.modelConfig?.template),
631
- timestamp: new Date().toISOString()
632
- };
633
- });
634
- const generateAIResponseWithSandbox = (inngest, container) => inngest.createFunction({
635
- id: 'generate-ai-response-with-sandbox'
636
- }, {
637
- event: 'ai.response.generate'
638
- }, async ({
639
- event,
640
- step
641
- }) => {
642
- console.log('=== AI Response Generation with Sandbox FUNCTION STARTED ===');
643
- console.log('Event data:', JSON.stringify(event.data, null, 2));
644
- const {
645
- projectId,
646
- post,
647
- modelConfig
648
- } = event.data || {};
649
- const message = post.message;
650
- // Validate required parameters
651
- if (!projectId || !message) {
652
- throw new Error('projectId and message are required');
653
- }
654
- // Create e2b sandbox
655
- const sandbox = await step.run('create-sandbox', async () => {
656
- try {
657
- const selectedTemplateId = getTemplateId(modelConfig);
658
- console.log(`Creating sandbox with template: ${selectedTemplateId} (requested: ${modelConfig?.template || 'vite-react'})`);
659
- const sandbox = await Sandbox.create(selectedTemplateId, {
660
- apiKey,
661
- domain,
662
- timeoutMs: 60_000 * 20 // 20 minutes timeout
663
- });
664
- return sandbox;
665
- } catch (error) {
666
- console.error('Failed to create sandbox:', error);
667
- throw new Error(`Failed to create sandbox: ${error.message}`);
668
- }
669
- });
670
- // Create the appropriate coding prompt based on framework
671
- let codingPrompt = CODING_PROMPT;
672
- if (modelConfig?.template === 'vue') {
673
- codingPrompt = VUE_CODING_PROMPT;
674
- } else if (modelConfig?.template === 'vite-react') {
675
- codingPrompt = VITE_REACT_CODING_PROMPT;
676
- }
677
- // Create agent with sandbox tools (use modelConfig model if provided)
678
- const agent = createAgent({
679
- name: 'CodeGenerator',
680
- system: codingPrompt,
681
- model: createModelInstance(modelConfig?.modelConfig || modelConfig),
682
- tools: [createTool({
683
- name: 'createOrUpdateFiles',
684
- description: 'Create or update files in the sandbox',
685
- parameters: z.object({
686
- files: z.array(z.object({
687
- path: z.string(),
688
- content: z.string()
689
- }))
690
- }),
691
- handler: async ({
692
- files
693
- }) => {
694
- try {
695
- await sandbox.files.write(files);
696
- return {
697
- success: true,
698
- message: `Updated ${files.length} files`
699
- };
700
- } catch (error) {
701
- return {
702
- success: false,
703
- error: error.message
704
- };
705
- }
706
- }
707
- }), createTool({
708
- name: 'readFiles',
709
- description: 'Read files from the sandbox',
710
- parameters: z.object({
711
- paths: z.array(z.string())
712
- }),
713
- handler: async ({
714
- paths
715
- }) => {
716
- try {
717
- const files = await Promise.all(paths.map(async path => {
718
- try {
719
- const content = await sandbox.files.read(path);
720
- return {
721
- path,
722
- content,
723
- exists: true
724
- };
725
- } catch (error) {
726
- return {
727
- path,
728
- content: '',
729
- exists: false,
730
- error: error.message
731
- };
732
- }
733
- }));
734
- return {
735
- success: true,
736
- files
737
- };
738
- } catch (error) {
739
- return {
740
- success: false,
741
- error: error.message
742
- };
743
- }
744
- }
745
- }), createTool({
746
- name: 'terminal',
747
- description: 'Execute terminal commands in the sandbox',
748
- parameters: z.object({
749
- command: z.string()
750
- }),
751
- handler: async ({
752
- command
753
- }) => {
754
- try {
755
- const result = await sandbox.process.start({
756
- cmd: command
757
- });
758
- const output = await result.finished;
759
- return {
760
- success: true,
761
- output: output.stdout || output.stderr,
762
- exitCode: output.exitCode
763
- };
764
- } catch (error) {
765
- return {
766
- success: false,
767
- error: error.message
768
- };
769
- }
770
- }
771
- })]
772
- });
773
- // Generate AI response using agent-kit (completely outside of step.run to avoid nesting)
774
- let aiResponse;
775
- try {
776
- console.log('=== Starting AI response generation ===');
777
- console.log('Message:', message);
778
- // Generate response
779
- const result = await agent.run(message);
780
- // Parse the response to extract task summary and canvas layers
781
- const responseContent = lastAssistantTextMessageContent(result);
782
- console.log('=== AI Response Content ===');
783
- console.log('Response Content:', responseContent);
784
- const taskSummary = responseContent?.match(/<task_summary>([\s\S]*?)<\/task_summary>/)?.[1]?.trim();
785
- const canvasLayersMatch = responseContent?.match(/<canvas_layers>([\s\S]*?)<\/canvas_layers>/)?.[1];
786
- let canvasLayers = null;
787
- if (canvasLayersMatch) {
788
- try {
789
- canvasLayers = JSON.parse(canvasLayersMatch.trim());
790
- } catch (error) {
791
- console.error('Failed to parse canvas layers:', error);
792
- }
793
- }
794
- aiResponse = {
795
- success: true,
796
- response: responseContent,
797
- taskSummary,
798
- canvasLayers,
799
- agentResult: result
800
- };
801
- console.log('=== AI Response Object ===');
802
- console.log('AI Response:', JSON.stringify(aiResponse, null, 2));
803
- } catch (error) {
804
- console.error('AI response generation failed:', error);
805
- aiResponse = {
806
- success: false,
807
- error: error.message,
808
- response: null,
809
- taskSummary: null,
810
- canvasLayers: null
811
- };
812
- }
813
- // Generate sandbox URL
814
- const sandboxUrl = await step.run('generate-sandbox-url', async () => {
815
- try {
816
- // Your domain pattern: https://3000-<sandboxId>.yarntra.ai
817
- const url = `https://3000-${sandbox.sandboxId}.yarntra.ai`;
818
- console.log(`Generated sandbox URL: ${url}`);
819
- return url;
820
- } catch (error) {
821
- console.error('Failed to generate sandbox URL:', error);
822
- throw new Error(`Failed to generate sandbox URL: ${error.message}`);
823
- }
824
- });
825
- console.log('sandboxUrl', sandboxUrl);
826
- // Publish to subscription
827
- await step.run('publish-to-subscription', async () => {
828
- try {
829
- const pubsub = container.get('PubSub');
830
- const responseData = {
831
- projectId,
832
- sandboxId: sandbox.sandboxId,
833
- sandboxUrl,
834
- url: sandboxUrl,
835
- // Keep both for compatibility
836
- aiResponse: aiResponse.success ? aiResponse.response : null,
837
- taskSummary: aiResponse.success ? aiResponse.taskSummary : null,
838
- canvasLayers: aiResponse.success ? aiResponse.canvasLayers : null,
839
- error: aiResponse.success ? null : aiResponse.error,
840
- template: normalizeTemplateName(modelConfig?.template || 'vite-react'),
841
- timestamp: new Date().toISOString()
842
- };
843
- console.log('=== Response Data ===');
844
- console.log('Response Data:', JSON.stringify(responseData, null, 2));
845
- console.log('AI Response Success:', aiResponse.success);
846
- // console.log('AI Response Content:', aiResponse.response);
847
- // pubsub.publish(`AI_RESPONSE_GENERATED.${projectId}`, responseData);
848
- const postData = {
849
- ...post,
850
- props: {
851
- ...post.props,
852
- generatedResponse: responseData
853
- }
854
- };
855
- console.log('=== Publish to subscription Post Data:', JSON.stringify(postData, null, 2));
856
- pubsub.publish(`POST_CREATED.${projectId}`, postData);
857
- return responseData;
858
- } catch (error) {
859
- console.error('Failed to publish to subscription:', error);
860
- throw new Error(`Failed to publish to subscription: ${error.message}`);
861
- }
862
- });
863
- return {
864
- projectId,
865
- sandboxId: sandbox.sandboxId,
866
- sandboxUrl,
867
- url: sandboxUrl,
868
- // Keep both for compatibility
869
- aiResponse: aiResponse.success ? aiResponse.response : null,
870
- taskSummary: aiResponse.success ? aiResponse.taskSummary : null,
871
- canvasLayers: aiResponse.success ? aiResponse.canvasLayers : null,
872
- error: aiResponse.success ? null : aiResponse.error,
873
- template: normalizeTemplateName(modelConfig?.template || 'vite-react'),
874
- timestamp: new Date().toISOString()
875
- };
876
- });
877
191
  const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
878
- id: 'ai-code-agent'
192
+ id: WorkflowNamespace.MESSENGER_PLATFORM_GENERATE_AI_CODE_FUNCTION
879
193
  }, {
880
- event: 'ai-code-agent/run-code-generation'
194
+ event: WorkflowNamespace.MESSENGER_PLATFORM_GENERATE_AI_CODE_EVENT
881
195
  }, async ({
882
196
  event,
883
197
  step
@@ -890,7 +204,6 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
890
204
  } = event.data || {};
891
205
  const postService = container.getNamed(SERVER_TYPES.PostService, TaggedType.MICROSERVICE);
892
206
  const post = await postService.get(messageId);
893
- console.log('ai-event-post', JSON.stringify(post, null, 2));
894
207
  if (!post) {
895
208
  throw new Error('Post not found');
896
209
  }
@@ -919,7 +232,6 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
919
232
  const previousMessages = event.data.activeFragmentFiles ? [] // Skip fetching previous messages when we have active fragment files
920
233
  : await step.run('get-previous-messages', async () => {
921
234
  const result = await postService.getPreviousMessagesByProjectId(post.props.projectId, 5);
922
- console.log('previousMessages', JSON.stringify(result, null, 2));
923
235
  // Handle error case - return empty array if getPreviousMessagesByProjectId returns an Error
924
236
  if (result instanceof Error) {
925
237
  console.warn('Failed to get previous messages:', result.message);
@@ -1119,21 +431,45 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1119
431
  // If we have activeFragmentFiles, include them in the message to the AI
1120
432
  if (event.data.activeFragmentFiles && Object.keys(event.data.activeFragmentFiles).length > 0) {
1121
433
  // Check if ViteVisualEditor exists and warn if it's missing for vite-react template
1122
- const hasViteVisualEditor = 'src/components/ViteVisualEditor.tsx' in event.data.activeFragmentFiles;
1123
- const isViteReact = modelConfig?.template === 'vite-react';
434
+ 'src/components/ViteVisualEditor.tsx' in event.data.activeFragmentFiles;
435
+ modelConfig?.template === 'vite-react';
1124
436
  enhancedInput = `${post.message}
1125
437
  ACTIVE FRAGMENT FILES CONTEXT:
1126
438
  The current sandbox contains the following files that you MUST include in your createOrUpdateFiles call:
1127
439
 
1128
- ${Object.entries(event.data.activeFragmentFiles).map(([path, content]) => `FILE: ${path}\n${typeof content === 'string' ? content.substring(0, 500) + (content.length > 500 ? '...' : '') : '[Non-string content]'}`).join('\n\n')}
1129
-
1130
- CRITICAL INSTRUCTIONS FOR VISUAL CHANGES:
1131
- - You MUST include ALL ${Object.keys(event.data.activeFragmentFiles).length} files from the active fragment files in your createOrUpdateFiles call
1132
- - Apply the visual changes described above to the appropriate files
1133
- - Preserve ALL existing files and their content except for the specific changes requested
1134
- - Use the complete file context provided above as your current codebase state
1135
- - DO NOT output only the changed file - output ALL files to rebuild the complete sandbox${isViteReact && !hasViteVisualEditor ? '\n- IMPORTANT: For vite-react template, you MUST import ViteVisualEditor from "./components/ViteVisualEditor" (it exists in the template), do NOT create a new component' : ''}`;
440
+ ${Object.entries(event.data.activeFragmentFiles).map(([path, content]) => `FILE: ${path}\n${typeof content === 'string' ? content.substring(0, 500) + (content.length > 500 ? '...' : '') : '[Non-string content]'}`).join('\n\n')}`;
1136
441
  }
442
+ // // If we have activeFragmentFiles, include them in the message to the AI
443
+ // if (event.data.activeFragmentFiles && Object.keys(event.data.activeFragmentFiles).length > 0) {
444
+ // // Check if ViteVisualEditor exists and warn if it's missing for vite-react template
445
+ // const hasViteVisualEditor = 'src/components/ViteVisualEditor.tsx' in event.data.activeFragmentFiles;
446
+ // const isViteReact = modelConfig?.template === 'vite-react';
447
+ // enhancedInput = `${post.message}
448
+ // ACTIVE FRAGMENT FILES CONTEXT:
449
+ // The current sandbox contains the following files that you MUST include in your createOrUpdateFiles call:
450
+ // ${Object.entries(event.data.activeFragmentFiles)
451
+ // .map(
452
+ // ([path, content]) =>
453
+ // `FILE: ${path}\n${
454
+ // typeof content === 'string'
455
+ // ? content.substring(0, 500) + (content.length > 500 ? '...' : '')
456
+ // : '[Non-string content]'
457
+ // }`,
458
+ // )
459
+ // .join('\n\n')}
460
+ // CRITICAL INSTRUCTIONS FOR VISUAL CHANGES:
461
+ // - You MUST include ALL ${
462
+ // Object.keys(event.data.activeFragmentFiles).length
463
+ // } files from the active fragment files in your createOrUpdateFiles call
464
+ // - Apply the visual changes described above to the appropriate files
465
+ // - Preserve ALL existing files and their content except for the specific changes requested
466
+ // - Use the complete file context provided above as your current codebase state
467
+ // - DO NOT output only the changed file - output ALL files to rebuild the complete sandbox${
468
+ // isViteReact && !hasViteVisualEditor
469
+ // ? '\n- IMPORTANT: For vite-react template, you MUST import ViteVisualEditor from "./components/ViteVisualEditor" (it exists in the template), do NOT create a new component'
470
+ // : ''
471
+ // }`;
472
+ // }
1137
473
  const result = await network.run(enhancedInput, {
1138
474
  state
1139
475
  });
@@ -1188,7 +524,7 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1188
524
  author: post.editedBy,
1189
525
  files: [],
1190
526
  props: {
1191
- role: AiAgentMessageRole.ASSISTANT,
527
+ role: AiAgentMessageRole.Assistant,
1192
528
  projectId: post.props.projectId,
1193
529
  template: modelConfig?.template || 'vite-react',
1194
530
  sendNotificationWithProjectId: true,
@@ -1198,7 +534,7 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1198
534
  files: result.state.data.files || [],
1199
535
  summary: result.state.data.summary || '',
1200
536
  canvasLayers: result.state.data.canvasLayers || [],
1201
- type: AiAgentMessageType.ERROR,
537
+ type: AiAgentMessageType.Error,
1202
538
  messageId: messageId,
1203
539
  isError: agentError
1204
540
  }
@@ -1213,7 +549,7 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1213
549
  author: post.editedBy,
1214
550
  files: [],
1215
551
  props: {
1216
- role: AiAgentMessageRole.ASSISTANT,
552
+ role: AiAgentMessageRole.Assistant,
1217
553
  projectId: post.props.projectId,
1218
554
  template: modelConfig?.template || 'vite-react',
1219
555
  sendNotificationWithProjectId: true,
@@ -1223,7 +559,7 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1223
559
  files: result.state.data.files || [],
1224
560
  summary: result.state.data.summary || '',
1225
561
  canvasLayers: result.state.data.canvasLayers || [],
1226
- type: AiAgentMessageType.RESULT,
562
+ type: AiAgentMessageType.Result,
1227
563
  messageId: messageId,
1228
564
  isError: agentError
1229
565
  }
@@ -1242,9 +578,9 @@ const generateAiCodeFunction = (inngest, container) => inngest.createFunction({
1242
578
  });
1243
579
  // Sandbox recreation function - recreates sandbox with existing files from fragment
1244
580
  const recreateSandboxUrlFunction = (inngest, container) => inngest.createFunction({
1245
- id: 'recreate-sandbox-url-function'
581
+ id: WorkflowNamespace.MESSENGER_PLATFORM_RECREATE_SANDBOX_FUNCTION
1246
582
  }, {
1247
- event: 'recreate-sandbox-url'
583
+ event: WorkflowNamespace.MESSENGER_PLATFORM_RECREATE_SANDBOX_EVENT
1248
584
  }, async ({
1249
585
  event,
1250
586
  step
@@ -1319,67 +655,4 @@ const recreateSandboxUrlFunction = (inngest, container) => inngest.createFunctio
1319
655
  newSandboxUrl: sandboxUrl,
1320
656
  newSandboxId: sandboxId
1321
657
  };
1322
- });
1323
- const regenerateAiCodeFunction = (inngest, container) => inngest.createFunction({
1324
- id: 'regenerate-ai-code-agent'
1325
- }, {
1326
- event: 'regenerate-ai-code'
1327
- }, async ({
1328
- event,
1329
- step
1330
- }) => {
1331
- console.log('=== REGENERATE AI CODE AGENT FUNCTION STARTED ===');
1332
- console.log('Event data:', JSON.stringify(event.data, null, 2));
1333
- const {
1334
- messageId,
1335
- modelConfig
1336
- } = event.data || {};
1337
- const postService = container.getNamed(SERVER_TYPES.PostService, TaggedType.MICROSERVICE);
1338
- const post = await postService.get(messageId);
1339
- if (!post) {
1340
- throw new Error('Post not found');
1341
- }
1342
- const {
1343
- sandboxId,
1344
- sandboxUrl
1345
- } = await step.run('create-sandbox-and-start-monitoring', async () => {
1346
- const selectedTemplateId = getTemplateId(modelConfig);
1347
- const sandbox = await Sandbox.create(selectedTemplateId, {
1348
- apiKey,
1349
- domain,
1350
- timeoutMs: 60_000 * 20
1351
- });
1352
- const sandboxUrl = `https://3000-${sandbox.sandboxId}.yarntra.ai`;
1353
- // Start error monitoring immediately after sandbox creation
1354
- // const container = await initializeContainer();
1355
- // const sandboxErrorService = container.get<ISandboxErrorService>(SERVER_TYPES.SandboxErrorService);
1356
- // console.log(`Starting immediate error monitoring for sandbox ${sandbox.sandboxId}`);
1357
- // await sandboxErrorService.startErrorMonitoring(post.props.projectId, sandbox.sandboxId, sandboxUrl,messageId);
1358
- return {
1359
- sandboxId: sandbox.sandboxId,
1360
- sandboxUrl
1361
- };
1362
- });
1363
- // Save to database using handler
1364
- const messageData = await step.run('save-ai-code-result', async () => {
1365
- return await postService.update(messageId, {
1366
- props: {
1367
- ...post.props,
1368
- sendNotificationWithProjectId: false,
1369
- fragment: {
1370
- sandboxUrl: sandboxUrl
1371
- // files: result.state.data.files || [],
1372
- }
1373
- }
1374
- });
1375
- });
1376
- // Publish subscription update for real-time client updates
1377
- await step.run('publish-subscription-ai-code-result', async () => {
1378
- const pubsub = container.get('PubSub');
1379
- console.log('=== Publish to subscription Post Data:', JSON.stringify(messageData, null, 2));
1380
- pubsub.publish(`POST_CREATED.${post.props.projectId}`, messageData);
1381
- });
1382
- // Error monitoring was already started immediately after sandbox creation
1383
- // No need to start it again here
1384
- return messageData;
1385
- });export{codeAgentFunction,createChannelWithProjectId,generateAIResponseWithSandbox,generateAiCodeFunction,recreateSandboxUrlFunction,regenerateAiCodeFunction,sendMessageHandler};//# sourceMappingURL=functions.js.map
658
+ });export{createChannelWithProjectId,generateAiCodeFunction,recreateSandboxUrlFunction,sendMessageHandler};//# sourceMappingURL=functions.js.map