@happyvertical/smrt-prompts 0.51.39 → 0.53.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var __exportAll = (all, no_symbols) => {
15
15
  };
16
16
  //#endregion
17
17
  //#region src/__smrt-register__.ts
18
- ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-prompts\",\"packageVersion\":\"0.51.39\",\"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},\"getOverrideMapForKeys\":{\"name\":\"getOverrideMapForKeys\",\"async\":true,\"parameters\":[{\"name\":\"keys\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Map<string, PromptOverride>>\",\"isStatic\":false,\"isPublic\":true},\"findByScope\":{\"name\":\"findByScope\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<PromptOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"setTemplateOverride\":{\"name\":\"setTemplateOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false},{\"name\":\"template\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<PromptOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_prompt_overrides\",\"api\":false,\"mcp\":false,\"cli\":false},\"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 \\\"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\"},\"importPath\":\"@happyvertical/smrt-prompts\"},\"@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\":false,\"cli\":false,\"mcp\":false},\"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\"},\"importPath\":\"@happyvertical/smrt-prompts\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tenancy\"]}"));
18
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-prompts\",\"packageVersion\":\"0.53.1\",\"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},\"getOverrideMapForKeys\":{\"name\":\"getOverrideMapForKeys\",\"async\":true,\"parameters\":[{\"name\":\"keys\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Map<string, PromptOverride>>\",\"isStatic\":false,\"isPublic\":true},\"findByScope\":{\"name\":\"findByScope\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<PromptOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"setTemplateOverride\":{\"name\":\"setTemplateOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false},{\"name\":\"template\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<PromptOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"scopeType\",\"type\":\"PromptOverrideScopeType\",\"optional\":false},{\"name\":\"scopeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_prompt_overrides\",\"api\":false,\"mcp\":false,\"cli\":false},\"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 \\\"key\\\" TEXT NOT NULL DEFAULT '',\\n \\\"tenant_id\\\" UUID,\\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\":\"UUID\",\"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\":\"38f505e7\"},\"importPath\":\"@happyvertical/smrt-prompts\"},\"@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\":{\"sqlType\":\"UUID\",\"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\":false,\"cli\":false,\"mcp\":false},\"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\\\" UUID,\\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\":\"UUID\",\"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\":\"38f505e7\"},\"importPath\":\"@happyvertical/smrt-prompts\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tenancy\"]}"));
19
19
  //#endregion
20
20
  //#region src/cache.ts
21
21
  var PROMPT_CACHE_TTL_MS = 3e4;
@@ -511,7 +511,7 @@ var PromptOverride = class extends SmrtObject {
511
511
  };
512
512
  __decorateClass([field({ required: true })], PromptOverride.prototype, "key", 2);
513
513
  __decorateClass([field({
514
- type: "text",
514
+ sqlType: "UUID",
515
515
  nullable: true
516
516
  })], PromptOverride.prototype, "tenantId", 2);
