@zodic/shared 0.0.239 → 0.0.241
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/services/ConceptService.ts +259 -3
- package/db/migrations/0001_mysterious_mystique.sql +47 -0
- package/db/migrations/meta/0001_snapshot.json +2200 -0
- package/db/migrations/meta/_journal.json +7 -0
- package/db/schema.ts +45 -41
- package/package.json +1 -1
- package/types/scopes/generic.ts +40 -0
- package/types/scopes/legacy.ts +60 -54
- package/utils/astroPrompts/index.ts +64 -6
- package/utils/buildMessages.ts +59 -1
- package/utils/index.ts +8 -0
|
@@ -7,9 +7,20 @@ import { drizzle } from 'drizzle-orm/d1';
|
|
|
7
7
|
import { inject, injectable } from 'inversify';
|
|
8
8
|
import 'reflect-metadata';
|
|
9
9
|
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
-
import { schema } from '../..';
|
|
11
|
-
import {
|
|
12
|
-
|
|
10
|
+
import { cleanText, schema } from '../..';
|
|
11
|
+
import {
|
|
12
|
+
aspectReports,
|
|
13
|
+
astroReports,
|
|
14
|
+
conceptsData,
|
|
15
|
+
houseReports,
|
|
16
|
+
} from '../../db/schema';
|
|
17
|
+
import {
|
|
18
|
+
AstrologicalReport,
|
|
19
|
+
AstroReportParams,
|
|
20
|
+
Concept,
|
|
21
|
+
ControlNetConfig,
|
|
22
|
+
Languages,
|
|
23
|
+
} from '../../types';
|
|
13
24
|
import {
|
|
14
25
|
KVConcept,
|
|
15
26
|
sizes,
|
|
@@ -1993,4 +2004,249 @@ export class ConceptService {
|
|
|
1993
2004
|
|
|
1994
2005
|
console.log(`✅ Stored duplicate keys for ${conceptSlug} in cache.`);
|
|
1995
2006
|
}
|
|
2007
|
+
|
|
2008
|
+
// ? ASTRO PROCESSING
|
|
2009
|
+
async generateAstroReportContent(
|
|
2010
|
+
params: AstroReportParams,
|
|
2011
|
+
override: boolean = false
|
|
2012
|
+
): Promise<void> {
|
|
2013
|
+
console.log(
|
|
2014
|
+
`🚀 Generating report content for ${JSON.stringify(
|
|
2015
|
+
params
|
|
2016
|
+
)}, override: ${override}`
|
|
2017
|
+
);
|
|
2018
|
+
|
|
2019
|
+
const db = drizzle(this.context.env.DB);
|
|
2020
|
+
let table, idField, whereClause;
|
|
2021
|
+
|
|
2022
|
+
// Determine table and ID
|
|
2023
|
+
switch (params.reportType) {
|
|
2024
|
+
case 'sign':
|
|
2025
|
+
case 'house':
|
|
2026
|
+
table = astroReports;
|
|
2027
|
+
idField =
|
|
2028
|
+
params.reportType === 'sign'
|
|
2029
|
+
? sql`SELECT id FROM astro_reports WHERE name = ${params.pointName} AND sign = ${params.sign} AND house IS NULL`
|
|
2030
|
+
: sql`SELECT id FROM astro_reports WHERE name = ${params.pointName} AND house = ${params.house} AND sign IS NULL`;
|
|
2031
|
+
break;
|
|
2032
|
+
case 'signInHouse':
|
|
2033
|
+
table = houseReports;
|
|
2034
|
+
idField = sql`SELECT id FROM house_reports WHERE sign = ${params.sign} AND house = ${params.houseNumber}`;
|
|
2035
|
+
break;
|
|
2036
|
+
case 'aspect':
|
|
2037
|
+
table = aspectReports;
|
|
2038
|
+
idField = sql`SELECT id FROM aspect_reports WHERE aspecting_planet = ${params.aspectingPlanet} AND aspected_planet = ${params.aspectedPlanet} AND aspect = ${params.aspectingType}`;
|
|
2039
|
+
break;
|
|
2040
|
+
default:
|
|
2041
|
+
throw new Error(`Unknown report type: ${(params as any).reportType}`);
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
const report = await db
|
|
2045
|
+
.select()
|
|
2046
|
+
.from(table)
|
|
2047
|
+
.where(sql`${idField}`)
|
|
2048
|
+
.get();
|
|
2049
|
+
if (!report) {
|
|
2050
|
+
throw new Error(`❌ No report found for ${JSON.stringify(params)}`);
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
const id = report.id;
|
|
2054
|
+
const hasContent = report.enReport && report.ptReport;
|
|
2055
|
+
|
|
2056
|
+
if (!override && hasContent) {
|
|
2057
|
+
console.log(`⚡ Content already exists for ${id}, skipping`);
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
let attempts = 0;
|
|
2062
|
+
const maxAttempts = 2;
|
|
2063
|
+
|
|
2064
|
+
while (attempts < maxAttempts) {
|
|
2065
|
+
let phase = 'generation';
|
|
2066
|
+
try {
|
|
2067
|
+
attempts++;
|
|
2068
|
+
console.log(`🔄 Attempt ${attempts} to generate report content...`);
|
|
2069
|
+
|
|
2070
|
+
// Use buildLLMMessages().generateAstroReportContent
|
|
2071
|
+
const messages = this.context
|
|
2072
|
+
.buildLLMMessages()
|
|
2073
|
+
.generateAstroReportContent({ params });
|
|
2074
|
+
|
|
2075
|
+
const response = await this.context
|
|
2076
|
+
.api()
|
|
2077
|
+
.callTogether.single(messages, {});
|
|
2078
|
+
if (!response) {
|
|
2079
|
+
throw new Error(`❌ AI returned an empty response`);
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
phase = 'parsing';
|
|
2083
|
+
|
|
2084
|
+
const { enReport, ptReport } =
|
|
2085
|
+
await this.parseAstrologicalReportContent(
|
|
2086
|
+
params.reportType,
|
|
2087
|
+
response
|
|
2088
|
+
);
|
|
2089
|
+
|
|
2090
|
+
console.log(`💾 Storing report content for ${id}`);
|
|
2091
|
+
await db
|
|
2092
|
+
.update(table)
|
|
2093
|
+
.set({
|
|
2094
|
+
enReport: JSON.stringify(enReport),
|
|
2095
|
+
ptReport: JSON.stringify(ptReport),
|
|
2096
|
+
})
|
|
2097
|
+
.where(eq(table.id, id))
|
|
2098
|
+
.run();
|
|
2099
|
+
|
|
2100
|
+
console.log(`✅ Report content stored for ${id}`);
|
|
2101
|
+
return;
|
|
2102
|
+
} catch (error) {
|
|
2103
|
+
console.error(
|
|
2104
|
+
`❌ Attempt ${attempts} failed at phase: ${phase}`,
|
|
2105
|
+
(error as Error).message
|
|
2106
|
+
);
|
|
2107
|
+
|
|
2108
|
+
const failureKey = `failures:astro:${params.reportType}:${id}`;
|
|
2109
|
+
await this.context.kvConceptFailuresStore().put(
|
|
2110
|
+
failureKey,
|
|
2111
|
+
JSON.stringify({
|
|
2112
|
+
error: (error as Error).message,
|
|
2113
|
+
attempt: attempts,
|
|
2114
|
+
phase,
|
|
2115
|
+
params,
|
|
2116
|
+
timestamp: new Date().toISOString(),
|
|
2117
|
+
})
|
|
2118
|
+
);
|
|
2119
|
+
|
|
2120
|
+
if (attempts >= maxAttempts) {
|
|
2121
|
+
console.error(
|
|
2122
|
+
`🚨 All ${maxAttempts} attempts failed at phase ${phase}`
|
|
2123
|
+
);
|
|
2124
|
+
throw new Error(
|
|
2125
|
+
`Failed to generate content after ${maxAttempts} attempts`
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
console.log('🔁 Retrying...');
|
|
2130
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
async parseAstrologicalReportContent(
|
|
2136
|
+
reportType: AstroReportParams['reportType'],
|
|
2137
|
+
response: string
|
|
2138
|
+
): Promise<{
|
|
2139
|
+
enReport: AstrologicalReport['sections'];
|
|
2140
|
+
ptReport: AstrologicalReport['sections'];
|
|
2141
|
+
}> {
|
|
2142
|
+
console.log(`📌 [START] Parsing report content for ${reportType}`);
|
|
2143
|
+
|
|
2144
|
+
try {
|
|
2145
|
+
const parsed = this.parseAstrologicalReport(response); // Your existing parser
|
|
2146
|
+
|
|
2147
|
+
const enReport = parsed.find((r) => r.language === 'EN');
|
|
2148
|
+
const ptReport = parsed.find((r) => r.language === 'PT');
|
|
2149
|
+
|
|
2150
|
+
if (!enReport || !ptReport) {
|
|
2151
|
+
throw new Error(`❌ Missing EN or PT report in response`);
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
console.log(
|
|
2155
|
+
`✅ Parsed EN report sections:`,
|
|
2156
|
+
Object.keys(enReport.sections)
|
|
2157
|
+
);
|
|
2158
|
+
console.log(
|
|
2159
|
+
`✅ Parsed PT report sections:`,
|
|
2160
|
+
Object.keys(ptReport.sections)
|
|
2161
|
+
);
|
|
2162
|
+
|
|
2163
|
+
return {
|
|
2164
|
+
enReport: enReport.sections,
|
|
2165
|
+
ptReport: ptReport.sections,
|
|
2166
|
+
};
|
|
2167
|
+
} catch (error) {
|
|
2168
|
+
console.error(`❌ Parsing failed for ${reportType}`);
|
|
2169
|
+
|
|
2170
|
+
const failureKey = `failures:astro:parsing:${reportType}:${new Date().toISOString()}`;
|
|
2171
|
+
await this.context.kvConceptFailuresStore().put(
|
|
2172
|
+
failureKey,
|
|
2173
|
+
JSON.stringify({
|
|
2174
|
+
error: (error as Error).message,
|
|
2175
|
+
reportType,
|
|
2176
|
+
response,
|
|
2177
|
+
timestamp: new Date().toISOString(),
|
|
2178
|
+
})
|
|
2179
|
+
);
|
|
2180
|
+
|
|
2181
|
+
throw error;
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
private parseAstrologicalReport(response: string): AstrologicalReport[] {
|
|
2186
|
+
const reports: AstrologicalReport[] = [];
|
|
2187
|
+
const languageSections = response
|
|
2188
|
+
.split(/--\s*(EN|PT)\s*\n/)
|
|
2189
|
+
.filter(Boolean);
|
|
2190
|
+
|
|
2191
|
+
for (let i = 0; i < languageSections.length; i += 2) {
|
|
2192
|
+
const language = languageSections[i].trim();
|
|
2193
|
+
const content = languageSections[i + 1]?.trim();
|
|
2194
|
+
if (!content || !language.match(/^(EN|PT)$/)) continue;
|
|
2195
|
+
|
|
2196
|
+
const report: AstrologicalReport = {
|
|
2197
|
+
language,
|
|
2198
|
+
title: [],
|
|
2199
|
+
sections: {},
|
|
2200
|
+
};
|
|
2201
|
+
|
|
2202
|
+
const lines = content.split('\n').map((line) => line.trim());
|
|
2203
|
+
let currentSection = '';
|
|
2204
|
+
|
|
2205
|
+
for (const line of lines) {
|
|
2206
|
+
if (line.startsWith('### ') && report.title.length === 0) {
|
|
2207
|
+
report.title.push({
|
|
2208
|
+
type: 'title',
|
|
2209
|
+
content: cleanText(line.replace('### ', '')),
|
|
2210
|
+
});
|
|
2211
|
+
continue;
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
if (line.startsWith('#### ')) {
|
|
2215
|
+
currentSection = cleanText(line.replace('#### ', '').trim());
|
|
2216
|
+
report.sections[currentSection] =
|
|
2217
|
+
report.sections[currentSection] || [];
|
|
2218
|
+
continue;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
if (!line || !currentSection) continue;
|
|
2222
|
+
|
|
2223
|
+
if (line.match(/^\d+\.\s/) || line.startsWith('- ')) {
|
|
2224
|
+
const listItem = line.replace(/^\d+\.\s|- /, '').trim();
|
|
2225
|
+
const boldMatch = listItem.match(/^\*\*(.+?)\*\*:\s*(.+)$/);
|
|
2226
|
+
if (boldMatch) {
|
|
2227
|
+
report.sections[currentSection].push({
|
|
2228
|
+
type: 'bullet-point',
|
|
2229
|
+
title: cleanText(boldMatch[1]),
|
|
2230
|
+
content: cleanText(boldMatch[2]),
|
|
2231
|
+
});
|
|
2232
|
+
} else {
|
|
2233
|
+
report.sections[currentSection].push({
|
|
2234
|
+
type: 'bullet-point',
|
|
2235
|
+
content: cleanText(listItem),
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
2238
|
+
continue;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
report.sections[currentSection].push({
|
|
2242
|
+
type: 'p',
|
|
2243
|
+
content: cleanText(line),
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
reports.push(report);
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
return reports;
|
|
2251
|
+
}
|
|
1996
2252
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
CREATE TABLE `aspect_reports` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`aspecting_planet` text NOT NULL,
|
|
4
|
+
`aspected_planet` text NOT NULL,
|
|
5
|
+
`aspect` text NOT NULL,
|
|
6
|
+
`en_description` text,
|
|
7
|
+
`pt_description` text,
|
|
8
|
+
`en_report` text,
|
|
9
|
+
`pt_report` text,
|
|
10
|
+
`created_at` integer DEFAULT CURRENT_TIMESTAMP,
|
|
11
|
+
`updated_at` integer DEFAULT CURRENT_TIMESTAMP
|
|
12
|
+
);
|
|
13
|
+
--> statement-breakpoint
|
|
14
|
+
CREATE INDEX `aspect_reports_aspecting_idx` ON `aspect_reports` (`aspecting_planet`);--> statement-breakpoint
|
|
15
|
+
CREATE INDEX `aspect_reports_aspected_idx` ON `aspect_reports` (`aspected_planet`);--> statement-breakpoint
|
|
16
|
+
CREATE INDEX `aspect_reports_aspect_idx` ON `aspect_reports` (`aspect`);--> statement-breakpoint
|
|
17
|
+
CREATE INDEX `aspect_reports_combined_idx` ON `aspect_reports` (`aspecting_planet`,`aspected_planet`,`aspect`);--> statement-breakpoint
|
|
18
|
+
CREATE TABLE `astro_reports` (
|
|
19
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
20
|
+
`type` text NOT NULL,
|
|
21
|
+
`name` text NOT NULL,
|
|
22
|
+
`sign` text,
|
|
23
|
+
`house` integer,
|
|
24
|
+
`en_description` text,
|
|
25
|
+
`pt_description` text,
|
|
26
|
+
`en_report` text,
|
|
27
|
+
`pt_report` text,
|
|
28
|
+
`created_at` integer DEFAULT CURRENT_TIMESTAMP,
|
|
29
|
+
`updated_at` integer DEFAULT CURRENT_TIMESTAMP
|
|
30
|
+
);
|
|
31
|
+
--> statement-breakpoint
|
|
32
|
+
CREATE INDEX `astro_reports_type_idx` ON `astro_reports` (`type`);--> statement-breakpoint
|
|
33
|
+
CREATE INDEX `astro_reports_name_sign_idx` ON `astro_reports` (`name`,`sign`);--> statement-breakpoint
|
|
34
|
+
CREATE INDEX `astro_reports_name_house_idx` ON `astro_reports` (`name`,`house`);--> statement-breakpoint
|
|
35
|
+
CREATE TABLE `house_reports` (
|
|
36
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
37
|
+
`sign` text NOT NULL,
|
|
38
|
+
`house` integer NOT NULL,
|
|
39
|
+
`en_description` text,
|
|
40
|
+
`pt_description` text,
|
|
41
|
+
`en_report` text,
|
|
42
|
+
`pt_report` text,
|
|
43
|
+
`created_at` integer DEFAULT CURRENT_TIMESTAMP,
|
|
44
|
+
`updated_at` integer DEFAULT CURRENT_TIMESTAMP
|
|
45
|
+
);
|
|
46
|
+
--> statement-breakpoint
|
|
47
|
+
CREATE INDEX `house_reports_sign_house_idx` ON `house_reports` (`sign`,`house`);
|