@paroicms/site-generator-plugin 0.15.1 → 0.16.0
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/gen-backend/dist/commands/execute-command.js +1 -1
- package/gen-backend/dist/context.js +3 -3
- package/gen-backend/dist/data-format.js +97 -35
- package/gen-backend/dist/db/db-init.js +1 -1
- package/gen-backend/dist/db/db-read.queries.js +92 -31
- package/gen-backend/dist/db/db-write.queries.js +3 -2
- package/gen-backend/dist/db/formatters.js +11 -33
- package/gen-backend/dist/generator/lib/calling-llm-mistral.js +1 -1
- package/gen-backend/dist/generator/lib/create-prompt.js +1 -1
- package/gen-backend/dist/generator/lib/debug-utils.js +1 -1
- package/gen-backend/dist/generator/lib/session-utils.js +1 -1
- package/gen-backend/dist/generator/lib/tasks.js +1 -1
- package/gen-backend/dist/generator/llm-queries/invoke-message-guard.js +9 -17
- package/gen-backend/dist/generator/site-generator/site-generator.js +1 -1
- package/gen-backend/dist/lib/create-raw-context.js +1 -1
- package/gen-backend/dist/plugin.js +5 -4
- package/gen-front/dist/gen-front.mjs +120 -76
- package/package.json +9 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { messageOf } from "@
|
|
1
|
+
import { messageOf } from "@paroicms/public-anywhere-lib";
|
|
2
2
|
import { fetchWorkSession, loadStep } from "../db/db-read.queries.js";
|
|
3
3
|
import { insertIssueEvent, updateSession } from "../db/db-write.queries.js";
|
|
4
4
|
import { invokeMessageGuard } from "../generator/llm-queries/invoke-message-guard.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { strVal } from "@paroi/data-formatters-lib";
|
|
2
|
-
import { resolveModuleDirectory } from "@paroicms/public-server-lib";
|
|
3
1
|
import { readFileSync } from "node:fs";
|
|
4
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { resolveModuleDirectory } from "@paroicms/public-server-lib";
|
|
4
|
+
import { type } from "arktype";
|
|
5
5
|
export const projectDir = resolveModuleDirectory(import.meta.url, { parent: true });
|
|
6
6
|
export const packageDir = dirname(projectDir);
|
|
7
|
-
export const pluginVersion =
|
|
7
|
+
export const pluginVersion = type({ version: "string", "+": "ignore" }).assert(JSON.parse(readFileSync(join(packageDir, "package.json"), "utf-8"))).version;
|
|
8
8
|
export const SLUG = "site-generator";
|
|
@@ -1,82 +1,144 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isObj } from "@paroicms/public-anywhere-lib";
|
|
2
2
|
import { ApiError } from "@paroicms/public-server-lib";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { type } from "arktype";
|
|
4
|
+
export const GeneratorPluginConfigurationAT = type({
|
|
5
|
+
anthropicApiKey: "string",
|
|
6
|
+
mistralApiKey: "string",
|
|
7
|
+
packName: "string",
|
|
8
|
+
"googleRecaptchaSiteKey?": "string|undefined",
|
|
9
|
+
"debugDir?": "string|undefined",
|
|
10
|
+
"+": "reject",
|
|
11
|
+
}).pipe((data) => data);
|
|
12
|
+
const BaseCommandAT = type({
|
|
13
|
+
command: "string",
|
|
14
|
+
"+": "ignore",
|
|
15
|
+
});
|
|
16
|
+
const NewSessionCommandAT = type({
|
|
17
|
+
command: '"newSession"',
|
|
18
|
+
language: "string",
|
|
19
|
+
recaptchaToken: "string",
|
|
20
|
+
"+": "reject",
|
|
21
|
+
});
|
|
22
|
+
const RenewSessionCommandAT = type({
|
|
23
|
+
command: '"renewSession"',
|
|
24
|
+
sessionToken: "string",
|
|
25
|
+
recaptchaToken: "string",
|
|
26
|
+
"+": "reject",
|
|
27
|
+
});
|
|
28
|
+
const SetLanguageCommandAT = type({
|
|
29
|
+
command: '"setLanguage"',
|
|
30
|
+
sessionToken: "string",
|
|
31
|
+
language: "string",
|
|
32
|
+
"+": "reject",
|
|
33
|
+
});
|
|
34
|
+
const LoadWorkSessionCommandAT = type({
|
|
35
|
+
command: '"loadWorkSession"',
|
|
36
|
+
sessionToken: "string",
|
|
37
|
+
"+": "reject",
|
|
38
|
+
});
|
|
39
|
+
const LoadStepCommandAT = type({
|
|
40
|
+
command: '"loadStep"',
|
|
41
|
+
sessionToken: "string",
|
|
42
|
+
stepNumber: "number",
|
|
43
|
+
"+": "reject",
|
|
44
|
+
});
|
|
45
|
+
const CreateSiteSchemaCommandAT = type({
|
|
46
|
+
command: '"createSiteSchema"',
|
|
47
|
+
sessionToken: "string",
|
|
48
|
+
prompt: "string",
|
|
49
|
+
"+": "reject",
|
|
50
|
+
});
|
|
51
|
+
const UpdateSiteSchemaCommandAT = type({
|
|
52
|
+
command: '"updateSiteSchema"',
|
|
53
|
+
sessionToken: "string",
|
|
54
|
+
prompt: "string",
|
|
55
|
+
fromStepNumber: "number",
|
|
56
|
+
"+": "reject",
|
|
57
|
+
});
|
|
58
|
+
const GenerateSiteCommandAT = type({
|
|
59
|
+
command: '"generateSite"',
|
|
60
|
+
sessionToken: "string",
|
|
61
|
+
fromStepNumber: "number",
|
|
62
|
+
withSampleData: "boolean",
|
|
63
|
+
"+": "reject",
|
|
64
|
+
});
|
|
65
|
+
const PromptAT = type("string").narrow((prompt) => {
|
|
66
|
+
if (prompt.length > 5000) {
|
|
67
|
+
throw new ApiError("Prompt is too long", 400);
|
|
10
68
|
}
|
|
11
|
-
return
|
|
12
|
-
}
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
13
71
|
export function formatGeneratorCommand(data) {
|
|
14
72
|
if (!isObj(data))
|
|
15
73
|
throw new ApiError("Invalid input", 400);
|
|
16
|
-
const
|
|
74
|
+
const baseCommand = BaseCommandAT.assert(data);
|
|
75
|
+
const command = baseCommand.command;
|
|
17
76
|
if (command === "newSession") {
|
|
77
|
+
const validated = NewSessionCommandAT.assert(data);
|
|
18
78
|
return {
|
|
19
79
|
command: "newSession",
|
|
20
|
-
language:
|
|
21
|
-
recaptchaToken:
|
|
80
|
+
language: validated.language,
|
|
81
|
+
recaptchaToken: validated.recaptchaToken,
|
|
22
82
|
};
|
|
23
83
|
}
|
|
24
84
|
if (command === "renewSession") {
|
|
85
|
+
const validated = RenewSessionCommandAT.assert(data);
|
|
25
86
|
return {
|
|
26
87
|
command: "renewSession",
|
|
27
|
-
sessionToken:
|
|
28
|
-
recaptchaToken:
|
|
88
|
+
sessionToken: validated.sessionToken,
|
|
89
|
+
recaptchaToken: validated.recaptchaToken,
|
|
29
90
|
};
|
|
30
91
|
}
|
|
31
92
|
if (command === "setLanguage") {
|
|
93
|
+
const validated = SetLanguageCommandAT.assert(data);
|
|
32
94
|
return {
|
|
33
95
|
command: "setLanguage",
|
|
34
|
-
sessionToken:
|
|
35
|
-
language:
|
|
96
|
+
sessionToken: validated.sessionToken,
|
|
97
|
+
language: validated.language,
|
|
36
98
|
};
|
|
37
99
|
}
|
|
38
100
|
if (command === "loadWorkSession") {
|
|
101
|
+
const validated = LoadWorkSessionCommandAT.assert(data);
|
|
39
102
|
return {
|
|
40
103
|
command: "loadWorkSession",
|
|
41
|
-
sessionToken:
|
|
104
|
+
sessionToken: validated.sessionToken,
|
|
42
105
|
};
|
|
43
106
|
}
|
|
44
107
|
if (command === "loadStep") {
|
|
108
|
+
const validated = LoadStepCommandAT.assert(data);
|
|
45
109
|
return {
|
|
46
110
|
command: "loadStep",
|
|
47
|
-
sessionToken:
|
|
48
|
-
stepNumber:
|
|
111
|
+
sessionToken: validated.sessionToken,
|
|
112
|
+
stepNumber: validated.stepNumber,
|
|
49
113
|
};
|
|
50
114
|
}
|
|
51
115
|
if (command === "createSiteSchema") {
|
|
116
|
+
const validated = CreateSiteSchemaCommandAT.assert(data);
|
|
117
|
+
const prompt = PromptAT.assert(validated.prompt);
|
|
52
118
|
return {
|
|
53
119
|
command: "createSiteSchema",
|
|
54
|
-
sessionToken:
|
|
55
|
-
prompt
|
|
120
|
+
sessionToken: validated.sessionToken,
|
|
121
|
+
prompt,
|
|
56
122
|
};
|
|
57
123
|
}
|
|
58
124
|
if (command === "updateSiteSchema") {
|
|
125
|
+
const validated = UpdateSiteSchemaCommandAT.assert(data);
|
|
126
|
+
const prompt = PromptAT.assert(validated.prompt);
|
|
59
127
|
return {
|
|
60
128
|
command: "updateSiteSchema",
|
|
61
|
-
sessionToken:
|
|
62
|
-
prompt
|
|
63
|
-
fromStepNumber:
|
|
129
|
+
sessionToken: validated.sessionToken,
|
|
130
|
+
prompt,
|
|
131
|
+
fromStepNumber: validated.fromStepNumber,
|
|
64
132
|
};
|
|
65
133
|
}
|
|
66
134
|
if (command === "generateSite") {
|
|
135
|
+
const validated = GenerateSiteCommandAT.assert(data);
|
|
67
136
|
return {
|
|
68
137
|
command: "generateSite",
|
|
69
|
-
sessionToken:
|
|
70
|
-
fromStepNumber:
|
|
71
|
-
withSampleData:
|
|
138
|
+
sessionToken: validated.sessionToken,
|
|
139
|
+
fromStepNumber: validated.fromStepNumber,
|
|
140
|
+
withSampleData: validated.withSampleData,
|
|
72
141
|
};
|
|
73
142
|
}
|
|
74
143
|
throw new ApiError(`Invalid command: ${command}`, 400);
|
|
75
144
|
}
|
|
76
|
-
function formatPrompt(val) {
|
|
77
|
-
const prompt = strVal(val, { varName: "prompt" });
|
|
78
|
-
if (prompt.length > 5000) {
|
|
79
|
-
throw new ApiError("Prompt is too long", 400);
|
|
80
|
-
}
|
|
81
|
-
return prompt;
|
|
82
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createOrOpenSqliteConnection, createSqlLogger, getMetadataDbSchemaVersion, } from "@paroicms/internal-server-lib";
|
|
2
1
|
import { join } from "node:path";
|
|
2
|
+
import { createOrOpenSqliteConnection, createSqlLogger, getMetadataDbSchemaVersion, } from "@paroicms/internal-server-lib";
|
|
3
3
|
import { projectDir } from "../context.js";
|
|
4
4
|
import { currentDbSchemaVersion, dbSchemaName, migrateSiteGeneratorDb } from "./ddl-migration.js";
|
|
5
5
|
export async function createOrOpenSiteGeneratorConnection({ sqliteFile, canCreate, logger, }) {
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseSqliteDateTime } from "@paroicms/internal-server-lib";
|
|
2
|
+
import { type } from "arktype";
|
|
2
3
|
import { ensureType, formatActivityCode, formatStepKind, formatStepStatus } from "./formatters.js";
|
|
4
|
+
const SessionRowAT = type({
|
|
5
|
+
id: "string",
|
|
6
|
+
expireAt: "string|number|Date",
|
|
7
|
+
successStepCount: "number",
|
|
8
|
+
"+": "reject",
|
|
9
|
+
});
|
|
3
10
|
export async function getInvalidSessionError(ctx, sessionId) {
|
|
4
11
|
const { cn } = ctx;
|
|
5
12
|
const row = await cn("PgSession as s")
|
|
@@ -10,13 +17,19 @@ export async function getInvalidSessionError(ctx, sessionId) {
|
|
|
10
17
|
.first();
|
|
11
18
|
if (!row)
|
|
12
19
|
return "not found";
|
|
13
|
-
const
|
|
14
|
-
if (successStepCount >= 20)
|
|
20
|
+
const validated = SessionRowAT.assert(row);
|
|
21
|
+
if (validated.successStepCount >= 20)
|
|
15
22
|
return "too many steps";
|
|
16
|
-
const expireAt =
|
|
23
|
+
const expireAt = parseSqliteDateTime(validated.expireAt).getTime();
|
|
17
24
|
if (expireAt < Date.now())
|
|
18
25
|
return "expired";
|
|
19
26
|
}
|
|
27
|
+
const StepSchemaRowAT = type({
|
|
28
|
+
siteSchema: "string",
|
|
29
|
+
l10n: "string",
|
|
30
|
+
localizedValues: "string",
|
|
31
|
+
"+": "reject",
|
|
32
|
+
});
|
|
20
33
|
export async function readStepSchema(ctx, stepNumber) {
|
|
21
34
|
const { cn, sessionId } = ctx;
|
|
22
35
|
const row = await cn("PgSchemaStep")
|
|
@@ -25,12 +38,20 @@ export async function readStepSchema(ctx, stepNumber) {
|
|
|
25
38
|
.first();
|
|
26
39
|
if (!row)
|
|
27
40
|
throw new Error(`[${sessionId}] Step "${stepNumber}" not found`);
|
|
41
|
+
const validated = StepSchemaRowAT.assert(row);
|
|
28
42
|
return {
|
|
29
|
-
siteSchema: JSON.parse(
|
|
30
|
-
l10n: JSON.parse(
|
|
31
|
-
localizedValues: JSON.parse(
|
|
43
|
+
siteSchema: JSON.parse(validated.siteSchema),
|
|
44
|
+
l10n: JSON.parse(validated.l10n),
|
|
45
|
+
localizedValues: JSON.parse(validated.localizedValues),
|
|
32
46
|
};
|
|
33
47
|
}
|
|
48
|
+
const WorkSessionRowAT = type({
|
|
49
|
+
id: "string",
|
|
50
|
+
createdAt: "string|number|Date",
|
|
51
|
+
expireAt: "string|number|Date",
|
|
52
|
+
language: "string",
|
|
53
|
+
"+": "reject",
|
|
54
|
+
});
|
|
34
55
|
export async function fetchWorkSession(ctx) {
|
|
35
56
|
const { cn, sessionId } = ctx;
|
|
36
57
|
const row = await cn("PgSession")
|
|
@@ -40,12 +61,13 @@ export async function fetchWorkSession(ctx) {
|
|
|
40
61
|
if (!row) {
|
|
41
62
|
throw new Error(`Session not found: ${sessionId}`);
|
|
42
63
|
}
|
|
64
|
+
const validated = WorkSessionRowAT.assert(row);
|
|
43
65
|
const steps = await loadSessionSteps(ctx);
|
|
44
66
|
return {
|
|
45
|
-
id:
|
|
46
|
-
createdAt:
|
|
47
|
-
expireAt:
|
|
48
|
-
language:
|
|
67
|
+
id: validated.id,
|
|
68
|
+
createdAt: parseSqliteDateTime(validated.createdAt).toISOString(),
|
|
69
|
+
expireAt: parseSqliteDateTime(validated.expireAt).toISOString(),
|
|
70
|
+
language: validated.language,
|
|
49
71
|
steps,
|
|
50
72
|
};
|
|
51
73
|
}
|
|
@@ -78,51 +100,90 @@ function buildStepsQuery(cn) {
|
|
|
78
100
|
"i.sessionId": "s.sessionId",
|
|
79
101
|
});
|
|
80
102
|
}
|
|
103
|
+
const StepRowAT = type({
|
|
104
|
+
stepNumber: "number",
|
|
105
|
+
explanation: "string|null",
|
|
106
|
+
status: "string",
|
|
107
|
+
kind: "string",
|
|
108
|
+
currentActivity: "string|null",
|
|
109
|
+
promptTitle: "string|null",
|
|
110
|
+
siteSchema: "string|null",
|
|
111
|
+
l10n: "string|null",
|
|
112
|
+
schemaLocalizedValues: "string|null",
|
|
113
|
+
siteId: "string|null",
|
|
114
|
+
siteLocalizedValues: "string|null",
|
|
115
|
+
siteUrl: "string|null",
|
|
116
|
+
loginEmail: "string|null",
|
|
117
|
+
loginPassword: "string|null",
|
|
118
|
+
"+": "reject",
|
|
119
|
+
}).pipe((r) => ({
|
|
120
|
+
...r,
|
|
121
|
+
explanation: r.explanation ?? undefined,
|
|
122
|
+
currentActivity: r.currentActivity ?? undefined,
|
|
123
|
+
promptTitle: r.promptTitle ?? undefined,
|
|
124
|
+
siteSchema: r.siteSchema ?? undefined,
|
|
125
|
+
l10n: r.l10n ?? undefined,
|
|
126
|
+
schemaLocalizedValues: r.schemaLocalizedValues ?? undefined,
|
|
127
|
+
siteId: r.siteId ?? undefined,
|
|
128
|
+
siteLocalizedValues: r.siteLocalizedValues ?? undefined,
|
|
129
|
+
siteUrl: r.siteUrl ?? undefined,
|
|
130
|
+
loginEmail: r.loginEmail ?? undefined,
|
|
131
|
+
loginPassword: r.loginPassword ?? undefined,
|
|
132
|
+
}));
|
|
81
133
|
function mapRowToStep(row, sessionId) {
|
|
134
|
+
const validated = StepRowAT.assert(row);
|
|
82
135
|
const baseStep = {
|
|
83
|
-
stepNumber:
|
|
84
|
-
explanation:
|
|
136
|
+
stepNumber: validated.stepNumber,
|
|
137
|
+
explanation: validated.explanation,
|
|
85
138
|
};
|
|
86
|
-
const status = formatStepStatus(
|
|
87
|
-
const kind = formatStepKind(
|
|
139
|
+
const status = formatStepStatus(validated.status);
|
|
140
|
+
const kind = formatStepKind(validated.kind);
|
|
88
141
|
if (status === "pending") {
|
|
89
142
|
return ensureType({
|
|
90
143
|
...baseStep,
|
|
91
144
|
status,
|
|
92
145
|
kind,
|
|
93
|
-
currentActivity: formatActivityCode(
|
|
146
|
+
currentActivity: formatActivityCode(validated.currentActivity),
|
|
94
147
|
});
|
|
95
148
|
}
|
|
96
149
|
if (status === "completed") {
|
|
97
150
|
if (kind === "initialSchema" || kind === "updateSchema") {
|
|
98
|
-
if (!
|
|
99
|
-
throw new Error(`[Session "${sessionId}"] PgSchemaStep row is missing for completed step "${
|
|
151
|
+
if (!validated.siteSchema) {
|
|
152
|
+
throw new Error(`[Session "${sessionId}"] PgSchemaStep row is missing for completed step "${validated.stepNumber}"`);
|
|
153
|
+
}
|
|
154
|
+
if (!validated.l10n || !validated.schemaLocalizedValues) {
|
|
155
|
+
throw new Error(`[Session "${sessionId}"] Missing schema data for completed step "${validated.stepNumber}"`);
|
|
100
156
|
}
|
|
101
157
|
return ensureType({
|
|
102
158
|
...baseStep,
|
|
103
159
|
status,
|
|
104
160
|
kind,
|
|
105
|
-
promptTitle:
|
|
106
|
-
siteSchema: JSON.parse(
|
|
107
|
-
l10n: JSON.parse(
|
|
108
|
-
localizedValues: JSON.parse(
|
|
161
|
+
promptTitle: validated.promptTitle,
|
|
162
|
+
siteSchema: JSON.parse(validated.siteSchema),
|
|
163
|
+
l10n: JSON.parse(validated.l10n),
|
|
164
|
+
localizedValues: JSON.parse(validated.schemaLocalizedValues),
|
|
109
165
|
});
|
|
110
166
|
}
|
|
111
167
|
if (kind === "generateSite") {
|
|
112
|
-
if (!
|
|
113
|
-
throw new Error(`[Session "${sessionId}"] PgGeneratedSiteStep row is missing for completed step "${
|
|
168
|
+
if (!validated.siteId) {
|
|
169
|
+
throw new Error(`[Session "${sessionId}"] PgGeneratedSiteStep row is missing for completed step "${validated.stepNumber}"`);
|
|
170
|
+
}
|
|
171
|
+
if (!validated.siteUrl ||
|
|
172
|
+
!validated.loginEmail ||
|
|
173
|
+
!validated.loginPassword ||
|
|
174
|
+
!validated.siteLocalizedValues) {
|
|
175
|
+
throw new Error(`[Session "${sessionId}"] Missing generated site data for completed step "${validated.stepNumber}"`);
|
|
114
176
|
}
|
|
115
|
-
const siteUrl = strVal(row.siteUrl);
|
|
116
177
|
return ensureType({
|
|
117
178
|
...baseStep,
|
|
118
179
|
status,
|
|
119
180
|
kind,
|
|
120
|
-
siteId:
|
|
121
|
-
siteUrl,
|
|
122
|
-
adminUiUrl: `${siteUrl}/adm`,
|
|
123
|
-
loginEmail:
|
|
124
|
-
loginPassword:
|
|
125
|
-
localizedValues: JSON.parse(
|
|
181
|
+
siteId: validated.siteId,
|
|
182
|
+
siteUrl: validated.siteUrl,
|
|
183
|
+
adminUiUrl: `${validated.siteUrl}/adm`,
|
|
184
|
+
loginEmail: validated.loginEmail,
|
|
185
|
+
loginPassword: validated.loginPassword,
|
|
186
|
+
localizedValues: JSON.parse(validated.siteLocalizedValues),
|
|
126
187
|
});
|
|
127
188
|
}
|
|
128
189
|
throw new Error(`[Session "${sessionId}"] invalid step kind "${kind}"`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { strVal } from "@paroi/data-formatters-lib";
|
|
2
1
|
import { sqliteDateTime } from "@paroicms/internal-server-lib";
|
|
2
|
+
import { type } from "arktype";
|
|
3
3
|
export async function insertSession(ctx, values) {
|
|
4
4
|
const { cn } = ctx;
|
|
5
5
|
await cn("PgSession").insert({
|
|
@@ -128,6 +128,7 @@ export async function updateGeneratedSiteStepSetAsCompleted(ctx, stepHandle, val
|
|
|
128
128
|
});
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
+
const InsertedAT = type({ id: "string", "+": "reject" });
|
|
131
132
|
export async function insertIssueEvent(ctx, values) {
|
|
132
133
|
const { cn, sessionId } = ctx;
|
|
133
134
|
const [inserted] = await cn("PgIssueEvent")
|
|
@@ -140,5 +141,5 @@ export async function insertIssueEvent(ctx, values) {
|
|
|
140
141
|
siteId: values.siteId,
|
|
141
142
|
})
|
|
142
143
|
.returning("id");
|
|
143
|
-
return
|
|
144
|
+
return InsertedAT.assert(inserted);
|
|
144
145
|
}
|
|
@@ -1,46 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
export function ensureType(value) {
|
|
3
3
|
return value;
|
|
4
4
|
}
|
|
5
|
+
const StepKindAT = type('"initialSchema"|"updateSchema"|"generateSite"');
|
|
5
6
|
export function formatStepKind(value) {
|
|
6
|
-
|
|
7
|
-
if (v === "initialSchema" || v === "updateSchema" || v === "generateSite") {
|
|
8
|
-
return v;
|
|
9
|
-
}
|
|
10
|
-
throw new Error(`Invalid step kind "${v}"`);
|
|
7
|
+
return StepKindAT.assert(value);
|
|
11
8
|
}
|
|
9
|
+
const SchemaStepKindAT = type('"initialSchema"|"updateSchema"');
|
|
12
10
|
export function formatSchemaStepKind(value) {
|
|
13
|
-
|
|
14
|
-
if (v === "initialSchema" || v === "updateSchema") {
|
|
15
|
-
return v;
|
|
16
|
-
}
|
|
17
|
-
throw new Error(`Invalid schema step kind "${v}"`);
|
|
11
|
+
return SchemaStepKindAT.assert(value);
|
|
18
12
|
}
|
|
13
|
+
const GeneratedSiteStepKindAT = type('"generateSite"');
|
|
19
14
|
export function formatGeneratedSiteStepKind(value) {
|
|
20
|
-
|
|
21
|
-
if (v === "generateSite") {
|
|
22
|
-
return v;
|
|
23
|
-
}
|
|
24
|
-
throw new Error(`Invalid generated site step kind "${v}"`);
|
|
15
|
+
return GeneratedSiteStepKindAT.assert(value);
|
|
25
16
|
}
|
|
17
|
+
const StepStatusAT = type('"completed"|"pending"|"failed"|"noEffect"');
|
|
26
18
|
export function formatStepStatus(value) {
|
|
27
|
-
|
|
28
|
-
if (v === "completed" || v === "pending" || v === "failed" || v === "noEffect") {
|
|
29
|
-
return v;
|
|
30
|
-
}
|
|
31
|
-
throw new Error(`Invalid step status "${v}"`);
|
|
19
|
+
return StepStatusAT.assert(value);
|
|
32
20
|
}
|
|
21
|
+
const ActivityCodeAT = type('"initial1"|"initial2"|"updating1"|"updating2"|"generatingSite"|"generatingContent"|undefined');
|
|
33
22
|
export function formatActivityCode(value) {
|
|
34
|
-
|
|
35
|
-
if (v === undefined)
|
|
36
|
-
return;
|
|
37
|
-
if (v === "initial1" ||
|
|
38
|
-
v === "initial2" ||
|
|
39
|
-
v === "updating1" ||
|
|
40
|
-
v === "updating2" ||
|
|
41
|
-
v === "generatingSite" ||
|
|
42
|
-
v === "generatingContent") {
|
|
43
|
-
return v;
|
|
44
|
-
}
|
|
45
|
-
throw new Error(`Invalid activity code "${v}"`);
|
|
23
|
+
return ActivityCodeAT.assert(value);
|
|
46
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { connectorPackageDir } from "@paroicms/connector";
|
|
2
1
|
import { readFile } from "node:fs/promises";
|
|
3
2
|
import { join } from "node:path";
|
|
3
|
+
import { connectorPackageDir } from "@paroicms/connector";
|
|
4
4
|
import { projectDir } from "../../context.js";
|
|
5
5
|
import { buildPromptTemplate } from "./prompt-template.js";
|
|
6
6
|
const contextContent = await readPromptFile("0-context.md");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { messageOf } from "@paroi/data-formatters-lib";
|
|
2
1
|
import { ensureDirectory } from "@paroicms/internal-server-lib";
|
|
2
|
+
import { messageOf } from "@paroicms/public-anywhere-lib";
|
|
3
3
|
import { readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { estimateTokenCount } from "./llm-tokens.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { messageOf } from "@
|
|
1
|
+
import { messageOf } from "@paroicms/public-anywhere-lib";
|
|
2
2
|
import { insertIssueEvent, updateStep } from "../../db/db-write.queries.js";
|
|
3
3
|
export function safeCallStep(ctx, stepHandle, cb) {
|
|
4
4
|
void safeCallStepExec(ctx, stepHandle, cb);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import { insertIssueEvent } from "../../db/db-write.queries.js";
|
|
3
3
|
import { invokeClaude } from "../lib/calling-llm-anthropic.js";
|
|
4
4
|
import { createPromptTemplate } from "../lib/create-prompt.js";
|
|
@@ -7,7 +7,13 @@ import { parseLlmResponseAsProperties } from "../lib/parse-llm-response.js";
|
|
|
7
7
|
const guardPrompt = await createPromptTemplate({
|
|
8
8
|
filename: "message-guard.md",
|
|
9
9
|
});
|
|
10
|
-
const
|
|
10
|
+
const MessageGuardReportAT = type({
|
|
11
|
+
"language?": "string|undefined",
|
|
12
|
+
valid: "boolean",
|
|
13
|
+
"causes?": '("rude"|"malicious"|"outOfScope"|"technicalLimits"|"noSense")[]|undefined',
|
|
14
|
+
"explanation?": "string|undefined",
|
|
15
|
+
"+": "reject",
|
|
16
|
+
});
|
|
11
17
|
export async function invokeMessageGuard(ctx, input, { skipOutOfScopeCheck = false } = {}) {
|
|
12
18
|
const llmTaskName = "guard";
|
|
13
19
|
const llmInput = {
|
|
@@ -34,7 +40,7 @@ export async function invokeMessageGuard(ctx, input, { skipOutOfScopeCheck = fal
|
|
|
34
40
|
format: "yaml",
|
|
35
41
|
},
|
|
36
42
|
]);
|
|
37
|
-
const report =
|
|
43
|
+
const report = MessageGuardReportAT.assert(rawReport.guard);
|
|
38
44
|
if (report.causes && skipOutOfScopeCheck) {
|
|
39
45
|
report.causes = report.causes.filter((cause) => cause !== "outOfScope");
|
|
40
46
|
if (report.causes.length === 0) {
|
|
@@ -89,17 +95,3 @@ function getCauseLabel(cause, language) {
|
|
|
89
95
|
return cause;
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
|
-
function formatMessageGuardReport(rawReport) {
|
|
93
|
-
return {
|
|
94
|
-
language: strValOrUndef(rawReport.language, { varName: "language" }),
|
|
95
|
-
valid: boolVal(rawReport.valid, { varName: "valid" }),
|
|
96
|
-
causes: listValOrUndef(rawReport.causes, formatGuardInvalidCause),
|
|
97
|
-
explanation: strValOrUndef(rawReport.explanation, { varName: "explanation" }),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function formatGuardInvalidCause(cause) {
|
|
101
|
-
const v = strVal(cause, { varName: "cause" });
|
|
102
|
-
if (!invalidCauses.has(v))
|
|
103
|
-
throw new Error(`Invalid cause: "${v}"`);
|
|
104
|
-
return v;
|
|
105
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { generateSlug } from "@paroicms/public-anywhere-lib";
|
|
2
1
|
import { randomUUID } from "node:crypto";
|
|
3
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
3
|
import { join } from "node:path";
|
|
4
|
+
import { generateSlug } from "@paroicms/public-anywhere-lib";
|
|
5
5
|
import { loadStep, readStepSchema } from "../../db/db-read.queries.js";
|
|
6
6
|
import { insertStep, saveGeneratedSiteStep, } from "../../db/db-write.queries.js";
|
|
7
7
|
import { fillSiteWithFakeContent } from "../fake-content-generator/create-database-with-fake-content.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
3
|
import { Mistral } from "@mistralai/mistralai";
|
|
3
4
|
import { readOrCreateJwtSecretSync } from "@paroicms/internal-server-lib";
|
|
4
|
-
import { join } from "node:path";
|
|
5
5
|
export function createRawContext(service, options) {
|
|
6
6
|
const { cn, logNextQuery, pluginConf, debugDir } = options;
|
|
7
7
|
const packConf = service.connector.getSitePackConf(pluginConf.packName);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { messageOf } from "@paroi/data-formatters-lib";
|
|
2
1
|
import { pathExists } from "@paroicms/internal-server-lib";
|
|
2
|
+
import { messageOf } from "@paroicms/public-anywhere-lib";
|
|
3
3
|
import { ApiError, escapeHtml, makeStylesheetLinkAsyncTag, } from "@paroicms/public-server-lib";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { executeCommand } from "./commands/execute-command.js";
|
|
6
6
|
import { SLUG, packageDir, pluginVersion } from "./context.js";
|
|
7
|
-
import {
|
|
7
|
+
import { GeneratorPluginConfigurationAT, formatGeneratorCommand } from "./data-format.js";
|
|
8
8
|
import { createOrOpenSiteGeneratorConnection } from "./db/db-init.js";
|
|
9
9
|
import { initializeImageNames } from "./generator/lib/images-lib.js";
|
|
10
10
|
import { createRawContext } from "./lib/create-raw-context.js";
|
|
@@ -19,7 +19,7 @@ const plugin = {
|
|
|
19
19
|
canCreate: true,
|
|
20
20
|
logger: service.logger,
|
|
21
21
|
});
|
|
22
|
-
const pluginConf =
|
|
22
|
+
const pluginConf = GeneratorPluginConfigurationAT.assert(service.configuration);
|
|
23
23
|
let debugDir = pluginConf.debugDir;
|
|
24
24
|
if (debugDir) {
|
|
25
25
|
if (!(await pathExists(debugDir))) {
|
|
@@ -47,7 +47,7 @@ const plugin = {
|
|
|
47
47
|
return;
|
|
48
48
|
return [
|
|
49
49
|
makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/gen-front.css`),
|
|
50
|
-
`<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/gen-front.mjs`)}" class="js-script-${SLUG}" data-google-recaptcha-site-key="${escapeHtml(
|
|
50
|
+
`<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/gen-front.mjs`)}" class="js-script-${SLUG}" data-google-recaptcha-site-key="${escapeHtml(pluginConf.googleRecaptchaSiteKey)}" async></script>`,
|
|
51
51
|
];
|
|
52
52
|
});
|
|
53
53
|
service.setPublicApiHandler(async (service, httpContext, relativePath) => {
|
|
@@ -64,6 +64,7 @@ const plugin = {
|
|
|
64
64
|
command = formatGeneratorCommand(req.body);
|
|
65
65
|
}
|
|
66
66
|
catch (error) {
|
|
67
|
+
service.logger.error("Invalid command:", error);
|
|
67
68
|
res.status(400).send({ status: 400, message: messageOf(error) });
|
|
68
69
|
return;
|
|
69
70
|
}
|