promptopskit 0.5.0 → 0.7.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/README.md +9 -7
- package/SKILL.md +16 -10
- package/dist/{chunk-QK3WKE3K.js → chunk-35NN5F6O.js} +2 -2
- package/dist/{chunk-D75HKF64.js → chunk-3G3EAV7H.js} +2 -2
- package/dist/{chunk-LNGHGGJN.js → chunk-6NOUETAC.js} +2 -2
- package/dist/{chunk-KN7H4JRK.js → chunk-F552OBUV.js} +619 -502
- package/dist/chunk-F552OBUV.js.map +1 -0
- package/dist/{chunk-6BOUQVSX.js → chunk-FICB2ZSK.js} +3 -3
- package/dist/{chunk-6VLKZCNS.js → chunk-OWMP5NMV.js} +2 -2
- package/dist/{chunk-IN4KT5EU.js → chunk-R65RAHAG.js} +3 -3
- package/dist/{chunk-K6ZU3CGV.js → chunk-ULVY473P.js} +306 -17
- package/dist/chunk-ULVY473P.js.map +1 -0
- package/dist/cli/index.js +446 -103
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1223 -772
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +67 -18
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +902 -502
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +2 -2
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +3 -3
- package/dist/providers/gemini.cjs +902 -502
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.d.cts +2 -2
- package/dist/providers/gemini.d.ts +2 -2
- package/dist/providers/gemini.js +3 -3
- package/dist/providers/llmasaservice.cjs +901 -501
- package/dist/providers/llmasaservice.cjs.map +1 -1
- package/dist/providers/llmasaservice.d.cts +2 -2
- package/dist/providers/llmasaservice.d.ts +2 -2
- package/dist/providers/llmasaservice.js +4 -4
- package/dist/providers/openai-responses.cjs +902 -502
- package/dist/providers/openai-responses.cjs.map +1 -1
- package/dist/providers/openai-responses.d.cts +2 -2
- package/dist/providers/openai-responses.d.ts +2 -2
- package/dist/providers/openai-responses.js +3 -3
- package/dist/providers/openai.cjs +902 -502
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +2 -2
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +3 -3
- package/dist/providers/openrouter.cjs +902 -502
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.d.cts +2 -2
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/openrouter.js +4 -4
- package/dist/{schema-D-RI4w-k.d.cts → schema-DBcSns_b.d.cts} +732 -206
- package/dist/{schema-D-RI4w-k.d.ts → schema-DBcSns_b.d.ts} +732 -206
- package/dist/testing.cjs +54 -5
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-B3dxBGu6.d.ts → types-8T2D5KB5.d.cts} +20 -2
- package/dist/{types-DbTAjlTN.d.cts → types-BlLXT5Qb.d.ts} +20 -2
- package/dist/usagetap/index.d.cts +2 -2
- package/dist/usagetap/index.d.ts +2 -2
- package/package.json +9 -2
- package/dist/chunk-K6ZU3CGV.js.map +0 -1
- package/dist/chunk-KN7H4JRK.js.map +0 -1
- /package/dist/{chunk-QK3WKE3K.js.map → chunk-35NN5F6O.js.map} +0 -0
- /package/dist/{chunk-D75HKF64.js.map → chunk-3G3EAV7H.js.map} +0 -0
- /package/dist/{chunk-LNGHGGJN.js.map → chunk-6NOUETAC.js.map} +0 -0
- /package/dist/{chunk-6BOUQVSX.js.map → chunk-FICB2ZSK.js.map} +0 -0
- /package/dist/{chunk-6VLKZCNS.js.map → chunk-OWMP5NMV.js.map} +0 -0
- /package/dist/{chunk-IN4KT5EU.js.map → chunk-R65RAHAG.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
5
5
|
|
|
6
6
|
// src/cli/commands/validate.ts
|
|
7
7
|
import { readdir, stat } from "fs/promises";
|
|
8
|
-
import { join as join3, extname } from "path";
|
|
8
|
+
import { join as join3, extname as extname2 } from "path";
|
|
9
9
|
|
|
10
10
|
// src/parser/parser.ts
|
|
11
11
|
import matter from "gray-matter";
|
|
@@ -41,10 +41,26 @@ var ResponseSchema = z.object({
|
|
|
41
41
|
format: z.enum(["text", "json", "markdown"]).optional(),
|
|
42
42
|
stream: z.boolean().optional(),
|
|
43
43
|
schema: z.record(z.unknown()).optional(),
|
|
44
|
+
schema_ref: z.string().min(1).optional(),
|
|
45
|
+
schema_source: z.object({
|
|
46
|
+
mode: z.enum(["inline", "schema_ref_json", "schema_ref_zod_module"]).optional(),
|
|
47
|
+
ref: z.string().optional(),
|
|
48
|
+
resolved_path: z.string().optional(),
|
|
49
|
+
hash: z.string().optional()
|
|
50
|
+
}).optional(),
|
|
44
51
|
schema_name: z.string().optional(),
|
|
45
52
|
schema_description: z.string().optional(),
|
|
46
53
|
schema_strict: z.boolean().optional()
|
|
47
54
|
});
|
|
55
|
+
var ResponseSchemaWithValidation = ResponseSchema.superRefine((value, ctx) => {
|
|
56
|
+
if (value.schema !== void 0 && value.schema_ref !== void 0) {
|
|
57
|
+
ctx.addIssue({
|
|
58
|
+
code: z.ZodIssueCode.custom,
|
|
59
|
+
message: "response.schema and response.schema_ref are mutually exclusive",
|
|
60
|
+
path: ["schema_ref"]
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
48
64
|
var AnthropicProviderOptionsSchema = z.object({
|
|
49
65
|
top_k: z.number().int().min(0).optional(),
|
|
50
66
|
tool_choice: z.record(z.unknown()).optional(),
|
|
@@ -96,6 +112,14 @@ var RawProviderBodySchema = z.object({
|
|
|
96
112
|
openrouter: z.record(z.unknown()).optional(),
|
|
97
113
|
llmasaservice: z.record(z.unknown()).optional()
|
|
98
114
|
});
|
|
115
|
+
var TheTokenCompanyCompressionSchema = z.object({
|
|
116
|
+
enabled: z.boolean().optional(),
|
|
117
|
+
model: z.string().min(1).optional(),
|
|
118
|
+
aggressiveness: z.number().min(0).max(1).optional()
|
|
119
|
+
});
|
|
120
|
+
var CompressionSchema = z.object({
|
|
121
|
+
thetokencompany: TheTokenCompanyCompressionSchema.optional()
|
|
122
|
+
});
|
|
99
123
|
var OpenAICacheSchema = z.object({
|
|
100
124
|
prompt_cache_key: z.string().min(1).optional(),
|
|
101
125
|
retention: z.enum(["in_memory", "24h"]).optional()
|
|
@@ -136,6 +160,8 @@ var ContextBuiltInValidatorSchema = z.union([
|
|
|
136
160
|
]);
|
|
137
161
|
var ContextInputDefinitionObjectSchema = z.object({
|
|
138
162
|
name: z.string(),
|
|
163
|
+
optional: z.boolean().optional(),
|
|
164
|
+
warnings: z.boolean().optional(),
|
|
139
165
|
max_size: z.number().int().positive().optional(),
|
|
140
166
|
trim: z.union([z.boolean(), z.enum(["start", "end", "both"])]).optional(),
|
|
141
167
|
allow_regex: ContextRegexSchema.optional(),
|
|
@@ -165,7 +191,8 @@ var PromptAssetOverridesSchema = z.object({
|
|
|
165
191
|
fallback_models: z.array(z.string()).optional(),
|
|
166
192
|
reasoning: ReasoningSchema.optional(),
|
|
167
193
|
sampling: SamplingSchema.optional(),
|
|
168
|
-
response:
|
|
194
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
195
|
+
compression: CompressionSchema.optional(),
|
|
169
196
|
cache: CacheSchema.optional(),
|
|
170
197
|
raw: RawProviderBodySchema.optional(),
|
|
171
198
|
tools: z.array(ToolRefSchema).optional(),
|
|
@@ -183,7 +210,20 @@ var SectionsSchema = z.object({
|
|
|
183
210
|
var PromptDefaultsSchema = z.object({
|
|
184
211
|
provider: z.enum(["openai", "openai-responses", "anthropic", "google", "gemini", "openrouter", "llmasaservice", "any"]).optional(),
|
|
185
212
|
model: z.string().optional(),
|
|
213
|
+
fallback_models: z.array(z.string()).optional(),
|
|
214
|
+
reasoning: ReasoningSchema.optional(),
|
|
215
|
+
sampling: SamplingSchema.optional(),
|
|
216
|
+
response: ResponseSchema.optional(),
|
|
217
|
+
compression: CompressionSchema.optional(),
|
|
186
218
|
cache: CacheSchema.optional(),
|
|
219
|
+
raw: RawProviderBodySchema.optional(),
|
|
220
|
+
tools: z.array(ToolRefSchema).optional(),
|
|
221
|
+
provider_options: ProviderOptionsSchema.optional(),
|
|
222
|
+
mcp: MCPSchema.optional(),
|
|
223
|
+
context: ContextSchema.optional(),
|
|
224
|
+
includes: z.array(z.string()).optional(),
|
|
225
|
+
environments: z.record(PromptAssetOverridesSchema).optional(),
|
|
226
|
+
tiers: z.record(PromptAssetOverridesSchema).optional(),
|
|
187
227
|
metadata: MetadataSchema.optional(),
|
|
188
228
|
sections: z.object({
|
|
189
229
|
system_instructions: z.string().optional()
|
|
@@ -198,7 +238,8 @@ var PromptAssetSchema = z.object({
|
|
|
198
238
|
fallback_models: z.array(z.string()).optional(),
|
|
199
239
|
reasoning: ReasoningSchema.optional(),
|
|
200
240
|
sampling: SamplingSchema.optional(),
|
|
201
|
-
response:
|
|
241
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
242
|
+
compression: CompressionSchema.optional(),
|
|
202
243
|
cache: CacheSchema.optional(),
|
|
203
244
|
raw: RawProviderBodySchema.optional(),
|
|
204
245
|
tools: z.array(ToolRefSchema).optional(),
|
|
@@ -390,16 +431,122 @@ function parsePrompt(content, filePath) {
|
|
|
390
431
|
}
|
|
391
432
|
|
|
392
433
|
// src/parser/loader.ts
|
|
393
|
-
import { readFile } from "fs/promises";
|
|
394
|
-
import { dirname, join, resolve } from "path";
|
|
434
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
435
|
+
import { dirname as dirname2, join, relative, resolve as resolve2 } from "path";
|
|
395
436
|
import matter2 from "gray-matter";
|
|
437
|
+
|
|
438
|
+
// src/parser/response-schema-ref.ts
|
|
439
|
+
import { readFile } from "fs/promises";
|
|
440
|
+
import { createHash } from "crypto";
|
|
441
|
+
import { dirname, extname, resolve } from "path";
|
|
442
|
+
import { pathToFileURL } from "url";
|
|
443
|
+
import { z as z2 } from "zod";
|
|
444
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
445
|
+
var SUPPORTED_SCHEMA_REF_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
446
|
+
async function resolveJsonSchemaRef(schemaRef, promptFilePath) {
|
|
447
|
+
const resolvedPath = resolve(dirname(promptFilePath), schemaRef);
|
|
448
|
+
let raw;
|
|
449
|
+
try {
|
|
450
|
+
raw = await readFile(resolvedPath, "utf-8");
|
|
451
|
+
} catch (error) {
|
|
452
|
+
const code = error.code;
|
|
453
|
+
if (code === "ENOENT") {
|
|
454
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
455
|
+
}
|
|
456
|
+
throw error;
|
|
457
|
+
}
|
|
458
|
+
let parsed;
|
|
459
|
+
try {
|
|
460
|
+
parsed = JSON.parse(raw);
|
|
461
|
+
} catch {
|
|
462
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" is not valid JSON`);
|
|
463
|
+
}
|
|
464
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
465
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" must resolve to a JSON object schema`);
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
schema: parsed,
|
|
469
|
+
resolvedPath,
|
|
470
|
+
hash: createHash("sha256").update(raw).digest("hex")
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function resolveZodSchemaRef(schemaRef, promptFilePath) {
|
|
474
|
+
const resolvedPath = resolve(dirname(promptFilePath), schemaRef);
|
|
475
|
+
let moduleSource;
|
|
476
|
+
try {
|
|
477
|
+
moduleSource = await readFile(resolvedPath, "utf-8");
|
|
478
|
+
} catch (error) {
|
|
479
|
+
const code = error.code;
|
|
480
|
+
if (code === "ENOENT") {
|
|
481
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
482
|
+
}
|
|
483
|
+
throw error;
|
|
484
|
+
}
|
|
485
|
+
let imported;
|
|
486
|
+
try {
|
|
487
|
+
imported = await import(pathToFileURL(resolvedPath).href);
|
|
488
|
+
} catch (error) {
|
|
489
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
490
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" could not be imported as a module (${message})`);
|
|
491
|
+
}
|
|
492
|
+
const mod = imported;
|
|
493
|
+
const candidate = mod.default ?? mod.schema;
|
|
494
|
+
if (!(candidate instanceof z2.ZodType)) {
|
|
495
|
+
throw new Error('POK051: zod schema modules must export a Zod schema as default export or named export "schema"');
|
|
496
|
+
}
|
|
497
|
+
const jsonSchema = zodToJsonSchema(candidate, {
|
|
498
|
+
target: "jsonSchema7",
|
|
499
|
+
$refStrategy: "none"
|
|
500
|
+
});
|
|
501
|
+
if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
|
|
502
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" did not produce a valid JSON schema object`);
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
schema: jsonSchema,
|
|
506
|
+
resolvedPath,
|
|
507
|
+
hash: createHash("sha256").update(moduleSource).digest("hex")
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
async function resolveResponseSchemaRef(asset, promptFilePath) {
|
|
511
|
+
const schemaRef = asset.response?.schema_ref;
|
|
512
|
+
if (!schemaRef) return asset;
|
|
513
|
+
const ext = extname(schemaRef).toLowerCase();
|
|
514
|
+
if (!SUPPORTED_SCHEMA_REF_EXTENSIONS.has(ext)) {
|
|
515
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" has unsupported extension "${ext}". Use .json, .js, .mjs, or .cjs`);
|
|
516
|
+
}
|
|
517
|
+
const resolved = ext === ".json" ? await resolveJsonSchemaRef(schemaRef, promptFilePath) : await resolveZodSchemaRef(schemaRef, promptFilePath);
|
|
518
|
+
return {
|
|
519
|
+
...asset,
|
|
520
|
+
response: {
|
|
521
|
+
...asset.response,
|
|
522
|
+
schema: resolved.schema,
|
|
523
|
+
schema_ref: void 0,
|
|
524
|
+
schema_source: {
|
|
525
|
+
mode: ext === ".json" ? "schema_ref_json" : "schema_ref_zod_module",
|
|
526
|
+
ref: schemaRef,
|
|
527
|
+
resolved_path: resolved.resolvedPath,
|
|
528
|
+
hash: resolved.hash
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// src/parser/loader.ts
|
|
396
535
|
var DEFAULTS_FILE_NAME = "defaults.md";
|
|
397
536
|
async function loadPromptFile(filePath, options = {}) {
|
|
398
|
-
const content = await
|
|
537
|
+
const content = await readFile2(filePath, "utf-8");
|
|
399
538
|
const parsed = parsePrompt(content, filePath);
|
|
400
|
-
const root = options.defaultsRoot ??
|
|
539
|
+
const root = options.defaultsRoot ?? dirname2(filePath);
|
|
401
540
|
const defaults = await loadDefaultsForPath(filePath, root);
|
|
402
|
-
const
|
|
541
|
+
const withDefaults = applyDefaults(parsed.asset, defaults);
|
|
542
|
+
const resolved = await resolveResponseSchemaRef(withDefaults, filePath);
|
|
543
|
+
const asset = resolved.response?.schema !== void 0 && !resolved.response?.schema_source ? {
|
|
544
|
+
...resolved,
|
|
545
|
+
response: {
|
|
546
|
+
...resolved.response,
|
|
547
|
+
schema_source: { mode: "inline" }
|
|
548
|
+
}
|
|
549
|
+
} : resolved;
|
|
403
550
|
return {
|
|
404
551
|
...parsed,
|
|
405
552
|
asset
|
|
@@ -411,8 +558,8 @@ async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
|
411
558
|
for (const dir of directories) {
|
|
412
559
|
const defaultsPath = join(dir, DEFAULTS_FILE_NAME);
|
|
413
560
|
try {
|
|
414
|
-
const defaultsContent = await
|
|
415
|
-
const defaults = parseDefaults(defaultsContent);
|
|
561
|
+
const defaultsContent = await readFile2(defaultsPath, "utf-8");
|
|
562
|
+
const defaults = normalizeDefaultIncludes(parseDefaults(defaultsContent), defaultsPath, filePath);
|
|
416
563
|
merged = mergeDefaults(merged, defaults);
|
|
417
564
|
} catch (error) {
|
|
418
565
|
if (error.code !== "ENOENT") {
|
|
@@ -424,14 +571,14 @@ async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
|
424
571
|
}
|
|
425
572
|
function getDirectoriesToCheck(filePath, defaultsRoot) {
|
|
426
573
|
const dirs = [];
|
|
427
|
-
let current =
|
|
428
|
-
const boundary = defaultsRoot ?
|
|
574
|
+
let current = resolve2(dirname2(filePath));
|
|
575
|
+
const boundary = defaultsRoot ? resolve2(defaultsRoot) : void 0;
|
|
429
576
|
while (true) {
|
|
430
577
|
dirs.unshift(current);
|
|
431
|
-
if (boundary && current === boundary || current ===
|
|
578
|
+
if (boundary && current === boundary || current === dirname2(current)) {
|
|
432
579
|
break;
|
|
433
580
|
}
|
|
434
|
-
current =
|
|
581
|
+
current = dirname2(current);
|
|
435
582
|
}
|
|
436
583
|
return dirs;
|
|
437
584
|
}
|
|
@@ -449,7 +596,20 @@ function mergeDefaults(base, local) {
|
|
|
449
596
|
return {
|
|
450
597
|
provider: local.provider ?? base.provider,
|
|
451
598
|
model: local.model ?? base.model,
|
|
599
|
+
fallback_models: local.fallback_models ?? base.fallback_models,
|
|
600
|
+
reasoning: mergeRecordBlock(base.reasoning, local.reasoning),
|
|
601
|
+
sampling: mergeRecordBlock(base.sampling, local.sampling),
|
|
602
|
+
response: mergeRecordBlock(base.response, local.response),
|
|
603
|
+
compression: mergeCompression(base.compression, local.compression),
|
|
452
604
|
cache: mergeCache(base.cache, local.cache),
|
|
605
|
+
raw: mergeRaw(base.raw, local.raw),
|
|
606
|
+
tools: local.tools ?? base.tools,
|
|
607
|
+
provider_options: mergeProviderOptions(base.provider_options, local.provider_options),
|
|
608
|
+
mcp: mergeMcp(base.mcp, local.mcp),
|
|
609
|
+
context: mergeContext(base.context, local.context),
|
|
610
|
+
includes: local.includes ?? base.includes,
|
|
611
|
+
environments: mergeOverrideMap(base.environments, local.environments),
|
|
612
|
+
tiers: mergeOverrideMap(base.tiers, local.tiers),
|
|
453
613
|
metadata: {
|
|
454
614
|
...base.metadata ?? {},
|
|
455
615
|
...local.metadata ?? {}
|
|
@@ -461,12 +621,22 @@ function mergeDefaults(base, local) {
|
|
|
461
621
|
};
|
|
462
622
|
}
|
|
463
623
|
function applyDefaults(asset, defaults) {
|
|
624
|
+
const compression = mergeCompression(defaults.compression, asset.compression);
|
|
464
625
|
const cache = mergeCache(defaults.cache, asset.cache);
|
|
626
|
+
const raw = mergeRaw(defaults.raw, asset.raw);
|
|
627
|
+
const providerOptions = mergeProviderOptions(defaults.provider_options, asset.provider_options);
|
|
628
|
+
const reasoning = mergeRecordBlock(defaults.reasoning, asset.reasoning);
|
|
629
|
+
const sampling = mergeRecordBlock(defaults.sampling, asset.sampling);
|
|
630
|
+
const response = mergeRecordBlock(defaults.response, asset.response);
|
|
631
|
+
const mcp = mergeMcp(defaults.mcp, asset.mcp);
|
|
632
|
+
const context = mergeContext(defaults.context, asset.context);
|
|
633
|
+
const environments = mergeOverrideMap(defaults.environments, asset.environments);
|
|
634
|
+
const tiers = mergeOverrideMap(defaults.tiers, asset.tiers);
|
|
465
635
|
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
466
636
|
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
467
|
-
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0;
|
|
468
|
-
const
|
|
469
|
-
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !
|
|
637
|
+
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0 || defaults.fallback_models !== void 0 || defaults.tools !== void 0 || defaults.includes !== void 0;
|
|
638
|
+
const hasDefaultObjects = compression !== void 0 || cache !== void 0 || raw !== void 0 || providerOptions !== void 0 || reasoning !== void 0 || sampling !== void 0 || response !== void 0 || mcp !== void 0 || context !== void 0 || environments !== void 0 || tiers !== void 0;
|
|
639
|
+
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultObjects) {
|
|
470
640
|
return asset;
|
|
471
641
|
}
|
|
472
642
|
const mergedMetadata = {
|
|
@@ -480,11 +650,53 @@ function applyDefaults(asset, defaults) {
|
|
|
480
650
|
...asset,
|
|
481
651
|
provider: asset.provider ?? defaults.provider,
|
|
482
652
|
model: asset.model ?? defaults.model,
|
|
653
|
+
fallback_models: asset.fallback_models ?? defaults.fallback_models,
|
|
654
|
+
reasoning,
|
|
655
|
+
sampling,
|
|
656
|
+
response,
|
|
657
|
+
compression,
|
|
483
658
|
cache,
|
|
659
|
+
raw,
|
|
660
|
+
tools: asset.tools ?? defaults.tools,
|
|
661
|
+
provider_options: providerOptions,
|
|
662
|
+
mcp,
|
|
663
|
+
context,
|
|
664
|
+
includes: asset.includes ?? defaults.includes,
|
|
665
|
+
environments,
|
|
666
|
+
tiers,
|
|
484
667
|
metadata,
|
|
485
668
|
sections
|
|
486
669
|
};
|
|
487
670
|
}
|
|
671
|
+
function normalizeDefaultIncludes(defaults, defaultsPath, filePath) {
|
|
672
|
+
if (!defaults.includes) return defaults;
|
|
673
|
+
const promptDir = dirname2(filePath);
|
|
674
|
+
const defaultsDir = dirname2(defaultsPath);
|
|
675
|
+
const includes = defaults.includes.map((includePath) => {
|
|
676
|
+
const relativePath = relative(promptDir, resolve2(defaultsDir, includePath)).replace(/\\/g, "/");
|
|
677
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
678
|
+
});
|
|
679
|
+
return {
|
|
680
|
+
...defaults,
|
|
681
|
+
includes
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function mergeRecordBlock(base, local) {
|
|
685
|
+
if (base === void 0) return local;
|
|
686
|
+
if (local === void 0) return base;
|
|
687
|
+
return { ...base, ...local };
|
|
688
|
+
}
|
|
689
|
+
function mergeMcp(base, local) {
|
|
690
|
+
return mergeRecordBlock(base, local);
|
|
691
|
+
}
|
|
692
|
+
function mergeContext(base, local) {
|
|
693
|
+
const merged = {
|
|
694
|
+
...base ?? {},
|
|
695
|
+
...local ?? {},
|
|
696
|
+
history: mergeRecordBlock(base?.history, local?.history)
|
|
697
|
+
};
|
|
698
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
699
|
+
}
|
|
488
700
|
function mergeCache(base, local) {
|
|
489
701
|
const merged = {
|
|
490
702
|
...base ?? {},
|
|
@@ -512,6 +724,83 @@ function mergeCache(base, local) {
|
|
|
512
724
|
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
513
725
|
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
514
726
|
}
|
|
727
|
+
function mergeCompression(base, local) {
|
|
728
|
+
const merged = {
|
|
729
|
+
...base ?? {},
|
|
730
|
+
...local ?? {},
|
|
731
|
+
thetokencompany: mergeRecordBlock(base?.thetokencompany, local?.thetokencompany)
|
|
732
|
+
};
|
|
733
|
+
removeEmptyProviderBlocks(merged);
|
|
734
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
735
|
+
}
|
|
736
|
+
function mergeRaw(base, local) {
|
|
737
|
+
const merged = {
|
|
738
|
+
...base ?? {},
|
|
739
|
+
...local ?? {},
|
|
740
|
+
openai: mergeRecordBlock(base?.openai, local?.openai),
|
|
741
|
+
"openai-responses": mergeRecordBlock(base?.["openai-responses"], local?.["openai-responses"]),
|
|
742
|
+
openai_responses: mergeRecordBlock(base?.openai_responses, local?.openai_responses),
|
|
743
|
+
anthropic: mergeRecordBlock(base?.anthropic, local?.anthropic),
|
|
744
|
+
gemini: mergeRecordBlock(base?.gemini, local?.gemini),
|
|
745
|
+
google: mergeRecordBlock(base?.google, local?.google),
|
|
746
|
+
openrouter: mergeRecordBlock(base?.openrouter, local?.openrouter),
|
|
747
|
+
llmasaservice: mergeRecordBlock(base?.llmasaservice, local?.llmasaservice)
|
|
748
|
+
};
|
|
749
|
+
removeEmptyProviderBlocks(merged);
|
|
750
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
751
|
+
}
|
|
752
|
+
function mergeProviderOptions(base, local) {
|
|
753
|
+
const merged = {
|
|
754
|
+
...base ?? {},
|
|
755
|
+
...local ?? {},
|
|
756
|
+
anthropic: mergeRecordBlock(base?.anthropic, local?.anthropic),
|
|
757
|
+
gemini: mergeRecordBlock(base?.gemini, local?.gemini),
|
|
758
|
+
openrouter: mergeRecordBlock(base?.openrouter, local?.openrouter),
|
|
759
|
+
llmasaservice: mergeRecordBlock(base?.llmasaservice, local?.llmasaservice)
|
|
760
|
+
};
|
|
761
|
+
removeEmptyProviderBlocks(merged);
|
|
762
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
763
|
+
}
|
|
764
|
+
function mergeOverrideMap(base, local) {
|
|
765
|
+
const merged = { ...base ?? {} };
|
|
766
|
+
for (const [name, localOverride] of Object.entries(local ?? {})) {
|
|
767
|
+
merged[name] = mergeOverrideConfig(merged[name], localOverride);
|
|
768
|
+
}
|
|
769
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
770
|
+
}
|
|
771
|
+
function mergeOverrideConfig(base, local) {
|
|
772
|
+
const merged = {
|
|
773
|
+
...base ?? {},
|
|
774
|
+
...local
|
|
775
|
+
};
|
|
776
|
+
const reasoning = mergeRecordBlock(base?.reasoning, local.reasoning);
|
|
777
|
+
const sampling = mergeRecordBlock(base?.sampling, local.sampling);
|
|
778
|
+
const response = mergeRecordBlock(base?.response, local.response);
|
|
779
|
+
const compression = mergeCompression(base?.compression, local.compression);
|
|
780
|
+
const cache = mergeCache(base?.cache, local.cache);
|
|
781
|
+
const raw = mergeRaw(base?.raw, local.raw);
|
|
782
|
+
const providerOptions = mergeProviderOptions(base?.provider_options, local.provider_options);
|
|
783
|
+
if (reasoning !== void 0) merged.reasoning = reasoning;
|
|
784
|
+
if (sampling !== void 0) merged.sampling = sampling;
|
|
785
|
+
if (response !== void 0) merged.response = response;
|
|
786
|
+
if (compression !== void 0) merged.compression = compression;
|
|
787
|
+
if (cache !== void 0) merged.cache = cache;
|
|
788
|
+
if (raw !== void 0) merged.raw = raw;
|
|
789
|
+
if (providerOptions !== void 0) merged.provider_options = providerOptions;
|
|
790
|
+
return merged;
|
|
791
|
+
}
|
|
792
|
+
function removeEmptyProviderBlocks(value) {
|
|
793
|
+
for (const key of Object.keys(value)) {
|
|
794
|
+
const block = value[key];
|
|
795
|
+
if (block === void 0) {
|
|
796
|
+
delete value[key];
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
if (block !== null && typeof block === "object" && !Array.isArray(block) && Object.keys(block).length === 0) {
|
|
800
|
+
delete value[key];
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
515
804
|
|
|
516
805
|
// src/renderer/interpolate.ts
|
|
517
806
|
var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
@@ -519,12 +808,13 @@ var ESCAPED_OPEN = /\\\{\\\{/g;
|
|
|
519
808
|
var ESCAPE_PLACEHOLDER = "\0ESCAPED_OPEN\0";
|
|
520
809
|
function interpolate(template, variables, options = {}) {
|
|
521
810
|
const { strict = false } = options;
|
|
811
|
+
const optionalVariables = new Set(options.optionalVariables ?? []);
|
|
522
812
|
let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);
|
|
523
813
|
result = result.replace(VARIABLE_RE, (match, name) => {
|
|
524
814
|
if (name in variables) {
|
|
525
815
|
return variables[name];
|
|
526
816
|
}
|
|
527
|
-
if (strict) {
|
|
817
|
+
if (strict && !optionalVariables.has(name)) {
|
|
528
818
|
throw new Error(`Missing required variable: "${name}"`);
|
|
529
819
|
}
|
|
530
820
|
return match;
|
|
@@ -542,59 +832,19 @@ function extractVariables(template) {
|
|
|
542
832
|
return [...vars];
|
|
543
833
|
}
|
|
544
834
|
|
|
545
|
-
// src/composition/resolve-includes.ts
|
|
546
|
-
import { readFile as readFile2 } from "fs/promises";
|
|
547
|
-
import { resolve as resolve2, dirname as dirname2 } from "path";
|
|
548
|
-
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
549
|
-
if (!asset.includes || asset.includes.length === 0) {
|
|
550
|
-
return asset;
|
|
551
|
-
}
|
|
552
|
-
const baseDir = dirname2(basePath);
|
|
553
|
-
const resolvedPath = resolve2(basePath);
|
|
554
|
-
if (visited.has(resolvedPath)) {
|
|
555
|
-
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
556
|
-
}
|
|
557
|
-
visited.add(resolvedPath);
|
|
558
|
-
let mergedSystemInstructions = "";
|
|
559
|
-
for (const includePath of asset.includes) {
|
|
560
|
-
const fullPath = resolve2(baseDir, includePath);
|
|
561
|
-
if (visited.has(fullPath)) {
|
|
562
|
-
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
563
|
-
}
|
|
564
|
-
const content = await readFile2(fullPath, "utf-8");
|
|
565
|
-
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
566
|
-
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
567
|
-
if (resolved.sections?.system_instructions) {
|
|
568
|
-
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
const localSystem = asset.sections?.system_instructions ?? "";
|
|
572
|
-
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
573
|
-
return {
|
|
574
|
-
...asset,
|
|
575
|
-
sections: {
|
|
576
|
-
...asset.sections,
|
|
577
|
-
system_instructions: combinedSystem
|
|
578
|
-
},
|
|
579
|
-
// Drop includes from the resolved asset — they've been inlined
|
|
580
|
-
includes: void 0
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
|
|
584
835
|
// src/context.ts
|
|
585
836
|
var textEncoder = new TextEncoder();
|
|
586
837
|
function getContextInputs(asset) {
|
|
587
838
|
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
588
839
|
}
|
|
589
|
-
function getContextInputNames(asset) {
|
|
590
|
-
return getContextInputs(asset).map((input) => input.name);
|
|
591
|
-
}
|
|
592
840
|
function normalizeContextInput(input) {
|
|
593
841
|
if (typeof input === "string") {
|
|
594
842
|
return { name: input };
|
|
595
843
|
}
|
|
596
844
|
return {
|
|
597
845
|
name: input.name,
|
|
846
|
+
optional: input.optional,
|
|
847
|
+
warnings: input.warnings,
|
|
598
848
|
max_size: input.max_size,
|
|
599
849
|
trim: input.trim,
|
|
600
850
|
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
@@ -603,6 +853,9 @@ function normalizeContextInput(input) {
|
|
|
603
853
|
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
604
854
|
};
|
|
605
855
|
}
|
|
856
|
+
function areContextInputWarningsEnabled(input) {
|
|
857
|
+
return input.warnings !== false;
|
|
858
|
+
}
|
|
606
859
|
function normalizeContextRegex(value) {
|
|
607
860
|
if (value === void 0) {
|
|
608
861
|
return void 0;
|
|
@@ -689,6 +942,45 @@ function compileContextRegex(regex, details) {
|
|
|
689
942
|
}
|
|
690
943
|
}
|
|
691
944
|
|
|
945
|
+
// src/composition/resolve-includes.ts
|
|
946
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
947
|
+
import { resolve as resolve3, dirname as dirname3 } from "path";
|
|
948
|
+
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
949
|
+
if (!asset.includes || asset.includes.length === 0) {
|
|
950
|
+
return asset;
|
|
951
|
+
}
|
|
952
|
+
const baseDir = dirname3(basePath);
|
|
953
|
+
const resolvedPath = resolve3(basePath);
|
|
954
|
+
if (visited.has(resolvedPath)) {
|
|
955
|
+
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
956
|
+
}
|
|
957
|
+
visited.add(resolvedPath);
|
|
958
|
+
let mergedSystemInstructions = "";
|
|
959
|
+
for (const includePath of asset.includes) {
|
|
960
|
+
const fullPath = resolve3(baseDir, includePath);
|
|
961
|
+
if (visited.has(fullPath)) {
|
|
962
|
+
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
963
|
+
}
|
|
964
|
+
const content = await readFile3(fullPath, "utf-8");
|
|
965
|
+
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
966
|
+
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
967
|
+
if (resolved.sections?.system_instructions) {
|
|
968
|
+
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
const localSystem = asset.sections?.system_instructions ?? "";
|
|
972
|
+
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
973
|
+
return {
|
|
974
|
+
...asset,
|
|
975
|
+
sections: {
|
|
976
|
+
...asset.sections,
|
|
977
|
+
system_instructions: combinedSystem
|
|
978
|
+
},
|
|
979
|
+
// Drop includes from the resolved asset — they've been inlined
|
|
980
|
+
includes: void 0
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
692
984
|
// src/validation/levenshtein.ts
|
|
693
985
|
function levenshtein(a, b) {
|
|
694
986
|
const m = a.length;
|
|
@@ -730,9 +1022,22 @@ var KNOWN_FRONT_MATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
730
1022
|
"tiers",
|
|
731
1023
|
"metadata",
|
|
732
1024
|
"cache",
|
|
1025
|
+
"compression",
|
|
733
1026
|
"provider_options",
|
|
734
1027
|
"raw"
|
|
735
1028
|
]);
|
|
1029
|
+
function collectSchemaKeywords(value, acc) {
|
|
1030
|
+
if (!value || typeof value !== "object") return;
|
|
1031
|
+
if (Array.isArray(value)) {
|
|
1032
|
+
for (const item of value) collectSchemaKeywords(item, acc);
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
const record = value;
|
|
1036
|
+
for (const [key, child] of Object.entries(record)) {
|
|
1037
|
+
acc.add(key);
|
|
1038
|
+
collectSchemaKeywords(child, acc);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
736
1041
|
var RISKY_UNBOUNDED_INPUT_NAMES = [
|
|
737
1042
|
"message",
|
|
738
1043
|
"prompt",
|
|
@@ -784,7 +1089,9 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
784
1089
|
}
|
|
785
1090
|
}
|
|
786
1091
|
}
|
|
787
|
-
const
|
|
1092
|
+
const contextInputs = getContextInputs(asset);
|
|
1093
|
+
const declaredInputs = new Set(contextInputs.map((input) => input.name));
|
|
1094
|
+
const declaredInputsByName = new Map(contextInputs.map((input) => [input.name, input]));
|
|
788
1095
|
const usedVars = /* @__PURE__ */ new Set();
|
|
789
1096
|
if (asset.sections?.system_instructions) {
|
|
790
1097
|
for (const v of extractVariables(asset.sections.system_instructions)) {
|
|
@@ -806,7 +1113,8 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
806
1113
|
}
|
|
807
1114
|
}
|
|
808
1115
|
for (const v of declaredInputs) {
|
|
809
|
-
|
|
1116
|
+
const input = declaredInputsByName.get(v);
|
|
1117
|
+
if (!usedVars.has(v) && input?.optional !== true && areContextInputWarningsEnabled(input ?? {})) {
|
|
810
1118
|
warnings.push({
|
|
811
1119
|
code: "POK012",
|
|
812
1120
|
message: `Variable "${v}" is declared in context.inputs but never used`,
|
|
@@ -822,9 +1130,10 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
822
1130
|
suggestion: "Declare context.inputs to enable input policy validation."
|
|
823
1131
|
});
|
|
824
1132
|
}
|
|
825
|
-
for (const input of
|
|
1133
|
+
for (const input of contextInputs) {
|
|
826
1134
|
const lowerName = input.name.toLowerCase();
|
|
827
|
-
|
|
1135
|
+
const inputWarningsEnabled = areContextInputWarningsEnabled(input);
|
|
1136
|
+
if (inputWarningsEnabled && input.max_size === void 0 && RISKY_UNBOUNDED_INPUT_NAMES.some((needle) => lowerName.includes(needle))) {
|
|
828
1137
|
warnings.push({
|
|
829
1138
|
code: "POK040",
|
|
830
1139
|
message: `Context input "${input.name}" has no max_size and appears unbounded.`,
|
|
@@ -832,7 +1141,7 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
832
1141
|
suggestion: "Add max_size to constrain prompt payload growth."
|
|
833
1142
|
});
|
|
834
1143
|
}
|
|
835
|
-
if (input.allow_regex === void 0 && input.deny_regex === void 0 && input.non_empty === void 0 && input.reject_secrets === void 0) {
|
|
1144
|
+
if (inputWarningsEnabled && input.optional !== true && input.allow_regex === void 0 && input.deny_regex === void 0 && input.non_empty === void 0 && input.reject_secrets === void 0) {
|
|
836
1145
|
warnings.push({
|
|
837
1146
|
code: "POK041",
|
|
838
1147
|
message: `Context input "${input.name}" has no input hardening validators.`,
|
|
@@ -840,7 +1149,7 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
840
1149
|
suggestion: "Consider non_empty/reject_secrets and allow/deny regex validators."
|
|
841
1150
|
});
|
|
842
1151
|
}
|
|
843
|
-
if (input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
1152
|
+
if (inputWarningsEnabled && input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
844
1153
|
warnings.push({
|
|
845
1154
|
code: "POK014",
|
|
846
1155
|
message: `Context input "${input.name}" sets trim but has no max_size; trim-to-budget will be skipped.`,
|
|
@@ -867,6 +1176,30 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
867
1176
|
}
|
|
868
1177
|
}
|
|
869
1178
|
}
|
|
1179
|
+
if (asset.response?.schema && asset.provider) {
|
|
1180
|
+
const keywords = /* @__PURE__ */ new Set();
|
|
1181
|
+
collectSchemaKeywords(asset.response.schema, keywords);
|
|
1182
|
+
const openAIUnsupported = ["patternProperties", "unevaluatedProperties", "$dynamicRef"];
|
|
1183
|
+
const geminiUnsupported = ["patternProperties", "$dynamicRef", "dependentSchemas"];
|
|
1184
|
+
const anthropicCaution = ["if", "then", "else"];
|
|
1185
|
+
const checks = [
|
|
1186
|
+
{ provider: ["openai", "openai-responses", "openrouter", "llmasaservice"], unsupported: openAIUnsupported, code: "POK052" },
|
|
1187
|
+
{ provider: ["gemini", "google"], unsupported: geminiUnsupported, code: "POK053" },
|
|
1188
|
+
{ provider: ["anthropic"], unsupported: anthropicCaution, code: "POK054" }
|
|
1189
|
+
];
|
|
1190
|
+
for (const check of checks) {
|
|
1191
|
+
if (!check.provider.includes(asset.provider)) continue;
|
|
1192
|
+
const hits = check.unsupported.filter((k) => keywords.has(k));
|
|
1193
|
+
if (hits.length > 0) {
|
|
1194
|
+
warnings.push({
|
|
1195
|
+
code: check.code,
|
|
1196
|
+
message: `response.schema includes provider-sensitive JSON Schema keywords for "${asset.provider}": ${hits.join(", ")}`,
|
|
1197
|
+
filePath,
|
|
1198
|
+
suggestion: "Validate schema compatibility with your provider docs or simplify the schema dialect."
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
870
1203
|
if (asset.provider) {
|
|
871
1204
|
let providerCache;
|
|
872
1205
|
let cacheSuggestionField;
|
|
@@ -993,9 +1326,9 @@ function isRecord(value) {
|
|
|
993
1326
|
}
|
|
994
1327
|
|
|
995
1328
|
// src/prompt-resolution.ts
|
|
996
|
-
import { readFile as
|
|
1329
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
997
1330
|
import { existsSync, statSync as statSync2 } from "fs";
|
|
998
|
-
import { resolve as
|
|
1331
|
+
import { resolve as resolve4 } from "path";
|
|
999
1332
|
|
|
1000
1333
|
// src/cache.ts
|
|
1001
1334
|
import { statSync } from "fs";
|
|
@@ -1071,28 +1404,38 @@ function mergeOverride(base, override) {
|
|
|
1071
1404
|
if (override.response !== void 0) {
|
|
1072
1405
|
result.response = { ...result.response, ...override.response };
|
|
1073
1406
|
}
|
|
1407
|
+
if (override.compression !== void 0) {
|
|
1408
|
+
result.compression = {
|
|
1409
|
+
...result.compression,
|
|
1410
|
+
...override.compression,
|
|
1411
|
+
thetokencompany: mergeRecordBlock2(
|
|
1412
|
+
result.compression?.thetokencompany,
|
|
1413
|
+
override.compression.thetokencompany
|
|
1414
|
+
)
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1074
1417
|
if (override.cache !== void 0) {
|
|
1075
1418
|
result.cache = {
|
|
1076
1419
|
...result.cache,
|
|
1077
1420
|
...override.cache,
|
|
1078
|
-
openai:
|
|
1079
|
-
anthropic:
|
|
1080
|
-
gemini:
|
|
1081
|
-
google:
|
|
1421
|
+
openai: mergeRecordBlock2(result.cache?.openai, override.cache.openai),
|
|
1422
|
+
anthropic: mergeRecordBlock2(result.cache?.anthropic, override.cache.anthropic),
|
|
1423
|
+
gemini: mergeRecordBlock2(result.cache?.gemini, override.cache.gemini),
|
|
1424
|
+
google: mergeRecordBlock2(result.cache?.google, override.cache.google)
|
|
1082
1425
|
};
|
|
1083
1426
|
}
|
|
1084
1427
|
if (override.raw !== void 0) {
|
|
1085
1428
|
result.raw = {
|
|
1086
1429
|
...result.raw,
|
|
1087
1430
|
...override.raw,
|
|
1088
|
-
openai:
|
|
1089
|
-
"openai-responses":
|
|
1090
|
-
openai_responses:
|
|
1091
|
-
anthropic:
|
|
1092
|
-
gemini:
|
|
1093
|
-
google:
|
|
1094
|
-
openrouter:
|
|
1095
|
-
llmasaservice:
|
|
1431
|
+
openai: mergeRecordBlock2(result.raw?.openai, override.raw.openai),
|
|
1432
|
+
"openai-responses": mergeRecordBlock2(result.raw?.["openai-responses"], override.raw["openai-responses"]),
|
|
1433
|
+
openai_responses: mergeRecordBlock2(result.raw?.openai_responses, override.raw.openai_responses),
|
|
1434
|
+
anthropic: mergeRecordBlock2(result.raw?.anthropic, override.raw.anthropic),
|
|
1435
|
+
gemini: mergeRecordBlock2(result.raw?.gemini, override.raw.gemini),
|
|
1436
|
+
google: mergeRecordBlock2(result.raw?.google, override.raw.google),
|
|
1437
|
+
openrouter: mergeRecordBlock2(result.raw?.openrouter, override.raw.openrouter),
|
|
1438
|
+
llmasaservice: mergeRecordBlock2(result.raw?.llmasaservice, override.raw.llmasaservice)
|
|
1096
1439
|
};
|
|
1097
1440
|
}
|
|
1098
1441
|
if (override.provider_options !== void 0) {
|
|
@@ -1119,7 +1462,7 @@ function mergeOverride(base, override) {
|
|
|
1119
1462
|
}
|
|
1120
1463
|
return result;
|
|
1121
1464
|
}
|
|
1122
|
-
function
|
|
1465
|
+
function mergeRecordBlock2(base, override) {
|
|
1123
1466
|
if (override === void 0) return base;
|
|
1124
1467
|
return { ...base, ...override };
|
|
1125
1468
|
}
|
|
@@ -1135,9 +1478,9 @@ var sharedPromptCache = new PromptCache();
|
|
|
1135
1478
|
|
|
1136
1479
|
// src/cli/commands/defaults-root.ts
|
|
1137
1480
|
import { existsSync as existsSync2 } from "fs";
|
|
1138
|
-
import { dirname as
|
|
1481
|
+
import { dirname as dirname4, join as join2, resolve as resolve5 } from "path";
|
|
1139
1482
|
function findDefaultsRoot(filePath) {
|
|
1140
|
-
let current =
|
|
1483
|
+
let current = resolve5(dirname4(filePath));
|
|
1141
1484
|
let root = current;
|
|
1142
1485
|
let foundDefaults = false;
|
|
1143
1486
|
while (true) {
|
|
@@ -1147,7 +1490,7 @@ function findDefaultsRoot(filePath) {
|
|
|
1147
1490
|
} else if (foundDefaults) {
|
|
1148
1491
|
return root;
|
|
1149
1492
|
}
|
|
1150
|
-
const parent =
|
|
1493
|
+
const parent = dirname4(current);
|
|
1151
1494
|
if (parent === current) {
|
|
1152
1495
|
return root;
|
|
1153
1496
|
}
|
|
@@ -1242,7 +1585,7 @@ function getFlag(args, ...flags) {
|
|
|
1242
1585
|
async function collectPromptFiles(target) {
|
|
1243
1586
|
const targetStats = await stat(target);
|
|
1244
1587
|
if (targetStats.isFile()) {
|
|
1245
|
-
if (
|
|
1588
|
+
if (extname2(target) !== ".md" || target.endsWith("defaults.md") || target.endsWith(".test.md")) {
|
|
1246
1589
|
return [];
|
|
1247
1590
|
}
|
|
1248
1591
|
return [target];
|
|
@@ -1250,7 +1593,7 @@ async function collectPromptFiles(target) {
|
|
|
1250
1593
|
const results = [];
|
|
1251
1594
|
const entries = await readdir(target, { withFileTypes: true, recursive: true });
|
|
1252
1595
|
for (const entry of entries) {
|
|
1253
|
-
if (entry.isFile() &&
|
|
1596
|
+
if (entry.isFile() && extname2(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
|
|
1254
1597
|
results.push(join3(entry.parentPath ?? target, entry.name));
|
|
1255
1598
|
}
|
|
1256
1599
|
}
|
|
@@ -1259,7 +1602,7 @@ async function collectPromptFiles(target) {
|
|
|
1259
1602
|
|
|
1260
1603
|
// src/cli/commands/compile.ts
|
|
1261
1604
|
import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
|
|
1262
|
-
import { join as join4, extname as
|
|
1605
|
+
import { join as join4, extname as extname3, relative as relative2, dirname as dirname6 } from "path";
|
|
1263
1606
|
var HELP2 = `
|
|
1264
1607
|
promptopskit compile [sourceDir] [outputDir] [options]
|
|
1265
1608
|
|
|
@@ -1299,7 +1642,7 @@ async function compile(args) {
|
|
|
1299
1642
|
let compiled = 0;
|
|
1300
1643
|
let errors = 0;
|
|
1301
1644
|
for (const file of files) {
|
|
1302
|
-
const rel =
|
|
1645
|
+
const rel = relative2(sourceDir, file).replace(/\.md$/, "");
|
|
1303
1646
|
const outExt = format === "esm" ? ".mjs" : ".json";
|
|
1304
1647
|
const outPath = join4(outputDir, rel + outExt);
|
|
1305
1648
|
try {
|
|
@@ -1312,7 +1655,7 @@ async function compile(args) {
|
|
|
1312
1655
|
if (dryRun) {
|
|
1313
1656
|
console.log(` Would create: ${outPath}`);
|
|
1314
1657
|
} else {
|
|
1315
|
-
await mkdir(
|
|
1658
|
+
await mkdir(dirname6(outPath), { recursive: true });
|
|
1316
1659
|
if (format === "esm") {
|
|
1317
1660
|
const esmContent = `export default ${JSON.stringify(asset, null, 2)};
|
|
1318
1661
|
`;
|
|
@@ -1368,7 +1711,7 @@ async function collectPromptFiles2(dir) {
|
|
|
1368
1711
|
const results = [];
|
|
1369
1712
|
const entries = await readdir2(dir, { withFileTypes: true, recursive: true });
|
|
1370
1713
|
for (const entry of entries) {
|
|
1371
|
-
if (entry.isFile() &&
|
|
1714
|
+
if (entry.isFile() && extname3(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
|
|
1372
1715
|
results.push(join4(entry.parentPath ?? dir, entry.name));
|
|
1373
1716
|
}
|
|
1374
1717
|
}
|
|
@@ -1376,7 +1719,7 @@ async function collectPromptFiles2(dir) {
|
|
|
1376
1719
|
}
|
|
1377
1720
|
|
|
1378
1721
|
// src/cli/commands/render.ts
|
|
1379
|
-
import { readFile as
|
|
1722
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
1380
1723
|
import { existsSync as existsSync3 } from "fs";
|
|
1381
1724
|
var HELP3 = `
|
|
1382
1725
|
promptopskit render <file> [options]
|
|
@@ -1407,13 +1750,13 @@ async function render(args) {
|
|
|
1407
1750
|
const jsonOutput = args.includes("--json");
|
|
1408
1751
|
let variables = {};
|
|
1409
1752
|
if (varsFile) {
|
|
1410
|
-
const varsContent = await
|
|
1753
|
+
const varsContent = await readFile5(varsFile, "utf-8");
|
|
1411
1754
|
variables = JSON.parse(varsContent);
|
|
1412
1755
|
} else {
|
|
1413
1756
|
const sidecarPath = file.replace(/\.md$/, ".test.yaml");
|
|
1414
1757
|
if (existsSync3(sidecarPath)) {
|
|
1415
1758
|
const { default: yaml } = await import("gray-matter");
|
|
1416
|
-
const sidecarContent = await
|
|
1759
|
+
const sidecarContent = await readFile5(sidecarPath, "utf-8");
|
|
1417
1760
|
const parsed2 = yaml(`---
|
|
1418
1761
|
${sidecarContent}---
|
|
1419
1762
|
`);
|
|
@@ -1512,7 +1855,7 @@ async function inspect(args) {
|
|
|
1512
1855
|
|
|
1513
1856
|
// src/cli/commands/init.ts
|
|
1514
1857
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1515
|
-
import { join as join5, dirname as
|
|
1858
|
+
import { join as join5, dirname as dirname7, relative as relative3 } from "path";
|
|
1516
1859
|
import { existsSync as existsSync4, readFileSync } from "fs";
|
|
1517
1860
|
var HELP5 = `
|
|
1518
1861
|
promptopskit init [dir]
|
|
@@ -1663,8 +2006,8 @@ async function init(args) {
|
|
|
1663
2006
|
return;
|
|
1664
2007
|
}
|
|
1665
2008
|
const dir = args.find((a) => !a.startsWith("--")) ?? "./prompts";
|
|
1666
|
-
const testFilePath = join5(
|
|
1667
|
-
const promptsDirFromTest =
|
|
2009
|
+
const testFilePath = join5(dirname7(dir), "tests", "hello.prompt.test.mjs");
|
|
2010
|
+
const promptsDirFromTest = relative3(dirname7(testFilePath), dir) || ".";
|
|
1668
2011
|
const helloPromptTest = createHelloPromptTest(promptsDirFromTest);
|
|
1669
2012
|
const files = [
|
|
1670
2013
|
{ path: join5(dir, "defaults.md"), content: DEFAULTS },
|
|
@@ -1682,7 +2025,7 @@ async function init(args) {
|
|
|
1682
2025
|
skipped++;
|
|
1683
2026
|
continue;
|
|
1684
2027
|
}
|
|
1685
|
-
await mkdir2(
|
|
2028
|
+
await mkdir2(dirname7(file.path), { recursive: true });
|
|
1686
2029
|
await writeFile2(file.path, file.content, "utf-8");
|
|
1687
2030
|
console.log(` \u2713 ${file.path}`);
|
|
1688
2031
|
created++;
|
|
@@ -1750,8 +2093,8 @@ test('hello prompt can return a deterministic response without calling a model',
|
|
|
1750
2093
|
}
|
|
1751
2094
|
|
|
1752
2095
|
// src/cli/commands/skill.ts
|
|
1753
|
-
import { writeFile as writeFile3, readFile as
|
|
1754
|
-
import { dirname as
|
|
2096
|
+
import { writeFile as writeFile3, readFile as readFile6, mkdir as mkdir3 } from "fs/promises";
|
|
2097
|
+
import { dirname as dirname8 } from "path";
|
|
1755
2098
|
import { existsSync as existsSync5 } from "fs";
|
|
1756
2099
|
var MARKER_START = "<!-- promptopskit:start -->";
|
|
1757
2100
|
var MARKER_END = "<!-- promptopskit:end -->";
|
|
@@ -1839,7 +2182,7 @@ async function skill(args) {
|
|
|
1839
2182
|
}
|
|
1840
2183
|
const markedContent = config.wrap(wrapMarkers(STUB_CONTENT));
|
|
1841
2184
|
if (existsSync5(filePath) && !force) {
|
|
1842
|
-
const existing = await
|
|
2185
|
+
const existing = await readFile6(filePath, "utf-8");
|
|
1843
2186
|
const merged = mergeContent(existing, markedContent);
|
|
1844
2187
|
if (merged === existing) {
|
|
1845
2188
|
console.log(` skip ${filePath} (already up to date)`);
|
|
@@ -1850,7 +2193,7 @@ async function skill(args) {
|
|
|
1850
2193
|
written++;
|
|
1851
2194
|
continue;
|
|
1852
2195
|
}
|
|
1853
|
-
await mkdir3(
|
|
2196
|
+
await mkdir3(dirname8(filePath), { recursive: true });
|
|
1854
2197
|
await writeFile3(filePath, markedContent, "utf-8");
|
|
1855
2198
|
console.log(` \u2713 ${filePath}`);
|
|
1856
2199
|
written++;
|
|
@@ -1863,12 +2206,12 @@ async function skill(args) {
|
|
|
1863
2206
|
async function deployClaude(filePath, force) {
|
|
1864
2207
|
const content = CLAUDE_LINE + "\n";
|
|
1865
2208
|
if (!existsSync5(filePath) || force) {
|
|
1866
|
-
await mkdir3(
|
|
2209
|
+
await mkdir3(dirname8(filePath), { recursive: true });
|
|
1867
2210
|
await writeFile3(filePath, content, "utf-8");
|
|
1868
2211
|
console.log(` \u2713 ${filePath}`);
|
|
1869
2212
|
return 1;
|
|
1870
2213
|
}
|
|
1871
|
-
const existing = await
|
|
2214
|
+
const existing = await readFile6(filePath, "utf-8");
|
|
1872
2215
|
if (existing.split("\n").some((line) => line.trim() === CLAUDE_LINE)) {
|
|
1873
2216
|
console.log(` skip ${filePath} (already up to date)`);
|
|
1874
2217
|
return 0;
|