517
517
  __decorateClass([field({
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-override-service.ts","../src/prompt-resolver.ts","../src/prompt-settings.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 description: string;\n ai: NormalizedPromptAI;\n editable: PromptEditableConfig;\n} {\n return {\n key: input.key,\n template: input.template,\n description: input.description ?? '',\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 {\n APP_PROMPT_SCOPE_ID,\n type PromptLayer,\n type PromptPackageConfig,\n type 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// Override rows are authorization state: any scope (app-wide, or another\n// tenant) can be written, and the object is not tenant-scoped by the request\n// context — `tenantId` is an ordinary settable field. Generated REST routes\n// and MCP tools only check authentication, so they are closed (#3013, mirrored\n// from `@happyvertical/smrt-features`). Hosts write overrides server-side\n// through `PromptOverrideService`, which requires an explicit authorizer for\n// every write (or `PromptOverrideCollection.setTemplateOverride()` /\n// `removeOverride()` after their own authorization decision). The CLI is\n// closed too: generated CLI commands dispatch through the generated API.\n@smrt({\n tableName: '_smrt_prompt_overrides',\n conflictColumns: ['key', 'context'],\n api: false,\n cli: false,\n mcp: false,\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_PROMPT_SCOPE_ID;\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';\nimport type { PromptOverrideScopeType } from '../types.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 /**\n * The override row for every key in `keys` at one scope, in a single query.\n *\n * Used by `PromptSettingsService.listPromptSettings()` to enumerate the\n * whole registry's override state without one round trip per key. Because\n * this is an enumeration read — a host-configured\n * `defaultListLimit`/`maxListLimit` on the collection's options would\n * silently drop keys past the cap, changing which prompts a management\n * screen reports as overridden, with no error (the #3056 hazard class in\n * `@happyvertical/smrt-features`'s `getOverrideMap`) — callers that need the\n * full map construct this collection through\n * `PromptSettingsService.create()`, which strips those bounds.\n */\n async getOverrideMapForKeys(\n keys: string[],\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<Map<string, PromptOverride>> {\n const result = new Map<string, PromptOverride>();\n if (keys.length === 0) {\n return result;\n }\n\n const tenantId = scopeType === 'app' ? null : scopeId;\n const rows = await this.list({ where: { key: keys, tenantId } });\n for (const row of rows) {\n result.set(row.key, row);\n }\n\n return result;\n }\n\n /** The override row for a scope request, in the vocabulary used at the write boundary. */\n async findByScope(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<PromptOverride | null> {\n return scopeType === 'app'\n ? this.getAppOverride(key)\n : this.getTenantOverride(key, scopeId);\n }\n\n /**\n * Set (or clear, with `template: null`) the `template` field of the override\n * row for one scope, creating the row if it did not exist. Other fields\n * (`profile`, `model`, `params`) on an existing row are left untouched, per\n * this package's field-by-field inheritance model.\n */\n async setTemplateOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n const existing = await this.findByScope(key, scopeType, scopeId);\n\n if (existing) {\n existing.template = template;\n await existing.save();\n return existing;\n }\n\n const created = await this.create({\n key,\n tenantId: scopeType === 'app' ? null : scopeId,\n template,\n });\n await created.save();\n return created;\n }\n\n /** Remove the override row for one scope entirely, if one exists. */\n async removeOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<boolean> {\n const existing = await this.findByScope(key, scopeType, scopeId);\n if (!existing) {\n return false;\n }\n\n await existing.delete();\n return true;\n }\n}\n","import type { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport type { PromptOverride } from './models/PromptOverride.js';\nimport { APP_PROMPT_SCOPE_ID, type PromptOverrideScopeType } from './types.js';\n\n/** One override write the host must authorize before it runs (mirrors #3013). */\nexport interface PromptOverrideWriteRequest {\n operation: 'set' | 'remove';\n key: string;\n scopeType: PromptOverrideScopeType;\n scopeId: string;\n /** Present for `set`. `null` clears the template field. */\n template?: string | null;\n}\n\n/**\n * The host's explicit authorization decision for one override write. Return\n * `true` only when the current caller may write that exact scope; anything\n * else denies.\n */\nexport type PromptOverrideAuthorizer = (\n request: PromptOverrideWriteRequest,\n) => boolean | Promise<boolean>;\n\n/** Thrown when the authorizer does not return `true`. Nothing is written. */\nexport class PromptOverrideAuthorizationError extends Error {\n readonly status = 403;\n constructor(readonly request: PromptOverrideWriteRequest) {\n super(\n `Prompt override ${request.operation} denied for ${request.scopeType} scope`,\n );\n this.name = 'PromptOverrideAuthorizationError';\n }\n}\n\n/**\n * Thrown when a write names a scope the resolver never reads: an unknown scope\n * type, an app scope other than {@link APP_PROMPT_SCOPE_ID}, or a blank /\n * untrimmed / non-string tenant id. Checked before the authorizer runs, so a\n * malformed tenant scope can never resolve to the app-wide row. Nothing is\n * written.\n */\nexport class InvalidPromptScopeError extends Error {\n readonly status = 400;\n constructor(\n readonly scopeType: string,\n readonly scopeId: string,\n reason: string,\n ) {\n super(`Invalid prompt override scope (${scopeType}): ${reason}`);\n this.name = 'InvalidPromptScopeError';\n }\n}\n\n/** Reject any scope the resolver does not read (see {@link InvalidPromptScopeError}). */\nexport function assertValidPromptScope(\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n): void {\n if (scopeType !== 'app' && scopeType !== 'tenant') {\n throw new InvalidPromptScopeError(\n String(scopeType),\n String(scopeId),\n 'scope type must be \"app\" or \"tenant\"',\n );\n }\n if (typeof scopeId !== 'string') {\n throw new InvalidPromptScopeError(\n scopeType,\n String(scopeId),\n 'scope id must be a string',\n );\n }\n if (scopeType === 'app' && scopeId !== APP_PROMPT_SCOPE_ID) {\n throw new InvalidPromptScopeError(\n scopeType,\n scopeId,\n `the app scope is only ever \"${APP_PROMPT_SCOPE_ID}\"`,\n );\n }\n if (\n scopeType === 'tenant' &&\n (!scopeId.trim() ||\n scopeId !== scopeId.trim() ||\n scopeId === APP_PROMPT_SCOPE_ID)\n ) {\n throw new InvalidPromptScopeError(\n scopeType,\n scopeId,\n 'a tenant scope id must be non-blank, already trimmed, and not the app scope id',\n );\n }\n}\n\n/**\n * Authorized write path for prompt overrides (mirrors `FeatureOverrideService`,\n * #3013). Override rows are authorization state for every scope and\n * `PromptOverride` is not tenant-scoped by the request context, so generated\n * surfaces are closed. Hosts that let callers change prompt text construct\n * this service with an authorizer bound to the current caller and write\n * through it; every write asks the authorizer first and fails closed.\n */\nexport class PromptOverrideService {\n constructor(\n private readonly overrides: PromptOverrideCollection,\n private readonly authorize: PromptOverrideAuthorizer,\n ) {}\n\n async setTemplateOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n await this.require({ operation: 'set', key, scopeType, scopeId, template });\n return this.overrides.setTemplateOverride(\n key,\n scopeType,\n scopeId,\n template,\n );\n }\n\n async removeOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<boolean> {\n await this.require({ operation: 'remove', key, scopeType, scopeId });\n return this.overrides.removeOverride(key, scopeType, scopeId);\n }\n\n private async require(request: PromptOverrideWriteRequest): Promise<void> {\n assertValidPromptScope(request.scopeType, request.scopeId);\n let allowed = false;\n try {\n allowed = (await this.authorize(request)) === true;\n } catch {\n allowed = false;\n }\n if (!allowed) throw new PromptOverrideAuthorizationError(request);\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","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport type {\n SmrtClassOptions,\n SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport type { PromptOverride } from './models/PromptOverride.js';\nimport {\n assertValidPromptScope,\n type PromptOverrideAuthorizer,\n PromptOverrideService,\n} from './prompt-override-service.js';\nimport { PromptRegistry } from './prompt-registry.js';\nimport {\n APP_PROMPT_SCOPE_ID,\n type PromptDefinition,\n type PromptEditableConfig,\n type PromptLayer,\n type PromptOverrideScopeType,\n type PromptPackageConfig,\n} from './types.js';\nimport { mergePromptLayers, normalizePromptLayer } from './utils.js';\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\n/**\n * The caller's options with its list bounds removed.\n *\n * `SmrtCollection.create()` forwards `defaultListLimit`/`maxListLimit` from\n * any options bag it is handed (#2367), so a host that sets those\n * application-wide would silently cap the bulk override-enumeration read\n * {@link PromptSettingsService.listPromptSettings} runs\n * (`getOverrideMapForKeys`) — a management screen showing every prompt, not a\n * user-facing page of results. A dropped row here is an override an operator\n * cannot see, and the prompt then reports as unoverridden, silently (the\n * `#3056` hazard class in `@happyvertical/smrt-features`'s `getOverrideMap`,\n * applied here proactively rather than left for a follow-up). Only the list\n * bounds are stripped; the database and every other option still apply.\n */\nfunction withoutListBounds(\n options: SmrtClassOptions | SmrtCollectionOptions,\n): SmrtCollectionOptions {\n return { ...options, defaultListLimit: undefined, maxListLimit: undefined };\n}\n\n/** The level that supplied a prompt's effective template. */\nexport type PromptSettingsLevel = 'default' | 'config' | 'app' | 'tenant';\n\n/**\n * One prompt, rendered for a management screen: the code-owned definition,\n * the text actually in effect for the requested tenant, and the raw override\n * state at each scope so the UI can show *why* it is in effect and what\n * reverting a scope produces.\n */\nexport interface PromptSettingsRow {\n /**\n * The persisted identifier. Renaming it orphans every existing override —\n * see the warning on {@link PromptSettingsService}.\n */\n key: string;\n /** Human description from the definition; may be empty. */\n description: string;\n /** Which fields a stored override may change, from the definition. */\n editable: PromptEditableConfig;\n /** The code-registered template, before the config layer or any override. */\n defaultTemplate: string;\n /**\n * What {@link resolvePrompt} resolves the template to for the requested\n * context — the text the application actually uses (unrendered: no\n * `{variable}` substitution).\n */\n effectiveTemplate: string;\n /** The app-level override row's `template` field, or `null` when there is none. */\n appTemplate: string | null;\n /**\n * The tenant-level override row's `template` field, or `null` when there is\n * none (or when no `tenantId` was requested).\n */\n tenantTemplate: string | null;\n /**\n * What the **app** scope's \"revert to default\" produces: the code default\n * merged with the config-file layer. Always knowable — nothing sits above\n * the app scope — unlike {@link inheritedTemplate}.\n */\n appDefaultTemplate: string;\n /**\n * What the **tenant** scope's \"revert to default\" produces: the code\n * default, the config-file layer, and the app-level override, merged with\n * no tenant override of its own. `null` when no `tenantId` was requested.\n *\n * This is the value a \"revert to default\" control for the tenant scope must\n * show or apply — never {@link defaultTemplate}, which ignores the config\n * layer and any app-level override and would silently discard them.\n */\n inheritedTemplate: string | null;\n /** Which level supplied {@link effectiveTemplate}. */\n supplyingLevel: PromptSettingsLevel;\n}\n\n/** Selection for {@link PromptSettingsService.listPromptSettings}. */\nexport interface ListPromptSettingsOptions {\n /**\n * Tenant whose overrides and effective template to report. Omit for an\n * app-only view.\n */\n tenantId?: string | null;\n /**\n * Restrict to an explicit allowlist of keys. Keys with no definition are\n * simply absent from the result — this filters, it does not validate.\n */\n keys?: string[];\n}\n\n/** One override write requested through {@link PromptSettingsService}. */\nexport interface SetPromptOverrideRequest {\n key: string;\n scopeType: PromptOverrideScopeType;\n scopeId: string;\n /** `null` clears the override, returning the scope to whatever it inherits. */\n template: string | null;\n}\n\n/**\n * Thrown when a write names a `key` that has no registered {@link PromptDefinition}.\n * Nothing is written.\n *\n * This is the generalized form of the per-app \"is this one of my keys?\" guard\n * every consumer would otherwise hand-roll to keep a form post from creating an\n * override for an arbitrary string.\n */\nexport class UnknownPromptKeyError extends Error {\n readonly status = 400;\n constructor(readonly key: string) {\n super(`Unknown prompt key: ${key}`);\n this.name = 'UnknownPromptKeyError';\n }\n}\n\n/**\n * Thrown when a write would set a field the definition's `editable` config\n * does not allow overriding. Nothing is written.\n */\nexport class PromptFieldNotEditableError extends Error {\n readonly status = 400;\n constructor(\n readonly key: string,\n readonly field: string,\n ) {\n super(`Prompt \"${key}\" does not allow ${field} overrides`);\n this.name = 'PromptFieldNotEditableError';\n }\n}\n\n/** Options for {@link PromptSettingsService.create}. */\nexport interface PromptSettingsServiceOptions {\n /**\n * The host's authorization decision for each override write, bound to the\n * current caller. **Omitting it makes the service read-only**: every write\n * then fails closed with `PromptOverrideAuthorizationError`. This package\n * never decides who may write.\n */\n authorize?: PromptOverrideAuthorizer;\n}\n\n/**\n * Read and write side of a prompt management screen, so consumers do not\n * re-derive the row shape or the unknown-key guard.\n *\n * **Authorization stays with the consumer.** This service makes no\n * authorization decision of its own: reads are unfiltered, and every write is\n * delegated to {@link PromptOverrideService}, which asks the host-supplied\n * {@link PromptOverrideAuthorizer} first and fails closed. Call it only from\n * server code that has already established who the caller is. See\n * `packages/prompts/README.md` for the consumer recipe.\n *\n * **Prompt keys are persisted identifiers.** Overrides are stored keyed by the\n * exact `key` string and resolved by that string at runtime. Renaming a key\n * orphans every existing override, silently reverting all tenants to the\n * registry default. Treat a key as immutable once shipped; a rename needs a\n * data migration, not an edit.\n */\nexport class PromptSettingsService {\n private readonly writes: PromptOverrideService;\n\n constructor(\n private readonly overrides: PromptOverrideCollection,\n authorize?: PromptOverrideAuthorizer,\n ) {\n this.writes = new PromptOverrideService(\n overrides,\n authorize ?? (() => false),\n );\n }\n\n /**\n * Build a service over the given database options.\n *\n * The internal bulk override-enumeration read {@link listPromptSettings}\n * runs is always issued without the caller's\n * `defaultListLimit`/`maxListLimit` — see {@link withoutListBounds}. Only\n * that read is affected; a `db` option is still honored.\n *\n * @param options - SMRT database options, as passed to any collection.\n * @param serviceOptions - Host authorizer. Omit for a read-only (load-function) service.\n */\n static async create(\n options: SmrtClassOptions = {},\n serviceOptions: PromptSettingsServiceOptions = {},\n ): Promise<PromptSettingsService> {\n const overrides = await PromptOverrideCollection.create(\n withoutListBounds(options),\n );\n return new PromptSettingsService(\n overrides as PromptOverrideCollection,\n serviceOptions.authorize,\n );\n }\n\n /**\n * One {@link PromptSettingsRow} per matching registered prompt, ordered by\n * key, so a rendered list is stable across loads.\n *\n * Makes no authorization decision — the caller has already decided that this\n * principal may see this tenant's prompts.\n */\n async listPromptSettings(\n options: ListPromptSettingsOptions = {},\n ): Promise<PromptSettingsRow[]> {\n const definitions = this.loadDefinitions(options);\n const keys = definitions.map((definition) => definition.key);\n const tenantId = options.tenantId;\n\n // Two bulk reads instead of up to 2N: see getOverrideMapForKeys for why\n // these must run through a bounds-stripped collection (#3056 class).\n const [appOverrides, tenantOverrides] = await Promise.all([\n this.overrides.getOverrideMapForKeys(keys, 'app', APP_PROMPT_SCOPE_ID),\n tenantId\n ? this.overrides.getOverrideMapForKeys(keys, 'tenant', tenantId)\n : Promise.resolve(new Map<string, PromptOverride>()),\n ]);\n\n return definitions.map((definition) =>\n this.toRow(\n definition,\n tenantId,\n appOverrides.get(definition.key) ?? null,\n tenantOverrides.get(definition.key) ?? null,\n ),\n );\n }\n\n /** The single row for one key, or `null` when no definition owns that key. */\n async getPromptSetting(\n key: string,\n tenantId?: string | null,\n ): Promise<PromptSettingsRow | null> {\n const definition = PromptRegistry.get(key);\n if (!definition) {\n return null;\n }\n\n const [appOverride, tenantOverride] = await Promise.all([\n this.overrides.getAppOverride(key),\n tenantId\n ? this.overrides.getTenantOverride(key, tenantId)\n : Promise.resolve(null),\n ]);\n\n return this.toRow(definition, tenantId, appOverride, tenantOverride);\n }\n\n /**\n * Apply one override change to the `template` field.\n *\n * Refuses any `key` without a registered {@link PromptDefinition}, any scope\n * the resolver would never read back, and a non-`null` template when the\n * definition's `editable.template` is `false`, then delegates to\n * {@link PromptOverrideService} so the host authorizer decides whether this\n * caller may write this scope. `template: null` clears the override.\n *\n * @throws {UnknownPromptKeyError} when the key has no definition.\n * @throws {InvalidPromptScopeError} when the scope is not one the resolver reads.\n * @throws {PromptFieldNotEditableError} when the definition disallows template overrides.\n * @throws `PromptOverrideAuthorizationError` when the authorizer declines.\n */\n async setPromptOverride(\n request: SetPromptOverrideRequest,\n ): Promise<PromptOverride> {\n const { key, scopeType, scopeId, template } = request;\n\n assertValidPromptScope(scopeType, scopeId);\n const definition = this.assertKnownPromptKey(key);\n\n if (template !== null && !definition.editable.template) {\n throw new PromptFieldNotEditableError(key, 'template');\n }\n\n return this.writes.setTemplateOverride(key, scopeType, scopeId, template);\n }\n\n /** {@link setPromptOverride} for the app-wide scope. */\n async setAppPromptOverride(\n key: string,\n template: string | null,\n ): Promise<PromptOverride> {\n return this.setPromptOverride({\n key,\n scopeType: 'app',\n scopeId: APP_PROMPT_SCOPE_ID,\n template,\n });\n }\n\n /** {@link setPromptOverride} for one tenant. */\n async setTenantPromptOverride(\n key: string,\n tenantId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n return this.setPromptOverride({\n key,\n scopeType: 'tenant',\n scopeId: tenantId,\n template,\n });\n }\n\n private assertKnownPromptKey(key: string): PromptDefinition {\n const trimmed = typeof key === 'string' ? key.trim() : '';\n if (!trimmed || trimmed !== key) {\n throw new UnknownPromptKeyError(String(key));\n }\n const definition = PromptRegistry.get(trimmed);\n if (!definition) {\n throw new UnknownPromptKeyError(trimmed);\n }\n return definition;\n }\n\n private loadDefinitions(\n options: ListPromptSettingsOptions,\n ): PromptDefinition[] {\n const all = PromptRegistry.getAll();\n const allowed = options.keys ? new Set(options.keys) : null;\n const selected = allowed\n ? all.filter((definition) => allowed.has(definition.key))\n : all;\n\n return [...selected].sort((a, b) => a.key.localeCompare(b.key));\n }\n\n private toRow(\n definition: PromptDefinition,\n tenantId: string | null | undefined,\n appOverride: PromptOverride | null,\n tenantOverride: PromptOverride | null,\n ): PromptSettingsRow {\n const { key } = definition;\n const config = getPromptConfig();\n\n const registryLayer: PromptLayer = {\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n };\n const configLayer = normalizePromptLayer(config.prompts?.[key]);\n\n const appLayer = appOverride ? appOverride.toPromptLayer() : null;\n const tenantLayer = tenantOverride ? tenantOverride.toPromptLayer() : null;\n\n // What the \"app\" scope's own revert-to-default produces: registry + config\n // only. This intentionally excludes the app override itself, so it must\n // NOT be reused as the app-only effective value below (that bug shipped\n // and broke both `effectiveTemplate` when no tenant is requested and every\n // tenant's inherited fallback until caught by this package's own tests).\n const appDefaultMerge = mergePromptLayers(registryLayer, configLayer);\n const inheritedMerge = tenantId\n ? mergePromptLayers(registryLayer, configLayer, appLayer)\n : null;\n // The effective template always includes the app override when present;\n // only the tenant layer is conditional on a requested tenantId.\n const effectiveMerge = mergePromptLayers(\n registryLayer,\n configLayer,\n appLayer,\n tenantId ? tenantLayer : null,\n );\n\n const appTemplate = appOverride?.template ?? null;\n const tenantTemplate = tenantId ? (tenantOverride?.template ?? null) : null;\n\n let supplyingLevel: PromptSettingsLevel = 'default';\n if (tenantId && tenantTemplate != null) {\n supplyingLevel = 'tenant';\n } else if (appTemplate != null) {\n supplyingLevel = 'app';\n } else if (configLayer.template != null) {\n supplyingLevel = 'config';\n }\n\n return {\n key,\n description: definition.description,\n editable: definition.editable,\n defaultTemplate: definition.template,\n effectiveTemplate: effectiveMerge.template,\n appTemplate,\n tenantTemplate,\n appDefaultTemplate: appDefaultMerge.template,\n inheritedTemplate: inheritedMerge ? inheritedMerge.template : null,\n supplyingLevel,\n };\n }\n}\n\n/**\n * Reject a scope the resolver would never read back.\n *\n * `PromptOverride` rows are looked up by the exact `(key, tenantId)` pair —\n * `tenantId: null` for the app scope, a tenant id otherwise. A row written\n * under a scope nothing queries is invisible state: it never takes effect,\n * and the host authorizer cannot catch it, because `scopeType: 'app'` with\n * someone else's tenant id looks like an ordinary app write to an authorizer\n * that only gates the app scope.\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 {\n InvalidPromptScopeError,\n PromptOverrideAuthorizationError,\n type PromptOverrideAuthorizer,\n PromptOverrideService,\n type PromptOverrideWriteRequest,\n} from './prompt-override-service.js';\nexport { definePrompt, PromptRegistry } from './prompt-registry.js';\nexport { resolvePrompt } from './prompt-resolver.js';\nexport {\n type ListPromptSettingsOptions,\n PromptFieldNotEditableError,\n type PromptSettingsLevel,\n type PromptSettingsRow,\n PromptSettingsService,\n type PromptSettingsServiceOptions,\n type SetPromptOverrideRequest,\n UnknownPromptKeyError,\n} from './prompt-settings.js';\nexport type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinition,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptOverrideScopeType,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPrompt,\n ResolvedPromptAI,\n ResolvePromptOptions,\n} from './types.js';\nexport { APP_PROMPT_SCOPE_ID } from './types.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":"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"}
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-override-service.ts","../src/prompt-resolver.ts","../src/prompt-settings.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 description: string;\n ai: NormalizedPromptAI;\n editable: PromptEditableConfig;\n} {\n return {\n key: input.key,\n template: input.template,\n description: input.description ?? '',\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 {\n APP_PROMPT_SCOPE_ID,\n type PromptLayer,\n type PromptPackageConfig,\n type 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// Override rows are authorization state: any scope (app-wide, or another\n// tenant) can be written, and the object is not tenant-scoped by the request\n// context — `tenantId` is an ordinary settable field. Generated REST routes\n// and MCP tools only check authentication, so they are closed (#3013, mirrored\n// from `@happyvertical/smrt-features`). Hosts write overrides server-side\n// through `PromptOverrideService`, which requires an explicit authorizer for\n// every write (or `PromptOverrideCollection.setTemplateOverride()` /\n// `removeOverride()` after their own authorization decision). The CLI is\n// closed too: generated CLI commands dispatch through the generated API.\n@smrt({\n tableName: '_smrt_prompt_overrides',\n conflictColumns: ['key', 'context'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class PromptOverride extends SmrtObject {\n @field({ required: true })\n key: string = '';\n\n // Not tenant-scoped (any scope is writable), but the value is a tenant id:\n // uuid on Postgres, so it compares with every other tenant_id column.\n @field({ sqlType: 'UUID', 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_PROMPT_SCOPE_ID;\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';\nimport type { PromptOverrideScopeType } from '../types.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 /**\n * The override row for every key in `keys` at one scope, in a single query.\n *\n * Used by `PromptSettingsService.listPromptSettings()` to enumerate the\n * whole registry's override state without one round trip per key. Because\n * this is an enumeration read — a host-configured\n * `defaultListLimit`/`maxListLimit` on the collection's options would\n * silently drop keys past the cap, changing which prompts a management\n * screen reports as overridden, with no error (the #3056 hazard class in\n * `@happyvertical/smrt-features`'s `getOverrideMap`) — callers that need the\n * full map construct this collection through\n * `PromptSettingsService.create()`, which strips those bounds.\n */\n async getOverrideMapForKeys(\n keys: string[],\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<Map<string, PromptOverride>> {\n const result = new Map<string, PromptOverride>();\n if (keys.length === 0) {\n return result;\n }\n\n const tenantId = scopeType === 'app' ? null : scopeId;\n const rows = await this.list({ where: { key: keys, tenantId } });\n for (const row of rows) {\n result.set(row.key, row);\n }\n\n return result;\n }\n\n /** The override row for a scope request, in the vocabulary used at the write boundary. */\n async findByScope(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<PromptOverride | null> {\n return scopeType === 'app'\n ? this.getAppOverride(key)\n : this.getTenantOverride(key, scopeId);\n }\n\n /**\n * Set (or clear, with `template: null`) the `template` field of the override\n * row for one scope, creating the row if it did not exist. Other fields\n * (`profile`, `model`, `params`) on an existing row are left untouched, per\n * this package's field-by-field inheritance model.\n */\n async setTemplateOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n const existing = await this.findByScope(key, scopeType, scopeId);\n\n if (existing) {\n existing.template = template;\n await existing.save();\n return existing;\n }\n\n const created = await this.create({\n key,\n tenantId: scopeType === 'app' ? null : scopeId,\n template,\n });\n await created.save();\n return created;\n }\n\n /** Remove the override row for one scope entirely, if one exists. */\n async removeOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<boolean> {\n const existing = await this.findByScope(key, scopeType, scopeId);\n if (!existing) {\n return false;\n }\n\n await existing.delete();\n return true;\n }\n}\n","import type { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport type { PromptOverride } from './models/PromptOverride.js';\nimport { APP_PROMPT_SCOPE_ID, type PromptOverrideScopeType } from './types.js';\n\n/** One override write the host must authorize before it runs (mirrors #3013). */\nexport interface PromptOverrideWriteRequest {\n operation: 'set' | 'remove';\n key: string;\n scopeType: PromptOverrideScopeType;\n scopeId: string;\n /** Present for `set`. `null` clears the template field. */\n template?: string | null;\n}\n\n/**\n * The host's explicit authorization decision for one override write. Return\n * `true` only when the current caller may write that exact scope; anything\n * else denies.\n */\nexport type PromptOverrideAuthorizer = (\n request: PromptOverrideWriteRequest,\n) => boolean | Promise<boolean>;\n\n/** Thrown when the authorizer does not return `true`. Nothing is written. */\nexport class PromptOverrideAuthorizationError extends Error {\n readonly status = 403;\n constructor(readonly request: PromptOverrideWriteRequest) {\n super(\n `Prompt override ${request.operation} denied for ${request.scopeType} scope`,\n );\n this.name = 'PromptOverrideAuthorizationError';\n }\n}\n\n/**\n * Thrown when a write names a scope the resolver never reads: an unknown scope\n * type, an app scope other than {@link APP_PROMPT_SCOPE_ID}, or a blank /\n * untrimmed / non-string tenant id. Checked before the authorizer runs, so a\n * malformed tenant scope can never resolve to the app-wide row. Nothing is\n * written.\n */\nexport class InvalidPromptScopeError extends Error {\n readonly status = 400;\n constructor(\n readonly scopeType: string,\n readonly scopeId: string,\n reason: string,\n ) {\n super(`Invalid prompt override scope (${scopeType}): ${reason}`);\n this.name = 'InvalidPromptScopeError';\n }\n}\n\n/** Reject any scope the resolver does not read (see {@link InvalidPromptScopeError}). */\nexport function assertValidPromptScope(\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n): void {\n if (scopeType !== 'app' && scopeType !== 'tenant') {\n throw new InvalidPromptScopeError(\n String(scopeType),\n String(scopeId),\n 'scope type must be \"app\" or \"tenant\"',\n );\n }\n if (typeof scopeId !== 'string') {\n throw new InvalidPromptScopeError(\n scopeType,\n String(scopeId),\n 'scope id must be a string',\n );\n }\n if (scopeType === 'app' && scopeId !== APP_PROMPT_SCOPE_ID) {\n throw new InvalidPromptScopeError(\n scopeType,\n scopeId,\n `the app scope is only ever \"${APP_PROMPT_SCOPE_ID}\"`,\n );\n }\n if (\n scopeType === 'tenant' &&\n (!scopeId.trim() ||\n scopeId !== scopeId.trim() ||\n scopeId === APP_PROMPT_SCOPE_ID)\n ) {\n throw new InvalidPromptScopeError(\n scopeType,\n scopeId,\n 'a tenant scope id must be non-blank, already trimmed, and not the app scope id',\n );\n }\n}\n\n/**\n * Authorized write path for prompt overrides (mirrors `FeatureOverrideService`,\n * #3013). Override rows are authorization state for every scope and\n * `PromptOverride` is not tenant-scoped by the request context, so generated\n * surfaces are closed. Hosts that let callers change prompt text construct\n * this service with an authorizer bound to the current caller and write\n * through it; every write asks the authorizer first and fails closed.\n */\nexport class PromptOverrideService {\n constructor(\n private readonly overrides: PromptOverrideCollection,\n private readonly authorize: PromptOverrideAuthorizer,\n ) {}\n\n async setTemplateOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n await this.require({ operation: 'set', key, scopeType, scopeId, template });\n return this.overrides.setTemplateOverride(\n key,\n scopeType,\n scopeId,\n template,\n );\n }\n\n async removeOverride(\n key: string,\n scopeType: PromptOverrideScopeType,\n scopeId: string,\n ): Promise<boolean> {\n await this.require({ operation: 'remove', key, scopeType, scopeId });\n return this.overrides.removeOverride(key, scopeType, scopeId);\n }\n\n private async require(request: PromptOverrideWriteRequest): Promise<void> {\n assertValidPromptScope(request.scopeType, request.scopeId);\n let allowed = false;\n try {\n allowed = (await this.authorize(request)) === true;\n } catch {\n allowed = false;\n }\n if (!allowed) throw new PromptOverrideAuthorizationError(request);\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","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport type {\n SmrtClassOptions,\n SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport { PromptOverrideCollection } from './collections/PromptOverrideCollection.js';\nimport type { PromptOverride } from './models/PromptOverride.js';\nimport {\n assertValidPromptScope,\n type PromptOverrideAuthorizer,\n PromptOverrideService,\n} from './prompt-override-service.js';\nimport { PromptRegistry } from './prompt-registry.js';\nimport {\n APP_PROMPT_SCOPE_ID,\n type PromptDefinition,\n type PromptEditableConfig,\n type PromptLayer,\n type PromptOverrideScopeType,\n type PromptPackageConfig,\n} from './types.js';\nimport { mergePromptLayers, normalizePromptLayer } from './utils.js';\n\nfunction getPromptConfig(): PromptPackageConfig {\n return getPackageConfig<PromptPackageConfig>('prompts', {\n profiles: {},\n prompts: {},\n });\n}\n\n/**\n * The caller's options with its list bounds removed.\n *\n * `SmrtCollection.create()` forwards `defaultListLimit`/`maxListLimit` from\n * any options bag it is handed (#2367), so a host that sets those\n * application-wide would silently cap the bulk override-enumeration read\n * {@link PromptSettingsService.listPromptSettings} runs\n * (`getOverrideMapForKeys`) — a management screen showing every prompt, not a\n * user-facing page of results. A dropped row here is an override an operator\n * cannot see, and the prompt then reports as unoverridden, silently (the\n * `#3056` hazard class in `@happyvertical/smrt-features`'s `getOverrideMap`,\n * applied here proactively rather than left for a follow-up). Only the list\n * bounds are stripped; the database and every other option still apply.\n */\nfunction withoutListBounds(\n options: SmrtClassOptions | SmrtCollectionOptions,\n): SmrtCollectionOptions {\n return { ...options, defaultListLimit: undefined, maxListLimit: undefined };\n}\n\n/** The level that supplied a prompt's effective template. */\nexport type PromptSettingsLevel = 'default' | 'config' | 'app' | 'tenant';\n\n/**\n * One prompt, rendered for a management screen: the code-owned definition,\n * the text actually in effect for the requested tenant, and the raw override\n * state at each scope so the UI can show *why* it is in effect and what\n * reverting a scope produces.\n */\nexport interface PromptSettingsRow {\n /**\n * The persisted identifier. Renaming it orphans every existing override —\n * see the warning on {@link PromptSettingsService}.\n */\n key: string;\n /** Human description from the definition; may be empty. */\n description: string;\n /** Which fields a stored override may change, from the definition. */\n editable: PromptEditableConfig;\n /** The code-registered template, before the config layer or any override. */\n defaultTemplate: string;\n /**\n * What {@link resolvePrompt} resolves the template to for the requested\n * context — the text the application actually uses (unrendered: no\n * `{variable}` substitution).\n */\n effectiveTemplate: string;\n /** The app-level override row's `template` field, or `null` when there is none. */\n appTemplate: string | null;\n /**\n * The tenant-level override row's `template` field, or `null` when there is\n * none (or when no `tenantId` was requested).\n */\n tenantTemplate: string | null;\n /**\n * What the **app** scope's \"revert to default\" produces: the code default\n * merged with the config-file layer. Always knowable — nothing sits above\n * the app scope — unlike {@link inheritedTemplate}.\n */\n appDefaultTemplate: string;\n /**\n * What the **tenant** scope's \"revert to default\" produces: the code\n * default, the config-file layer, and the app-level override, merged with\n * no tenant override of its own. `null` when no `tenantId` was requested.\n *\n * This is the value a \"revert to default\" control for the tenant scope must\n * show or apply — never {@link defaultTemplate}, which ignores the config\n * layer and any app-level override and would silently discard them.\n */\n inheritedTemplate: string | null;\n /** Which level supplied {@link effectiveTemplate}. */\n supplyingLevel: PromptSettingsLevel;\n}\n\n/** Selection for {@link PromptSettingsService.listPromptSettings}. */\nexport interface ListPromptSettingsOptions {\n /**\n * Tenant whose overrides and effective template to report. Omit for an\n * app-only view.\n */\n tenantId?: string | null;\n /**\n * Restrict to an explicit allowlist of keys. Keys with no definition are\n * simply absent from the result — this filters, it does not validate.\n */\n keys?: string[];\n}\n\n/** One override write requested through {@link PromptSettingsService}. */\nexport interface SetPromptOverrideRequest {\n key: string;\n scopeType: PromptOverrideScopeType;\n scopeId: string;\n /** `null` clears the override, returning the scope to whatever it inherits. */\n template: string | null;\n}\n\n/**\n * Thrown when a write names a `key` that has no registered {@link PromptDefinition}.\n * Nothing is written.\n *\n * This is the generalized form of the per-app \"is this one of my keys?\" guard\n * every consumer would otherwise hand-roll to keep a form post from creating an\n * override for an arbitrary string.\n */\nexport class UnknownPromptKeyError extends Error {\n readonly status = 400;\n constructor(readonly key: string) {\n super(`Unknown prompt key: ${key}`);\n this.name = 'UnknownPromptKeyError';\n }\n}\n\n/**\n * Thrown when a write would set a field the definition's `editable` config\n * does not allow overriding. Nothing is written.\n */\nexport class PromptFieldNotEditableError extends Error {\n readonly status = 400;\n constructor(\n readonly key: string,\n readonly field: string,\n ) {\n super(`Prompt \"${key}\" does not allow ${field} overrides`);\n this.name = 'PromptFieldNotEditableError';\n }\n}\n\n/** Options for {@link PromptSettingsService.create}. */\nexport interface PromptSettingsServiceOptions {\n /**\n * The host's authorization decision for each override write, bound to the\n * current caller. **Omitting it makes the service read-only**: every write\n * then fails closed with `PromptOverrideAuthorizationError`. This package\n * never decides who may write.\n */\n authorize?: PromptOverrideAuthorizer;\n}\n\n/**\n * Read and write side of a prompt management screen, so consumers do not\n * re-derive the row shape or the unknown-key guard.\n *\n * **Authorization stays with the consumer.** This service makes no\n * authorization decision of its own: reads are unfiltered, and every write is\n * delegated to {@link PromptOverrideService}, which asks the host-supplied\n * {@link PromptOverrideAuthorizer} first and fails closed. Call it only from\n * server code that has already established who the caller is. See\n * `packages/prompts/README.md` for the consumer recipe.\n *\n * **Prompt keys are persisted identifiers.** Overrides are stored keyed by the\n * exact `key` string and resolved by that string at runtime. Renaming a key\n * orphans every existing override, silently reverting all tenants to the\n * registry default. Treat a key as immutable once shipped; a rename needs a\n * data migration, not an edit.\n */\nexport class PromptSettingsService {\n private readonly writes: PromptOverrideService;\n\n constructor(\n private readonly overrides: PromptOverrideCollection,\n authorize?: PromptOverrideAuthorizer,\n ) {\n this.writes = new PromptOverrideService(\n overrides,\n authorize ?? (() => false),\n );\n }\n\n /**\n * Build a service over the given database options.\n *\n * The internal bulk override-enumeration read {@link listPromptSettings}\n * runs is always issued without the caller's\n * `defaultListLimit`/`maxListLimit` — see {@link withoutListBounds}. Only\n * that read is affected; a `db` option is still honored.\n *\n * @param options - SMRT database options, as passed to any collection.\n * @param serviceOptions - Host authorizer. Omit for a read-only (load-function) service.\n */\n static async create(\n options: SmrtClassOptions = {},\n serviceOptions: PromptSettingsServiceOptions = {},\n ): Promise<PromptSettingsService> {\n const overrides = await PromptOverrideCollection.create(\n withoutListBounds(options),\n );\n return new PromptSettingsService(\n overrides as PromptOverrideCollection,\n serviceOptions.authorize,\n );\n }\n\n /**\n * One {@link PromptSettingsRow} per matching registered prompt, ordered by\n * key, so a rendered list is stable across loads.\n *\n * Makes no authorization decision — the caller has already decided that this\n * principal may see this tenant's prompts.\n */\n async listPromptSettings(\n options: ListPromptSettingsOptions = {},\n ): Promise<PromptSettingsRow[]> {\n const definitions = this.loadDefinitions(options);\n const keys = definitions.map((definition) => definition.key);\n const tenantId = options.tenantId;\n\n // Two bulk reads instead of up to 2N: see getOverrideMapForKeys for why\n // these must run through a bounds-stripped collection (#3056 class).\n const [appOverrides, tenantOverrides] = await Promise.all([\n this.overrides.getOverrideMapForKeys(keys, 'app', APP_PROMPT_SCOPE_ID),\n tenantId\n ? this.overrides.getOverrideMapForKeys(keys, 'tenant', tenantId)\n : Promise.resolve(new Map<string, PromptOverride>()),\n ]);\n\n return definitions.map((definition) =>\n this.toRow(\n definition,\n tenantId,\n appOverrides.get(definition.key) ?? null,\n tenantOverrides.get(definition.key) ?? null,\n ),\n );\n }\n\n /** The single row for one key, or `null` when no definition owns that key. */\n async getPromptSetting(\n key: string,\n tenantId?: string | null,\n ): Promise<PromptSettingsRow | null> {\n const definition = PromptRegistry.get(key);\n if (!definition) {\n return null;\n }\n\n const [appOverride, tenantOverride] = await Promise.all([\n this.overrides.getAppOverride(key),\n tenantId\n ? this.overrides.getTenantOverride(key, tenantId)\n : Promise.resolve(null),\n ]);\n\n return this.toRow(definition, tenantId, appOverride, tenantOverride);\n }\n\n /**\n * Apply one override change to the `template` field.\n *\n * Refuses any `key` without a registered {@link PromptDefinition}, any scope\n * the resolver would never read back, and a non-`null` template when the\n * definition's `editable.template` is `false`, then delegates to\n * {@link PromptOverrideService} so the host authorizer decides whether this\n * caller may write this scope. `template: null` clears the override.\n *\n * @throws {UnknownPromptKeyError} when the key has no definition.\n * @throws {InvalidPromptScopeError} when the scope is not one the resolver reads.\n * @throws {PromptFieldNotEditableError} when the definition disallows template overrides.\n * @throws `PromptOverrideAuthorizationError` when the authorizer declines.\n */\n async setPromptOverride(\n request: SetPromptOverrideRequest,\n ): Promise<PromptOverride> {\n const { key, scopeType, scopeId, template } = request;\n\n assertValidPromptScope(scopeType, scopeId);\n const definition = this.assertKnownPromptKey(key);\n\n if (template !== null && !definition.editable.template) {\n throw new PromptFieldNotEditableError(key, 'template');\n }\n\n return this.writes.setTemplateOverride(key, scopeType, scopeId, template);\n }\n\n /** {@link setPromptOverride} for the app-wide scope. */\n async setAppPromptOverride(\n key: string,\n template: string | null,\n ): Promise<PromptOverride> {\n return this.setPromptOverride({\n key,\n scopeType: 'app',\n scopeId: APP_PROMPT_SCOPE_ID,\n template,\n });\n }\n\n /** {@link setPromptOverride} for one tenant. */\n async setTenantPromptOverride(\n key: string,\n tenantId: string,\n template: string | null,\n ): Promise<PromptOverride> {\n return this.setPromptOverride({\n key,\n scopeType: 'tenant',\n scopeId: tenantId,\n template,\n });\n }\n\n private assertKnownPromptKey(key: string): PromptDefinition {\n const trimmed = typeof key === 'string' ? key.trim() : '';\n if (!trimmed || trimmed !== key) {\n throw new UnknownPromptKeyError(String(key));\n }\n const definition = PromptRegistry.get(trimmed);\n if (!definition) {\n throw new UnknownPromptKeyError(trimmed);\n }\n return definition;\n }\n\n private loadDefinitions(\n options: ListPromptSettingsOptions,\n ): PromptDefinition[] {\n const all = PromptRegistry.getAll();\n const allowed = options.keys ? new Set(options.keys) : null;\n const selected = allowed\n ? all.filter((definition) => allowed.has(definition.key))\n : all;\n\n return [...selected].sort((a, b) => a.key.localeCompare(b.key));\n }\n\n private toRow(\n definition: PromptDefinition,\n tenantId: string | null | undefined,\n appOverride: PromptOverride | null,\n tenantOverride: PromptOverride | null,\n ): PromptSettingsRow {\n const { key } = definition;\n const config = getPromptConfig();\n\n const registryLayer: PromptLayer = {\n template: definition.template,\n profile: definition.ai.profile ?? null,\n model: definition.ai.model ?? null,\n params: definition.ai.params,\n };\n const configLayer = normalizePromptLayer(config.prompts?.[key]);\n\n const appLayer = appOverride ? appOverride.toPromptLayer() : null;\n const tenantLayer = tenantOverride ? tenantOverride.toPromptLayer() : null;\n\n // What the \"app\" scope's own revert-to-default produces: registry + config\n // only. This intentionally excludes the app override itself, so it must\n // NOT be reused as the app-only effective value below (that bug shipped\n // and broke both `effectiveTemplate` when no tenant is requested and every\n // tenant's inherited fallback until caught by this package's own tests).\n const appDefaultMerge = mergePromptLayers(registryLayer, configLayer);\n const inheritedMerge = tenantId\n ? mergePromptLayers(registryLayer, configLayer, appLayer)\n : null;\n // The effective template always includes the app override when present;\n // only the tenant layer is conditional on a requested tenantId.\n const effectiveMerge = mergePromptLayers(\n registryLayer,\n configLayer,\n appLayer,\n tenantId ? tenantLayer : null,\n );\n\n const appTemplate = appOverride?.template ?? null;\n const tenantTemplate = tenantId ? (tenantOverride?.template ?? null) : null;\n\n let supplyingLevel: PromptSettingsLevel = 'default';\n if (tenantId && tenantTemplate != null) {\n supplyingLevel = 'tenant';\n } else if (appTemplate != null) {\n supplyingLevel = 'app';\n } else if (configLayer.template != null) {\n supplyingLevel = 'config';\n }\n\n return {\n key,\n description: definition.description,\n editable: definition.editable,\n defaultTemplate: definition.template,\n effectiveTemplate: effectiveMerge.template,\n appTemplate,\n tenantTemplate,\n appDefaultTemplate: appDefaultMerge.template,\n inheritedTemplate: inheritedMerge ? inheritedMerge.template : null,\n supplyingLevel,\n };\n }\n}\n\n/**\n * Reject a scope the resolver would never read back.\n *\n * `PromptOverride` rows are looked up by the exact `(key, tenantId)` pair —\n * `tenantId: null` for the app scope, a tenant id otherwise. A row written\n * under a scope nothing queries is invisible state: it never takes effect,\n * and the host authorizer cannot catch it, because `scopeType: 'app'` with\n * someone else's tenant id looks like an ordinary app write to an authorizer\n * that only gates the app scope.\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 {\n InvalidPromptScopeError,\n PromptOverrideAuthorizationError,\n type PromptOverrideAuthorizer,\n PromptOverrideService,\n type PromptOverrideWriteRequest,\n} from './prompt-override-service.js';\nexport { definePrompt, PromptRegistry } from './prompt-registry.js';\nexport { resolvePrompt } from './prompt-resolver.js';\nexport {\n type ListPromptSettingsOptions,\n PromptFieldNotEditableError,\n type PromptSettingsLevel,\n type PromptSettingsRow,\n PromptSettingsService,\n type PromptSettingsServiceOptions,\n type SetPromptOverrideRequest,\n UnknownPromptKeyError,\n} from './prompt-settings.js';\nexport type {\n NormalizedPromptAI,\n PromptAIInput,\n PromptConfigOverrideInput,\n PromptDefinition,\n PromptDefinitionInput,\n PromptEditableConfig,\n PromptLayer,\n PromptOverrideScopeType,\n PromptPackageConfig,\n PromptParams,\n PromptProfileConfig,\n ResolvedPrompt,\n ResolvedPromptAI,\n ResolvePromptOptions,\n} from './types.js';\nexport { APP_PROMPT_SCOPE_ID } from './types.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-prompts",
5
- "packageVersion": "0.51.39",
5
+ "packageVersion": "0.53.1",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-prompts:PromptOverrideCollection": {
8
8
  "name": "promptoverridecollection",
@@ -219,7 +219,7 @@
219
219
  "collectionExportName": "PromptOverrideCollectionCollection",
220
220
  "schema": {
221
221
  "tableName": "_smrt_prompt_overrides",
222
- "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);",
222
+ "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\" UUID,\n \"template\" TEXT,\n \"profile\" TEXT,\n \"model\" TEXT,\n \"params\" TEXT\n);",
223
223
  "columns": {
224
224
  "id": {
225
225
  "type": "UUID",
@@ -253,7 +253,7 @@
253
253
  "default": ""
254
254
  },
255
255
  "tenant_id": {
256
- "type": "TEXT",
256
+ "type": "UUID",
257
257
  "notNull": false,
258
258
  "unique": false
259
259
  },
@@ -301,7 +301,7 @@
301
301
  ]
302
302
  }
303
303
  ],
304
- "version": "6f475427"
304
+ "version": "38f505e7"
305
305
  },
306
306
  "importPath": "@happyvertical/smrt-prompts"
307
307
  },
@@ -325,6 +325,7 @@
325
325
  "type": "text",
326
326
  "required": false,
327
327
  "_meta": {
328
+ "sqlType": "UUID",
328
329
  "nullable": true
329
330
  }
330
331
  },
@@ -435,7 +436,7 @@
435
436
  ],
436
437
  "schema": {
437
438
  "tableName": "_smrt_prompt_overrides",
438
- "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);",
439
+ "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\" UUID,\n \"template\" TEXT,\n \"profile\" TEXT,\n \"model\" TEXT,\n \"params\" TEXT\n);",
439
440
  "columns": {
440
441
  "id": {
441
442
  "type": "UUID",
@@ -469,7 +470,7 @@
469
470
  "default": ""
470
471
  },
471
472
  "tenant_id": {
472
- "type": "TEXT",
473
+ "type": "UUID",
473
474
  "notNull": false,
474
475
  "unique": false
475
476
  },
@@ -517,7 +518,7 @@
517
518
  ]
518
519
  }
519
520
  ],
520
- "version": "6f475427"
521
+ "version": "38f505e7"
521
522
  },
522
523
  "importPath": "@happyvertical/smrt-prompts"
523
524
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PromptOverride.d.ts","sourceRoot":"","sources":["../../src/models/PromptOverride.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAUrB,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;CACvC;AA4BD,qBAOa,cAAe,SAAQ,UAAU;IAE5C,GAAG,EAAE,MAAM,CAAM;IAGjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAEjB,OAAO,GAAE,qBAA0B;IAiB/C,SAAS,IAAI,YAAY;IAIzB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAI5C,aAAa,IAAI,WAAW;IASb,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA4BtB,uBAAuB;YAQvB,oCAAoC;YA+BpC,yCAAyC;IA6BxC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAOxB,sBAAsB;YA+DtB,wBAAwB;IAmCtC,OAAO,CAAC,6BAA6B;YAuBvB,oBAAoB;CAqBnC"}
1
+ {"version":3,"file":"PromptOverride.d.ts","sourceRoot":"","sources":["../../src/models/PromptOverride.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAUrB,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;CACvC;AA4BD,qBAOa,cAAe,SAAQ,UAAU;IAE5C,GAAG,EAAE,MAAM,CAAM;IAKjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAEjB,OAAO,GAAE,qBAA0B;IAiB/C,SAAS,IAAI,YAAY;IAIzB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAI5C,aAAa,IAAI,WAAW;IASb,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA4BtB,uBAAuB;YAQvB,oCAAoC;YA+BpC,yCAAyC;IA6BxC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAOxB,sBAAsB;YA+DtB,wBAAwB;IAmCtC,OAAO,CAAC,6BAA6B;YAuBvB,oBAAoB;CAqBnC"}
@@ -3,12 +3,12 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-prompts",
6
- "packageVersion": "0.51.39",
6
+ "packageVersion": "0.53.1",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "cb87fa187838a1cb26e6a883598fcc025dd1bb5917b9deccc268fa68e723d331",
11
- "packageJson": "cbfa94beed1a2b82a1dc4ec52c1893cf3a3d0023e4a34d7dd8c1d3331857d506",
10
+ "manifest": "5c59fe2cee671156e7f8160bccbdf3ad763e05a9e57d86b5595254b58ebe392f",
11
+ "packageJson": "ee3ca1558b88ed8179dcc52a740c0ced4517f782ab0cf203940c377399db3202",
12
12
  "agents": "45d48bbf65b540f94cd3a9c261f21c883d3f5fef0681931d5438842cf1727a66"
13
13
  },
14
14
  "exports": [
@@ -28,7 +28,7 @@
28
28
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
29
29
  "@types/node": "24.13.6",
30
30
  "jsdom": "^29.1.1",
31
- "svelte": "^5.57.1",
31
+ "svelte": "^5.57.0",
32
32
  "svelte-check": "^4.7.6",
33
33
  "typescript": "6.0.3",
34
34
  "vite": "8.1.4",
@@ -223,7 +223,7 @@
223
223
  "name": "tenantId",
224
224
  "type": "text",
225
225
  "required": false,
226
- "columnType": "TEXT"
226
+ "columnType": "UUID"
227
227
  },
228
228
  {
229
229
  "name": "template",
@@ -364,7 +364,7 @@
364
364
  "junctionCollections": 0,
365
365
  "hierarchicalObjects": 0,
366
366
  "polymorphicAssociations": 0,
367
- "uuidColumns": 2
367
+ "uuidColumns": 4
368
368
  },
369
369
  "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` — collection API, plus `setTemplateOverride()` / `removeOverride()` / `findByScope()` / `getOverrideMapForKeys()` for the write and enumeration paths below\n- `PromptOverrideService` — the only write path a host should use directly; asks a host-supplied authorizer before every write and fails closed (mirrors `FeatureOverrideService`, #3013); before authorizing it rejects any scope the resolver never reads (`InvalidPromptScopeError`: unknown type, app id other than `__app__`, blank/untrimmed/`__app__` tenant id), so a malformed tenant write cannot reach the app-wide row\n- `PromptSettingsService` — read/write helper for a management screen: `listPromptSettings()` returns one `PromptSettingsRow` per registered key (the effective template, `appTemplate`/`tenantTemplate` for the raw override at each scope, `appDefaultTemplate`/`inheritedTemplate` for what reverting each scope produces, and `supplyingLevel`); `setPromptOverride()` refuses unknown keys and fields the definition marks not editable, then delegates to `PromptOverrideService` (#3053)\n- `./svelte` subpath — `PromptSettingsPanel`, the presentational management panel (#3053)\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## Generated surfaces\n\n`PromptOverride` ships with generated REST routes, MCP tools, and CLI commands\nclosed (`api: false`, `cli: false`, `mcp: false`, mirrors `FeatureOverride`,\n#3013). Override rows are authorization state for every scope and `tenantId` is\nan ordinary settable field, not request-derived tenant scoping — a generated\nauthentication-only surface would let any signed-in principal set another\ntenant's prompt text. Hosts write overrides server-side with\n`PromptOverrideService` (which requires an explicit authorizer for every\nwrite) or `PromptOverrideCollection.setTemplateOverride()` /\n`removeOverride()` only after their own authorization decision.\n\n## Management UI (`./svelte`)\n\n- Built like every other Svelte-shipping package here (`smrt-features`/`smrt-tenancy` are the closest models): `vite build --mode library && svelte-package -i src/svelte -o dist/svelte`, an `./svelte` export with a `svelte` condition, `svelte` as an **optional** peer dependency, plus `scripts/prune-svelte-package-artifacts.js` so `svelte-package` does not copy `__tests__/` into the published `dist/svelte`. The root export stays Svelte-free so server-only consumers are unaffected.\n- `PromptSettingsPanel` is presentational: rows and callbacks in, no fetching, no authorization. `src/svelte/types.ts` deliberately imports nothing from `smrt-core` or the `@smrt()` models, so the browser bundle stays thin; `PromptSettingsRow` is structurally assignable to `PromptSettingsView`.\n- Each row is its own `<form>` with a checkbox + `<textarea>` pair per scope (`tenantOverride`/`tenantTemplate`, and `appOverride`/`appTemplate` when `showApp` is set). The checkbox's presence in the submitted `FormData` — not whether the textarea is disabled — decides override vs. revert, because a plain HTML submit cannot un-disable a field the browser already marked disabled. `onSave` reads the same `FormData` when driving the panel from a client handler instead of `formAction`.\n- Two invariants, both regression-tested. (1) The \"revert\" preview never claims the bare registry default: `tenantRevertPreview()` shows `inheritedTemplate` (registry + config + app override), falling back to `appDefaultTemplate` only when the row does not carry it, and `appRevertPreview()` shows `appDefaultTemplate` (registry + config, never the app override itself). `PromptSettingsService` computes both explicitly rather than deriving one from the other — an earlier draft reused the app-only merge as the \"no tenant requested\" effective value and broke both. (2) The rows remount on `contextKey ?? prompts`, so an unsaved edit cannot survive a reload or a tenant switch and be submitted against the new rows.\n- **Authorization stays with the consumer.** `PromptSettingsService` reads are unfiltered and every write goes through `PromptOverrideService`; constructing the settings service without an `authorize` option makes it read-only (writes fail closed). Never add an authorization decision to this package.\n- `vitest.config.ts` runs two projects (`server` node + `smrtVitestPlugin`, `svelte` jsdom + `@sveltejs/vite-plugin-svelte` with `conditions: ['browser']`) because the browser condition would send `smrt-core` to its browser build if applied globally.\n- `PromptSettingsService.create()` builds its `PromptOverrideCollection` with the caller's `defaultListLimit`/`maxListLimit` stripped before the bulk `getOverrideMapForKeys()` enumeration read that backs `listPromptSettings()` — the #3056 hazard class in `smrt-features`'s `FeatureOverrideCollection.getOverrideMap()`, applied here proactively rather than left for a follow-up issue. A host-configured list bound must never silently drop a key's override from a management screen.\n\n## Prompt keys are persisted identifiers\n\nOverrides are stored keyed by the exact `key` string and resolved by that\nstring at runtime. **Renaming a key orphans every existing override and\nsilently reverts every tenant to the registry default.** Treat a shipped key\nas immutable; a rename needs a data migration over\n`_smrt_prompt_overrides.key`, not an edit.\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"
370
370
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-prompts",
3
- "version": "0.51.39",
3
+ "version": "0.53.1",
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",
@@ -24,14 +24,14 @@
24
24
  "./manifest.json": "./dist/manifest.json"
25
25
  },
26
26
  "dependencies": {
27
- "@happyvertical/smrt-config": "0.51.39",
28
- "@happyvertical/smrt-core": "0.51.39",
29
- "@happyvertical/smrt-tenancy": "0.51.39",
30
- "@happyvertical/smrt-ui": "0.51.39",
31
- "@happyvertical/sql": "^0.96.0"
27
+ "@happyvertical/smrt-config": "0.53.1",
28
+ "@happyvertical/smrt-core": "0.53.1",
29
+ "@happyvertical/smrt-tenancy": "0.53.1",
30
+ "@happyvertical/smrt-ui": "0.53.1",
31
+ "@happyvertical/sql": "^0.98.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@happyvertical/smrt-vitest": "0.51.39",
34
+ "@happyvertical/smrt-vitest": "0.53.1",
35
35
  "@sveltejs/package": "^2.5.8",
36
36
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
37
37
  "@types/node": "24.13.6",
@@ -43,7 +43,7 @@
43
43
  "vitest": "4.1.10"
44
44
  },
45
45
  "peerDependencies": {
46
- "svelte": "^5.57.1"
46
+ "svelte": "^5.57.0"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "svelte": {