@zodic/shared 0.0.148 → 0.0.150

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/app/api/index.ts CHANGED
@@ -28,7 +28,70 @@ const deepseek = (env: BackendBindings) =>
28
28
  baseURL: 'https://api.deepseek.com/v1',
29
29
  });
30
30
 
31
+ const together = (env: BackendBindings) =>
32
+ new OpenAI({
33
+ apiKey: env.TOGETHER_API_KEY,
34
+ baseURL: 'https://api.together.xyz/v1',
35
+ });
36
+
31
37
  export const Api = (env: BackendBindings) => ({
38
+ callTogether: {
39
+ single: async (
40
+ messages: ChatMessages,
41
+ { model = 'deepseek-ai/DeepSeek-V3', options = {} }: DeepSeekOptions
42
+ ): Promise<string> => {
43
+ try {
44
+ const response = await together(env).chat.completions.create({
45
+ model,
46
+ messages,
47
+ ...options,
48
+ });
49
+
50
+ if (response.choices[0].message.content) {
51
+ return response.choices[0].message.content.trim();
52
+ } else {
53
+ throw new Error('Content is null');
54
+ }
55
+ } catch (err: any) {
56
+ console.error('Error calling DeepSeek API:', err.message);
57
+ throw err;
58
+ }
59
+ },
60
+
61
+ // batch: async (
62
+ // batchItems: DeepSeekBatchInputItem[]
63
+ // ): Promise<DeepSeekBatchResponse> => {
64
+ // console.log('Preparing to send DeepSeek batch request.');
65
+
66
+ // try {
67
+ // const responses: DeepSeekBatchResponse = [];
68
+
69
+ // for (const item of batchItems) {
70
+ // const { messages, options } = item;
71
+ // const response = await deepseek(env).chat.completions.create({
72
+ // model: options?.model || 'deepseek-v3',
73
+ // messages,
74
+ // ...options,
75
+ // });
76
+
77
+ // if (response.choices[0].message.content) {
78
+ // responses.push({
79
+ // input: item,
80
+ // output: response.choices[0].message.content.trim(),
81
+ // });
82
+ // } else {
83
+ // console.error('Content is null');
84
+ // }
85
+ // }
86
+
87
+ // console.log('Batch processing completed successfully.');
88
+ // return responses;
89
+ // } catch (error) {
90
+ // console.error('Error in callDeepSeekBatch:', error);
91
+ // throw error;
92
+ // }
93
+ // },
94
+ },
32
95
  callDeepSeek: {
33
96
  single: async (
34
97
  messages: ChatMessages,
@@ -77,7 +77,7 @@ export class ConceptService {
77
77
  // ✅ Call ChatGPT API
78
78
  const response = await this.context
79
79
  .api()
80
- .callChatGPT.single(messages, {});
80
+ .callTogether.single(messages, {});
81
81
  if (!response) {
82
82
  throw new Error(`❌ AI returned an empty response`);
83
83
  }
@@ -155,34 +155,38 @@ export class ConceptService {
155
155
  poemPT: string[];
156
156
  } {
157
157
  console.log('📌 Parsing basic info response from ChatGPT:', response);
158
-
158
+
159
159
  const enMatch = response.match(
160
160
  /EN:\s*•\s*Name:\s*(.+?)\s*•\s*Description:\s*([\s\S]+?)\s*•\s*Poetic Passage:\s*([\s\S]+?)\s*(?=PT:|$)/
161
161
  );
162
162
  const ptMatch = response.match(
163
163
  /PT:\s*•\s*Nome:\s*(.+?)\s*•\s*Descrição:\s*([\s\S]+?)\s*•\s*Passagem Poética:\s*([\s\S]+)/
164
164
  );
165
-
165
+
166
166
  if (!enMatch || !ptMatch) {
167
167
  console.error('❌ Invalid basic info response format:', response);
168
168
  throw new Error('Invalid basic info response format');
169
169
  }
170
-
171
- const nameEN = enMatch[1].trim();
172
- const descriptionEN = enMatch[2].trim();
170
+
171
+ // Function to clean text (removes leading/trailing spaces & unwanted "*")
172
+ const cleanText = (text: string) => text.trim().replace(/\*/g, '');
173
+
174
+ // ✅ Parse and clean extracted content
175
+ const nameEN = cleanText(enMatch[1]);
176
+ const descriptionEN = cleanText(enMatch[2]);
173
177
  const poemEN = enMatch[3]
174
178
  .trim()
175
179
  .split(/\n+/)
176
- .map((line) => line.trim()); // ✅ Split into array
177
-
178
- const namePT = ptMatch[1].trim();
179
- const descriptionPT = ptMatch[2].trim();
180
+ .map((line) => cleanText(line)); // ✅ Split into array & clean lines
181
+
182
+ const namePT = cleanText(ptMatch[1]);
183
+ const descriptionPT = cleanText(ptMatch[2]);
180
184
  const poemPT = ptMatch[3]
181
185
  .trim()
182
186
  .split(/\n+/)
183
- .map((line) => line.trim()); // ✅ Split into array
184
-
185
- console.log('✅ Successfully parsed basic info:', {
187
+ .map((line) => cleanText(line)); // ✅ Split into array & clean lines
188
+
189
+ console.log('✅ Successfully parsed and cleaned basic info:', {
186
190
  nameEN,
187
191
  descriptionEN,
188
192
  poemEN,
@@ -190,7 +194,7 @@ export class ConceptService {
190
194
  descriptionPT,
191
195
  poemPT,
192
196
  });
193
-
197
+
194
198
  return { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT };
195
199
  }
196
200
 
@@ -239,7 +243,7 @@ export class ConceptService {
239
243
  });
240
244
 
241
245
  // ✅ Call ChatGPT API
242
- const response = await this.context.api().callChatGPT.single(messages, {});
246
+ const response = await this.context.api().callTogether.single(messages, {});
243
247
  if (!response) {
244
248
  throw new Error(
245
249
  `❌ Failed to generate Leonardo prompt for concept: ${conceptSlug}`
@@ -327,7 +331,7 @@ export class ConceptService {
327
331
  // ✅ Call ChatGPT API
328
332
  const response = await this.context
329
333
  .api()
330
- .callChatGPT.single(messages, {});
334
+ .callTogether.single(messages, {});
331
335
  if (!response) {
332
336
  throw new Error(`❌ AI returned an empty response`);
333
337
  }
@@ -388,19 +392,16 @@ export class ConceptService {
388
392
  structuredContentEN: StructuredConceptContent;
389
393
  structuredContentPT: StructuredConceptContent;
390
394
  } {
391
- console.log(
392
- '📌 Parsing structured content from ChatGPT response:',
393
- response
394
- );
395
-
396
- const sections = [
395
+ console.log('📌 Parsing structured content from ChatGPT response:', response);
396
+
397
+ const sectionsEN = [
397
398
  'Core Identity',
398
399
  'Strengths and Challenges',
399
400
  'Path to Fulfillment',
400
401
  'Emotional Depth',
401
402
  'Vision and Aspirations',
402
403
  ];
403
-
404
+
404
405
  const sectionsPT = [
405
406
  'Identidade Essencial',
406
407
  'Forças e Desafios',
@@ -408,39 +409,49 @@ export class ConceptService {
408
409
  'Profundidade Emocional',
409
410
  'Visão e Aspirações',
410
411
  ];
411
-
412
+
412
413
  // ✅ Match English and Portuguese content separately
413
414
  const enMatches = response.match(/EN:\s*([\s\S]+?)\s*PT:/);
414
415
  const ptMatches = response.match(/PT:\s*([\s\S]+)/);
415
-
416
+
416
417
  if (!enMatches || !ptMatches) {
418
+ console.error('❌ Missing English or Portuguese content in response.');
417
419
  throw new Error('❌ Missing English or Portuguese content in response.');
418
420
  }
419
-
421
+
420
422
  const enContent = enMatches[1].trim();
421
423
  const ptContent = ptMatches[1].trim();
422
-
424
+
425
+ // ✅ Function to clean AI artifacts (removes * and trims text)
426
+ function cleanText(text: string): string {
427
+ return text.replace(/\*/g, '').trim();
428
+ }
429
+
430
+ // ✅ Function to extract structured sections from text
423
431
  function extractSections(text: string, sectionTitles: string[]) {
424
432
  return sectionTitles.map((title) => {
425
- const regex = new RegExp(`${title}:\\s*([\\s\\S]+?)(?=\\n\\d|$)`);
433
+ // ✅ Improved regex: Ensures section detection even with different AI formatting
434
+ const regex = new RegExp(`${title}:\\s*([\\s\\S]+?)(?=\\n\\d|\\n[A-Z]|$)`);
426
435
  const match = text.match(regex);
427
-
436
+
428
437
  if (!match) {
438
+ console.warn(`⚠️ Missing section: ${title}`);
429
439
  return { type: 'section', title, content: ['❌ Section Missing'] };
430
440
  }
431
-
432
- // ✅ Split content into paragraphs
441
+
442
+ // ✅ Split content into paragraphs and clean them
433
443
  const paragraphs = match[1]
434
444
  .trim()
435
- .split(/\n\n+/)
436
- .map((p) => p.trim());
437
-
445
+ .split(/\n{2,}/) // Handles cases where paragraphs are separated by multiple new lines
446
+ .map((p) => cleanText(p));
447
+
438
448
  return { type: 'section', title, content: paragraphs };
439
449
  });
440
450
  }
441
-
451
+
452
+ // ✅ Return parsed and cleaned structured content
442
453
  return {
443
- structuredContentEN: extractSections(enContent, sections),
454
+ structuredContentEN: extractSections(enContent, sectionsEN),
444
455
  structuredContentPT: extractSections(ptContent, sectionsPT),
445
456
  };
446
457
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.148",
3
+ "version": "0.0.150",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {