@zodic/shared 0.0.251 → 0.0.253

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.
@@ -2012,22 +2012,30 @@ export class ConceptService {
2012
2012
  }
2013
2013
 
2014
2014
  async generateAstroReportContent(
2015
- params: AstroReportParams | { entityType: string; name: string; override?: boolean },
2015
+ params:
2016
+ | AstroReportParams
2017
+ | { entityType: string; name: string; override?: boolean },
2016
2018
  override: boolean = false
2017
2019
  ): Promise<void> {
2018
- console.log(`🚀 Generating content for ${JSON.stringify(params)}, override: ${override}`);
2020
+ console.log(
2021
+ `🚀 Generating content for ${JSON.stringify(
2022
+ params
2023
+ )}, override: ${override}`
2024
+ );
2019
2025
 
2020
2026
  const db = drizzle(this.context.env.DB);
2021
2027
  let table, whereClause;
2022
2028
 
2023
2029
  let report: AstroReportRow | DescriptionTemplateRow;
2024
- const isReport = "reportType" in params;
2030
+ const isReport = 'reportType' in params;
2025
2031
 
2026
2032
  if (isReport) {
2027
2033
  // Handle existing report types (sign, house, signInHouse, aspect, feature)
2028
2034
  switch (params.reportType) {
2029
- case "sign":
2030
- console.log(`🗂️ Handling sign report: type=${params.type}, pointName=${params.pointName}, sign=${params.sign}`);
2035
+ case 'sign':
2036
+ console.log(
2037
+ `🗂️ Handling sign report: type=${params.type}, pointName=${params.pointName}, sign=${params.sign}`
2038
+ );
2031
2039
  table = astroReports;
2032
2040
  whereClause = and(
2033
2041
  eq(astroReports.name, params.pointName),
@@ -2035,8 +2043,10 @@ export class ConceptService {
2035
2043
  isNull(astroReports.house)
2036
2044
  );
2037
2045
  break;
2038
- case "house":
2039
- console.log(`🗂️ Handling house report: type=${params.type}, pointName=${params.pointName}, house=${params.house}`);
2046
+ case 'house':
2047
+ console.log(
2048
+ `🗂️ Handling house report: type=${params.type}, pointName=${params.pointName}, house=${params.house}`
2049
+ );
2040
2050
  table = astroReports;
2041
2051
  whereClause = and(
2042
2052
  eq(astroReports.name, params.pointName),
@@ -2044,16 +2054,20 @@ export class ConceptService {
2044
2054
  isNull(astroReports.sign)
2045
2055
  );
2046
2056
  break;
2047
- case "signInHouse":
2048
- console.log(`🗂️ Handling signInHouse report: sign=${params.sign}, houseNumber=${params.houseNumber}`);
2057
+ case 'signInHouse':
2058
+ console.log(
2059
+ `🗂️ Handling signInHouse report: sign=${params.sign}, houseNumber=${params.houseNumber}`
2060
+ );
2049
2061
  table = houseReports;
2050
2062
  whereClause = and(
2051
2063
  eq(houseReports.sign, params.sign),
2052
2064
  eq(houseReports.house, params.houseNumber)
2053
2065
  );
2054
2066
  break;
2055
- case "aspect":
2056
- console.log(`🗂️ Handling aspect report: aspectingPlanet=${params.aspectingPlanet}, aspectedPlanet=${params.aspectedPlanet}, aspectingType=${params.aspectingType}`);
2067
+ case 'aspect':
2068
+ console.log(
2069
+ `🗂️ Handling aspect report: aspectingPlanet=${params.aspectingPlanet}, aspectedPlanet=${params.aspectedPlanet}, aspectingType=${params.aspectingType}`
2070
+ );
2057
2071
  table = aspectReports;
2058
2072
  whereClause = and(
2059
2073
  eq(aspectReports.aspectingPlanet, params.aspectingPlanet),
@@ -2061,29 +2075,46 @@ export class ConceptService {
2061
2075
  eq(aspectReports.aspect, params.aspectingType)
2062
2076
  );
2063
2077
  break;
2064
- case "feature":
2065
- console.log(`🗂️ Handling feature report: featureType=${params.featureType}, ${JSON.stringify(params)}`);
2078
+ case 'feature':
2079
+ console.log(
2080
+ `🗂️ Handling feature report: featureType=${
2081
+ params.featureType
2082
+ }, ${JSON.stringify(params)}`
2083
+ );
2066
2084
  table = astroFeatureReports;
2067
2085
  let nameValue: string;
2068
- if (params.featureType === "element") {
2069
- if (!("subtype" in params)) throw new Error("Missing subtype for element feature report");
2086
+ if (params.featureType === 'element') {
2087
+ if (!('subtype' in params))
2088
+ throw new Error('Missing subtype for element feature report');
2070
2089
  switch (params.subtype) {
2071
- case "balanced":
2072
- nameValue = "balanced";
2090
+ case 'balanced':
2091
+ nameValue = 'balanced';
2073
2092
  break;
2074
- case "pure":
2075
- if (!("dominantElement" in params)) throw new Error("Missing dominantElement for pure element report");
2093
+ case 'pure':
2094
+ if (!('dominantElement' in params))
2095
+ throw new Error(
2096
+ 'Missing dominantElement for pure element report'
2097
+ );
2076
2098
  nameValue = params.dominantElement;
2077
2099
  break;
2078
- case "preponderant_lacking":
2079
- if (!("dominantElement" in params) || !("lackingElement" in params)) throw new Error("Missing dominantElement or lackingElement for preponderant_lacking element report");
2100
+ case 'preponderant_lacking':
2101
+ if (
2102
+ !('dominantElement' in params) ||
2103
+ !('lackingElement' in params)
2104
+ )
2105
+ throw new Error(
2106
+ 'Missing dominantElement or lackingElement for preponderant_lacking element report'
2107
+ );
2080
2108
  nameValue = `${params.dominantElement}-${params.lackingElement}`;
2081
2109
  break;
2082
2110
  default:
2083
- throw new Error(`Unknown element subtype: ${(params as any).subtype}`);
2111
+ throw new Error(
2112
+ `Unknown element subtype: ${(params as any).subtype}`
2113
+ );
2084
2114
  }
2085
2115
  } else {
2086
- if (!("name" in params)) throw new Error("Missing name for non-element feature report");
2116
+ if (!('name' in params))
2117
+ throw new Error('Missing name for non-element feature report');
2087
2118
  nameValue = params.name;
2088
2119
  }
2089
2120
  whereClause = and(
@@ -2094,22 +2125,36 @@ export class ConceptService {
2094
2125
  default:
2095
2126
  throw new Error(`Unknown report type: ${(params as any).reportType}`);
2096
2127
  }
2097
- report = await db.select().from(table as any).where(whereClause).get() as AstroReportRow;
2128
+ report = (await db
2129
+ .select()
2130
+ .from(table as any)
2131
+ .where(whereClause)
2132
+ .get()) as AstroReportRow;
2098
2133
  } else {
2099
2134
  // Handle description templates
2100
- console.log(`🗂️ Handling description template: entityType=${params.entityType}, name=${params.name}`);
2135
+ console.log(
2136
+ `🗂️ Handling description template: entityType=${params.entityType}, name=${params.name}`
2137
+ );
2101
2138
  table = astroDescriptionTemplates;
2102
2139
  whereClause = and(
2103
2140
  eq(astroDescriptionTemplates.entityType, params.entityType),
2104
2141
  eq(astroDescriptionTemplates.name, params.name)
2105
2142
  );
2106
- report = await db.select().from(table as any).where(whereClause).get() as DescriptionTemplateRow;
2143
+ report = (await db
2144
+ .select()
2145
+ .from(table as any)
2146
+ .where(whereClause)
2147
+ .get()) as DescriptionTemplateRow;
2107
2148
  }
2108
2149
 
2109
2150
  const id = report.id;
2110
2151
  const hasContent = isReport
2111
- ? (report as AstroReportRow).enReport && (report as AstroReportRow).ptReport
2112
- : (report as DescriptionTemplateRow).enDescription && (report as DescriptionTemplateRow).ptDescription;
2152
+ ? (report as AstroReportRow).enReport &&
2153
+ (report as AstroReportRow).ptReport
2154
+ : (report as DescriptionTemplateRow).enDescription !==
2155
+ 'Pending generation' &&
2156
+ (report as DescriptionTemplateRow).ptDescription !==
2157
+ 'Pendente de geração';
2113
2158
 
2114
2159
  if (!override && hasContent) {
2115
2160
  console.log(`⚡ Content already exists for ${id}, skipping`);
@@ -2120,29 +2165,47 @@ export class ConceptService {
2120
2165
  const maxAttempts = 2;
2121
2166
 
2122
2167
  while (attempts < maxAttempts) {
2123
- let phase = "generation";
2168
+ let phase = 'generation';
2124
2169
  try {
2125
2170
  attempts++;
2126
- console.log(`🔄 Attempt ${attempts} to generate ${isReport ? "report" : "description"} content for ${id}...`);
2171
+ console.log(
2172
+ `🔄 Attempt ${attempts} to generate ${
2173
+ isReport ? 'report' : 'description'
2174
+ } content for ${id}...`
2175
+ );
2127
2176
 
2128
2177
  let messages: ChatMessages;
2129
2178
  if (isReport) {
2130
- messages = this.context.buildLLMMessages().generateAstroReportContent({ params: params as AstroReportParams });
2179
+ messages = this.context
2180
+ .buildLLMMessages()
2181
+ .generateAstroReportContent({
2182
+ params: params as AstroReportParams,
2183
+ });
2131
2184
  } else {
2132
2185
  messages = this.generateDescriptionMessages(params);
2133
2186
  }
2134
2187
 
2135
2188
  console.log(`📨 Sending messages to AI: ${JSON.stringify(messages)}`);
2136
- const response = await this.context.api().callTogether.single(messages, {});
2189
+ const response = await this.context
2190
+ .api()
2191
+ .callTogether.single(messages, {});
2137
2192
  if (!response) {
2138
2193
  throw new Error(`❌ AI returned an empty response for ${id}`);
2139
2194
  }
2140
2195
 
2141
- phase = "parsing";
2142
- console.log(`📝 Received AI response for ${id}: ${response.slice(0, 200)}${response.length > 200 ? "..." : ""}`);
2196
+ phase = 'parsing';
2197
+ console.log(
2198
+ `📝 Received AI response for ${id}: ${response.slice(0, 200)}${
2199
+ response.length > 200 ? '...' : ''
2200
+ }`
2201
+ );
2143
2202
 
2144
2203
  if (isReport) {
2145
- const { enReport, ptReport } = await this.parseAstrologicalReportContent((params as AstroReportParams).reportType, response);
2204
+ const { enReport, ptReport } =
2205
+ await this.parseAstrologicalReportContent(
2206
+ (params as AstroReportParams).reportType,
2207
+ response
2208
+ );
2146
2209
  console.log(`💾 Storing report content for ${id}`);
2147
2210
  await db
2148
2211
  .update(table as any)
@@ -2153,7 +2216,8 @@ export class ConceptService {
2153
2216
  .where(eq((table as any).id, id))
2154
2217
  .run();
2155
2218
  } else {
2156
- const { enDescription, ptDescription } = await this.parseDescriptionContent(response);
2219
+ const { enDescription, ptDescription } =
2220
+ await this.parseDescriptionContent(response);
2157
2221
  console.log(`💾 Storing description content for ${id}`);
2158
2222
  await db
2159
2223
  .update(table as any)
@@ -2165,12 +2229,19 @@ export class ConceptService {
2165
2229
  .run();
2166
2230
  }
2167
2231
 
2168
- console.log(`✅ ${isReport ? "Report" : "Description"} content stored for ${id}`);
2232
+ console.log(
2233
+ `✅ ${isReport ? 'Report' : 'Description'} content stored for ${id}`
2234
+ );
2169
2235
  return;
2170
2236
  } catch (error) {
2171
- console.error(`❌ Attempt ${attempts} failed at phase: ${phase} for ${id}`, (error as Error).message);
2237
+ console.error(
2238
+ `❌ Attempt ${attempts} failed at phase: ${phase} for ${id}`,
2239
+ (error as Error).message
2240
+ );
2172
2241
 
2173
- const failureKey = `failures:astro:${isReport ? (params as AstroReportParams).reportType : "description"}:${id}`;
2242
+ const failureKey = `failures:astro:${
2243
+ isReport ? (params as AstroReportParams).reportType : 'description'
2244
+ }:${id}`;
2174
2245
  await this.context.kvConceptFailuresStore().put(
2175
2246
  failureKey,
2176
2247
  JSON.stringify({
@@ -2183,11 +2254,17 @@ export class ConceptService {
2183
2254
  );
2184
2255
 
2185
2256
  if (attempts >= maxAttempts) {
2186
- console.error(`🚨 All ${maxAttempts} attempts failed at phase ${phase} for ${id}`);
2187
- throw new Error(`Failed to generate ${isReport ? "report" : "description"} for ${id} after ${maxAttempts} attempts`);
2257
+ console.error(
2258
+ `🚨 All ${maxAttempts} attempts failed at phase ${phase} for ${id}`
2259
+ );
2260
+ throw new Error(
2261
+ `Failed to generate ${
2262
+ isReport ? 'report' : 'description'
2263
+ } for ${id} after ${maxAttempts} attempts`
2264
+ );
2188
2265
  }
2189
2266
 
2190
- console.log("🔁 Retrying...");
2267
+ console.log('🔁 Retrying...');
2191
2268
  await new Promise((resolve) => setTimeout(resolve, 2000));
2192
2269
  }
2193
2270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.251",
3
+ "version": "0.0.253",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -170,7 +170,7 @@ export const astroPrompts = {
170
170
  `.trim();
171
171
 
172
172
  switch (params.featureType) {
173
- case "moon_phase": {
173
+ case 'moon_phase': {
174
174
  const formattedName = params.name
175
175
  .split('-')
176
176
  .map((word: string) => word.charAt(0).toUpperCase() + word.slice(1))
@@ -181,45 +181,58 @@ export const astroPrompts = {
181
181
  `.trim();
182
182
  }
183
183
 
184
- case "element": {
184
+ case 'element': {
185
185
  switch (params.subtype) {
186
- case "balanced":
186
+ case 'balanced':
187
187
  return `
188
188
  Make me an astrological report for a person with a balanced elemental distribution in their birth chart.
189
189
  ${baseFormat}
190
190
  `.trim();
191
- case "pure": {
192
- const dominant = params.dominantElement.charAt(0).toUpperCase() + params.dominantElement.slice(1);
191
+ case 'pure': {
192
+ const dominant =
193
+ params.dominantElement.charAt(0).toUpperCase() +
194
+ params.dominantElement.slice(1);
193
195
  return `
194
196
  Make me an astrological report for a person with a preponderance of the ${dominant} element in their birth chart.
195
197
  ${baseFormat}
196
198
  `.trim();
197
199
  }
198
- case "preponderant_lacking": {
199
- const dominant = params.dominantElement.charAt(0).toUpperCase() + params.dominantElement.slice(1);
200
- const lacking = params.lackingElement.charAt(0).toUpperCase() + params.lackingElement.slice(1);
200
+ case 'preponderant_lacking': {
201
+ const dominant =
202
+ params.dominantElement.charAt(0).toUpperCase() +
203
+ params.dominantElement.slice(1);
204
+ const lacking =
205
+ params.lackingElement.charAt(0).toUpperCase() +
206
+ params.lackingElement.slice(1);
201
207
  return `
202
208
  Make me an astrological report for a person with a preponderance of the ${dominant} element and a lack of the ${lacking} element in their birth chart.
203
209
  ${baseFormat}
204
210
  `.trim();
205
211
  }
206
212
  default:
207
- throw new Error(`Unknown element subtype: ${(params as any).subtype}`);
213
+ throw new Error(
214
+ `Unknown element subtype: ${(params as any).subtype}`
215
+ );
208
216
  }
209
217
  }
210
218
 
211
- case "mode": {
212
- const formattedName = params.name.charAt(0).toUpperCase() + params.name.slice(1);
219
+ case 'mode': {
220
+ const formattedName =
221
+ params.name.charAt(0).toUpperCase() + params.name.slice(1);
213
222
  return `
214
223
  Make me an astrological report for a person with a preponderance of the ${formattedName} mode in their birth chart.
215
224
  ${baseFormat}
216
225
  `.trim();
217
226
  }
218
227
 
219
- case "hemisphere_east_west":
220
- case "hemisphere_north_south": {
221
- const direction = params.name.charAt(0).toUpperCase() + params.name.slice(1);
222
- const hemisphereType = params.featureType === "hemisphere_east_west" ? "East-West" : "North-South";
228
+ case 'hemisphere_east_west':
229
+ case 'hemisphere_north_south': {
230
+ const direction =
231
+ params.name.charAt(0).toUpperCase() + params.name.slice(1);
232
+ const hemisphereType =
233
+ params.featureType === 'hemisphere_east_west'
234
+ ? 'East-West'
235
+ : 'North-South';
223
236
  return `
224
237
  Make me an astrological report for a person with the ${direction}ern hemisphere emphasized in their birth chart, based on the ${hemisphereType} orientation.
225
238
  ${baseFormat}
@@ -231,9 +244,47 @@ export const astroPrompts = {
231
244
  }
232
245
  },
233
246
 
234
- makeIntroDescription: ({ entityType, name, isGeneric }: DescriptionParams): string => {
247
+ makeIntroDescription: ({
248
+ entityType,
249
+ name,
250
+ isGeneric,
251
+ }: DescriptionParams): string => {
252
+ // Format name for human-readable display (capitalize and handle special cases)
253
+ const formatName = (entityType: string, name: string): string => {
254
+ switch (entityType) {
255
+ case 'planet':
256
+ case 'key_point':
257
+ case 'karmic_point':
258
+ case 'arabic_part':
259
+ // Capitalize first letter and handle special cases (e.g., "pars_amoris" -> "Pars Amoris")
260
+ return name
261
+ .split('_')
262
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
263
+ .join(' ');
264
+ case 'house':
265
+ return `House ${name.replace('house_', '')}`; // e.g., "house_1" -> "House 1"
266
+ case 'aspect':
267
+ case 'mode':
268
+ case 'element':
269
+ case 'moon_phase':
270
+ return name
271
+ .split('_')
272
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
273
+ .join(' ');
274
+ case 'hemisphere_east_west':
275
+ case 'hemisphere_north_south':
276
+ return name
277
+ .split('_')
278
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
279
+ .join(' ');
280
+ default:
281
+ return name.charAt(0).toUpperCase() + name.slice(1);
282
+ }
283
+ };
284
+
285
+ const formattedName = formatName(entityType, name);
286
+
235
287
  const baseFormat = `
236
- Make me an introductory, explanatory description of 150 to 180 words about the astrological ${entityType}.
237
288
  The result must have an English version and a Portuguese version.
238
289
  The result format must be exactly like the following:
239
290
  -- EN
@@ -244,10 +295,29 @@ export const astroPrompts = {
244
295
 
245
296
  if (isGeneric) {
246
297
  return `
247
- ${baseFormat.replace("astrological", "astrological concept representing").replace("about the astrological", "about what the")}
298
+ Make me an introductory, explanatory description of 150 to 180 words about the astrological concept of the ${formattedName}.
299
+ ${baseFormat}
248
300
  `.trim();
249
301
  } else {
250
- return `${baseFormat} ${name ? `named ${name}.` : ""}`.trim();
302
+ switch (entityType) {
303
+ case 'planet':
304
+ case 'key_point':
305
+ case 'karmic_point':
306
+ case 'arabic_part':
307
+ return `
308
+ Make me an introductory, explanatory description of 150 to 180 words about what the astrological placement: ${formattedName}.
309
+ ${baseFormat}
310
+ `.trim();
311
+ case 'house':
312
+ return `
313
+ Make me an introductory, explanatory description of 150 to 180 words about the astrological placement: ${formattedName}.
314
+ ${baseFormat}
315
+ `.trim();
316
+ default:
317
+ throw new Error(
318
+ `Unknown entity type for specific description: ${entityType}`
319
+ );
320
+ }
251
321
  }
252
322
  },
253
323
  };