@happyvertical/smrt-prompts 0.45.3 → 0.47.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/AGENTS.md +17 -0
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +32 -7
- package/dist/smrt-knowledge.json +36 -6
- package/package.json +7 -7
package/AGENTS.md
CHANGED
|
@@ -30,6 +30,23 @@ Each layer can override any subset of fields (template, profile, model, params).
|
|
|
30
30
|
|
|
31
31
|
`resolvePrompt()` results are cached per `(key, tenantId)` with a TTL. The cache is invalidated on `PromptOverride.save()` and `.delete()`. Use `clearPromptCache()` for manual invalidation in tests.
|
|
32
32
|
|
|
33
|
+
**A monotonic per-`(db, key)` invalidation generation guards the cache write.**
|
|
34
|
+
A resolution captures `getPromptCacheGeneration(key, db)` before its
|
|
35
|
+
asynchronous layer loads and hands it back to `setCachedPromptBase()`; a
|
|
36
|
+
concurrent `save()` / `delete()` bumps the generation and the in-flight
|
|
37
|
+
resolution is then refused the cache write instead of repopulating the key it
|
|
38
|
+
just invalidated with the pre-write value. Without it, "a stale entry is never
|
|
39
|
+
served after a write" held only until a read raced a write, and then failed for
|
|
40
|
+
the full 30s TTL (a raced `delete()` resurrected the deleted override).
|
|
41
|
+
Generations are tracked per `(db, key)`, not per tenant, because an app-level
|
|
42
|
+
row is inherited by every tenant. `clearPromptCache()` raises a single floor
|
|
43
|
+
(`clearedThrough`) rather than resetting or per-key bumping: a key that has
|
|
44
|
+
never been invalidated has no map entry and reads as generation 0, so a per-key
|
|
45
|
+
bump cannot reach it and a resolution that started before the clear would write
|
|
46
|
+
its pre-clear value back. `smrt-languages` carries the same mechanism, keyed
|
|
47
|
+
additionally by locale. `smrt-playbooks` has the generation but not the floor
|
|
48
|
+
(#2716).
|
|
49
|
+
|
|
33
50
|
## Related
|
|
34
51
|
|
|
35
52
|
- `@happyvertical/smrt-languages` — parallel package for language strings (uses the same architecture pattern)
|
package/dist/index.js
CHANGED
|
@@ -14,11 +14,14 @@ var __exportAll = (all, no_symbols) => {
|
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/__smrt-register__.ts
|
|
17
|
-
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-prompts\",\"packageVersion\":\"0.
|
|
17
|
+
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-prompts\",\"packageVersion\":\"0.47.0\",\"objects\":{\"@happyvertical/smrt-prompts:PromptOverrideCollection\":{\"name\":\"promptoverridecollection\",\"className\":\"PromptOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-prompts:PromptOverrideCollection\",\"collection\":\"promptoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/prompts/src/collections/PromptOverrideCollection.ts\",\"packageName\":\"@happyvertical/smrt-prompts\",\"fields\":{},\"methods\":{\"getAppOverride\":{\"name\":\"getAppOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<PromptOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getTenantOverride\":{\"name\":\"getTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<PromptOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getResolutionLayers\":{\"name\":\"getResolutionLayers\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_prompt_overrides\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"PromptOverride\",\"exportName\":\"PromptOverrideCollection\",\"collectionExportName\":\"PromptOverrideCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_prompt_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_prompt_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"_smrt_prompt_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"_smrt_prompt_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"67269c92\"}},\"@happyvertical/smrt-prompts:PromptOverride\":{\"name\":\"promptoverride\",\"className\":\"PromptOverride\",\"qualifiedName\":\"@happyvertical/smrt-prompts:PromptOverride\",\"collection\":\"promptoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/prompts/src/models/PromptOverride.ts\",\"packageName\":\"@happyvertical/smrt-prompts\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"template\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"profile\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"model\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"params\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}}},\"methods\":{\"getParams\":{\"name\":\"getParams\",\"async\":false,\"parameters\":[],\"returnType\":\"PromptParams\",\"isStatic\":false,\"isPublic\":true},\"setParams\":{\"name\":\"setParams\",\"async\":false,\"parameters\":[{\"name\":\"params\",\"type\":\"PromptParams | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"PromptParams\"},{\"type\":\"null\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"toPromptLayer\":{\"name\":\"toPromptLayer\",\"async\":false,\"parameters\":[],\"returnType\":\"PromptLayer\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_prompt_overrides\",\"conflictColumns\":[\"key\",\"context\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"],\"exclude\":[\"getParams\",\"setParams\",\"toPromptLayer\"]},\"mcp\":{\"include\":[]}},\"extends\":\"SmrtObject\",\"exportName\":\"PromptOverride\",\"collectionExportName\":\"PromptOverrideCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"_smrt_prompt_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_prompt_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL DEFAULT '',\\n \\\"tenant_id\\\" TEXT,\\n \\\"template\\\" TEXT,\\n \\\"profile\\\" TEXT,\\n \\\"model\\\" TEXT,\\n \\\"params\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"template\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"profile\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"model\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"params\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_prompt_overrides_key_context_idx\",\"columns\":[\"key\",\"context\"],\"unique\":true},{\"name\":\"_smrt_prompt_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_prompt_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"6f475427\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tenancy\"]}"));
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/cache.ts
|
|
20
20
|
var PROMPT_CACHE_TTL_MS = 3e4;
|
|
21
21
|
var promptCache = /* @__PURE__ */ new Map();
|
|
22
|
+
var cacheGenerations = /* @__PURE__ */ new Map();
|
|
23
|
+
var nextGeneration = 1;
|
|
24
|
+
var clearedThrough = 0;
|
|
22
25
|
var dbInstanceIds = /* @__PURE__ */ new WeakMap();
|
|
23
26
|
var nextDbId = 1;
|
|
24
27
|
function getDbNamespace(db) {
|
|
@@ -43,6 +46,12 @@ function getDbNamespace(db) {
|
|
|
43
46
|
function buildCacheKey(key, tenantId, db) {
|
|
44
47
|
return `${getDbNamespace(db)}::${key}::${tenantId ?? "app"}`;
|
|
45
48
|
}
|
|
49
|
+
function buildGenerationKey(key, db) {
|
|
50
|
+
return `${getDbNamespace(db)}::${key}`;
|
|
51
|
+
}
|
|
52
|
+
function bumpGeneration(key, db) {
|
|
53
|
+
cacheGenerations.set(buildGenerationKey(key, db), nextGeneration++);
|
|
54
|
+
}
|
|
46
55
|
function getPromptCacheTtlMs() {
|
|
47
56
|
return PROMPT_CACHE_TTL_MS;
|
|
48
57
|
}
|
|
@@ -56,7 +65,12 @@ function getCachedPromptBase(key, tenantId, db) {
|
|
|
56
65
|
}
|
|
57
66
|
return cached.value;
|
|
58
67
|
}
|
|
59
|
-
function
|
|
68
|
+
function getPromptCacheGeneration(key, db) {
|
|
69
|
+
const generation = cacheGenerations.get(buildGenerationKey(key, db)) ?? 0;
|
|
70
|
+
return generation > clearedThrough ? generation : clearedThrough;
|
|
71
|
+
}
|
|
72
|
+
function setCachedPromptBase(key, tenantId, db, value, loadedAtGeneration) {
|
|
73
|
+
if (getPromptCacheGeneration(key, db) !== loadedAtGeneration) return;
|
|
60
74
|
promptCache.set(buildCacheKey(key, tenantId, db), {
|
|
61
75
|
expiresAt: Date.now() + PROMPT_CACHE_TTL_MS,
|
|
62
76
|
value
|
|
@@ -64,6 +78,7 @@ function setCachedPromptBase(key, tenantId, db, value) {
|
|
|
64
78
|
}
|
|
65
79
|
function invalidatePromptCache(key, tenantId, db) {
|
|
66
80
|
const dbNamespace = getDbNamespace(db);
|
|
81
|
+
bumpGeneration(key, db);
|
|
67
82
|
if (tenantId !== null && tenantId !== void 0) {
|
|
68
83
|
promptCache.delete(buildCacheKey(key, tenantId, db));
|
|
69
84
|
return;
|
|
@@ -73,6 +88,8 @@ function invalidatePromptCache(key, tenantId, db) {
|
|
|
73
88
|
}
|
|
74
89
|
function clearPromptCache() {
|
|
75
90
|
promptCache.clear();
|
|
91
|
+
clearedThrough = nextGeneration++;
|
|
92
|
+
cacheGenerations.clear();
|
|
76
93
|
}
|
|
77
94
|
//#endregion
|
|
78
95
|
//#region src/utils.ts
|
|
@@ -588,6 +605,7 @@ async function loadPromptBase(key, options) {
|
|
|
588
605
|
}
|
|
589
606
|
const cached = getCachedPromptBase(key, tenantId, cacheDb);
|
|
590
607
|
if (cached) return cached;
|
|
608
|
+
const loadedAtGeneration = getPromptCacheGeneration(key, cacheDb);
|
|
591
609
|
const config = getPromptConfig();
|
|
592
610
|
const layers = [{
|
|
593
611
|
template: definition.template,
|
|
@@ -606,7 +624,7 @@ async function loadPromptBase(key, options) {
|
|
|
606
624
|
template: merged.template,
|
|
607
625
|
ai: merged.ai
|
|
608
626
|
};
|
|
609
|
-
setCachedPromptBase(key, tenantId, cacheDb, value);
|
|
627
|
+
setCachedPromptBase(key, tenantId, cacheDb, value, loadedAtGeneration);
|
|
610
628
|
return value;
|
|
611
629
|
}
|
|
612
630
|
async function resolvePrompt(key, options = {}) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/__smrt-register__.ts","../src/cache.ts","../src/utils.ts","../src/prompt-registry.ts","../src/models/PromptOverride.ts","../src/collections/PromptOverrideCollection.ts","../src/prompt-resolver.ts","../src/index.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt()\n * decorator in the package fires. Fixes issue #1132: in consumer runtimes\n * (tsx, SvelteKit SSR, plain `vite dev`) the decorator's synchronous manifest\n * lookup previously missed because no step populated the global manifest cache\n * — classes got registered with zero fields and `save()` / `toJSON()`\n * silently dropped every declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates\n * manifests via a different path. Only needs to succeed in the published dist\n * output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","import type { DatabaseInterface } from '@happyvertical/sql';\nimport type { PromptCacheValue } from './types.js';\n\nconst PROMPT_CACHE_TTL_MS = 30_000;\n\ntype CacheEntry = {\n expiresAt: number;\n value: PromptCacheValue;\n};\n\nconst promptCache = new Map<string, CacheEntry>();\nconst dbInstanceIds = new WeakMap<object, string>();\nlet nextDbId = 1;\n\nfunction getDbNamespace(db: unknown): string {\n if (!db) {\n return 'no-db';\n }\n\n if (typeof db === 'string') {\n return `db:${db}`;\n }\n\n if (typeof db === 'object') {\n const dbObject = db as Record<string, unknown>;\n if (typeof dbObject.query === 'function') {\n if (!dbInstanceIds.has(dbObject)) {\n dbInstanceIds.set(dbObject, `db-instance:${nextDbId++}`);\n }\n const namespace = dbInstanceIds.get(dbObject);\n if (namespace) {\n return namespace;\n }\n\n return 'db-instance:unknown';\n }\n\n try {\n return `db-config:${JSON.stringify(dbObject)}`;\n } catch {\n return 'db-config:opaque';\n }\n }\n\n return 'db:unknown';\n}\n\nfunction buildCacheKey(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): string {\n return `${getDbNamespace(db)}::${key}::${tenantId ?? 'app'}`;\n}\n\nexport function getPromptCacheTtlMs(): number {\n return PROMPT_CACHE_TTL_MS;\n}\n\nexport function getCachedPromptBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): PromptCacheValue | null {\n const cacheKey = buildCacheKey(key, tenantId, db);\n const cached = promptCache.get(cacheKey);\n\n if (!cached) {\n return null;\n }\n\n if (cached.expiresAt <= Date.now()) {\n promptCache.delete(cacheKey);\n return null;\n }\n\n return cached.value;\n}\n\nexport function setCachedPromptBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n value: PromptCacheValue,\n): void {\n promptCache.set(buildCacheKey(key, tenantId, db), {\n expiresAt: Date.now() + PROMPT_CACHE_TTL_MS,\n value,\n });\n}\n\nexport function invalidatePromptCache(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): void {\n const dbNamespace = getDbNamespace(db);\n\n if (tenantId !== null && tenantId !== undefined) {\n promptCache.delete(buildCacheKey(key, tenantId, db));\n return;\n }\n\n const keyPrefix = `${dbNamespace}::${key}::`;\n for (const cacheKey of promptCache.keys()) {\n if (cacheKey.startsWith(keyPrefix)) {\n promptCache.delete(cacheKey);\n }\n }\n}\n\nexport function clearPromptCache(): void {\n promptCache.clear();\n}\n","import type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPromptAI,\n} from './types.js';\n\nconst DEFAULT_EDITABLE: PromptEditableConfig = {\n template: false,\n profile: false,\n model: false,\n params: false,\n};\n\nconst TOP_LEVEL_RESERVED_KEYS = new Set([\n 'key',\n 'editable',\n 'template',\n 'ai',\n 'profile',\n 'provider',\n 'model',\n 'params',\n 'temperature',\n 'maxTokens',\n]);\n\nconst AI_RESERVED_KEYS = new Set([\n 'profile',\n 'provider',\n 'model',\n 'params',\n 'temperature',\n 'maxTokens',\n]);\n\nconst AI_ROUTING_PARAM_KEYS = new Set([\n 'profile',\n 'provider',\n 'type',\n 'model',\n 'defaultModel',\n]);\n\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function normalizeEditableConfig(\n editable?: Partial<PromptEditableConfig>,\n): PromptEditableConfig {\n return {\n template: editable?.template ?? DEFAULT_EDITABLE.template,\n profile: editable?.profile ?? DEFAULT_EDITABLE.profile,\n model: editable?.model ?? DEFAULT_EDITABLE.model,\n params: editable?.params ?? DEFAULT_EDITABLE.params,\n };\n}\n\nfunction extractPromptParams(\n source: Record<string, unknown>,\n reservedKeys: Set<string>,\n): PromptParams {\n const params: PromptParams = {};\n\n if (isPlainObject(source.params)) {\n Object.assign(params, sanitizePromptParams(source.params));\n }\n\n if ('temperature' in source && source.temperature !== undefined) {\n params.temperature = source.temperature;\n }\n\n if ('maxTokens' in source && source.maxTokens !== undefined) {\n params.maxTokens = source.maxTokens;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (reservedKeys.has(key) || value === undefined) {\n continue;\n }\n assignPromptParam(params, key, value);\n }\n\n return params;\n}\n\nfunction assignPromptParam(\n params: PromptParams,\n key: string,\n value: unknown,\n): void {\n if (AI_ROUTING_PARAM_KEYS.has(key) || value === undefined) {\n return;\n }\n\n params[key] = value;\n}\n\nexport function sanitizePromptParams(\n params: PromptParams | null | undefined,\n): PromptParams {\n const sanitized: PromptParams = {};\n\n if (!params) {\n return sanitized;\n }\n\n for (const [key, value] of Object.entries(params)) {\n assignPromptParam(sanitized, key, value);\n }\n\n return sanitized;\n}\n\nexport function mergePromptParams(\n ...paramLayers: Array<PromptParams | null | undefined>\n): PromptParams {\n const merged: PromptParams = {};\n\n for (const layer of paramLayers) {\n if (!layer) {\n continue;\n }\n\n for (const [key, value] of Object.entries(layer)) {\n assignPromptParam(merged, key, value);\n }\n }\n\n return merged;\n}\n\nfunction normalizeAIInput(ai?: PromptAIInput | null): NormalizedPromptAI {\n if (!isPlainObject(ai)) {\n return { params: {} };\n }\n\n const profile =\n typeof ai.profile === 'string' || ai.profile === null\n ? ai.profile\n : undefined;\n const model =\n typeof ai.model === 'string' || ai.model === null ? ai.model : undefined;\n\n return {\n profile: profile ?? undefined,\n model: model ?? undefined,\n params: extractPromptParams(ai, AI_RESERVED_KEYS),\n };\n}\n\nexport function normalizePromptDefinitionInput(input: PromptDefinitionInput): {\n key: string;\n template: string;\n ai: NormalizedPromptAI;\n editable: PromptEditableConfig;\n} {\n return {\n key: input.key,\n template: input.template,\n ai: normalizeAIInput(input.ai),\n editable: normalizeEditableConfig(input.editable),\n };\n}\n\nexport function normalizePromptLayer(\n input?: PromptConfigOverrideInput | null,\n): PromptLayer {\n if (!isPlainObject(input)) {\n return {};\n }\n\n const nestedAi = isPlainObject(input.ai)\n ? normalizeAIInput(input.ai)\n : { params: {} };\n const topLevelParams = extractPromptParams(input, TOP_LEVEL_RESERVED_KEYS);\n\n return {\n template:\n input.template === undefined\n ? undefined\n : input.template === null\n ? null\n : String(input.template),\n profile:\n input.profile === undefined\n ? nestedAi.profile\n : input.profile === null\n ? null\n : String(input.profile),\n model:\n input.model === undefined\n ? nestedAi.model\n : input.model === null\n ? null\n : String(input.model),\n params: mergePromptParams(topLevelParams, nestedAi.params),\n };\n}\n\nexport function mergePromptLayers(\n ...layers: Array<PromptLayer | null | undefined>\n): {\n template: string;\n ai: NormalizedPromptAI;\n} {\n let template = '';\n let profile: string | undefined;\n let model: string | undefined;\n let params: PromptParams = {};\n\n for (const layer of layers) {\n if (!layer) {\n continue;\n }\n\n if (layer.template !== undefined && layer.template !== null) {\n template = layer.template;\n }\n\n if (layer.profile !== undefined && layer.profile !== null) {\n profile = layer.profile;\n }\n\n if (layer.model !== undefined && layer.model !== null) {\n model = layer.model;\n }\n\n if (layer.params !== undefined && layer.params !== null) {\n params = mergePromptParams(params, layer.params);\n }\n }\n\n return {\n template,\n ai: {\n profile,\n model,\n params,\n },\n };\n}\n\nexport function normalizeProfileConfig(profile: PromptProfileConfig): {\n provider: string;\n model: string;\n params: PromptParams;\n} {\n const source = isPlainObject(profile) ? profile : {};\n const params = extractPromptParams(source, new Set(['provider', 'model']));\n\n return {\n provider: String(profile.provider),\n model: String(profile.model),\n params,\n };\n}\n\nexport function validateProfileName(\n profileName: string,\n config: PromptPackageConfig,\n): void {\n if (profileName.trim() === '') {\n throw new Error('Prompt profile names cannot be empty');\n }\n\n const allowedProfileNames = config.allowedProfileNames;\n if (\n Array.isArray(allowedProfileNames) &&\n !allowedProfileNames.includes(profileName)\n ) {\n throw new Error(\n `Prompt profile \"${profileName}\" is not in the allowed profile list`,\n );\n }\n\n if (!config.profiles?.[profileName]) {\n throw new Error(`Prompt profile \"${profileName}\" is not configured`);\n }\n}\n\nexport function validateModelName(\n modelName: string,\n config: PromptPackageConfig,\n): void {\n if (modelName.trim() === '') {\n throw new Error('Prompt model overrides cannot be empty');\n }\n\n const allowedModels = config.allowedModels;\n if (Array.isArray(allowedModels) && !allowedModels.includes(modelName)) {\n throw new Error(\n `Prompt model \"${modelName}\" is not in the allowed model list`,\n );\n }\n}\n\nexport function buildResolvedAI(\n ai: NormalizedPromptAI,\n config: PromptPackageConfig,\n): ResolvedPromptAI {\n let provider: string | undefined;\n let model = ai.model;\n let params = ai.params;\n\n if (ai.profile) {\n validateProfileName(ai.profile, config);\n const configuredProfile = config.profiles?.[ai.profile];\n if (!configuredProfile) {\n throw new Error(`Prompt profile \"${ai.profile}\" is not configured`);\n }\n const profileConfig = normalizeProfileConfig(configuredProfile);\n provider = profileConfig.provider;\n model = model ?? profileConfig.model;\n params = mergePromptParams(profileConfig.params, params);\n }\n\n if (ai.model) {\n validateModelName(ai.model, config);\n }\n\n if (ai.model && !ai.profile) {\n throw new Error(\n 'Direct prompt model overrides require an effective prompt profile',\n );\n }\n\n if (model && !ai.model && config.allowedModels) {\n validateModelName(model, config);\n }\n\n const resolved: ResolvedPromptAI = {\n ...params,\n profile: ai.profile,\n provider,\n model,\n ...(config.allowedModels\n ? { allowedModels: [...config.allowedModels] }\n : {}),\n params,\n };\n\n if (typeof params.temperature === 'number') {\n resolved.temperature = params.temperature;\n }\n\n if (typeof params.maxTokens === 'number') {\n resolved.maxTokens = params.maxTokens;\n }\n\n return resolved;\n}\n\nexport function renderPromptTemplate(\n template: string,\n variables?: Record<string, unknown>,\n): string {\n if (!variables || Object.keys(variables).length === 0) {\n return template;\n }\n\n return template.replace(/\\{([^{}]+)\\}/g, (_match, rawKey: string) => {\n const key = rawKey.trim();\n const value = variables[key];\n\n if (value === undefined || value === null) {\n return '';\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (Array.isArray(value) || isPlainObject(value)) {\n try {\n return JSON.stringify(value);\n } catch {\n return '';\n }\n }\n\n return String(value);\n });\n}\n\nexport function parsePromptParams(\n raw: string | null | undefined,\n): PromptParams {\n if (!raw) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return isPlainObject(parsed) ? sanitizePromptParams(parsed) : {};\n } catch {\n return {};\n }\n}\n\nexport function serializePromptParams(\n params: PromptParams | null | undefined,\n): string | null {\n if (params === null || params === undefined) {\n return null;\n }\n\n return JSON.stringify(sanitizePromptParams(params));\n}\n","import type { PromptDefinition, PromptDefinitionInput } from './types.js';\nimport { normalizePromptDefinitionInput } from './utils.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtPromptRegistry: Map<string, PromptDefinition> | undefined;\n}\n\nfunction getRegistry(): Map<string, PromptDefinition> {\n if (!globalThis.__smrtPromptRegistry) {\n globalThis.__smrtPromptRegistry = new Map<string, PromptDefinition>();\n }\n\n return globalThis.__smrtPromptRegistry;\n}\n\nfunction stableStringify(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map((item) => stableStringify(item)).join(',')}]`;\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>).sort(\n ([left], [right]) => left.localeCompare(right),\n );\n return `{${entries\n .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)\n .join(',')}}`;\n }\n\n return JSON.stringify(value);\n}\n\nexport const PromptRegistry = {\n register(input: PromptDefinitionInput): PromptDefinition {\n if (!input.key || input.key.trim() === '') {\n throw new Error('Prompt definitions require a non-empty key');\n }\n\n const definition = normalizePromptDefinitionInput(input);\n const registry = getRegistry();\n const existing = registry.get(definition.key);\n\n if (existing) {\n const existingSignature = stableStringify(existing);\n const incomingSignature = stableStringify(definition);\n\n if (existingSignature !== incomingSignature) {\n throw new Error(\n `Prompt \"${definition.key}\" is already registered with a different definition`,\n );\n }\n\n return existing;\n }\n\n registry.set(definition.key, definition);\n return definition;\n },\n\n get(key: string): PromptDefinition | undefined {\n return getRegistry().get(key);\n },\n\n has(key: string): boolean {\n return getRegistry().has(key);\n },\n\n getAll(): PromptDefinition[] {\n return Array.from(getRegistry().values());\n },\n\n clear(): void {\n getRegistry().clear();\n },\n};\n\nexport function definePrompt(input: PromptDefinitionInput): PromptDefinition {\n return PromptRegistry.register(input);\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { invalidatePromptCache } from '../cache.js';\nimport { PromptRegistry } from '../prompt-registry.js';\nimport type {\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n} from '../types.js';\nimport {\n mergePromptLayers,\n normalizePromptLayer,\n parsePromptParams,\n serializePromptParams,\n validateModelName,\n validateProfileName,\n} from '../utils.js';\n\nexport interface PromptOverrideOptions extends SmrtObjectOptions {\n key?: string;\n tenantId?: string | null;\n template?: string | null;\n profile?: string | null;\n model?: string | null;\n params?: string | PromptParams | null;\n}\n\ntype PromptOverrideIdentity = {\n key: string;\n tenantId: string | null;\n};\n\ntype PromptTransactionHandle = DatabaseInterface & {\n commit: () => Promise<void>;\n rollback: () => Promise<void>;\n};\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\n@smrt({\n tableName: '_smrt_prompt_overrides',\n conflictColumns: ['key', 'context'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n exclude: ['getParams', 'setParams', 'toPromptLayer'],\n },\n mcp: { include: [] },\n})\nexport class PromptOverride extends SmrtObject {\n @field({ required: true })\n key: string = '';\n\n @field({ type: 'text', nullable: true })\n tenantId: string | null = null;\n\n @field({ type: 'text', nullable: true })\n template: string | null = null;\n\n @field({ type: 'text', nullable: true })\n profile: string | null = null;\n\n @field({ type: 'text', nullable: true })\n model: string | null = null;\n\n @field({ type: 'text', nullable: true })\n params: string | null = null;\n\n constructor(options: PromptOverrideOptions = {}) {\n super(options);\n\n if (options.key !== undefined) this.key = options.key;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.template !== undefined) this.template = options.template;\n if (options.profile !== undefined) this.profile = options.profile;\n if (options.model !== undefined) this.model = options.model;\n if (options.params !== undefined) {\n if (typeof options.params === 'string' || options.params === null) {\n this.params = options.params;\n } else {\n this.params = serializePromptParams(options.params);\n }\n }\n }\n\n getParams(): PromptParams {\n return parsePromptParams(this.params);\n }\n\n setParams(params: PromptParams | null): void {\n this.params = serializePromptParams(params);\n }\n\n toPromptLayer(): PromptLayer {\n return {\n template: this.template,\n profile: this.profile,\n model: this.model,\n params: this.params === null ? null : this.getParams(),\n };\n }\n\n override async save(): Promise<this> {\n const previousIdentity = await this.getPersistedIdentity();\n this.normalizeParamsForPersistence();\n await this.validatePromptOverride();\n // Use context as the uniqueness scope so app-level rows remain unique even\n // though tenantId is nullable and would otherwise allow multiple NULL rows.\n this.context = this.tenantId ?? '__app__';\n const identityChanged =\n previousIdentity &&\n (previousIdentity.key !== this.key ||\n previousIdentity.tenantId !== this.tenantId);\n\n const result =\n identityChanged && previousIdentity\n ? await this.saveAfterIdentityChange()\n : await super.save();\n\n if (identityChanged && previousIdentity) {\n invalidatePromptCache(\n previousIdentity.key,\n previousIdentity.tenantId,\n this.db,\n );\n }\n invalidatePromptCache(this.key, this.tenantId, this.db);\n return result;\n }\n\n private async saveAfterIdentityChange(): Promise<this> {\n if (typeof this.db.beginTransaction === 'function') {\n return this.saveAfterIdentityChangeInTransaction();\n }\n\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n private async saveAfterIdentityChangeInTransaction(): Promise<this> {\n const originalDb = this._db;\n const originalOptionsDb = this.options.db;\n const tx = (await this.db.beginTransaction?.()) as\n | PromptTransactionHandle\n | undefined;\n\n if (!tx) {\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n try {\n this._db = tx;\n this.options.db = tx;\n await super.delete();\n const result = await super.save();\n await tx.commit();\n return result;\n } catch (error) {\n try {\n await tx.rollback();\n } catch {\n // Preserve the original save error; rollback failures are secondary.\n }\n throw error;\n } finally {\n this._db = originalDb;\n this.options.db = originalOptionsDb;\n }\n }\n\n private async saveAfterIdentityChangeWithDeferredDelete(): Promise<this> {\n const previousId = this.id;\n if (!previousId) {\n return super.save();\n }\n\n const replacementId = crypto.randomUUID();\n let replacementSaved = false;\n this.id = replacementId;\n\n try {\n const result = await super.save();\n replacementSaved = true;\n await this.db.delete(this.tableName, { id: previousId });\n return result;\n } catch (error) {\n if (replacementSaved) {\n try {\n await this.db.delete(this.tableName, { id: replacementId });\n } catch {\n // Best effort cleanup keeps the original row as the source of truth.\n }\n }\n\n this.id = previousId;\n throw error;\n }\n }\n\n override async delete(): Promise<void> {\n const key = this.key;\n const tenantId = this.tenantId;\n await super.delete();\n invalidatePromptCache(key, tenantId, this.db);\n }\n\n private async validatePromptOverride(): Promise<void> {\n if (!this.key || this.key.trim() === '') {\n throw new Error('PromptOverride.key is required');\n }\n\n const definition = PromptRegistry.get(this.key);\n if (!definition) {\n throw new Error(`Unknown prompt key \"${this.key}\"`);\n }\n\n const config = getPromptConfig();\n const editable = definition.editable;\n\n if (this.template !== null && !editable.template) {\n throw new Error(`Prompt \"${this.key}\" does not allow template overrides`);\n }\n\n if (this.profile !== null && !editable.profile) {\n throw new Error(`Prompt \"${this.key}\" does not allow profile overrides`);\n }\n\n if (this.model !== null && !editable.model) {\n throw new Error(`Prompt \"${this.key}\" does not allow model overrides`);\n }\n\n if (this.params !== null && !editable.params) {\n throw new Error(`Prompt \"${this.key}\" does not allow params overrides`);\n }\n\n if (this.params !== null) {\n try {\n const parsed = JSON.parse(this.params);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('Prompt params must be a JSON object');\n }\n } catch (error) {\n throw new Error(\n `Prompt \"${this.key}\" has invalid params JSON: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n if (this.profile !== null) {\n validateProfileName(this.profile, config);\n }\n\n if (this.model !== null) {\n validateModelName(this.model, config);\n }\n\n const lowerLayers = await this.getLowerPrecedenceLayers();\n const currentLayer = this.toPromptLayer();\n const merged = mergePromptLayers(...lowerLayers, currentLayer);\n\n if (currentLayer.model && !merged.ai.profile) {\n throw new Error(\n `Prompt \"${this.key}\" model overrides require an effective prompt profile`,\n );\n }\n }\n\n private async getLowerPrecedenceLayers(): Promise<PromptLayer[]> {\n const definition = PromptRegistry.get(this.key);\n const config = getPromptConfig();\n const layers: PromptLayer[] = [];\n\n if (definition) {\n layers.push({\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n });\n }\n\n layers.push(normalizePromptLayer(config.prompts?.[this.key]));\n\n const { PromptOverrideCollection } = await import(\n '../collections/PromptOverrideCollection.js'\n );\n const collection = await PromptOverrideCollection.create({\n db: this.options.db ?? this.options.persistence,\n });\n\n if (this.tenantId) {\n const appOverride = await collection.getAppOverride(this.key, {\n excludeId: this.id ?? undefined,\n });\n if (appOverride) {\n layers.push(appOverride.toPromptLayer());\n }\n }\n\n return layers;\n }\n\n private normalizeParamsForPersistence(): void {\n const rawParams = this.params as unknown;\n\n if (rawParams === null || rawParams === undefined) {\n this.params = null;\n return;\n }\n\n if (typeof rawParams === 'string') {\n this.params = rawParams;\n return;\n }\n\n if (typeof rawParams === 'object' && !Array.isArray(rawParams)) {\n this.params = serializePromptParams(rawParams as PromptParams);\n return;\n }\n\n throw new Error(\n `Prompt \"${this.key}\" params must be a JSON object or JSON string`,\n );\n }\n\n private async getPersistedIdentity(): Promise<PromptOverrideIdentity | null> {\n if (!this.id) {\n return null;\n }\n\n const existing = await this.db.get(this.tableName, { id: this.id });\n if (!existing) {\n return null;\n }\n\n return {\n key: String((existing as Record<string, unknown>).key ?? this.key),\n tenantId:\n (existing as Record<string, unknown>).tenantId !== undefined\n ? ((existing as Record<string, unknown>).tenantId as string | null)\n : (((existing as Record<string, unknown>).tenant_id as\n | string\n | null\n | undefined) ?? null),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PromptOverride } from '../models/PromptOverride.js';\n\nexport class PromptOverrideCollection extends SmrtCollection<PromptOverride> {\n static readonly _itemClass = PromptOverride;\n\n private excludeOverrideId(\n items: PromptOverride[],\n excludeId?: string,\n ): PromptOverride[] {\n return items.filter((item) => (excludeId ? item.id !== excludeId : true));\n }\n\n async getAppOverride(\n key: string,\n options: { excludeId?: string } = {},\n ): Promise<PromptOverride | null> {\n const items = await this.list({ where: { key, tenantId: null } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getTenantOverride(\n key: string,\n tenantId: string,\n options: { excludeId?: string } = {},\n ): Promise<PromptOverride | null> {\n const items = await this.list({ where: { key, tenantId } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getResolutionLayers(\n key: string,\n tenantId?: string | null,\n options: { excludeId?: string } = {},\n ): Promise<{ app: PromptOverride | null; tenant: PromptOverride | null }> {\n const [app, tenant] = await Promise.all([\n this.getAppOverride(key, options),\n tenantId != null\n ? this.getTenantOverride(key, tenantId, options)\n : Promise.resolve(null),\n ]);\n\n return {\n app,\n tenant,\n };\n }\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { getCachedPromptBase, setCachedPromptBase } from './cache.js';\nimport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport { PromptRegistry } from './prompt-registry.js';\nimport type {\n PromptCacheValue,\n PromptPackageConfig,\n ResolvedPrompt,\n ResolvePromptOptions,\n} from './types.js';\nimport {\n buildResolvedAI,\n mergePromptLayers,\n normalizePromptLayer,\n renderPromptTemplate,\n} from './utils.js';\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\nasync function loadPromptBase(\n key: string,\n options: ResolvePromptOptions,\n): Promise<PromptCacheValue> {\n const definition = PromptRegistry.get(key);\n if (!definition) {\n throw new Error(`Unknown prompt key \"${key}\"`);\n }\n\n const tenantId =\n options.tenantId !== undefined ? options.tenantId : (getTenantId() ?? null);\n\n let collection: PromptOverrideCollection | null = null;\n let cacheDb: ResolvePromptOptions['db'] | undefined = options.db;\n if (options.db) {\n const initializedCollection = await PromptOverrideCollection.create({\n db: options.db,\n });\n collection = initializedCollection;\n cacheDb = initializedCollection.db as ResolvePromptOptions['db'];\n }\n\n const cached = getCachedPromptBase(key, tenantId, cacheDb);\n if (cached) {\n return cached;\n }\n\n const config = getPromptConfig();\n const layers = [\n {\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n },\n normalizePromptLayer(config.prompts?.[key]),\n ];\n\n if (collection) {\n const stored = await collection.getResolutionLayers(key, tenantId);\n\n if (stored.app) {\n layers.push(stored.app.toPromptLayer());\n }\n\n if (stored.tenant) {\n layers.push(stored.tenant.toPromptLayer());\n }\n }\n\n const merged = mergePromptLayers(...layers);\n const value: PromptCacheValue = {\n key,\n template: merged.template,\n ai: merged.ai,\n };\n\n setCachedPromptBase(key, tenantId, cacheDb, value);\n return value;\n}\n\nexport async function resolvePrompt(\n key: string,\n options: ResolvePromptOptions = {},\n): Promise<ResolvedPrompt> {\n const config = getPromptConfig();\n const base = await loadPromptBase(key, options);\n const runtimeOverride = normalizePromptLayer(options.override);\n const merged = mergePromptLayers(\n {\n template: base.template,\n profile: base.ai.profile ?? null,\n model: base.ai.model ?? null,\n params: base.ai.params,\n },\n runtimeOverride,\n );\n\n return {\n key,\n template: merged.template,\n text: renderPromptTemplate(merged.template, options.variables),\n ai: buildResolvedAI(merged.ai, config),\n };\n}\n","/**\n * @happyvertical/smrt-prompts\n *\n * Code-first prompts with config overrides, stored app/tenant overrides,\n * and runtime resolution helpers for SMRT applications.\n *\n * @packageDocumentation\n */\n\n// Self-register this package's manifest before any @smrt() decorator fires\n// downstream. Must come first so the side effect runs ahead of the class\n// module loads below. See __smrt-register__.ts for issue #1132 context.\nimport './__smrt-register__.js';\n\nexport { clearPromptCache, getPromptCacheTtlMs } from './cache.js';\nexport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nexport {\n PromptOverride,\n type PromptOverrideOptions,\n} from './models/PromptOverride.js';\nexport { definePrompt, PromptRegistry } from './prompt-registry.js';\nexport { resolvePrompt } from './prompt-resolver.js';\nexport type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinition,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPrompt,\n ResolvedPromptAI,\n ResolvePromptOptions,\n} from './types.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":";;;;;;;;;;;;;;;;;;;ACGA,IAAM,sBAAsB;AAO5B,IAAM,8BAAc,IAAI,IAAwB;AAChD,IAAM,gCAAgB,IAAI,QAAwB;AAClD,IAAI,WAAW;AAEf,SAAS,eAAe,IAAqB;CAC3C,IAAI,CAAC,IACH,OAAO;CAGT,IAAI,OAAO,OAAO,UAChB,OAAO,MAAM;CAGf,IAAI,OAAO,OAAO,UAAU;EAC1B,MAAM,WAAW;EACjB,IAAI,OAAO,SAAS,UAAU,YAAY;GACxC,IAAI,CAAC,cAAc,IAAI,QAAQ,GAC7B,cAAc,IAAI,UAAU,eAAe,YAAY;GAEzD,MAAM,YAAY,cAAc,IAAI,QAAQ;GAC5C,IAAI,WACF,OAAO;GAGT,OAAO;EACT;EAEA,IAAI;GACF,OAAO,aAAa,KAAK,UAAU,QAAQ;EAC7C,QAAQ;GACN,OAAO;EACT;CACF;CAEA,OAAO;AACT;AAEA,SAAS,cACP,KACA,UACA,IACQ;CACR,OAAO,GAAG,eAAe,EAAE,EAAC,IAAK,IAAG,IAAK,YAAY;AACvD;AAEO,SAAS,sBAA8B;CAC5C,OAAO;AACT;AAEO,SAAS,oBACd,KACA,UACA,IACyB;CACzB,MAAM,WAAW,cAAc,KAAK,UAAU,EAAE;CAChD,MAAM,SAAS,YAAY,IAAI,QAAQ;CAEvC,IAAI,CAAC,QACH,OAAO;CAGT,IAAI,OAAO,aAAa,KAAK,IAAI,GAAG;EAClC,YAAY,OAAO,QAAQ;EAC3B,OAAO;CACT;CAEA,OAAO,OAAO;AAChB;AAEO,SAAS,oBACd,KACA,UACA,IACA,OACM;CACN,YAAY,IAAI,cAAc,KAAK,UAAU,EAAE,GAAG;EAChD,WAAW,KAAK,IAAI,IAAI;EACxB;CACF,CAAC;AACH;AAEO,SAAS,sBACd,KACA,UACA,IACM;CACN,MAAM,cAAc,eAAe,EAAE;CAErC,IAAI,aAAa,QAAQ,aAAa,KAAA,GAAW;EAC/C,YAAY,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;EACnD;CACF;CAEA,MAAM,YAAY,GAAG,YAAW,IAAK,IAAG;CACxC,KAAA,MAAW,YAAY,YAAY,KAAK,GACtC,IAAI,SAAS,WAAW,SAAS,GAC/B,YAAY,OAAO,QAAQ;AAGjC;AAEO,SAAS,mBAAyB;CACvC,YAAY,MAAM;AACpB;;;ACpGA,IAAM,mBAAyC;CAC7C,UAAU;CACV,SAAS;CACT,OAAO;CACP,QAAQ;AACV;AAEA,IAAM,0CAA0B,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,IAAM,mCAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,IAAM,wCAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;AACF,CAAC;AAEM,SAAS,cACd,OACkC;CAClC,OAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AACrE;AAEO,SAAS,wBACd,UACsB;CACtB,OAAO;EACL,UAAU,UAAU,YAAY,iBAAiB;EACjD,SAAS,UAAU,WAAW,iBAAiB;EAC/C,OAAO,UAAU,SAAS,iBAAiB;EAC3C,QAAQ,UAAU,UAAU,iBAAiB;CAC/C;AACF;AAEA,SAAS,oBACP,QACA,cACc;CACd,MAAM,SAAuB,CAAC;CAE9B,IAAI,cAAc,OAAO,MAAM,GAC7B,OAAO,OAAO,QAAQ,qBAAqB,OAAO,MAAM,CAAC;CAG3D,IAAI,iBAAiB,UAAU,OAAO,gBAAgB,KAAA,GACpD,OAAO,cAAc,OAAO;CAG9B,IAAI,eAAe,UAAU,OAAO,cAAc,KAAA,GAChD,OAAO,YAAY,OAAO;CAG5B,KAAA,MAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;EACjD,IAAI,aAAa,IAAI,GAAG,KAAK,UAAU,KAAA,GACrC;EAEF,kBAAkB,QAAQ,KAAK,KAAK;CACtC;CAEA,OAAO;AACT;AAEA,SAAS,kBACP,QACA,KACA,OACM;CACN,IAAI,sBAAsB,IAAI,GAAG,KAAK,UAAU,KAAA,GAC9C;CAGF,OAAO,OAAO;AAChB;AAEO,SAAS,qBACd,QACc;CACd,MAAM,YAA0B,CAAC;CAEjC,IAAI,CAAC,QACH,OAAO;CAGT,KAAA,MAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,kBAAkB,WAAW,KAAK,KAAK;CAGzC,OAAO;AACT;AAEO,SAAS,kBAAA,GACX,aACW;CACd,MAAM,SAAuB,CAAC;CAE9B,KAAA,MAAW,SAAS,aAAa;EAC/B,IAAI,CAAC,OACH;EAGF,KAAA,MAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,kBAAkB,QAAQ,KAAK,KAAK;CAExC;CAEA,OAAO;AACT;AAEA,SAAS,iBAAiB,IAA+C;CACvE,IAAI,CAAC,cAAc,EAAE,GACnB,OAAO,EAAE,QAAQ,CAAC,EAAE;CAGtB,MAAM,UACJ,OAAO,GAAG,YAAY,YAAY,GAAG,YAAY,OAC7C,GAAG,UACH,KAAA;CACN,MAAM,QACJ,OAAO,GAAG,UAAU,YAAY,GAAG,UAAU,OAAO,GAAG,QAAQ,KAAA;CAEjE,OAAO;EACL,SAAS,WAAW,KAAA;EACpB,OAAO,SAAS,KAAA;EAChB,QAAQ,oBAAoB,IAAI,gBAAgB;CAClD;AACF;AAEO,SAAS,+BAA+B,OAK7C;CACA,OAAO;EACL,KAAK,MAAM;EACX,UAAU,MAAM;EAChB,IAAI,iBAAiB,MAAM,EAAE;EAC7B,UAAU,wBAAwB,MAAM,QAAQ;CAClD;AACF;AAEO,SAAS,qBACd,OACa;CACb,IAAI,CAAC,cAAc,KAAK,GACtB,OAAO,CAAC;CAGV,MAAM,WAAW,cAAc,MAAM,EAAE,IACnC,iBAAiB,MAAM,EAAE,IACzB,EAAE,QAAQ,CAAC,EAAE;CACjB,MAAM,iBAAiB,oBAAoB,OAAO,uBAAuB;CAEzE,OAAO;EACL,UACE,MAAM,aAAa,KAAA,IACf,KAAA,IACA,MAAM,aAAa,OACjB,OACA,OAAO,MAAM,QAAQ;EAC7B,SACE,MAAM,YAAY,KAAA,IACd,SAAS,UACT,MAAM,YAAY,OAChB,OACA,OAAO,MAAM,OAAO;EAC5B,OACE,MAAM,UAAU,KAAA,IACZ,SAAS,QACT,MAAM,UAAU,OACd,OACA,OAAO,MAAM,KAAK;EAC1B,QAAQ,kBAAkB,gBAAgB,SAAS,MAAM;CAC3D;AACF;AAEO,SAAS,kBAAA,GACX,QAIH;CACA,IAAI,WAAW;CACf,IAAI;CACJ,IAAI;CACJ,IAAI,SAAuB,CAAC;CAE5B,KAAA,MAAW,SAAS,QAAQ;EAC1B,IAAI,CAAC,OACH;EAGF,IAAI,MAAM,aAAa,KAAA,KAAa,MAAM,aAAa,MACrD,WAAW,MAAM;EAGnB,IAAI,MAAM,YAAY,KAAA,KAAa,MAAM,YAAY,MACnD,UAAU,MAAM;EAGlB,IAAI,MAAM,UAAU,KAAA,KAAa,MAAM,UAAU,MAC/C,QAAQ,MAAM;EAGhB,IAAI,MAAM,WAAW,KAAA,KAAa,MAAM,WAAW,MACjD,SAAS,kBAAkB,QAAQ,MAAM,MAAM;CAEnD;CAEA,OAAO;EACL;EACA,IAAI;GACF;GACA;GACA;EACF;CACF;AACF;AAEO,SAAS,uBAAuB,SAIrC;CAEA,MAAM,SAAS,oBADA,cAAc,OAAO,IAAI,UAAU,CAAC,mBACR,IAAI,IAAI,CAAC,YAAY,OAAO,CAAC,CAAC;CAEzE,OAAO;EACL,UAAU,OAAO,QAAQ,QAAQ;EACjC,OAAO,OAAO,QAAQ,KAAK;EAC3B;CACF;AACF;AAEO,SAAS,oBACd,aACA,QACM;CACN,IAAI,YAAY,KAAK,MAAM,IACzB,MAAM,IAAI,MAAM,sCAAsC;CAGxD,MAAM,sBAAsB,OAAO;CACnC,IACE,MAAM,QAAQ,mBAAmB,KACjC,CAAC,oBAAoB,SAAS,WAAW,GAEzC,MAAM,IAAI,MACR,mBAAmB,YAAW,qCAChC;CAGF,IAAI,CAAC,OAAO,WAAW,cACrB,MAAM,IAAI,MAAM,mBAAmB,YAAW,oBAAqB;AAEvE;AAEO,SAAS,kBACd,WACA,QACM;CACN,IAAI,UAAU,KAAK,MAAM,IACvB,MAAM,IAAI,MAAM,wCAAwC;CAG1D,MAAM,gBAAgB,OAAO;CAC7B,IAAI,MAAM,QAAQ,aAAa,KAAK,CAAC,cAAc,SAAS,SAAS,GACnE,MAAM,IAAI,MACR,iBAAiB,UAAS,mCAC5B;AAEJ;AAEO,SAAS,gBACd,IACA,QACkB;CAClB,IAAI;CACJ,IAAI,QAAQ,GAAG;CACf,IAAI,SAAS,GAAG;CAEhB,IAAI,GAAG,SAAS;EACd,oBAAoB,GAAG,SAAS,MAAM;EACtC,MAAM,oBAAoB,OAAO,WAAW,GAAG;EAC/C,IAAI,CAAC,mBACH,MAAM,IAAI,MAAM,mBAAmB,GAAG,QAAO,oBAAqB;EAEpE,MAAM,gBAAgB,uBAAuB,iBAAiB;EAC9D,WAAW,cAAc;EACzB,QAAQ,SAAS,cAAc;EAC/B,SAAS,kBAAkB,cAAc,QAAQ,MAAM;CACzD;CAEA,IAAI,GAAG,OACL,kBAAkB,GAAG,OAAO,MAAM;CAGpC,IAAI,GAAG,SAAS,CAAC,GAAG,SAClB,MAAM,IAAI,MACR,mEACF;CAGF,IAAI,SAAS,CAAC,GAAG,SAAS,OAAO,eAC/B,kBAAkB,OAAO,MAAM;CAGjC,MAAM,WAA6B;EACjC,GAAG;EACH,SAAS,GAAG;EACZ;EACA;EACA,GAAI,OAAO,gBACP,EAAE,eAAe,CAAC,GAAG,OAAO,aAAa,EAAE,IAC3C,CAAC;EACL;CACF;CAEA,IAAI,OAAO,OAAO,gBAAgB,UAChC,SAAS,cAAc,OAAO;CAGhC,IAAI,OAAO,OAAO,cAAc,UAC9B,SAAS,YAAY,OAAO;CAG9B,OAAO;AACT;AAEO,SAAS,qBACd,UACA,WACQ;CACR,IAAI,CAAC,aAAa,OAAO,KAAK,SAAS,CAAA,CAAE,WAAW,GAClD,OAAO;CAGT,OAAO,SAAS,QAAQ,kBAAkB,QAAQ,WAAmB;EAEnE,MAAM,QAAQ,UADF,OAAO,KACK;EAExB,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO;EAGT,IAAI,iBAAiB,MACnB,OAAO,MAAM,YAAY;EAG3B,IAAI,MAAM,QAAQ,KAAK,KAAK,cAAc,KAAK,GAC7C,IAAI;GACF,OAAO,KAAK,UAAU,KAAK;EAC7B,QAAQ;GACN,OAAO;EACT;EAGF,OAAO,OAAO,KAAK;CACrB,CAAC;AACH;AAEO,SAAS,kBACd,KACc;CACd,IAAI,CAAC,KACH,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,OAAO,cAAc,MAAM,IAAI,qBAAqB,MAAM,IAAI,CAAC;CACjE,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEO,SAAS,sBACd,QACe;CACf,IAAI,WAAW,QAAQ,WAAW,KAAA,GAChC,OAAO;CAGT,OAAO,KAAK,UAAU,qBAAqB,MAAM,CAAC;AACpD;;;ACzZA,SAAS,cAA6C;CACpD,IAAI,CAAC,WAAW,sBACd,WAAW,uCAAuB,IAAI,IAA8B;CAGtE,OAAO,WAAW;AACpB;AAEA,SAAS,gBAAgB,OAAwB;CAC/C,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,IAAI,MAAM,KAAK,SAAS,gBAAgB,IAAI,CAAC,CAAA,CAAE,KAAK,GAAG,EAAC;CAGjE,IAAI,SAAS,OAAO,UAAU,UAI5B,OAAO,IAHS,OAAO,QAAQ,KAAgC,CAAA,CAAE,MAC9D,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,KAAK,CAEpC,CAAA,CACR,KAAK,CAAC,KAAK,UAAU,GAAG,KAAK,UAAU,GAAG,EAAC,GAAI,gBAAgB,IAAI,GAAG,CAAA,CACtE,KAAK,GAAG,EAAC;CAGd,OAAO,KAAK,UAAU,KAAK;AAC7B;AAEO,IAAM,iBAAiB;CAC5B,SAAS,OAAgD;EACvD,IAAI,CAAC,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,IACrC,MAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,aAAa,+BAA+B,KAAK;EACvD,MAAM,WAAW,YAAY;EAC7B,MAAM,WAAW,SAAS,IAAI,WAAW,GAAG;EAE5C,IAAI,UAAU;GAIZ,IAH0B,gBAAgB,QAGtC,MAFsB,gBAAgB,UAEhB,GACxB,MAAM,IAAI,MACR,WAAW,WAAW,IAAG,oDAC3B;GAGF,OAAO;EACT;EAEA,SAAS,IAAI,WAAW,KAAK,UAAU;EACvC,OAAO;CACT;CAEA,IAAI,KAA2C;EAC7C,OAAO,YAAY,CAAA,CAAE,IAAI,GAAG;CAC9B;CAEA,IAAI,KAAsB;EACxB,OAAO,YAAY,CAAA,CAAE,IAAI,GAAG;CAC9B;CAEA,SAA6B;EAC3B,OAAO,MAAM,KAAK,YAAY,CAAA,CAAE,OAAO,CAAC;CAC1C;CAEA,QAAc;EACZ,YAAY,CAAA,CAAE,MAAM;CACtB;AACF;AAEO,SAAS,aAAa,OAAgD;CAC3E,OAAO,eAAe,SAAS,KAAK;AACtC;;;;;;;;;;;ACpCA,SAAS,oBAAuC;CAC9C,OAAO,iBAAsC,WAAW;EACtD,UAAU,CAAC;EACX,SAAS,CAAC;CACZ,CAAC;AACH;AAYO,IAAM,iBAAN,cAA6B,WAAW;CAE7C,MAAc;CAGd,WAA0B;CAG1B,WAA0B;CAG1B,UAAyB;CAGzB,QAAuB;CAGvB,SAAwB;CAExB,YAAY,UAAiC,CAAC,GAAG;EAC/C,MAAM,OAAO;EAEb,IAAI,QAAQ,QAAQ,KAAA,GAAW,KAAK,MAAM,QAAQ;EAClD,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,UAAU,KAAA,GAAW,KAAK,QAAQ,QAAQ;EACtD,IAAI,QAAQ,WAAW,KAAA,GACrB,IAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,WAAW,MAC3D,KAAK,SAAS,QAAQ;OAEtB,KAAK,SAAS,sBAAsB,QAAQ,MAAM;CAGxD;CAEA,YAA0B;EACxB,OAAO,kBAAkB,KAAK,MAAM;CACtC;CAEA,UAAU,QAAmC;EAC3C,KAAK,SAAS,sBAAsB,MAAM;CAC5C;CAEA,gBAA6B;EAC3B,OAAO;GACL,UAAU,KAAK;GACf,SAAS,KAAK;GACd,OAAO,KAAK;GACZ,QAAQ,KAAK,WAAW,OAAO,OAAO,KAAK,UAAU;EACvD;CACF;CAEA,MAAe,OAAsB;EACnC,MAAM,mBAAmB,MAAM,KAAK,qBAAqB;EACzD,KAAK,8BAA8B;EACnC,MAAM,KAAK,uBAAuB;EAGlC,KAAK,UAAU,KAAK,YAAY;EAChC,MAAM,kBACJ,qBACC,iBAAiB,QAAQ,KAAK,OAC7B,iBAAiB,aAAa,KAAK;EAEvC,MAAM,SACJ,mBAAmB,mBACf,MAAM,KAAK,wBAAwB,IACnC,MAAM,MAAM,KAAK;EAEvB,IAAI,mBAAmB,kBACrB,sBACE,iBAAiB,KACjB,iBAAiB,UACjB,KAAK,EACP;EAEF,sBAAsB,KAAK,KAAK,KAAK,UAAU,KAAK,EAAE;EACtD,OAAO;CACT;CAEA,MAAc,0BAAyC;EACrD,IAAI,OAAO,KAAK,GAAG,qBAAqB,YACtC,OAAO,KAAK,qCAAqC;EAGnD,OAAO,KAAK,0CAA0C;CACxD;CAEA,MAAc,uCAAsD;EAClE,MAAM,aAAa,KAAK;EACxB,MAAM,oBAAoB,KAAK,QAAQ;EACvC,MAAM,KAAM,MAAM,KAAK,GAAG,mBAAmB;EAI7C,IAAI,CAAC,IACH,OAAO,KAAK,0CAA0C;EAGxD,IAAI;GACF,KAAK,MAAM;GACX,KAAK,QAAQ,KAAK;GAClB,MAAM,MAAM,OAAO;GACnB,MAAM,SAAS,MAAM,MAAM,KAAK;GAChC,MAAM,GAAG,OAAO;GAChB,OAAO;EACT,SAAS,OAAO;GACd,IAAI;IACF,MAAM,GAAG,SAAS;GACpB,QAAQ,CAER;GACA,MAAM;EACR,UAAE;GACA,KAAK,MAAM;GACX,KAAK,QAAQ,KAAK;EACpB;CACF;CAEA,MAAc,4CAA2D;EACvE,MAAM,aAAa,KAAK;EACxB,IAAI,CAAC,YACH,OAAO,MAAM,KAAK;EAGpB,MAAM,gBAAgB,OAAO,WAAW;EACxC,IAAI,mBAAmB;EACvB,KAAK,KAAK;EAEV,IAAI;GACF,MAAM,SAAS,MAAM,MAAM,KAAK;GAChC,mBAAmB;GACnB,MAAM,KAAK,GAAG,OAAO,KAAK,WAAW,EAAE,IAAI,WAAW,CAAC;GACvD,OAAO;EACT,SAAS,OAAO;GACd,IAAI,kBACF,IAAI;IACF,MAAM,KAAK,GAAG,OAAO,KAAK,WAAW,EAAE,IAAI,cAAc,CAAC;GAC5D,QAAQ,CAER;GAGF,KAAK,KAAK;GACV,MAAM;EACR;CACF;CAEA,MAAe,SAAwB;EACrC,MAAM,MAAM,KAAK;EACjB,MAAM,WAAW,KAAK;EACtB,MAAM,MAAM,OAAO;EACnB,sBAAsB,KAAK,UAAU,KAAK,EAAE;CAC9C;CAEA,MAAc,yBAAwC;EACpD,IAAI,CAAC,KAAK,OAAO,KAAK,IAAI,KAAK,MAAM,IACnC,MAAM,IAAI,MAAM,gCAAgC;EAGlD,MAAM,aAAa,eAAe,IAAI,KAAK,GAAG;EAC9C,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,uBAAuB,KAAK,IAAG,EAAG;EAGpD,MAAM,SAAS,kBAAgB;EAC/B,MAAM,WAAW,WAAW;EAE5B,IAAI,KAAK,aAAa,QAAQ,CAAC,SAAS,UACtC,MAAM,IAAI,MAAM,WAAW,KAAK,IAAG,oCAAqC;EAG1E,IAAI,KAAK,YAAY,QAAQ,CAAC,SAAS,SACrC,MAAM,IAAI,MAAM,WAAW,KAAK,IAAG,mCAAoC;EAGzE,IAAI,KAAK,UAAU,QAAQ,CAAC,SAAS,OACnC,MAAM,IAAI,MAAM,WAAW,KAAK,IAAG,iCAAkC;EAGvE,IAAI,KAAK,WAAW,QAAQ,CAAC,SAAS,QACpC,MAAM,IAAI,MAAM,WAAW,KAAK,IAAG,kCAAmC;EAGxE,IAAI,KAAK,WAAW,MAClB,IAAI;GACF,MAAM,SAAS,KAAK,MAAM,KAAK,MAAM;GACrC,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAC/D,MAAM,IAAI,MAAM,qCAAqC;EAEzD,SAAS,OAAO;GACd,MAAM,IAAI,MACR,WAAW,KAAK,IAAG,6BACjB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAEzD;EACF;EAGF,IAAI,KAAK,YAAY,MACnB,oBAAoB,KAAK,SAAS,MAAM;EAG1C,IAAI,KAAK,UAAU,MACjB,kBAAkB,KAAK,OAAO,MAAM;EAGtC,MAAM,cAAc,MAAM,KAAK,yBAAyB;EACxD,MAAM,eAAe,KAAK,cAAc;EACxC,MAAM,SAAS,kBAAkB,GAAG,aAAa,YAAY;EAE7D,IAAI,aAAa,SAAS,CAAC,OAAO,GAAG,SACnC,MAAM,IAAI,MACR,WAAW,KAAK,IAAG,sDACrB;CAEJ;CAEA,MAAc,2BAAmD;EAC/D,MAAM,aAAa,eAAe,IAAI,KAAK,GAAG;EAC9C,MAAM,SAAS,kBAAgB;EAC/B,MAAM,SAAwB,CAAC;EAE/B,IAAI,YACF,OAAO,KAAK;GACV,UAAU,WAAW;GACrB,SAAS,WAAW,GAAG,WAAW;GAClC,OAAO,WAAW,GAAG,SAAS;GAC9B,QAAQ,WAAW,GAAG;EACxB,CAAC;EAGH,OAAO,KAAK,qBAAqB,OAAO,UAAU,KAAK,IAAI,CAAC;EAE5D,MAAM,EAAE,6BAA6B,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,gCAAA;EAGrC,MAAM,aAAa,MAAM,yBAAyB,OAAO,EACvD,IAAI,KAAK,QAAQ,MAAM,KAAK,QAAQ,YACtC,CAAC;EAED,IAAI,KAAK,UAAU;GACjB,MAAM,cAAc,MAAM,WAAW,eAAe,KAAK,KAAK,EAC5D,WAAW,KAAK,MAAM,KAAA,EACxB,CAAC;GACD,IAAI,aACF,OAAO,KAAK,YAAY,cAAc,CAAC;EAE3C;EAEA,OAAO;CACT;CAEQ,gCAAsC;EAC5C,MAAM,YAAY,KAAK;EAEvB,IAAI,cAAc,QAAQ,cAAc,KAAA,GAAW;GACjD,KAAK,SAAS;GACd;EACF;EAEA,IAAI,OAAO,cAAc,UAAU;GACjC,KAAK,SAAS;GACd;EACF;EAEA,IAAI,OAAO,cAAc,YAAY,CAAC,MAAM,QAAQ,SAAS,GAAG;GAC9D,KAAK,SAAS,sBAAsB,SAAyB;GAC7D;EACF;EAEA,MAAM,IAAI,MACR,WAAW,KAAK,IAAG,8CACrB;CACF;CAEA,MAAc,uBAA+D;EAC3E,IAAI,CAAC,KAAK,IACR,OAAO;EAGT,MAAM,WAAW,MAAM,KAAK,GAAG,IAAI,KAAK,WAAW,EAAE,IAAI,KAAK,GAAG,CAAC;EAClE,IAAI,CAAC,UACH,OAAO;EAGT,OAAO;GACL,KAAK,OAAQ,SAAqC,OAAO,KAAK,GAAG;GACjE,UACG,SAAqC,aAAa,KAAA,IAC7C,SAAqC,WACpC,SAAqC,aAGtB;EAC1B;CACF;AACF;AAxSE,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GADd,eAEX,WAAA,OAAA,CAAA;AAGA,gBAAA,CADC,MAAM;CAAE,MAAM;CAAQ,UAAU;AAAK,CAAC,CAAA,GAJ5B,eAKX,WAAA,YAAA,CAAA;AAGA,gBAAA,CADC,MAAM;CAAE,MAAM;CAAQ,UAAU;AAAK,CAAC,CAAA,GAP5B,eAQX,WAAA,YAAA,CAAA;AAGA,gBAAA,CADC,MAAM;CAAE,MAAM;CAAQ,UAAU;AAAK,CAAC,CAAA,GAV5B,eAWX,WAAA,WAAA,CAAA;AAGA,gBAAA,CADC,MAAM;CAAE,MAAM;CAAQ,UAAU;AAAK,CAAC,CAAA,GAb5B,eAcX,WAAA,SAAA,CAAA;AAGA,gBAAA,CADC,MAAM;CAAE,MAAM;CAAQ,UAAU;AAAK,CAAC,CAAA,GAhB5B,eAiBX,WAAA,UAAA,CAAA;AAjBW,iBAAN,gBAAA,CAVN,KAAK;CACJ,WAAW;CACX,iBAAiB,CAAC,OAAO,SAAS;CAClC,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK;EACH,SAAS;GAAC;GAAQ;GAAO;GAAU;GAAU;EAAQ;EACrD,SAAS;GAAC;GAAa;GAAa;EAAe;CACrD;CACA,KAAK,EAAE,SAAS,CAAC,EAAE;AACrB,CAAC,CAAA,GACY,cAAA;;;;ACzDN,IAAM,2BAAN,cAAuC,eAA+B;CAC3E,OAAgB,aAAa;CAErB,kBACN,OACA,WACkB;EAClB,OAAO,MAAM,QAAQ,SAAU,YAAY,KAAK,OAAO,YAAY,IAAK;CAC1E;CAEA,MAAM,eACJ,KACA,UAAkC,CAAC,GACH;EAChC,MAAM,QAAQ,MAAM,KAAK,KAAK,EAAE,OAAO;GAAE;GAAK,UAAU;EAAK,EAAE,CAAC;EAChE,OAAO,KAAK,kBAAkB,OAAO,QAAQ,SAAS,CAAA,CAAE,MAAM;CAChE;CAEA,MAAM,kBACJ,KACA,UACA,UAAkC,CAAC,GACH;EAChC,MAAM,QAAQ,MAAM,KAAK,KAAK,EAAE,OAAO;GAAE;GAAK;EAAS,EAAE,CAAC;EAC1D,OAAO,KAAK,kBAAkB,OAAO,QAAQ,SAAS,CAAA,CAAE,MAAM;CAChE;CAEA,MAAM,oBACJ,KACA,UACA,UAAkC,CAAC,GACqC;EACxE,MAAM,CAAC,KAAK,UAAU,MAAM,QAAQ,IAAI,CACtC,KAAK,eAAe,KAAK,OAAO,GAChC,YAAY,OACR,KAAK,kBAAkB,KAAK,UAAU,OAAO,IAC7C,QAAQ,QAAQ,IAAI,CAC1B,CAAC;EAED,OAAO;GACL;GACA;EACF;CACF;AACF;;;AC7BA,SAAS,kBAAuC;CAC9C,OAAO,iBAAsC,WAAW;EACtD,UAAU,CAAC;EACX,SAAS,CAAC;CACZ,CAAC;AACH;AAEA,eAAe,eACb,KACA,SAC2B;CAC3B,MAAM,aAAa,eAAe,IAAI,GAAG;CACzC,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,uBAAuB,IAAG,EAAG;CAG/C,MAAM,WACJ,QAAQ,aAAa,KAAA,IAAY,QAAQ,WAAY,YAAY,KAAK;CAExE,IAAI,aAA8C;CAClD,IAAI,UAAkD,QAAQ;CAC9D,IAAI,QAAQ,IAAI;EACd,MAAM,wBAAwB,MAAM,yBAAyB,OAAO,EAClE,IAAI,QAAQ,GACd,CAAC;EACD,aAAa;EACb,UAAU,sBAAsB;CAClC;CAEA,MAAM,SAAS,oBAAoB,KAAK,UAAU,OAAO;CACzD,IAAI,QACF,OAAO;CAGT,MAAM,SAAS,gBAAgB;CAC/B,MAAM,SAAS,CACb;EACE,UAAU,WAAW;EACrB,SAAS,WAAW,GAAG,WAAW;EAClC,OAAO,WAAW,GAAG,SAAS;EAC9B,QAAQ,WAAW,GAAG;CACxB,GACA,qBAAqB,OAAO,UAAU,IAAI,CAC5C;CAEA,IAAI,YAAY;EACd,MAAM,SAAS,MAAM,WAAW,oBAAoB,KAAK,QAAQ;EAEjE,IAAI,OAAO,KACT,OAAO,KAAK,OAAO,IAAI,cAAc,CAAC;EAGxC,IAAI,OAAO,QACT,OAAO,KAAK,OAAO,OAAO,cAAc,CAAC;CAE7C;CAEA,MAAM,SAAS,kBAAkB,GAAG,MAAM;CAC1C,MAAM,QAA0B;EAC9B;EACA,UAAU,OAAO;EACjB,IAAI,OAAO;CACb;CAEA,oBAAoB,KAAK,UAAU,SAAS,KAAK;CACjD,OAAO;AACT;AAEA,eAAsB,cACpB,KACA,UAAgC,CAAC,GACR;CACzB,MAAM,SAAS,gBAAgB;CAC/B,MAAM,OAAO,MAAM,eAAe,KAAK,OAAO;CAC9C,MAAM,kBAAkB,qBAAqB,QAAQ,QAAQ;CAC7D,MAAM,SAAS,kBACb;EACE,UAAU,KAAK;EACf,SAAS,KAAK,GAAG,WAAW;EAC5B,OAAO,KAAK,GAAG,SAAS;EACxB,QAAQ,KAAK,GAAG;CAClB,GACA,eACF;CAEA,OAAO;EACL;EACA,UAAU,OAAO;EACjB,MAAM,qBAAqB,OAAO,UAAU,QAAQ,SAAS;EAC7D,IAAI,gBAAgB,OAAO,IAAI,MAAM;CACvC;AACF;;;ACtEO,IAAM,8BAA8B"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/__smrt-register__.ts","../src/cache.ts","../src/utils.ts","../src/prompt-registry.ts","../src/models/PromptOverride.ts","../src/collections/PromptOverrideCollection.ts","../src/prompt-resolver.ts","../src/index.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt()\n * decorator in the package fires. Fixes issue #1132: in consumer runtimes\n * (tsx, SvelteKit SSR, plain `vite dev`) the decorator's synchronous manifest\n * lookup previously missed because no step populated the global manifest cache\n * — classes got registered with zero fields and `save()` / `toJSON()`\n * silently dropped every declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates\n * manifests via a different path. Only needs to succeed in the published dist\n * output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","import type { DatabaseInterface } from '@happyvertical/sql';\nimport type { PromptCacheValue } from './types.js';\n\nconst PROMPT_CACHE_TTL_MS = 30_000;\n\ntype CacheEntry = {\n expiresAt: number;\n value: PromptCacheValue;\n};\n\nconst promptCache = new Map<string, CacheEntry>();\n/** Monotonic per-`(db, key)` invalidation counter; see getPromptCacheGeneration. */\nconst cacheGenerations = new Map<string, number>();\n/**\n * Source of every generation value. Drawing from one counter instead of\n * incrementing each key independently makes a generation unique across every\n * key and every clear, which is what lets `clearedThrough` work as a floor.\n */\nlet nextGeneration = 1;\n/**\n * Floor that `clearPromptCache()` raises for *every* key, including keys with\n * no map entry. A key that has never been invalidated in this process reads as\n * generation 0, so a resolution that captured 0 before a clear would still see\n * 0 after it and write its pre-clear value back — the flush would be silently\n * undone for the rest of the TTL.\n */\nlet clearedThrough = 0;\nconst dbInstanceIds = new WeakMap<object, string>();\nlet nextDbId = 1;\n\nfunction getDbNamespace(db: unknown): string {\n if (!db) {\n return 'no-db';\n }\n\n if (typeof db === 'string') {\n return `db:${db}`;\n }\n\n if (typeof db === 'object') {\n const dbObject = db as Record<string, unknown>;\n if (typeof dbObject.query === 'function') {\n if (!dbInstanceIds.has(dbObject)) {\n dbInstanceIds.set(dbObject, `db-instance:${nextDbId++}`);\n }\n const namespace = dbInstanceIds.get(dbObject);\n if (namespace) {\n return namespace;\n }\n\n return 'db-instance:unknown';\n }\n\n try {\n return `db-config:${JSON.stringify(dbObject)}`;\n } catch {\n return 'db-config:opaque';\n }\n }\n\n return 'db:unknown';\n}\n\nfunction buildCacheKey(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): string {\n return `${getDbNamespace(db)}::${key}::${tenantId ?? 'app'}`;\n}\n\nfunction buildGenerationKey(\n key: string,\n db: DatabaseInterface | unknown,\n): string {\n return `${getDbNamespace(db)}::${key}`;\n}\n\nfunction bumpGeneration(key: string, db: DatabaseInterface | unknown): void {\n cacheGenerations.set(buildGenerationKey(key, db), nextGeneration++);\n}\n\nexport function getPromptCacheTtlMs(): number {\n return PROMPT_CACHE_TTL_MS;\n}\n\nexport function getCachedPromptBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): PromptCacheValue | null {\n const cacheKey = buildCacheKey(key, tenantId, db);\n const cached = promptCache.get(cacheKey);\n\n if (!cached) {\n return null;\n }\n\n if (cached.expiresAt <= Date.now()) {\n promptCache.delete(cacheKey);\n return null;\n }\n\n return cached.value;\n}\n\n/**\n * Reads the current invalidation generation for a key.\n *\n * A resolution captures this *before* its asynchronous layer loads and hands\n * it back to {@link setCachedPromptBase}. Any write that lands while those\n * loads are in flight bumps the generation, so the in-flight resolution —\n * which read the pre-write layers — is refused the cache write instead of\n * repopulating the key it just invalidated. Without this, a read that raced a\n * write served the pre-write value for the full TTL, and a raced `delete()`\n * resurrected the deleted override.\n *\n * Tracked per `(db, key)` rather than per `(db, key, tenantId)`: an app-level\n * row is inherited by every tenant, so a write to any scope of a key must\n * invalidate every scope of it. This matches the coarsest fan-out of\n * {@link invalidatePromptCache}.\n *\n * A key with no entry of its own reports the {@link clearPromptCache} floor\n * rather than a bare 0, so a clear refuses in-flight writes for keys that have\n * never been invalidated too.\n */\nexport function getPromptCacheGeneration(\n key: string,\n db: DatabaseInterface | unknown,\n): number {\n const generation = cacheGenerations.get(buildGenerationKey(key, db)) ?? 0;\n return generation > clearedThrough ? generation : clearedThrough;\n}\n\nexport function setCachedPromptBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n value: PromptCacheValue,\n loadedAtGeneration: number,\n): void {\n if (getPromptCacheGeneration(key, db) !== loadedAtGeneration) {\n // A write landed while this resolution was loading. Its value is already\n // stale, so drop it rather than poison the key for the whole TTL.\n return;\n }\n\n promptCache.set(buildCacheKey(key, tenantId, db), {\n expiresAt: Date.now() + PROMPT_CACHE_TTL_MS,\n value,\n });\n}\n\n/**\n * Invalidates a cached resolution. An app-level write (tenantId null) clears\n * every tenant's entry for that key, because each tenant inherits from it.\n */\nexport function invalidatePromptCache(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): void {\n const dbNamespace = getDbNamespace(db);\n bumpGeneration(key, db);\n\n if (tenantId !== null && tenantId !== undefined) {\n promptCache.delete(buildCacheKey(key, tenantId, db));\n return;\n }\n\n const keyPrefix = `${dbNamespace}::${key}::`;\n for (const cacheKey of promptCache.keys()) {\n if (cacheKey.startsWith(keyPrefix)) {\n promptCache.delete(cacheKey);\n }\n }\n}\n\nexport function clearPromptCache(): void {\n promptCache.clear();\n // Raise the floor instead of resetting counters: a resolution that started\n // before the clear must be refused its write, and raising a single floor\n // covers keys with no generation entry, which a per-key bump cannot reach.\n // With the floor carrying the refusal, the per-key entries can be dropped.\n clearedThrough = nextGeneration++;\n cacheGenerations.clear();\n}\n","import type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPromptAI,\n} from './types.js';\n\nconst DEFAULT_EDITABLE: PromptEditableConfig = {\n template: false,\n profile: false,\n model: false,\n params: false,\n};\n\nconst TOP_LEVEL_RESERVED_KEYS = new Set([\n 'key',\n 'editable',\n 'template',\n 'ai',\n 'profile',\n 'provider',\n 'model',\n 'params',\n 'temperature',\n 'maxTokens',\n]);\n\nconst AI_RESERVED_KEYS = new Set([\n 'profile',\n 'provider',\n 'model',\n 'params',\n 'temperature',\n 'maxTokens',\n]);\n\nconst AI_ROUTING_PARAM_KEYS = new Set([\n 'profile',\n 'provider',\n 'type',\n 'model',\n 'defaultModel',\n]);\n\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function normalizeEditableConfig(\n editable?: Partial<PromptEditableConfig>,\n): PromptEditableConfig {\n return {\n template: editable?.template ?? DEFAULT_EDITABLE.template,\n profile: editable?.profile ?? DEFAULT_EDITABLE.profile,\n model: editable?.model ?? DEFAULT_EDITABLE.model,\n params: editable?.params ?? DEFAULT_EDITABLE.params,\n };\n}\n\nfunction extractPromptParams(\n source: Record<string, unknown>,\n reservedKeys: Set<string>,\n): PromptParams {\n const params: PromptParams = {};\n\n if (isPlainObject(source.params)) {\n Object.assign(params, sanitizePromptParams(source.params));\n }\n\n if ('temperature' in source && source.temperature !== undefined) {\n params.temperature = source.temperature;\n }\n\n if ('maxTokens' in source && source.maxTokens !== undefined) {\n params.maxTokens = source.maxTokens;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (reservedKeys.has(key) || value === undefined) {\n continue;\n }\n assignPromptParam(params, key, value);\n }\n\n return params;\n}\n\nfunction assignPromptParam(\n params: PromptParams,\n key: string,\n value: unknown,\n): void {\n if (AI_ROUTING_PARAM_KEYS.has(key) || value === undefined) {\n return;\n }\n\n params[key] = value;\n}\n\nexport function sanitizePromptParams(\n params: PromptParams | null | undefined,\n): PromptParams {\n const sanitized: PromptParams = {};\n\n if (!params) {\n return sanitized;\n }\n\n for (const [key, value] of Object.entries(params)) {\n assignPromptParam(sanitized, key, value);\n }\n\n return sanitized;\n}\n\nexport function mergePromptParams(\n ...paramLayers: Array<PromptParams | null | undefined>\n): PromptParams {\n const merged: PromptParams = {};\n\n for (const layer of paramLayers) {\n if (!layer) {\n continue;\n }\n\n for (const [key, value] of Object.entries(layer)) {\n assignPromptParam(merged, key, value);\n }\n }\n\n return merged;\n}\n\nfunction normalizeAIInput(ai?: PromptAIInput | null): NormalizedPromptAI {\n if (!isPlainObject(ai)) {\n return { params: {} };\n }\n\n const profile =\n typeof ai.profile === 'string' || ai.profile === null\n ? ai.profile\n : undefined;\n const model =\n typeof ai.model === 'string' || ai.model === null ? ai.model : undefined;\n\n return {\n profile: profile ?? undefined,\n model: model ?? undefined,\n params: extractPromptParams(ai, AI_RESERVED_KEYS),\n };\n}\n\nexport function normalizePromptDefinitionInput(input: PromptDefinitionInput): {\n key: string;\n template: string;\n ai: NormalizedPromptAI;\n editable: PromptEditableConfig;\n} {\n return {\n key: input.key,\n template: input.template,\n ai: normalizeAIInput(input.ai),\n editable: normalizeEditableConfig(input.editable),\n };\n}\n\nexport function normalizePromptLayer(\n input?: PromptConfigOverrideInput | null,\n): PromptLayer {\n if (!isPlainObject(input)) {\n return {};\n }\n\n const nestedAi = isPlainObject(input.ai)\n ? normalizeAIInput(input.ai)\n : { params: {} };\n const topLevelParams = extractPromptParams(input, TOP_LEVEL_RESERVED_KEYS);\n\n return {\n template:\n input.template === undefined\n ? undefined\n : input.template === null\n ? null\n : String(input.template),\n profile:\n input.profile === undefined\n ? nestedAi.profile\n : input.profile === null\n ? null\n : String(input.profile),\n model:\n input.model === undefined\n ? nestedAi.model\n : input.model === null\n ? null\n : String(input.model),\n params: mergePromptParams(topLevelParams, nestedAi.params),\n };\n}\n\nexport function mergePromptLayers(\n ...layers: Array<PromptLayer | null | undefined>\n): {\n template: string;\n ai: NormalizedPromptAI;\n} {\n let template = '';\n let profile: string | undefined;\n let model: string | undefined;\n let params: PromptParams = {};\n\n for (const layer of layers) {\n if (!layer) {\n continue;\n }\n\n if (layer.template !== undefined && layer.template !== null) {\n template = layer.template;\n }\n\n if (layer.profile !== undefined && layer.profile !== null) {\n profile = layer.profile;\n }\n\n if (layer.model !== undefined && layer.model !== null) {\n model = layer.model;\n }\n\n if (layer.params !== undefined && layer.params !== null) {\n params = mergePromptParams(params, layer.params);\n }\n }\n\n return {\n template,\n ai: {\n profile,\n model,\n params,\n },\n };\n}\n\nexport function normalizeProfileConfig(profile: PromptProfileConfig): {\n provider: string;\n model: string;\n params: PromptParams;\n} {\n const source = isPlainObject(profile) ? profile : {};\n const params = extractPromptParams(source, new Set(['provider', 'model']));\n\n return {\n provider: String(profile.provider),\n model: String(profile.model),\n params,\n };\n}\n\nexport function validateProfileName(\n profileName: string,\n config: PromptPackageConfig,\n): void {\n if (profileName.trim() === '') {\n throw new Error('Prompt profile names cannot be empty');\n }\n\n const allowedProfileNames = config.allowedProfileNames;\n if (\n Array.isArray(allowedProfileNames) &&\n !allowedProfileNames.includes(profileName)\n ) {\n throw new Error(\n `Prompt profile \"${profileName}\" is not in the allowed profile list`,\n );\n }\n\n if (!config.profiles?.[profileName]) {\n throw new Error(`Prompt profile \"${profileName}\" is not configured`);\n }\n}\n\nexport function validateModelName(\n modelName: string,\n config: PromptPackageConfig,\n): void {\n if (modelName.trim() === '') {\n throw new Error('Prompt model overrides cannot be empty');\n }\n\n const allowedModels = config.allowedModels;\n if (Array.isArray(allowedModels) && !allowedModels.includes(modelName)) {\n throw new Error(\n `Prompt model \"${modelName}\" is not in the allowed model list`,\n );\n }\n}\n\nexport function buildResolvedAI(\n ai: NormalizedPromptAI,\n config: PromptPackageConfig,\n): ResolvedPromptAI {\n let provider: string | undefined;\n let model = ai.model;\n let params = ai.params;\n\n if (ai.profile) {\n validateProfileName(ai.profile, config);\n const configuredProfile = config.profiles?.[ai.profile];\n if (!configuredProfile) {\n throw new Error(`Prompt profile \"${ai.profile}\" is not configured`);\n }\n const profileConfig = normalizeProfileConfig(configuredProfile);\n provider = profileConfig.provider;\n model = model ?? profileConfig.model;\n params = mergePromptParams(profileConfig.params, params);\n }\n\n if (ai.model) {\n validateModelName(ai.model, config);\n }\n\n if (ai.model && !ai.profile) {\n throw new Error(\n 'Direct prompt model overrides require an effective prompt profile',\n );\n }\n\n if (model && !ai.model && config.allowedModels) {\n validateModelName(model, config);\n }\n\n const resolved: ResolvedPromptAI = {\n ...params,\n profile: ai.profile,\n provider,\n model,\n ...(config.allowedModels\n ? { allowedModels: [...config.allowedModels] }\n : {}),\n params,\n };\n\n if (typeof params.temperature === 'number') {\n resolved.temperature = params.temperature;\n }\n\n if (typeof params.maxTokens === 'number') {\n resolved.maxTokens = params.maxTokens;\n }\n\n return resolved;\n}\n\nexport function renderPromptTemplate(\n template: string,\n variables?: Record<string, unknown>,\n): string {\n if (!variables || Object.keys(variables).length === 0) {\n return template;\n }\n\n return template.replace(/\\{([^{}]+)\\}/g, (_match, rawKey: string) => {\n const key = rawKey.trim();\n const value = variables[key];\n\n if (value === undefined || value === null) {\n return '';\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (Array.isArray(value) || isPlainObject(value)) {\n try {\n return JSON.stringify(value);\n } catch {\n return '';\n }\n }\n\n return String(value);\n });\n}\n\nexport function parsePromptParams(\n raw: string | null | undefined,\n): PromptParams {\n if (!raw) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return isPlainObject(parsed) ? sanitizePromptParams(parsed) : {};\n } catch {\n return {};\n }\n}\n\nexport function serializePromptParams(\n params: PromptParams | null | undefined,\n): string | null {\n if (params === null || params === undefined) {\n return null;\n }\n\n return JSON.stringify(sanitizePromptParams(params));\n}\n","import type { PromptDefinition, PromptDefinitionInput } from './types.js';\nimport { normalizePromptDefinitionInput } from './utils.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtPromptRegistry: Map<string, PromptDefinition> | undefined;\n}\n\nfunction getRegistry(): Map<string, PromptDefinition> {\n if (!globalThis.__smrtPromptRegistry) {\n globalThis.__smrtPromptRegistry = new Map<string, PromptDefinition>();\n }\n\n return globalThis.__smrtPromptRegistry;\n}\n\nfunction stableStringify(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map((item) => stableStringify(item)).join(',')}]`;\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>).sort(\n ([left], [right]) => left.localeCompare(right),\n );\n return `{${entries\n .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)\n .join(',')}}`;\n }\n\n return JSON.stringify(value);\n}\n\nexport const PromptRegistry = {\n register(input: PromptDefinitionInput): PromptDefinition {\n if (!input.key || input.key.trim() === '') {\n throw new Error('Prompt definitions require a non-empty key');\n }\n\n const definition = normalizePromptDefinitionInput(input);\n const registry = getRegistry();\n const existing = registry.get(definition.key);\n\n if (existing) {\n const existingSignature = stableStringify(existing);\n const incomingSignature = stableStringify(definition);\n\n if (existingSignature !== incomingSignature) {\n throw new Error(\n `Prompt \"${definition.key}\" is already registered with a different definition`,\n );\n }\n\n return existing;\n }\n\n registry.set(definition.key, definition);\n return definition;\n },\n\n get(key: string): PromptDefinition | undefined {\n return getRegistry().get(key);\n },\n\n has(key: string): boolean {\n return getRegistry().has(key);\n },\n\n getAll(): PromptDefinition[] {\n return Array.from(getRegistry().values());\n },\n\n clear(): void {\n getRegistry().clear();\n },\n};\n\nexport function definePrompt(input: PromptDefinitionInput): PromptDefinition {\n return PromptRegistry.register(input);\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { invalidatePromptCache } from '../cache.js';\nimport { PromptRegistry } from '../prompt-registry.js';\nimport type {\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n} from '../types.js';\nimport {\n mergePromptLayers,\n normalizePromptLayer,\n parsePromptParams,\n serializePromptParams,\n validateModelName,\n validateProfileName,\n} from '../utils.js';\n\nexport interface PromptOverrideOptions extends SmrtObjectOptions {\n key?: string;\n tenantId?: string | null;\n template?: string | null;\n profile?: string | null;\n model?: string | null;\n params?: string | PromptParams | null;\n}\n\ntype PromptOverrideIdentity = {\n key: string;\n tenantId: string | null;\n};\n\ntype PromptTransactionHandle = DatabaseInterface & {\n commit: () => Promise<void>;\n rollback: () => Promise<void>;\n};\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\n@smrt({\n tableName: '_smrt_prompt_overrides',\n conflictColumns: ['key', 'context'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n exclude: ['getParams', 'setParams', 'toPromptLayer'],\n },\n mcp: { include: [] },\n})\nexport class PromptOverride extends SmrtObject {\n @field({ required: true })\n key: string = '';\n\n @field({ type: 'text', nullable: true })\n tenantId: string | null = null;\n\n @field({ type: 'text', nullable: true })\n template: string | null = null;\n\n @field({ type: 'text', nullable: true })\n profile: string | null = null;\n\n @field({ type: 'text', nullable: true })\n model: string | null = null;\n\n @field({ type: 'text', nullable: true })\n params: string | null = null;\n\n constructor(options: PromptOverrideOptions = {}) {\n super(options);\n\n if (options.key !== undefined) this.key = options.key;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.template !== undefined) this.template = options.template;\n if (options.profile !== undefined) this.profile = options.profile;\n if (options.model !== undefined) this.model = options.model;\n if (options.params !== undefined) {\n if (typeof options.params === 'string' || options.params === null) {\n this.params = options.params;\n } else {\n this.params = serializePromptParams(options.params);\n }\n }\n }\n\n getParams(): PromptParams {\n return parsePromptParams(this.params);\n }\n\n setParams(params: PromptParams | null): void {\n this.params = serializePromptParams(params);\n }\n\n toPromptLayer(): PromptLayer {\n return {\n template: this.template,\n profile: this.profile,\n model: this.model,\n params: this.params === null ? null : this.getParams(),\n };\n }\n\n override async save(): Promise<this> {\n const previousIdentity = await this.getPersistedIdentity();\n this.normalizeParamsForPersistence();\n await this.validatePromptOverride();\n // Use context as the uniqueness scope so app-level rows remain unique even\n // though tenantId is nullable and would otherwise allow multiple NULL rows.\n this.context = this.tenantId ?? '__app__';\n const identityChanged =\n previousIdentity &&\n (previousIdentity.key !== this.key ||\n previousIdentity.tenantId !== this.tenantId);\n\n const result =\n identityChanged && previousIdentity\n ? await this.saveAfterIdentityChange()\n : await super.save();\n\n if (identityChanged && previousIdentity) {\n invalidatePromptCache(\n previousIdentity.key,\n previousIdentity.tenantId,\n this.db,\n );\n }\n invalidatePromptCache(this.key, this.tenantId, this.db);\n return result;\n }\n\n private async saveAfterIdentityChange(): Promise<this> {\n if (typeof this.db.beginTransaction === 'function') {\n return this.saveAfterIdentityChangeInTransaction();\n }\n\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n private async saveAfterIdentityChangeInTransaction(): Promise<this> {\n const originalDb = this._db;\n const originalOptionsDb = this.options.db;\n const tx = (await this.db.beginTransaction?.()) as\n | PromptTransactionHandle\n | undefined;\n\n if (!tx) {\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n try {\n this._db = tx;\n this.options.db = tx;\n await super.delete();\n const result = await super.save();\n await tx.commit();\n return result;\n } catch (error) {\n try {\n await tx.rollback();\n } catch {\n // Preserve the original save error; rollback failures are secondary.\n }\n throw error;\n } finally {\n this._db = originalDb;\n this.options.db = originalOptionsDb;\n }\n }\n\n private async saveAfterIdentityChangeWithDeferredDelete(): Promise<this> {\n const previousId = this.id;\n if (!previousId) {\n return super.save();\n }\n\n const replacementId = crypto.randomUUID();\n let replacementSaved = false;\n this.id = replacementId;\n\n try {\n const result = await super.save();\n replacementSaved = true;\n await this.db.delete(this.tableName, { id: previousId });\n return result;\n } catch (error) {\n if (replacementSaved) {\n try {\n await this.db.delete(this.tableName, { id: replacementId });\n } catch {\n // Best effort cleanup keeps the original row as the source of truth.\n }\n }\n\n this.id = previousId;\n throw error;\n }\n }\n\n override async delete(): Promise<void> {\n const key = this.key;\n const tenantId = this.tenantId;\n await super.delete();\n invalidatePromptCache(key, tenantId, this.db);\n }\n\n private async validatePromptOverride(): Promise<void> {\n if (!this.key || this.key.trim() === '') {\n throw new Error('PromptOverride.key is required');\n }\n\n const definition = PromptRegistry.get(this.key);\n if (!definition) {\n throw new Error(`Unknown prompt key \"${this.key}\"`);\n }\n\n const config = getPromptConfig();\n const editable = definition.editable;\n\n if (this.template !== null && !editable.template) {\n throw new Error(`Prompt \"${this.key}\" does not allow template overrides`);\n }\n\n if (this.profile !== null && !editable.profile) {\n throw new Error(`Prompt \"${this.key}\" does not allow profile overrides`);\n }\n\n if (this.model !== null && !editable.model) {\n throw new Error(`Prompt \"${this.key}\" does not allow model overrides`);\n }\n\n if (this.params !== null && !editable.params) {\n throw new Error(`Prompt \"${this.key}\" does not allow params overrides`);\n }\n\n if (this.params !== null) {\n try {\n const parsed = JSON.parse(this.params);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('Prompt params must be a JSON object');\n }\n } catch (error) {\n throw new Error(\n `Prompt \"${this.key}\" has invalid params JSON: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n if (this.profile !== null) {\n validateProfileName(this.profile, config);\n }\n\n if (this.model !== null) {\n validateModelName(this.model, config);\n }\n\n const lowerLayers = await this.getLowerPrecedenceLayers();\n const currentLayer = this.toPromptLayer();\n const merged = mergePromptLayers(...lowerLayers, currentLayer);\n\n if (currentLayer.model && !merged.ai.profile) {\n throw new Error(\n `Prompt \"${this.key}\" model overrides require an effective prompt profile`,\n );\n }\n }\n\n private async getLowerPrecedenceLayers(): Promise<PromptLayer[]> {\n const definition = PromptRegistry.get(this.key);\n const config = getPromptConfig();\n const layers: PromptLayer[] = [];\n\n if (definition) {\n layers.push({\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n });\n }\n\n layers.push(normalizePromptLayer(config.prompts?.[this.key]));\n\n const { PromptOverrideCollection } = await import(\n '../collections/PromptOverrideCollection.js'\n );\n const collection = await PromptOverrideCollection.create({\n db: this.options.db ?? this.options.persistence,\n });\n\n if (this.tenantId) {\n const appOverride = await collection.getAppOverride(this.key, {\n excludeId: this.id ?? undefined,\n });\n if (appOverride) {\n layers.push(appOverride.toPromptLayer());\n }\n }\n\n return layers;\n }\n\n private normalizeParamsForPersistence(): void {\n const rawParams = this.params as unknown;\n\n if (rawParams === null || rawParams === undefined) {\n this.params = null;\n return;\n }\n\n if (typeof rawParams === 'string') {\n this.params = rawParams;\n return;\n }\n\n if (typeof rawParams === 'object' && !Array.isArray(rawParams)) {\n this.params = serializePromptParams(rawParams as PromptParams);\n return;\n }\n\n throw new Error(\n `Prompt \"${this.key}\" params must be a JSON object or JSON string`,\n );\n }\n\n private async getPersistedIdentity(): Promise<PromptOverrideIdentity | null> {\n if (!this.id) {\n return null;\n }\n\n const existing = await this.db.get(this.tableName, { id: this.id });\n if (!existing) {\n return null;\n }\n\n return {\n key: String((existing as Record<string, unknown>).key ?? this.key),\n tenantId:\n (existing as Record<string, unknown>).tenantId !== undefined\n ? ((existing as Record<string, unknown>).tenantId as string | null)\n : (((existing as Record<string, unknown>).tenant_id as\n | string\n | null\n | undefined) ?? null),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PromptOverride } from '../models/PromptOverride.js';\n\nexport class PromptOverrideCollection extends SmrtCollection<PromptOverride> {\n static readonly _itemClass = PromptOverride;\n\n private excludeOverrideId(\n items: PromptOverride[],\n excludeId?: string,\n ): PromptOverride[] {\n return items.filter((item) => (excludeId ? item.id !== excludeId : true));\n }\n\n async getAppOverride(\n key: string,\n options: { excludeId?: string } = {},\n ): Promise<PromptOverride | null> {\n const items = await this.list({ where: { key, tenantId: null } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getTenantOverride(\n key: string,\n tenantId: string,\n options: { excludeId?: string } = {},\n ): Promise<PromptOverride | null> {\n const items = await this.list({ where: { key, tenantId } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getResolutionLayers(\n key: string,\n tenantId?: string | null,\n options: { excludeId?: string } = {},\n ): Promise<{ app: PromptOverride | null; tenant: PromptOverride | null }> {\n const [app, tenant] = await Promise.all([\n this.getAppOverride(key, options),\n tenantId != null\n ? this.getTenantOverride(key, tenantId, options)\n : Promise.resolve(null),\n ]);\n\n return {\n app,\n tenant,\n };\n }\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport {\n getCachedPromptBase,\n getPromptCacheGeneration,\n setCachedPromptBase,\n} from './cache.js';\nimport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport { PromptRegistry } from './prompt-registry.js';\nimport type {\n PromptCacheValue,\n PromptPackageConfig,\n ResolvedPrompt,\n ResolvePromptOptions,\n} from './types.js';\nimport {\n buildResolvedAI,\n mergePromptLayers,\n normalizePromptLayer,\n renderPromptTemplate,\n} from './utils.js';\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\nasync function loadPromptBase(\n key: string,\n options: ResolvePromptOptions,\n): Promise<PromptCacheValue> {\n const definition = PromptRegistry.get(key);\n if (!definition) {\n throw new Error(`Unknown prompt key \"${key}\"`);\n }\n\n const tenantId =\n options.tenantId !== undefined ? options.tenantId : (getTenantId() ?? null);\n\n let collection: PromptOverrideCollection | null = null;\n let cacheDb: ResolvePromptOptions['db'] | undefined = options.db;\n if (options.db) {\n const initializedCollection = await PromptOverrideCollection.create({\n db: options.db,\n });\n collection = initializedCollection;\n cacheDb = initializedCollection.db as ResolvePromptOptions['db'];\n }\n\n const cached = getCachedPromptBase(key, tenantId, cacheDb);\n if (cached) {\n return cached;\n }\n\n // Capture the invalidation generation before the asynchronous layer loads. A\n // write that lands while they are in flight bumps it, and the cache write\n // below is then refused rather than repopulating the key the write just\n // invalidated with the pre-write value.\n const loadedAtGeneration = getPromptCacheGeneration(key, cacheDb);\n\n const config = getPromptConfig();\n const layers = [\n {\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n },\n normalizePromptLayer(config.prompts?.[key]),\n ];\n\n if (collection) {\n const stored = await collection.getResolutionLayers(key, tenantId);\n\n if (stored.app) {\n layers.push(stored.app.toPromptLayer());\n }\n\n if (stored.tenant) {\n layers.push(stored.tenant.toPromptLayer());\n }\n }\n\n const merged = mergePromptLayers(...layers);\n const value: PromptCacheValue = {\n key,\n template: merged.template,\n ai: merged.ai,\n };\n\n setCachedPromptBase(key, tenantId, cacheDb, value, loadedAtGeneration);\n return value;\n}\n\nexport async function resolvePrompt(\n key: string,\n options: ResolvePromptOptions = {},\n): Promise<ResolvedPrompt> {\n const config = getPromptConfig();\n const base = await loadPromptBase(key, options);\n const runtimeOverride = normalizePromptLayer(options.override);\n const merged = mergePromptLayers(\n {\n template: base.template,\n profile: base.ai.profile ?? null,\n model: base.ai.model ?? null,\n params: base.ai.params,\n },\n runtimeOverride,\n );\n\n return {\n key,\n template: merged.template,\n text: renderPromptTemplate(merged.template, options.variables),\n ai: buildResolvedAI(merged.ai, config),\n };\n}\n","/**\n * @happyvertical/smrt-prompts\n *\n * Code-first prompts with config overrides, stored app/tenant overrides,\n * and runtime resolution helpers for SMRT applications.\n *\n * @packageDocumentation\n */\n\n// Self-register this package's manifest before any @smrt() decorator fires\n// downstream. Must come first so the side effect runs ahead of the class\n// module loads below. See __smrt-register__.ts for issue #1132 context.\nimport './__smrt-register__.js';\n\nexport { clearPromptCache, getPromptCacheTtlMs } from './cache.js';\nexport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nexport {\n PromptOverride,\n type PromptOverrideOptions,\n} from './models/PromptOverride.js';\nexport { definePrompt, PromptRegistry } from './prompt-registry.js';\nexport { resolvePrompt } from './prompt-resolver.js';\nexport type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinition,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPrompt,\n ResolvedPromptAI,\n ResolvePromptOptions,\n} from './types.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":"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"}
|
package/dist/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": "1.0.0",
|
|
3
3
|
"timestamp": 0,
|
|
4
4
|
"packageName": "@happyvertical/smrt-prompts",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.47.0",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-prompts:PromptOverrideCollection": {
|
|
8
8
|
"name": "promptoverridecollection",
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
{
|
|
26
26
|
"name": "options",
|
|
27
27
|
"type": "object",
|
|
28
|
-
"optional": true
|
|
28
|
+
"optional": true,
|
|
29
|
+
"memberTypes": [
|
|
30
|
+
"string"
|
|
31
|
+
]
|
|
29
32
|
}
|
|
30
33
|
],
|
|
31
34
|
"returnType": "Promise<PromptOverride | null>",
|
|
@@ -49,7 +52,10 @@
|
|
|
49
52
|
{
|
|
50
53
|
"name": "options",
|
|
51
54
|
"type": "object",
|
|
52
|
-
"optional": true
|
|
55
|
+
"optional": true,
|
|
56
|
+
"memberTypes": [
|
|
57
|
+
"string"
|
|
58
|
+
]
|
|
53
59
|
}
|
|
54
60
|
],
|
|
55
61
|
"returnType": "Promise<PromptOverride | null>",
|
|
@@ -68,12 +74,23 @@
|
|
|
68
74
|
{
|
|
69
75
|
"name": "tenantId",
|
|
70
76
|
"type": "string | null",
|
|
71
|
-
"optional": true
|
|
77
|
+
"optional": true,
|
|
78
|
+
"unionBranches": [
|
|
79
|
+
{
|
|
80
|
+
"type": "string"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "null"
|
|
84
|
+
}
|
|
85
|
+
]
|
|
72
86
|
},
|
|
73
87
|
{
|
|
74
88
|
"name": "options",
|
|
75
89
|
"type": "object",
|
|
76
|
-
"optional": true
|
|
90
|
+
"optional": true,
|
|
91
|
+
"memberTypes": [
|
|
92
|
+
"string"
|
|
93
|
+
]
|
|
77
94
|
}
|
|
78
95
|
],
|
|
79
96
|
"returnType": "Promise<object>",
|
|
@@ -205,7 +222,15 @@
|
|
|
205
222
|
{
|
|
206
223
|
"name": "params",
|
|
207
224
|
"type": "PromptParams | null",
|
|
208
|
-
"optional": false
|
|
225
|
+
"optional": false,
|
|
226
|
+
"unionBranches": [
|
|
227
|
+
{
|
|
228
|
+
"type": "PromptParams"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"type": "null"
|
|
232
|
+
}
|
|
233
|
+
]
|
|
209
234
|
}
|
|
210
235
|
],
|
|
211
236
|
"returnType": "void",
|
|
@@ -224,7 +249,7 @@
|
|
|
224
249
|
"name": "save",
|
|
225
250
|
"async": true,
|
|
226
251
|
"parameters": [],
|
|
227
|
-
"returnType": "Promise",
|
|
252
|
+
"returnType": "Promise<this>",
|
|
228
253
|
"isStatic": false,
|
|
229
254
|
"isPublic": true
|
|
230
255
|
},
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-prompts",
|
|
6
|
-
"packageVersion": "0.
|
|
6
|
+
"packageVersion": "0.47.0",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "b2e3493c15638858232d47ce915015823262cf2ed109db725b9675fe5fcd2c02",
|
|
11
|
+
"packageJson": "9f1efcf86751eaf33e0bf99be0f11d3ad6aff78302e6c86c20665529409ac1c0",
|
|
12
|
+
"agents": "f273f3ce4ed80310d9afdea484314a455a4f7927f79ad8d92a4dff37c20233fa"
|
|
13
13
|
},
|
|
14
14
|
"exports": [
|
|
15
15
|
".",
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
{
|
|
220
220
|
"name": "save",
|
|
221
221
|
"async": true,
|
|
222
|
-
"returns": "Promise"
|
|
222
|
+
"returns": "Promise<this>"
|
|
223
223
|
},
|
|
224
224
|
{
|
|
225
225
|
"name": "setParams",
|
|
@@ -309,6 +309,36 @@
|
|
|
309
309
|
"objectName": "@happyvertical/smrt-prompts:PromptOverride"
|
|
310
310
|
}
|
|
311
311
|
],
|
|
312
|
+
"withheldSurfaces": [
|
|
313
|
+
{
|
|
314
|
+
"kind": "api",
|
|
315
|
+
"operation": "getParams",
|
|
316
|
+
"code": "not-included",
|
|
317
|
+
"reason": "not listed in api.include",
|
|
318
|
+
"objectName": "@happyvertical/smrt-prompts:PromptOverride"
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"kind": "api",
|
|
322
|
+
"operation": "save",
|
|
323
|
+
"code": "lifecycle-method",
|
|
324
|
+
"reason": "`save` is a framework lifecycle method, not a distinct operation",
|
|
325
|
+
"objectName": "@happyvertical/smrt-prompts:PromptOverride"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"kind": "api",
|
|
329
|
+
"operation": "setParams",
|
|
330
|
+
"code": "not-included",
|
|
331
|
+
"reason": "not listed in api.include",
|
|
332
|
+
"objectName": "@happyvertical/smrt-prompts:PromptOverride"
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"kind": "api",
|
|
336
|
+
"operation": "toPromptLayer",
|
|
337
|
+
"code": "not-included",
|
|
338
|
+
"reason": "not listed in api.include",
|
|
339
|
+
"objectName": "@happyvertical/smrt-prompts:PromptOverride"
|
|
340
|
+
}
|
|
341
|
+
],
|
|
312
342
|
"relationshipFeatures": [
|
|
313
343
|
"uuidColumns"
|
|
314
344
|
],
|
|
@@ -467,5 +497,5 @@
|
|
|
467
497
|
"polymorphicAssociations": 0,
|
|
468
498
|
"uuidColumns": 2
|
|
469
499
|
},
|
|
470
|
-
"agentDoc": "# smrt-prompts\n\nSMRT prompt registry and tenant-aware prompt override package. Code defines defaults; config layers and DB-stored overrides personalize at app and tenant levels.\n\n## Core pieces\n\n- `definePrompt()` registers code defaults in a global process registry (`globalThis.__smrtPromptRegistry`)\n- `resolvePrompt()` merges code defaults, file/config overrides (via `@happyvertical/smrt-config`), stored app-level overrides, stored tenant-level overrides, and a runtime override\n- `PromptOverride` (`_smrt_prompt_overrides` table) stores partial app-level and tenant-level overrides with write-time validation\n- `PromptOverrideCollection` exposes the standard SmrtCollection CRUD surface\n\n## Resolution layers (priority low → high)\n\n1. Code default — registered via `definePrompt({ key, template, ai })`\n2. File/config override — `getPackageConfig<PromptPackageConfig>('prompts', defaults)`\n3. App-level stored override — `PromptOverride` row with `tenantId = null`\n4. Tenant-level stored override — `PromptOverride` row with current tenant\n5. Runtime override — passed to `resolvePrompt({ overrides })`\n\nEach layer can override any subset of fields (template, profile, model, params). Inheritance is field-by-field.\n\n## Conventions\n\n- **Namespace prompt keys** by package or domain: `projects.issue.incorporateFeedback`, `content.summarize.headline`\n- **Stored overrides use nullable fields** so inheritance stays field-by-field — null means \"use the lower layer\"\n- **Provider selection is indirect** in v1: prompts select named profiles, and profiles resolve to provider/model in `smrt-config`\n- **`editable` flags are enforced on `PromptOverride.save()`** — definitions can lock specific fields against tenant override\n\n## Caching\n\n`resolvePrompt()` results are cached per `(key, tenantId)` with a TTL. The cache is invalidated on `PromptOverride.save()` and `.delete()`. Use `clearPromptCache()` for manual invalidation in tests.\n\n## Related\n\n- `@happyvertical/smrt-languages` — parallel package for language strings (uses the same architecture pattern)\n- `@happyvertical/smrt-features` — parallel package for feature flags\n"
|
|
500
|
+
"agentDoc": "# smrt-prompts\n\nSMRT prompt registry and tenant-aware prompt override package. Code defines defaults; config layers and DB-stored overrides personalize at app and tenant levels.\n\n## Core pieces\n\n- `definePrompt()` registers code defaults in a global process registry (`globalThis.__smrtPromptRegistry`)\n- `resolvePrompt()` merges code defaults, file/config overrides (via `@happyvertical/smrt-config`), stored app-level overrides, stored tenant-level overrides, and a runtime override\n- `PromptOverride` (`_smrt_prompt_overrides` table) stores partial app-level and tenant-level overrides with write-time validation\n- `PromptOverrideCollection` exposes the standard SmrtCollection CRUD surface\n\n## Resolution layers (priority low → high)\n\n1. Code default — registered via `definePrompt({ key, template, ai })`\n2. File/config override — `getPackageConfig<PromptPackageConfig>('prompts', defaults)`\n3. App-level stored override — `PromptOverride` row with `tenantId = null`\n4. Tenant-level stored override — `PromptOverride` row with current tenant\n5. Runtime override — passed to `resolvePrompt({ overrides })`\n\nEach layer can override any subset of fields (template, profile, model, params). Inheritance is field-by-field.\n\n## Conventions\n\n- **Namespace prompt keys** by package or domain: `projects.issue.incorporateFeedback`, `content.summarize.headline`\n- **Stored overrides use nullable fields** so inheritance stays field-by-field — null means \"use the lower layer\"\n- **Provider selection is indirect** in v1: prompts select named profiles, and profiles resolve to provider/model in `smrt-config`\n- **`editable` flags are enforced on `PromptOverride.save()`** — definitions can lock specific fields against tenant override\n\n## Caching\n\n`resolvePrompt()` results are cached per `(key, tenantId)` with a TTL. The cache is invalidated on `PromptOverride.save()` and `.delete()`. Use `clearPromptCache()` for manual invalidation in tests.\n\n**A monotonic per-`(db, key)` invalidation generation guards the cache write.**\nA resolution captures `getPromptCacheGeneration(key, db)` before its\nasynchronous layer loads and hands it back to `setCachedPromptBase()`; a\nconcurrent `save()` / `delete()` bumps the generation and the in-flight\nresolution is then refused the cache write instead of repopulating the key it\njust invalidated with the pre-write value. Without it, \"a stale entry is never\nserved after a write\" held only until a read raced a write, and then failed for\nthe full 30s TTL (a raced `delete()` resurrected the deleted override).\nGenerations are tracked per `(db, key)`, not per tenant, because an app-level\nrow is inherited by every tenant. `clearPromptCache()` raises a single floor\n(`clearedThrough`) rather than resetting or per-key bumping: a key that has\nnever been invalidated has no map entry and reads as generation 0, so a per-key\nbump cannot reach it and a resolution that started before the clear would write\nits pre-clear value back. `smrt-languages` carries the same mechanism, keyed\nadditionally by locale. `smrt-playbooks` has the generation but not the floor\n(#2716).\n\n## Related\n\n- `@happyvertical/smrt-languages` — parallel package for language strings (uses the same architecture pattern)\n- `@happyvertical/smrt-features` — parallel package for feature flags\n"
|
|
471
501
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-prompts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"description": "Typed prompt registry, override resolution, and tenant-aware prompt settings for SMRT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
"./manifest.json": "./dist/manifest.json"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@happyvertical/
|
|
23
|
-
"@happyvertical/smrt-
|
|
24
|
-
"@happyvertical/smrt-
|
|
25
|
-
"@happyvertical/
|
|
22
|
+
"@happyvertical/smrt-config": "0.47.0",
|
|
23
|
+
"@happyvertical/smrt-core": "0.47.0",
|
|
24
|
+
"@happyvertical/smrt-tenancy": "0.47.0",
|
|
25
|
+
"@happyvertical/sql": "^0.89.4"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
+
"@happyvertical/smrt-vitest": "0.47.0",
|
|
28
29
|
"@types/node": "24.13.2",
|
|
29
30
|
"typescript": "5.9.3",
|
|
30
31
|
"vite": "8.1.4",
|
|
31
|
-
"vitest": "4.1.10"
|
|
32
|
-
"@happyvertical/smrt-vitest": "0.45.3"
|
|
32
|
+
"vitest": "4.1.10"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
35
|
"smrt",
|