@solidstarters/solid-core 1.2.178 → 1.2.179

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.178",
3
+ "version": "1.2.179",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -95,7 +95,7 @@ export class AiInteractionController {
95
95
  @ApiBearerAuth("jwt")
96
96
  @Post('/trigger-mcp-client-job')
97
97
  async triggerMcpClientJob(@Body() dto: InvokeAiPromptDto, @ActiveUser() activeUser: ActiveUserData) {
98
- return this.service.triggerMcpClientJob(dto,activeUser.sub);
98
+ return this.service.triggerMcpClientJob(dto, activeUser.sub);
99
99
  }
100
100
 
101
101
  @ApiBearerAuth("jwt")
@@ -92,7 +92,7 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
92
92
  responseTimeMs: 0, // Updated after we receive the response
93
93
  metadata: '', // Updated in the tool
94
94
  isApplied: false, // Updated after we receive the response
95
- status: '' // Updated after we receive the response
95
+ status: 'pending' // Updated after we receive the response
96
96
  });
97
97
 
98
98
  const finalPrompt = `
@@ -148,7 +148,7 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
148
148
  throw new Error(errorsStr);
149
149
  }
150
150
  else {
151
- // let nestedResponse = this.cleanNestedResponse(aiResponse);
151
+ let nestedResponse = this.cleanNestedResponse(aiResponse);
152
152
 
153
153
  // const genAiInteraction = await this.aiInteractionService.create({
154
154
  // userId: aiInteraction.user.id,
@@ -166,14 +166,19 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
166
166
  // });
167
167
 
168
168
  // TODO: Update the previously created genAiInteraction record with the respective success fields and save to DB
169
+ const errorsStr = nestedResponse.status == "error" && nestedResponse.errors.join('\n ');
170
+
169
171
  await this.aiInteractionService.update(genAiInteraction.id, {
172
+ errorMessage: nestedResponse.status == "error" ? `${errorsStr}` : "",
173
+ // errorMessage:"",
170
174
  // contentType: aiResponse.content_type,
171
- errorMessage: '',
172
175
  // message: nestedResponse,
173
176
  modelUsed: aiResponse.model,
174
177
  responseTimeMs: aiResponse.duration_ms,
175
178
  isApplied: aiInteraction.isApplied,
176
- status: aiResponse.success ? 'succeeded' : 'failed'
179
+
180
+ // status: aiResponse.success ? 'succeeded' : 'failed'
181
+ status: aiResponse.success && nestedResponse.status == "success" ? 'succeeded' : 'failed'
177
182
  }, [], true);
178
183
 
179
184
  // If the human interaction was with isAutoApply=true, then we can go ahead and autoApply.
@@ -12331,7 +12331,9 @@
12331
12331
  "type": "field",
12332
12332
  "attrs": {
12333
12333
  "name": "metadata",
12334
- "height": "80vh"
12334
+ "height": "80vh",
12335
+ "viewWidget":"SolidAiInteractionMetadataFieldFormWidget"
12336
+
12335
12337
  }
12336
12338
  }
12337
12339
  ]
@@ -149,6 +149,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
149
149
  }
150
150
  catch (ex) {
151
151
  this.logger.warn(`Attempting to parse mcp client response assuming it is JSON, however it is not: ${parsedResponse}`);
152
+ raw.success = false
152
153
  }
153
154
  // Parse the response string into an object
154
155
  // const parsedResponse = JSON.parse(raw.response);
@@ -121,7 +121,7 @@ export class IngestMetadataService {
121
121
  ingestionInfo.collectionId = collectionId;
122
122
 
123
123
  // Delete and re-insert a document representing the full json...
124
- await this.deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo, fullPath, fileName)
124
+ // await this.deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo, fullPath, fileName)
125
125
 
126
126
  // Delete and re-insert a chunk representing the module.
127
127
  await this.deleteInsertRagChunkForModule(ingestionInfo, moduleMetadata);
@@ -129,11 +129,29 @@ export class IngestMetadataService {
129
129
  // Delete and re-insert chunks representing each model.
130
130
  for (const model of moduleMetadata.models) {
131
131
  await this.deleteInsertRagChunkForModel(ingestionInfo, enabledModule, model);
132
- for (const field of model.fields) {
133
- await this.deleteInsertRagChunkForField(ingestionInfo, enabledModule, model.singularName, field);
134
- }
132
+
133
+ // Disabling this for now...
134
+ // for (const field of model.fields) {
135
+ // await this.deleteInsertRagChunkForField(ingestionInfo, enabledModule, model.singularName, field);
136
+ // }
135
137
  }
136
138
 
139
+ // TODO: Delete and re-insert chunks representing roles
140
+
141
+ // TODO: Delete and re-insert chunks representing menus
142
+
143
+ // TODO: Delete and re-insert chunks representing actions
144
+
145
+ // TODO: Delete and re-insert chunks representing list views
146
+
147
+ // TODO: Delete and re-insert chunks representing kanban views
148
+
149
+ // TODO: Delete and re-insert chunks representing form views
150
+
151
+ // TODO: Delete and re-insert chunks representing security rules
152
+
153
+ // TODO: Delete and re-insert chunks representing scheduled jobs
154
+
137
155
  // Save ingestion info to disk...
138
156
  fs.writeFileSync(enabledModulIngestionInfoFullPath, JSON.stringify({ ...ingestionInfo }, null, 2), 'utf8');
139
157
  }
@@ -242,7 +260,7 @@ export class IngestMetadataService {
242
260
  description: m?.description ?? null,
243
261
 
244
262
  // Include field names to detect field-level changes at module granularity - maybe remove this later?
245
- fields: Array.isArray(m?.fields) ? m.fields.map((f: any) => f?.name ?? null) : [],
263
+ // fields: Array.isArray(m?.fields) ? m.fields.map((f: any) => f?.name ?? null) : [],
246
264
  })),
247
265
  });
248
266
 
@@ -270,6 +288,7 @@ Usage: Use this chunk to choose the correct model/field chunks for code generati
270
288
 
271
289
  // metadata has to be concise and queryable
272
290
  const metadata = {
291
+ collectionName: `${moduleName}-rag-collection`,
273
292
  kind: 'solidx-metadata',
274
293
  type: 'module',
275
294
  moduleName,
@@ -288,7 +307,8 @@ Usage: Use this chunk to choose the correct model/field chunks for code generati
288
307
  }
289
308
 
290
309
  const r = await this.ragClient.documents.create({
291
- raw_text: text,
310
+ chunks: [text],
311
+ // raw_text: text,
292
312
  metadata: metadata,
293
313
  collectionIds: [ingestionInfo.collectionId],
294
314
  });
@@ -364,10 +384,15 @@ Fields (${fields.length}) [name:type|flags]:
364
384
  ${fieldSummaryLines.join('\n')}
365
385
 
366
386
  Usage: Use this chunk to generate DTOs, subscribers, custom service methods, and CRUD handlers for ${modelName}.
367
- For exact constraints (enum/min/max/regex/default), consult the individual field chunks.`;
387
+
388
+ Full model metadata json:
389
+ ${JSON.stringify(model)}
390
+
391
+ `;
368
392
 
369
393
  // 4) Metadata (concise & queryable)
370
394
  const metadata = {
395
+ collectionName: `${moduleName}-rag-collection`,
371
396
  kind: 'solidx-metadata',
372
397
  type: 'model',
373
398
  moduleName,
@@ -392,7 +417,7 @@ For exact constraints (enum/min/max/regex/default), consult the individual field
392
417
 
393
418
  // 6) Create new document (R2R auto-generates the ID)
394
419
  const r = await this.ragClient.documents.create({
395
- raw_text: text,
420
+ chunks: [text],
396
421
  metadata,
397
422
  collectionIds: [ingestionInfo.collectionId],
398
423
  });
@@ -661,6 +686,7 @@ For exact constraints (enum/min/max/regex/default), consult the individual field
661
686
 
662
687
  // 4) Build text + metadata tailored to FieldMetadata
663
688
  const { text, metadata } = this._buildFieldTextAndMetadata(moduleName, modelName, field);
689
+
664
690
  // also keep the hash in metadata for audit/debug
665
691
  (metadata as any).schemaHash = schemaHash;
666
692
 
@@ -566,10 +566,11 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
566
566
  // TODO Move this logic to field crud managers i.e add a parse method to the field crud manager interface
567
567
  switch (fieldType) {
568
568
  case SolidFieldType.relation: {
569
- return await this.populateDtoForRelations(fieldMetadata, record, key, dtoRecord);
569
+ return await this.populateDtoForRelations(fieldMetadata, record, key, dtoRecord);
570
570
  }
571
571
  case SolidFieldType.date:
572
- case SolidFieldType.datetime: return this.populateDtoForDate(record, key, fieldMetadata, dtoRecord);
572
+ case SolidFieldType.datetime:
573
+ return this.populateDtoForDate(record, key, fieldMetadata, dtoRecord);
573
574
  case SolidFieldType.int:
574
575
  case SolidFieldType.bigint:
575
576
  case SolidFieldType.decimal:
@@ -579,16 +580,24 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
579
580
  case SolidFieldType.selectionStatic:
580
581
  case SolidFieldType.selectionDynamic:
581
582
  return this.populateDtoForSelectionValues(dtoRecord, fieldMetadata, record, key);
582
- default:
583
+ case SolidFieldType.email:
584
+ case SolidFieldType.shortText:
585
+ case SolidFieldType.longtext:
586
+ case SolidFieldType.richText: {
587
+ dtoRecord[fieldMetadata.name] = record[key] ? String(record[key]).trim() : null; // Trim text fields and set to null if empty
588
+ return dtoRecord;
589
+ }
590
+ default: {
583
591
  dtoRecord[fieldMetadata.name] = record[key];
584
592
  return dtoRecord;
593
+ }
585
594
  }
586
595
  }
587
596
 
588
597
  private populateDtoForSelectionValues(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
589
598
  const rawValue = record[key];
590
599
 
591
- if (rawValue == null) {
600
+ if (rawValue == null || rawValue === '' || (typeof rawValue === 'string' && rawValue.trim() === '')) {
592
601
  dtoRecord[fieldMetadata.name] = null;
593
602
  return dtoRecord;
594
603
  }
@@ -611,16 +620,28 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
611
620
 
612
621
 
613
622
  private populateDtoForBoolean(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
614
- const booleanValue = Boolean(record[key]);
615
- if (typeof booleanValue !== 'boolean') {
616
- throw new Error(`Invalid boolean value for cell ${key} with value ${record[key]}`);
623
+ const cellValue = record[key];
624
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
625
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
626
+ return dtoRecord;
627
+ }
628
+
629
+ // If the cell contains values other than 'true', '1', 'yes', 'false', '0', 'no', throw an error
630
+ const booleanValue = (String(cellValue).toLowerCase() === 'true' || String(cellValue) === '1' || String(cellValue).toLowerCase() === 'yes') ? true : (String(cellValue).toLowerCase() === 'false' || String(cellValue) === '0' || String(cellValue).toLowerCase() === 'no') ? false : null;
631
+ if (booleanValue === null) {
632
+ throw new Error(`Invalid boolean value for cell ${key} with value ${cellValue}`);
617
633
  }
618
634
  dtoRecord[fieldMetadata.name] = booleanValue;
619
635
  return dtoRecord;
620
636
  }
621
637
 
622
638
  private populateDtoForNumber(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
623
- const numberValue = Number(record[key]);
639
+ const cellValue = record[key];
640
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
641
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
642
+ return dtoRecord;
643
+ }
644
+ const numberValue = Number(cellValue);
624
645
  if (isNaN(numberValue)) {
625
646
  throw new Error(`Invalid number value for cell ${key} with value ${record[key]}`);
626
647
  }
@@ -630,7 +651,13 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
630
651
 
631
652
  private populateDtoForDate(record: Record<string, any>, key: string, fieldMetadata: FieldMetadata, dtoRecord: Record<string, any>) {
632
653
  {
633
- const dateValue = new Date(record[key]);
654
+ // Get the cell value
655
+ const cellValue = record[key];
656
+ if (!cellValue) { //If cell is a falsy value (empty)
657
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
658
+ return dtoRecord;
659
+ }
660
+ const dateValue = new Date(cellValue);
634
661
  if (isNaN(dateValue.getTime())) {
635
662
  throw new Error(`Invalid date value for cell ${key} with value ${record[key]}`);
636
663
  }