@dexto/core 1.2.5 → 1.2.6
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/dist/agent/schemas.cjs +23 -19
- package/dist/agent/schemas.d.ts +111 -107
- package/dist/agent/schemas.d.ts.map +1 -1
- package/dist/agent/schemas.js +7 -3
- package/dist/memory/index.cjs +2 -0
- package/dist/memory/index.d.ts +1 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +3 -1
- package/dist/memory/schemas.cjs +10 -0
- package/dist/memory/schemas.d.ts +33 -4
- package/dist/memory/schemas.d.ts.map +1 -1
- package/dist/memory/schemas.js +9 -0
- package/dist/prompts/index.cjs +6 -8
- package/dist/prompts/index.d.ts +2 -4
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +4 -6
- package/dist/prompts/prompt-manager.cjs +2 -4
- package/dist/prompts/prompt-manager.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.js +2 -4
- package/dist/prompts/providers/config-prompt-provider.cjs +331 -0
- package/dist/prompts/providers/config-prompt-provider.d.ts +34 -0
- package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -0
- package/dist/prompts/providers/config-prompt-provider.js +308 -0
- package/dist/prompts/schemas.cjs +42 -23
- package/dist/prompts/schemas.d.ts +121 -12
- package/dist/prompts/schemas.d.ts.map +1 -1
- package/dist/prompts/schemas.js +39 -22
- package/dist/prompts/types.d.ts +1 -1
- package/dist/prompts/types.d.ts.map +1 -1
- package/dist/systemPrompt/in-built-prompts.cjs +0 -5
- package/dist/systemPrompt/in-built-prompts.d.ts +1 -2
- package/dist/systemPrompt/in-built-prompts.d.ts.map +1 -1
- package/dist/systemPrompt/in-built-prompts.js +0 -4
- package/dist/systemPrompt/manager.cjs +24 -19
- package/dist/systemPrompt/manager.d.ts +2 -2
- package/dist/systemPrompt/manager.d.ts.map +1 -1
- package/dist/systemPrompt/manager.js +24 -19
- package/dist/systemPrompt/registry.cjs +1 -2
- package/dist/systemPrompt/registry.d.ts +1 -1
- package/dist/systemPrompt/registry.d.ts.map +1 -1
- package/dist/systemPrompt/registry.js +1 -2
- package/dist/systemPrompt/schemas.cjs +3 -17
- package/dist/systemPrompt/schemas.d.ts +13 -189
- package/dist/systemPrompt/schemas.d.ts.map +1 -1
- package/dist/systemPrompt/schemas.js +3 -17
- package/dist/utils/service-initializer.cjs +1 -0
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +1 -0
- package/package.json +1 -1
- package/dist/prompts/providers/file-prompt-provider.cjs +0 -401
- package/dist/prompts/providers/file-prompt-provider.d.ts +0 -49
- package/dist/prompts/providers/file-prompt-provider.d.ts.map +0 -1
- package/dist/prompts/providers/file-prompt-provider.js +0 -378
- package/dist/prompts/providers/starter-prompt-provider.cjs +0 -172
- package/dist/prompts/providers/starter-prompt-provider.d.ts +0 -47
- package/dist/prompts/providers/starter-prompt-provider.d.ts.map +0 -1
- package/dist/prompts/providers/starter-prompt-provider.js +0 -149
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import "../../chunk-C6A6W6XS.js";
|
|
2
|
+
import { DextoLogComponent } from "../../logger/v2/types.js";
|
|
3
|
+
import { PromptError } from "../errors.js";
|
|
4
|
+
import { expandPlaceholders } from "../utils.js";
|
|
5
|
+
import { assertValidPromptName } from "../name-validation.js";
|
|
6
|
+
import { readFile, realpath } from "fs/promises";
|
|
7
|
+
import { existsSync } from "fs";
|
|
8
|
+
import { dirname, relative, sep } from "path";
|
|
9
|
+
class ConfigPromptProvider {
|
|
10
|
+
prompts = [];
|
|
11
|
+
promptsCache = [];
|
|
12
|
+
promptContent = /* @__PURE__ */ new Map();
|
|
13
|
+
cacheValid = false;
|
|
14
|
+
logger;
|
|
15
|
+
constructor(agentConfig, logger) {
|
|
16
|
+
this.logger = logger.createChild(DextoLogComponent.PROMPT);
|
|
17
|
+
this.prompts = agentConfig.prompts;
|
|
18
|
+
this.buildPromptsCache();
|
|
19
|
+
}
|
|
20
|
+
getSource() {
|
|
21
|
+
return "config";
|
|
22
|
+
}
|
|
23
|
+
invalidateCache() {
|
|
24
|
+
this.cacheValid = false;
|
|
25
|
+
this.promptsCache = [];
|
|
26
|
+
this.promptContent.clear();
|
|
27
|
+
this.logger.debug("ConfigPromptProvider cache invalidated");
|
|
28
|
+
}
|
|
29
|
+
updateConfig(agentConfig) {
|
|
30
|
+
this.prompts = agentConfig.prompts;
|
|
31
|
+
this.invalidateCache();
|
|
32
|
+
this.buildPromptsCache();
|
|
33
|
+
}
|
|
34
|
+
async listPrompts(_cursor) {
|
|
35
|
+
if (!this.cacheValid) {
|
|
36
|
+
await this.buildPromptsCache();
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
prompts: this.promptsCache
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async getPrompt(name, args) {
|
|
43
|
+
if (!this.cacheValid) {
|
|
44
|
+
await this.buildPromptsCache();
|
|
45
|
+
}
|
|
46
|
+
const promptInfo = this.promptsCache.find((p) => p.name === name);
|
|
47
|
+
if (!promptInfo) {
|
|
48
|
+
throw PromptError.notFound(name);
|
|
49
|
+
}
|
|
50
|
+
let content = this.promptContent.get(name);
|
|
51
|
+
if (!content) {
|
|
52
|
+
throw PromptError.missingText();
|
|
53
|
+
}
|
|
54
|
+
content = this.applyArguments(content, args);
|
|
55
|
+
return {
|
|
56
|
+
description: promptInfo.description,
|
|
57
|
+
messages: [
|
|
58
|
+
{
|
|
59
|
+
role: "user",
|
|
60
|
+
content: {
|
|
61
|
+
type: "text",
|
|
62
|
+
text: content
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async getPromptDefinition(name) {
|
|
69
|
+
if (!this.cacheValid) {
|
|
70
|
+
await this.buildPromptsCache();
|
|
71
|
+
}
|
|
72
|
+
const promptInfo = this.promptsCache.find((p) => p.name === name);
|
|
73
|
+
if (!promptInfo) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
name: promptInfo.name,
|
|
78
|
+
...promptInfo.title && { title: promptInfo.title },
|
|
79
|
+
...promptInfo.description && { description: promptInfo.description },
|
|
80
|
+
...promptInfo.arguments && { arguments: promptInfo.arguments }
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async buildPromptsCache() {
|
|
84
|
+
const cache = [];
|
|
85
|
+
const contentMap = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const prompt of this.prompts) {
|
|
87
|
+
try {
|
|
88
|
+
if (prompt.type === "inline") {
|
|
89
|
+
const { info, content } = this.processInlinePrompt(prompt);
|
|
90
|
+
cache.push(info);
|
|
91
|
+
contentMap.set(info.name, content);
|
|
92
|
+
} else if (prompt.type === "file") {
|
|
93
|
+
const result = await this.processFilePrompt(prompt);
|
|
94
|
+
if (result) {
|
|
95
|
+
cache.push(result.info);
|
|
96
|
+
contentMap.set(result.info.name, result.content);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
this.logger.warn(
|
|
101
|
+
`Failed to process prompt: ${error instanceof Error ? error.message : String(error)}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
cache.sort((a, b) => {
|
|
106
|
+
const priorityA = a.metadata?.priority ?? 0;
|
|
107
|
+
const priorityB = b.metadata?.priority ?? 0;
|
|
108
|
+
return priorityB - priorityA;
|
|
109
|
+
});
|
|
110
|
+
this.promptsCache = cache;
|
|
111
|
+
this.promptContent = contentMap;
|
|
112
|
+
this.cacheValid = true;
|
|
113
|
+
this.logger.debug(`Cached ${cache.length} config prompts`);
|
|
114
|
+
}
|
|
115
|
+
processInlinePrompt(prompt) {
|
|
116
|
+
const promptName = `config:${prompt.id}`;
|
|
117
|
+
const promptInfo = {
|
|
118
|
+
name: promptName,
|
|
119
|
+
title: prompt.title,
|
|
120
|
+
description: prompt.description,
|
|
121
|
+
source: "config",
|
|
122
|
+
metadata: {
|
|
123
|
+
type: "inline",
|
|
124
|
+
category: prompt.category,
|
|
125
|
+
priority: prompt.priority,
|
|
126
|
+
showInStarters: prompt.showInStarters,
|
|
127
|
+
originalId: prompt.id
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return { info: promptInfo, content: prompt.prompt };
|
|
131
|
+
}
|
|
132
|
+
async processFilePrompt(prompt) {
|
|
133
|
+
const filePath = prompt.file;
|
|
134
|
+
if (!existsSync(filePath)) {
|
|
135
|
+
this.logger.warn(`Prompt file not found: ${filePath}`);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const resolvedDir = await realpath(dirname(filePath));
|
|
140
|
+
const resolvedFile = await realpath(filePath);
|
|
141
|
+
const rel = relative(resolvedDir, resolvedFile);
|
|
142
|
+
if (rel.startsWith(".." + sep) || rel === "..") {
|
|
143
|
+
this.logger.warn(
|
|
144
|
+
`Skipping prompt file '${filePath}': path traversal attempt detected (resolved outside directory)`
|
|
145
|
+
);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
} catch (realpathError) {
|
|
149
|
+
this.logger.warn(
|
|
150
|
+
`Skipping prompt file '${filePath}': unable to resolve path (${realpathError instanceof Error ? realpathError.message : String(realpathError)})`
|
|
151
|
+
);
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const rawContent = await readFile(filePath, "utf-8");
|
|
156
|
+
const parsed = this.parseMarkdownPrompt(rawContent, filePath);
|
|
157
|
+
try {
|
|
158
|
+
assertValidPromptName(parsed.id, {
|
|
159
|
+
context: `file prompt '${filePath}'`,
|
|
160
|
+
hint: "Use kebab-case in the 'id:' frontmatter field or file name."
|
|
161
|
+
});
|
|
162
|
+
} catch (validationError) {
|
|
163
|
+
this.logger.warn(
|
|
164
|
+
`Invalid prompt name in '${filePath}': ${validationError instanceof Error ? validationError.message : String(validationError)}`
|
|
165
|
+
);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const promptInfo = {
|
|
169
|
+
name: `config:${parsed.id}`,
|
|
170
|
+
title: parsed.title,
|
|
171
|
+
description: parsed.description,
|
|
172
|
+
source: "config",
|
|
173
|
+
...parsed.arguments && { arguments: parsed.arguments },
|
|
174
|
+
metadata: {
|
|
175
|
+
type: "file",
|
|
176
|
+
filePath,
|
|
177
|
+
category: parsed.category,
|
|
178
|
+
priority: parsed.priority,
|
|
179
|
+
showInStarters: prompt.showInStarters,
|
|
180
|
+
originalId: parsed.id
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
return { info: promptInfo, content: parsed.content };
|
|
184
|
+
} catch (error) {
|
|
185
|
+
this.logger.warn(
|
|
186
|
+
`Failed to read prompt file ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
187
|
+
);
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
parseMarkdownPrompt(rawContent, filePath) {
|
|
192
|
+
const lines = rawContent.trim().split("\n");
|
|
193
|
+
const fileName = filePath.split("/").pop()?.replace(/\.md$/, "") ?? "unknown";
|
|
194
|
+
let id = fileName;
|
|
195
|
+
let title = fileName;
|
|
196
|
+
let description = `File prompt: ${fileName}`;
|
|
197
|
+
let category;
|
|
198
|
+
let priority;
|
|
199
|
+
let argumentHint;
|
|
200
|
+
let contentBody;
|
|
201
|
+
if (lines[0]?.trim() === "---") {
|
|
202
|
+
let frontmatterEnd = 0;
|
|
203
|
+
for (let i = 1; i < lines.length; i++) {
|
|
204
|
+
if (lines[i]?.trim() === "---") {
|
|
205
|
+
frontmatterEnd = i;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (frontmatterEnd > 0) {
|
|
210
|
+
const frontmatterLines = lines.slice(1, frontmatterEnd);
|
|
211
|
+
contentBody = lines.slice(frontmatterEnd + 1).join("\n");
|
|
212
|
+
for (const line of frontmatterLines) {
|
|
213
|
+
const match = (key) => {
|
|
214
|
+
const regex = new RegExp(`${key}:\\s*(?:['"](.+)['"]|(.+))`);
|
|
215
|
+
const m = line.match(regex);
|
|
216
|
+
return m ? (m[1] || m[2] || "").trim() : null;
|
|
217
|
+
};
|
|
218
|
+
if (line.includes("id:")) {
|
|
219
|
+
const val = match("id");
|
|
220
|
+
if (val) id = val;
|
|
221
|
+
} else if (line.includes("title:")) {
|
|
222
|
+
const val = match("title");
|
|
223
|
+
if (val) title = val;
|
|
224
|
+
} else if (line.includes("description:")) {
|
|
225
|
+
const val = match("description");
|
|
226
|
+
if (val) description = val;
|
|
227
|
+
} else if (line.includes("category:")) {
|
|
228
|
+
const val = match("category");
|
|
229
|
+
if (val) category = val;
|
|
230
|
+
} else if (line.includes("priority:")) {
|
|
231
|
+
const val = match("priority");
|
|
232
|
+
if (val) priority = parseInt(val, 10);
|
|
233
|
+
} else if (line.includes("argument-hint:")) {
|
|
234
|
+
const val = match("argument-hint");
|
|
235
|
+
if (val) argumentHint = val;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
contentBody = rawContent;
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
contentBody = rawContent;
|
|
243
|
+
}
|
|
244
|
+
if (title === fileName) {
|
|
245
|
+
for (const line of contentBody.trim().split("\n")) {
|
|
246
|
+
if (line.trim().startsWith("#")) {
|
|
247
|
+
title = line.trim().replace(/^#+\s*/, "");
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const parsedArguments = argumentHint ? this.parseArgumentHint(argumentHint) : void 0;
|
|
253
|
+
return {
|
|
254
|
+
id,
|
|
255
|
+
title,
|
|
256
|
+
description,
|
|
257
|
+
content: contentBody.trim(),
|
|
258
|
+
...category !== void 0 && { category },
|
|
259
|
+
...priority !== void 0 && { priority },
|
|
260
|
+
...parsedArguments !== void 0 && { arguments: parsedArguments }
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
parseArgumentHint(hint) {
|
|
264
|
+
const args = [];
|
|
265
|
+
const argPattern = /\[([^\]]+)\]/g;
|
|
266
|
+
let match;
|
|
267
|
+
while ((match = argPattern.exec(hint)) !== null) {
|
|
268
|
+
const argText = match[1];
|
|
269
|
+
if (!argText) continue;
|
|
270
|
+
const isOptional = argText.endsWith("?");
|
|
271
|
+
const name = isOptional ? argText.slice(0, -1).trim() : argText.trim();
|
|
272
|
+
if (name) {
|
|
273
|
+
args.push({
|
|
274
|
+
name,
|
|
275
|
+
required: !isOptional
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return args;
|
|
280
|
+
}
|
|
281
|
+
applyArguments(content, args) {
|
|
282
|
+
const detectionTarget = content.replaceAll("$$", "");
|
|
283
|
+
const usesPositionalPlaceholders = /\$[1-9](?!\d)/.test(detectionTarget) || detectionTarget.includes("$ARGUMENTS");
|
|
284
|
+
const expanded = expandPlaceholders(content, args).trim();
|
|
285
|
+
if (!args || typeof args !== "object" || Object.keys(args).length === 0) {
|
|
286
|
+
return expanded;
|
|
287
|
+
}
|
|
288
|
+
if (!usesPositionalPlaceholders) {
|
|
289
|
+
if (args._context) {
|
|
290
|
+
const contextString = String(args._context);
|
|
291
|
+
return `${expanded}
|
|
292
|
+
|
|
293
|
+
Context: ${contextString}`;
|
|
294
|
+
}
|
|
295
|
+
const argEntries = Object.entries(args).filter(([key]) => !key.startsWith("_"));
|
|
296
|
+
if (argEntries.length > 0) {
|
|
297
|
+
const formattedArgs = argEntries.map(([key, value]) => `${key}: ${value}`).join(", ");
|
|
298
|
+
return `${expanded}
|
|
299
|
+
|
|
300
|
+
Arguments: ${formattedArgs}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return expanded;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
export {
|
|
307
|
+
ConfigPromptProvider
|
|
308
|
+
};
|
package/dist/prompts/schemas.cjs
CHANGED
|
@@ -18,37 +18,56 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var schemas_exports = {};
|
|
20
20
|
__export(schemas_exports, {
|
|
21
|
-
|
|
21
|
+
FilePromptSchema: () => FilePromptSchema,
|
|
22
|
+
InlinePromptSchema: () => InlinePromptSchema,
|
|
23
|
+
PromptsSchema: () => PromptsSchema
|
|
22
24
|
});
|
|
23
25
|
module.exports = __toCommonJS(schemas_exports);
|
|
24
26
|
var import_zod = require("zod");
|
|
25
27
|
var import_name_validation = require("./name-validation.js");
|
|
26
|
-
const
|
|
27
|
-
import_zod.z.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
).
|
|
28
|
+
const InlinePromptSchema = import_zod.z.object({
|
|
29
|
+
type: import_zod.z.literal("inline").describe("Inline prompt type"),
|
|
30
|
+
id: import_zod.z.string().min(1).max(64).regex(import_name_validation.PROMPT_NAME_REGEX, `Prompt id must be ${import_name_validation.PROMPT_NAME_GUIDANCE}`).describe("Kebab-case slug id for the prompt (e.g., quick-start)"),
|
|
31
|
+
title: import_zod.z.string().optional().describe("Display title for the prompt"),
|
|
32
|
+
description: import_zod.z.string().optional().default("").describe("Description shown on hover or in the UI"),
|
|
33
|
+
prompt: import_zod.z.string().describe("The actual prompt text"),
|
|
34
|
+
category: import_zod.z.string().optional().default("general").describe("Category for organizing prompts (e.g., general, coding, analysis, tools)"),
|
|
35
|
+
priority: import_zod.z.number().optional().default(0).describe("Higher numbers appear first in the list"),
|
|
36
|
+
showInStarters: import_zod.z.boolean().optional().default(false).describe("Show as a clickable button in WebUI starter prompts")
|
|
37
|
+
}).strict().describe("Inline prompt with text defined directly in config");
|
|
38
|
+
const FilePromptSchema = import_zod.z.object({
|
|
39
|
+
type: import_zod.z.literal("file").describe("File-based prompt type"),
|
|
40
|
+
file: import_zod.z.string().describe(
|
|
41
|
+
"Path to markdown file containing prompt (supports ${{dexto.agent_dir}} template)"
|
|
42
|
+
),
|
|
43
|
+
showInStarters: import_zod.z.boolean().optional().default(false).describe("Show as a clickable button in WebUI starter prompts")
|
|
44
|
+
}).strict().describe("File-based prompt loaded from a markdown file");
|
|
45
|
+
const PromptsSchema = import_zod.z.array(import_zod.z.discriminatedUnion("type", [InlinePromptSchema, FilePromptSchema])).superRefine((arr, ctx) => {
|
|
38
46
|
const seen = /* @__PURE__ */ new Map();
|
|
39
47
|
arr.forEach((p, idx) => {
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
if (p.type === "inline") {
|
|
49
|
+
if (seen.has(p.id)) {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
52
|
+
message: `Duplicate prompt id: ${p.id}`,
|
|
53
|
+
path: [idx, "id"]
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
seen.set(p.id, idx);
|
|
57
|
+
}
|
|
48
58
|
}
|
|
49
59
|
});
|
|
50
|
-
}).transform(
|
|
60
|
+
}).transform(
|
|
61
|
+
(arr) => arr.map((p) => {
|
|
62
|
+
if (p.type === "inline") {
|
|
63
|
+
return { ...p, title: p.title ?? p.id.replace(/-/g, " ") };
|
|
64
|
+
}
|
|
65
|
+
return p;
|
|
66
|
+
})
|
|
67
|
+
).default([]).describe("Agent prompts - inline text or file-based");
|
|
51
68
|
// Annotate the CommonJS export names for ESM import in node:
|
|
52
69
|
0 && (module.exports = {
|
|
53
|
-
|
|
70
|
+
FilePromptSchema,
|
|
71
|
+
InlinePromptSchema,
|
|
72
|
+
PromptsSchema
|
|
54
73
|
});
|
|
@@ -1,65 +1,174 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Zod schemas for prompt-related configurations
|
|
3
|
+
*
|
|
4
|
+
* Unified prompt system with discriminated union:
|
|
5
|
+
* - type: 'inline' - Prompt text defined directly in config
|
|
6
|
+
* - type: 'file' - Prompt loaded from a markdown file
|
|
7
|
+
*
|
|
8
|
+
* Both support showInStarters flag to control WebUI button display.
|
|
3
9
|
*/
|
|
4
10
|
import { z } from 'zod';
|
|
5
11
|
/**
|
|
6
|
-
* Schema for
|
|
7
|
-
*
|
|
8
|
-
* Starter prompts appear as clickable buttons in the WebUI, providing users
|
|
9
|
-
* with quick-start templates for common tasks and interactions.
|
|
12
|
+
* Schema for inline prompts - text defined directly in config
|
|
10
13
|
*/
|
|
11
|
-
export declare const
|
|
14
|
+
export declare const InlinePromptSchema: z.ZodObject<{
|
|
15
|
+
type: z.ZodLiteral<"inline">;
|
|
12
16
|
id: z.ZodString;
|
|
13
17
|
title: z.ZodOptional<z.ZodString>;
|
|
14
18
|
description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
15
19
|
prompt: z.ZodString;
|
|
16
20
|
category: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
17
21
|
priority: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
22
|
+
showInStarters: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
18
23
|
}, "strict", z.ZodTypeAny, {
|
|
19
24
|
prompt: string;
|
|
20
25
|
description: string;
|
|
26
|
+
type: "inline";
|
|
21
27
|
id: string;
|
|
22
28
|
priority: number;
|
|
23
29
|
category: string;
|
|
30
|
+
showInStarters: boolean;
|
|
24
31
|
title?: string | undefined;
|
|
25
32
|
}, {
|
|
26
33
|
prompt: string;
|
|
34
|
+
type: "inline";
|
|
27
35
|
id: string;
|
|
28
36
|
description?: string | undefined;
|
|
29
37
|
title?: string | undefined;
|
|
30
38
|
priority?: number | undefined;
|
|
31
39
|
category?: string | undefined;
|
|
32
|
-
|
|
40
|
+
showInStarters?: boolean | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Schema for file-based prompts - loaded from markdown files
|
|
44
|
+
*/
|
|
45
|
+
export declare const FilePromptSchema: z.ZodObject<{
|
|
46
|
+
type: z.ZodLiteral<"file">;
|
|
47
|
+
file: z.ZodString;
|
|
48
|
+
showInStarters: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
49
|
+
}, "strict", z.ZodTypeAny, {
|
|
50
|
+
file: string;
|
|
51
|
+
type: "file";
|
|
52
|
+
showInStarters: boolean;
|
|
53
|
+
}, {
|
|
54
|
+
file: string;
|
|
55
|
+
type: "file";
|
|
56
|
+
showInStarters?: boolean | undefined;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Unified prompts schema - array of inline or file-based prompts
|
|
60
|
+
* Replaces the old StarterPromptsSchema
|
|
61
|
+
*/
|
|
62
|
+
export declare const PromptsSchema: z.ZodDefault<z.ZodEffects<z.ZodEffects<z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
63
|
+
type: z.ZodLiteral<"inline">;
|
|
64
|
+
id: z.ZodString;
|
|
65
|
+
title: z.ZodOptional<z.ZodString>;
|
|
66
|
+
description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
67
|
+
prompt: z.ZodString;
|
|
68
|
+
category: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
69
|
+
priority: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
70
|
+
showInStarters: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
71
|
+
}, "strict", z.ZodTypeAny, {
|
|
33
72
|
prompt: string;
|
|
34
73
|
description: string;
|
|
74
|
+
type: "inline";
|
|
35
75
|
id: string;
|
|
36
76
|
priority: number;
|
|
37
77
|
category: string;
|
|
78
|
+
showInStarters: boolean;
|
|
38
79
|
title?: string | undefined;
|
|
39
|
-
}
|
|
80
|
+
}, {
|
|
40
81
|
prompt: string;
|
|
82
|
+
type: "inline";
|
|
41
83
|
id: string;
|
|
42
84
|
description?: string | undefined;
|
|
43
85
|
title?: string | undefined;
|
|
44
86
|
priority?: number | undefined;
|
|
45
87
|
category?: string | undefined;
|
|
46
|
-
|
|
88
|
+
showInStarters?: boolean | undefined;
|
|
89
|
+
}>, z.ZodObject<{
|
|
90
|
+
type: z.ZodLiteral<"file">;
|
|
91
|
+
file: z.ZodString;
|
|
92
|
+
showInStarters: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
93
|
+
}, "strict", z.ZodTypeAny, {
|
|
94
|
+
file: string;
|
|
95
|
+
type: "file";
|
|
96
|
+
showInStarters: boolean;
|
|
97
|
+
}, {
|
|
98
|
+
file: string;
|
|
99
|
+
type: "file";
|
|
100
|
+
showInStarters?: boolean | undefined;
|
|
101
|
+
}>]>, "many">, ({
|
|
102
|
+
prompt: string;
|
|
103
|
+
description: string;
|
|
104
|
+
type: "inline";
|
|
105
|
+
id: string;
|
|
106
|
+
priority: number;
|
|
107
|
+
category: string;
|
|
108
|
+
showInStarters: boolean;
|
|
109
|
+
title?: string | undefined;
|
|
110
|
+
} | {
|
|
111
|
+
file: string;
|
|
112
|
+
type: "file";
|
|
113
|
+
showInStarters: boolean;
|
|
114
|
+
})[], ({
|
|
115
|
+
prompt: string;
|
|
116
|
+
type: "inline";
|
|
117
|
+
id: string;
|
|
118
|
+
description?: string | undefined;
|
|
119
|
+
title?: string | undefined;
|
|
120
|
+
priority?: number | undefined;
|
|
121
|
+
category?: string | undefined;
|
|
122
|
+
showInStarters?: boolean | undefined;
|
|
123
|
+
} | {
|
|
124
|
+
file: string;
|
|
125
|
+
type: "file";
|
|
126
|
+
showInStarters?: boolean | undefined;
|
|
127
|
+
})[]>, ({
|
|
128
|
+
file: string;
|
|
129
|
+
type: "file";
|
|
130
|
+
showInStarters: boolean;
|
|
131
|
+
} | {
|
|
47
132
|
title: string;
|
|
48
133
|
prompt: string;
|
|
49
134
|
description: string;
|
|
135
|
+
type: "inline";
|
|
50
136
|
id: string;
|
|
51
137
|
priority: number;
|
|
52
138
|
category: string;
|
|
53
|
-
|
|
139
|
+
showInStarters: boolean;
|
|
140
|
+
})[], ({
|
|
54
141
|
prompt: string;
|
|
142
|
+
type: "inline";
|
|
55
143
|
id: string;
|
|
56
144
|
description?: string | undefined;
|
|
57
145
|
title?: string | undefined;
|
|
58
146
|
priority?: number | undefined;
|
|
59
147
|
category?: string | undefined;
|
|
60
|
-
|
|
148
|
+
showInStarters?: boolean | undefined;
|
|
149
|
+
} | {
|
|
150
|
+
file: string;
|
|
151
|
+
type: "file";
|
|
152
|
+
showInStarters?: boolean | undefined;
|
|
153
|
+
})[]>>;
|
|
154
|
+
/**
|
|
155
|
+
* Type for a single inline prompt (validated)
|
|
156
|
+
*/
|
|
157
|
+
export type ValidatedInlinePrompt = z.output<typeof InlinePromptSchema>;
|
|
158
|
+
/**
|
|
159
|
+
* Type for a single file-based prompt (validated)
|
|
160
|
+
*/
|
|
161
|
+
export type ValidatedFilePrompt = z.output<typeof FilePromptSchema>;
|
|
162
|
+
/**
|
|
163
|
+
* Type for a single prompt (either inline or file)
|
|
164
|
+
*/
|
|
165
|
+
export type ValidatedPrompt = ValidatedInlinePrompt | ValidatedFilePrompt;
|
|
166
|
+
/**
|
|
167
|
+
* Validated prompts configuration type
|
|
168
|
+
*/
|
|
169
|
+
export type ValidatedPromptsConfig = z.output<typeof PromptsSchema>;
|
|
61
170
|
/**
|
|
62
|
-
*
|
|
171
|
+
* Input type for prompts configuration (before validation)
|
|
63
172
|
*/
|
|
64
|
-
export type
|
|
173
|
+
export type PromptsConfig = z.input<typeof PromptsSchema>;
|
|
65
174
|
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/prompts/schemas.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/prompts/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCoC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAeiC,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6BgC,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
package/dist/prompts/schemas.js
CHANGED
|
@@ -1,31 +1,48 @@
|
|
|
1
1
|
import "../chunk-C6A6W6XS.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { PROMPT_NAME_REGEX, PROMPT_NAME_GUIDANCE } from "./name-validation.js";
|
|
4
|
-
const
|
|
5
|
-
z.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
).
|
|
4
|
+
const InlinePromptSchema = z.object({
|
|
5
|
+
type: z.literal("inline").describe("Inline prompt type"),
|
|
6
|
+
id: z.string().min(1).max(64).regex(PROMPT_NAME_REGEX, `Prompt id must be ${PROMPT_NAME_GUIDANCE}`).describe("Kebab-case slug id for the prompt (e.g., quick-start)"),
|
|
7
|
+
title: z.string().optional().describe("Display title for the prompt"),
|
|
8
|
+
description: z.string().optional().default("").describe("Description shown on hover or in the UI"),
|
|
9
|
+
prompt: z.string().describe("The actual prompt text"),
|
|
10
|
+
category: z.string().optional().default("general").describe("Category for organizing prompts (e.g., general, coding, analysis, tools)"),
|
|
11
|
+
priority: z.number().optional().default(0).describe("Higher numbers appear first in the list"),
|
|
12
|
+
showInStarters: z.boolean().optional().default(false).describe("Show as a clickable button in WebUI starter prompts")
|
|
13
|
+
}).strict().describe("Inline prompt with text defined directly in config");
|
|
14
|
+
const FilePromptSchema = z.object({
|
|
15
|
+
type: z.literal("file").describe("File-based prompt type"),
|
|
16
|
+
file: z.string().describe(
|
|
17
|
+
"Path to markdown file containing prompt (supports ${{dexto.agent_dir}} template)"
|
|
18
|
+
),
|
|
19
|
+
showInStarters: z.boolean().optional().default(false).describe("Show as a clickable button in WebUI starter prompts")
|
|
20
|
+
}).strict().describe("File-based prompt loaded from a markdown file");
|
|
21
|
+
const PromptsSchema = z.array(z.discriminatedUnion("type", [InlinePromptSchema, FilePromptSchema])).superRefine((arr, ctx) => {
|
|
16
22
|
const seen = /* @__PURE__ */ new Map();
|
|
17
23
|
arr.forEach((p, idx) => {
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (p.type === "inline") {
|
|
25
|
+
if (seen.has(p.id)) {
|
|
26
|
+
ctx.addIssue({
|
|
27
|
+
code: z.ZodIssueCode.custom,
|
|
28
|
+
message: `Duplicate prompt id: ${p.id}`,
|
|
29
|
+
path: [idx, "id"]
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
seen.set(p.id, idx);
|
|
33
|
+
}
|
|
26
34
|
}
|
|
27
35
|
});
|
|
28
|
-
}).transform(
|
|
36
|
+
}).transform(
|
|
37
|
+
(arr) => arr.map((p) => {
|
|
38
|
+
if (p.type === "inline") {
|
|
39
|
+
return { ...p, title: p.title ?? p.id.replace(/-/g, " ") };
|
|
40
|
+
}
|
|
41
|
+
return p;
|
|
42
|
+
})
|
|
43
|
+
).default([]).describe("Agent prompts - inline text or file-based");
|
|
29
44
|
export {
|
|
30
|
-
|
|
45
|
+
FilePromptSchema,
|
|
46
|
+
InlinePromptSchema,
|
|
47
|
+
PromptsSchema
|
|
31
48
|
};
|
package/dist/prompts/types.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface PromptDefinition {
|
|
|
22
22
|
* Enhanced prompt info with MCP-compliant structure
|
|
23
23
|
*/
|
|
24
24
|
export interface PromptInfo extends PromptDefinition {
|
|
25
|
-
source: 'mcp' | '
|
|
25
|
+
source: 'mcp' | 'config' | 'custom';
|
|
26
26
|
metadata?: Record<string, unknown>;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/prompts/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,MAAM,EAAE,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/prompts/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC;IAEpB;;OAEG;IACH,eAAe,IAAI,IAAI,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAExD;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAElF;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CACvE"}
|