@fabricorg/experiments-prompts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # @fabricorg/experiments-prompts
2
+
3
+ Typed prompt messages, model parameters, variable rendering, and content-hash
4
+ version identity for Fabric Experiments AI Quality suites.
5
+
6
+ ```ts
7
+ import { hashTemplate, renderPrompt } from '@fabricorg/experiments-prompts';
8
+ ```
9
+
10
+ See [experiments.fabric.pro/docs/ai-quality/overview](https://experiments.fabric.pro/docs/ai-quality/overview).
package/dist/index.cjs ADDED
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+ var experimentsDatasets = require('@fabricorg/experiments-datasets');
5
+
6
+ // src/schema.ts
7
+ var PromptId = zod.z.string().min(2).max(64).regex(/^[a-z][a-z0-9-]*$/, "lowercase kebab-case, must start with a letter");
8
+ var PromptMessage = zod.z.object({
9
+ role: zod.z.enum(["system", "user", "assistant"]),
10
+ /** Template text; {{variable}} placeholders are substituted at render time. */
11
+ content: zod.z.string().min(1).max(1e5)
12
+ });
13
+ var ModelParams = zod.z.object({
14
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
15
+ model: zod.z.string().max(256).optional(),
16
+ temperature: zod.z.number().min(0).max(2).optional(),
17
+ maxTokens: zod.z.number().int().min(1).max(2e5).optional(),
18
+ topP: zod.z.number().min(0).max(1).optional()
19
+ });
20
+ var PromptTemplate = zod.z.object({
21
+ messages: zod.z.array(PromptMessage).min(1).max(50),
22
+ params: ModelParams.default({})
23
+ });
24
+ var Prompt = zod.z.object({
25
+ tenantId: zod.z.string().min(1),
26
+ id: PromptId,
27
+ name: zod.z.string().min(1).max(120),
28
+ description: zod.z.string().max(2e3).optional(),
29
+ latestVersion: zod.z.number().int().min(0),
30
+ createdAtIso: zod.z.string().datetime(),
31
+ updatedAtIso: zod.z.string().datetime()
32
+ });
33
+ var PromptVersion = zod.z.object({
34
+ promptId: PromptId,
35
+ version: zod.z.number().int().min(1),
36
+ template: PromptTemplate,
37
+ contentHash: zod.z.string().regex(/^[a-f0-9]{64}$/),
38
+ createdAtIso: zod.z.string().datetime(),
39
+ note: zod.z.string().max(500).optional()
40
+ });
41
+ var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
42
+ function templateVariables(template) {
43
+ const seen = /* @__PURE__ */ new Set();
44
+ const out = [];
45
+ for (const m of template.messages) {
46
+ for (const match of m.content.matchAll(VARIABLE_RE)) {
47
+ const name = match[1];
48
+ if (!seen.has(name)) {
49
+ seen.add(name);
50
+ out.push(name);
51
+ }
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+ function renderPrompt(template, variables) {
57
+ const missing = templateVariables(template).filter((v) => !(v in variables));
58
+ const messages = template.messages.map((m) => ({
59
+ role: m.role,
60
+ content: m.content.replace(VARIABLE_RE, (_, name) => variables[name] ?? "")
61
+ }));
62
+ return { messages, missing };
63
+ }
64
+ function hashTemplate(template) {
65
+ return experimentsDatasets.sha256Hex(experimentsDatasets.canonicalJson(template));
66
+ }
67
+
68
+ exports.ModelParams = ModelParams;
69
+ exports.Prompt = Prompt;
70
+ exports.PromptId = PromptId;
71
+ exports.PromptMessage = PromptMessage;
72
+ exports.PromptTemplate = PromptTemplate;
73
+ exports.PromptVersion = PromptVersion;
74
+ exports.hashTemplate = hashTemplate;
75
+ exports.renderPrompt = renderPrompt;
76
+ exports.templateVariables = templateVariables;
77
+ //# sourceMappingURL=index.cjs.map
78
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/render.ts"],"names":["z","sha256Hex","canonicalJson"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\nexport const PromptId = z\n .string()\n .min(2)\n .max(64)\n .regex(/^[a-z][a-z0-9-]*$/, 'lowercase kebab-case, must start with a letter');\nexport type PromptId = z.infer<typeof PromptId>;\n\nexport const PromptMessage = z.object({\n role: z.enum(['system', 'user', 'assistant']),\n /** Template text; {{variable}} placeholders are substituted at render time. */\n content: z.string().min(1).max(100000),\n});\nexport type PromptMessage = z.infer<typeof PromptMessage>;\n\nexport const ModelParams = z.object({\n /** Model Serving endpoint or model name; resolution happens in the control plane. */\n model: z.string().max(256).optional(),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().min(1).max(200000).optional(),\n topP: z.number().min(0).max(1).optional(),\n});\nexport type ModelParams = z.infer<typeof ModelParams>;\n\n/** The versionable content of a prompt — what the content hash covers. */\nexport const PromptTemplate = z.object({\n messages: z.array(PromptMessage).min(1).max(50),\n params: ModelParams.default({}),\n});\nexport type PromptTemplate = z.infer<typeof PromptTemplate>;\n\nexport const Prompt = z.object({\n tenantId: z.string().min(1),\n id: PromptId,\n name: z.string().min(1).max(120),\n description: z.string().max(2000).optional(),\n latestVersion: z.number().int().min(0),\n createdAtIso: z.string().datetime(),\n updatedAtIso: z.string().datetime(),\n});\nexport type Prompt = z.infer<typeof Prompt>;\n\n/**\n * Immutable prompt version. Content-addressed like dataset versions and the\n * edge manifest: identical templates always yield identical hashes, so a\n * judge's provenance promptHash can be traced back to a registry version.\n */\nexport const PromptVersion = z.object({\n promptId: PromptId,\n version: z.number().int().min(1),\n template: PromptTemplate,\n contentHash: z.string().regex(/^[a-f0-9]{64}$/),\n createdAtIso: z.string().datetime(),\n note: z.string().max(500).optional(),\n});\nexport type PromptVersion = z.infer<typeof PromptVersion>;\n","import { canonicalJson, sha256Hex } from '@fabricorg/experiments-datasets';\nimport type { PromptMessage, PromptTemplate } from './schema.js';\n\n/** {{variable}} — same placeholder syntax as the evals judge templates. */\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\n\n/** Distinct variable names referenced by a template, in first-appearance order. */\nexport function templateVariables(template: PromptTemplate): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const m of template.messages) {\n for (const match of m.content.matchAll(VARIABLE_RE)) {\n const name = match[1]!;\n if (!seen.has(name)) {\n seen.add(name);\n out.push(name);\n }\n }\n }\n return out;\n}\n\nexport interface RenderResult {\n messages: PromptMessage[];\n /** Variables referenced by the template but absent from the input. */\n missing: string[];\n}\n\n/**\n * Substitute variables into every message. Missing variables render as empty\n * strings and are reported — the playground surfaces them as a warning\n * rather than refusing to run (matching judge-template render semantics).\n */\nexport function renderPrompt(\n template: PromptTemplate,\n variables: Record<string, string>,\n): RenderResult {\n const missing = templateVariables(template).filter((v) => !(v in variables));\n const messages = template.messages.map((m) => ({\n role: m.role,\n content: m.content.replace(VARIABLE_RE, (_, name: string) => variables[name] ?? ''),\n }));\n return { messages, missing };\n}\n\n/** Content hash over the canonical template JSON — version identity. */\nexport function hashTemplate(template: PromptTemplate): string {\n return sha256Hex(canonicalJson(template));\n}\n"]}
@@ -0,0 +1,233 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const PromptId: z.ZodString;
4
+ type PromptId = z.infer<typeof PromptId>;
5
+ declare const PromptMessage: z.ZodObject<{
6
+ role: z.ZodEnum<["system", "user", "assistant"]>;
7
+ /** Template text; {{variable}} placeholders are substituted at render time. */
8
+ content: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ role: "system" | "user" | "assistant";
11
+ content: string;
12
+ }, {
13
+ role: "system" | "user" | "assistant";
14
+ content: string;
15
+ }>;
16
+ type PromptMessage = z.infer<typeof PromptMessage>;
17
+ declare const ModelParams: z.ZodObject<{
18
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
19
+ model: z.ZodOptional<z.ZodString>;
20
+ temperature: z.ZodOptional<z.ZodNumber>;
21
+ maxTokens: z.ZodOptional<z.ZodNumber>;
22
+ topP: z.ZodOptional<z.ZodNumber>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ model?: string | undefined;
25
+ temperature?: number | undefined;
26
+ maxTokens?: number | undefined;
27
+ topP?: number | undefined;
28
+ }, {
29
+ model?: string | undefined;
30
+ temperature?: number | undefined;
31
+ maxTokens?: number | undefined;
32
+ topP?: number | undefined;
33
+ }>;
34
+ type ModelParams = z.infer<typeof ModelParams>;
35
+ /** The versionable content of a prompt — what the content hash covers. */
36
+ declare const PromptTemplate: z.ZodObject<{
37
+ messages: z.ZodArray<z.ZodObject<{
38
+ role: z.ZodEnum<["system", "user", "assistant"]>;
39
+ /** Template text; {{variable}} placeholders are substituted at render time. */
40
+ content: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ role: "system" | "user" | "assistant";
43
+ content: string;
44
+ }, {
45
+ role: "system" | "user" | "assistant";
46
+ content: string;
47
+ }>, "many">;
48
+ params: z.ZodDefault<z.ZodObject<{
49
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
50
+ model: z.ZodOptional<z.ZodString>;
51
+ temperature: z.ZodOptional<z.ZodNumber>;
52
+ maxTokens: z.ZodOptional<z.ZodNumber>;
53
+ topP: z.ZodOptional<z.ZodNumber>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ model?: string | undefined;
56
+ temperature?: number | undefined;
57
+ maxTokens?: number | undefined;
58
+ topP?: number | undefined;
59
+ }, {
60
+ model?: string | undefined;
61
+ temperature?: number | undefined;
62
+ maxTokens?: number | undefined;
63
+ topP?: number | undefined;
64
+ }>>;
65
+ }, "strip", z.ZodTypeAny, {
66
+ params: {
67
+ model?: string | undefined;
68
+ temperature?: number | undefined;
69
+ maxTokens?: number | undefined;
70
+ topP?: number | undefined;
71
+ };
72
+ messages: {
73
+ role: "system" | "user" | "assistant";
74
+ content: string;
75
+ }[];
76
+ }, {
77
+ messages: {
78
+ role: "system" | "user" | "assistant";
79
+ content: string;
80
+ }[];
81
+ params?: {
82
+ model?: string | undefined;
83
+ temperature?: number | undefined;
84
+ maxTokens?: number | undefined;
85
+ topP?: number | undefined;
86
+ } | undefined;
87
+ }>;
88
+ type PromptTemplate = z.infer<typeof PromptTemplate>;
89
+ declare const Prompt: z.ZodObject<{
90
+ tenantId: z.ZodString;
91
+ id: z.ZodString;
92
+ name: z.ZodString;
93
+ description: z.ZodOptional<z.ZodString>;
94
+ latestVersion: z.ZodNumber;
95
+ createdAtIso: z.ZodString;
96
+ updatedAtIso: z.ZodString;
97
+ }, "strip", z.ZodTypeAny, {
98
+ tenantId: string;
99
+ id: string;
100
+ name: string;
101
+ latestVersion: number;
102
+ createdAtIso: string;
103
+ updatedAtIso: string;
104
+ description?: string | undefined;
105
+ }, {
106
+ tenantId: string;
107
+ id: string;
108
+ name: string;
109
+ latestVersion: number;
110
+ createdAtIso: string;
111
+ updatedAtIso: string;
112
+ description?: string | undefined;
113
+ }>;
114
+ type Prompt = z.infer<typeof Prompt>;
115
+ /**
116
+ * Immutable prompt version. Content-addressed like dataset versions and the
117
+ * edge manifest: identical templates always yield identical hashes, so a
118
+ * judge's provenance promptHash can be traced back to a registry version.
119
+ */
120
+ declare const PromptVersion: z.ZodObject<{
121
+ promptId: z.ZodString;
122
+ version: z.ZodNumber;
123
+ template: z.ZodObject<{
124
+ messages: z.ZodArray<z.ZodObject<{
125
+ role: z.ZodEnum<["system", "user", "assistant"]>;
126
+ /** Template text; {{variable}} placeholders are substituted at render time. */
127
+ content: z.ZodString;
128
+ }, "strip", z.ZodTypeAny, {
129
+ role: "system" | "user" | "assistant";
130
+ content: string;
131
+ }, {
132
+ role: "system" | "user" | "assistant";
133
+ content: string;
134
+ }>, "many">;
135
+ params: z.ZodDefault<z.ZodObject<{
136
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
137
+ model: z.ZodOptional<z.ZodString>;
138
+ temperature: z.ZodOptional<z.ZodNumber>;
139
+ maxTokens: z.ZodOptional<z.ZodNumber>;
140
+ topP: z.ZodOptional<z.ZodNumber>;
141
+ }, "strip", z.ZodTypeAny, {
142
+ model?: string | undefined;
143
+ temperature?: number | undefined;
144
+ maxTokens?: number | undefined;
145
+ topP?: number | undefined;
146
+ }, {
147
+ model?: string | undefined;
148
+ temperature?: number | undefined;
149
+ maxTokens?: number | undefined;
150
+ topP?: number | undefined;
151
+ }>>;
152
+ }, "strip", z.ZodTypeAny, {
153
+ params: {
154
+ model?: string | undefined;
155
+ temperature?: number | undefined;
156
+ maxTokens?: number | undefined;
157
+ topP?: number | undefined;
158
+ };
159
+ messages: {
160
+ role: "system" | "user" | "assistant";
161
+ content: string;
162
+ }[];
163
+ }, {
164
+ messages: {
165
+ role: "system" | "user" | "assistant";
166
+ content: string;
167
+ }[];
168
+ params?: {
169
+ model?: string | undefined;
170
+ temperature?: number | undefined;
171
+ maxTokens?: number | undefined;
172
+ topP?: number | undefined;
173
+ } | undefined;
174
+ }>;
175
+ contentHash: z.ZodString;
176
+ createdAtIso: z.ZodString;
177
+ note: z.ZodOptional<z.ZodString>;
178
+ }, "strip", z.ZodTypeAny, {
179
+ createdAtIso: string;
180
+ promptId: string;
181
+ version: number;
182
+ template: {
183
+ params: {
184
+ model?: string | undefined;
185
+ temperature?: number | undefined;
186
+ maxTokens?: number | undefined;
187
+ topP?: number | undefined;
188
+ };
189
+ messages: {
190
+ role: "system" | "user" | "assistant";
191
+ content: string;
192
+ }[];
193
+ };
194
+ contentHash: string;
195
+ note?: string | undefined;
196
+ }, {
197
+ createdAtIso: string;
198
+ promptId: string;
199
+ version: number;
200
+ template: {
201
+ messages: {
202
+ role: "system" | "user" | "assistant";
203
+ content: string;
204
+ }[];
205
+ params?: {
206
+ model?: string | undefined;
207
+ temperature?: number | undefined;
208
+ maxTokens?: number | undefined;
209
+ topP?: number | undefined;
210
+ } | undefined;
211
+ };
212
+ contentHash: string;
213
+ note?: string | undefined;
214
+ }>;
215
+ type PromptVersion = z.infer<typeof PromptVersion>;
216
+
217
+ /** Distinct variable names referenced by a template, in first-appearance order. */
218
+ declare function templateVariables(template: PromptTemplate): string[];
219
+ interface RenderResult {
220
+ messages: PromptMessage[];
221
+ /** Variables referenced by the template but absent from the input. */
222
+ missing: string[];
223
+ }
224
+ /**
225
+ * Substitute variables into every message. Missing variables render as empty
226
+ * strings and are reported — the playground surfaces them as a warning
227
+ * rather than refusing to run (matching judge-template render semantics).
228
+ */
229
+ declare function renderPrompt(template: PromptTemplate, variables: Record<string, string>): RenderResult;
230
+ /** Content hash over the canonical template JSON — version identity. */
231
+ declare function hashTemplate(template: PromptTemplate): string;
232
+
233
+ export { ModelParams, Prompt, PromptId, PromptMessage, PromptTemplate, PromptVersion, type RenderResult, hashTemplate, renderPrompt, templateVariables };
@@ -0,0 +1,233 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const PromptId: z.ZodString;
4
+ type PromptId = z.infer<typeof PromptId>;
5
+ declare const PromptMessage: z.ZodObject<{
6
+ role: z.ZodEnum<["system", "user", "assistant"]>;
7
+ /** Template text; {{variable}} placeholders are substituted at render time. */
8
+ content: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ role: "system" | "user" | "assistant";
11
+ content: string;
12
+ }, {
13
+ role: "system" | "user" | "assistant";
14
+ content: string;
15
+ }>;
16
+ type PromptMessage = z.infer<typeof PromptMessage>;
17
+ declare const ModelParams: z.ZodObject<{
18
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
19
+ model: z.ZodOptional<z.ZodString>;
20
+ temperature: z.ZodOptional<z.ZodNumber>;
21
+ maxTokens: z.ZodOptional<z.ZodNumber>;
22
+ topP: z.ZodOptional<z.ZodNumber>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ model?: string | undefined;
25
+ temperature?: number | undefined;
26
+ maxTokens?: number | undefined;
27
+ topP?: number | undefined;
28
+ }, {
29
+ model?: string | undefined;
30
+ temperature?: number | undefined;
31
+ maxTokens?: number | undefined;
32
+ topP?: number | undefined;
33
+ }>;
34
+ type ModelParams = z.infer<typeof ModelParams>;
35
+ /** The versionable content of a prompt — what the content hash covers. */
36
+ declare const PromptTemplate: z.ZodObject<{
37
+ messages: z.ZodArray<z.ZodObject<{
38
+ role: z.ZodEnum<["system", "user", "assistant"]>;
39
+ /** Template text; {{variable}} placeholders are substituted at render time. */
40
+ content: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ role: "system" | "user" | "assistant";
43
+ content: string;
44
+ }, {
45
+ role: "system" | "user" | "assistant";
46
+ content: string;
47
+ }>, "many">;
48
+ params: z.ZodDefault<z.ZodObject<{
49
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
50
+ model: z.ZodOptional<z.ZodString>;
51
+ temperature: z.ZodOptional<z.ZodNumber>;
52
+ maxTokens: z.ZodOptional<z.ZodNumber>;
53
+ topP: z.ZodOptional<z.ZodNumber>;
54
+ }, "strip", z.ZodTypeAny, {
55
+ model?: string | undefined;
56
+ temperature?: number | undefined;
57
+ maxTokens?: number | undefined;
58
+ topP?: number | undefined;
59
+ }, {
60
+ model?: string | undefined;
61
+ temperature?: number | undefined;
62
+ maxTokens?: number | undefined;
63
+ topP?: number | undefined;
64
+ }>>;
65
+ }, "strip", z.ZodTypeAny, {
66
+ params: {
67
+ model?: string | undefined;
68
+ temperature?: number | undefined;
69
+ maxTokens?: number | undefined;
70
+ topP?: number | undefined;
71
+ };
72
+ messages: {
73
+ role: "system" | "user" | "assistant";
74
+ content: string;
75
+ }[];
76
+ }, {
77
+ messages: {
78
+ role: "system" | "user" | "assistant";
79
+ content: string;
80
+ }[];
81
+ params?: {
82
+ model?: string | undefined;
83
+ temperature?: number | undefined;
84
+ maxTokens?: number | undefined;
85
+ topP?: number | undefined;
86
+ } | undefined;
87
+ }>;
88
+ type PromptTemplate = z.infer<typeof PromptTemplate>;
89
+ declare const Prompt: z.ZodObject<{
90
+ tenantId: z.ZodString;
91
+ id: z.ZodString;
92
+ name: z.ZodString;
93
+ description: z.ZodOptional<z.ZodString>;
94
+ latestVersion: z.ZodNumber;
95
+ createdAtIso: z.ZodString;
96
+ updatedAtIso: z.ZodString;
97
+ }, "strip", z.ZodTypeAny, {
98
+ tenantId: string;
99
+ id: string;
100
+ name: string;
101
+ latestVersion: number;
102
+ createdAtIso: string;
103
+ updatedAtIso: string;
104
+ description?: string | undefined;
105
+ }, {
106
+ tenantId: string;
107
+ id: string;
108
+ name: string;
109
+ latestVersion: number;
110
+ createdAtIso: string;
111
+ updatedAtIso: string;
112
+ description?: string | undefined;
113
+ }>;
114
+ type Prompt = z.infer<typeof Prompt>;
115
+ /**
116
+ * Immutable prompt version. Content-addressed like dataset versions and the
117
+ * edge manifest: identical templates always yield identical hashes, so a
118
+ * judge's provenance promptHash can be traced back to a registry version.
119
+ */
120
+ declare const PromptVersion: z.ZodObject<{
121
+ promptId: z.ZodString;
122
+ version: z.ZodNumber;
123
+ template: z.ZodObject<{
124
+ messages: z.ZodArray<z.ZodObject<{
125
+ role: z.ZodEnum<["system", "user", "assistant"]>;
126
+ /** Template text; {{variable}} placeholders are substituted at render time. */
127
+ content: z.ZodString;
128
+ }, "strip", z.ZodTypeAny, {
129
+ role: "system" | "user" | "assistant";
130
+ content: string;
131
+ }, {
132
+ role: "system" | "user" | "assistant";
133
+ content: string;
134
+ }>, "many">;
135
+ params: z.ZodDefault<z.ZodObject<{
136
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
137
+ model: z.ZodOptional<z.ZodString>;
138
+ temperature: z.ZodOptional<z.ZodNumber>;
139
+ maxTokens: z.ZodOptional<z.ZodNumber>;
140
+ topP: z.ZodOptional<z.ZodNumber>;
141
+ }, "strip", z.ZodTypeAny, {
142
+ model?: string | undefined;
143
+ temperature?: number | undefined;
144
+ maxTokens?: number | undefined;
145
+ topP?: number | undefined;
146
+ }, {
147
+ model?: string | undefined;
148
+ temperature?: number | undefined;
149
+ maxTokens?: number | undefined;
150
+ topP?: number | undefined;
151
+ }>>;
152
+ }, "strip", z.ZodTypeAny, {
153
+ params: {
154
+ model?: string | undefined;
155
+ temperature?: number | undefined;
156
+ maxTokens?: number | undefined;
157
+ topP?: number | undefined;
158
+ };
159
+ messages: {
160
+ role: "system" | "user" | "assistant";
161
+ content: string;
162
+ }[];
163
+ }, {
164
+ messages: {
165
+ role: "system" | "user" | "assistant";
166
+ content: string;
167
+ }[];
168
+ params?: {
169
+ model?: string | undefined;
170
+ temperature?: number | undefined;
171
+ maxTokens?: number | undefined;
172
+ topP?: number | undefined;
173
+ } | undefined;
174
+ }>;
175
+ contentHash: z.ZodString;
176
+ createdAtIso: z.ZodString;
177
+ note: z.ZodOptional<z.ZodString>;
178
+ }, "strip", z.ZodTypeAny, {
179
+ createdAtIso: string;
180
+ promptId: string;
181
+ version: number;
182
+ template: {
183
+ params: {
184
+ model?: string | undefined;
185
+ temperature?: number | undefined;
186
+ maxTokens?: number | undefined;
187
+ topP?: number | undefined;
188
+ };
189
+ messages: {
190
+ role: "system" | "user" | "assistant";
191
+ content: string;
192
+ }[];
193
+ };
194
+ contentHash: string;
195
+ note?: string | undefined;
196
+ }, {
197
+ createdAtIso: string;
198
+ promptId: string;
199
+ version: number;
200
+ template: {
201
+ messages: {
202
+ role: "system" | "user" | "assistant";
203
+ content: string;
204
+ }[];
205
+ params?: {
206
+ model?: string | undefined;
207
+ temperature?: number | undefined;
208
+ maxTokens?: number | undefined;
209
+ topP?: number | undefined;
210
+ } | undefined;
211
+ };
212
+ contentHash: string;
213
+ note?: string | undefined;
214
+ }>;
215
+ type PromptVersion = z.infer<typeof PromptVersion>;
216
+
217
+ /** Distinct variable names referenced by a template, in first-appearance order. */
218
+ declare function templateVariables(template: PromptTemplate): string[];
219
+ interface RenderResult {
220
+ messages: PromptMessage[];
221
+ /** Variables referenced by the template but absent from the input. */
222
+ missing: string[];
223
+ }
224
+ /**
225
+ * Substitute variables into every message. Missing variables render as empty
226
+ * strings and are reported — the playground surfaces them as a warning
227
+ * rather than refusing to run (matching judge-template render semantics).
228
+ */
229
+ declare function renderPrompt(template: PromptTemplate, variables: Record<string, string>): RenderResult;
230
+ /** Content hash over the canonical template JSON — version identity. */
231
+ declare function hashTemplate(template: PromptTemplate): string;
232
+
233
+ export { ModelParams, Prompt, PromptId, PromptMessage, PromptTemplate, PromptVersion, type RenderResult, hashTemplate, renderPrompt, templateVariables };
package/dist/index.js ADDED
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import { sha256Hex, canonicalJson } from '@fabricorg/experiments-datasets';
3
+
4
+ // src/schema.ts
5
+ var PromptId = z.string().min(2).max(64).regex(/^[a-z][a-z0-9-]*$/, "lowercase kebab-case, must start with a letter");
6
+ var PromptMessage = z.object({
7
+ role: z.enum(["system", "user", "assistant"]),
8
+ /** Template text; {{variable}} placeholders are substituted at render time. */
9
+ content: z.string().min(1).max(1e5)
10
+ });
11
+ var ModelParams = z.object({
12
+ /** Model Serving endpoint or model name; resolution happens in the control plane. */
13
+ model: z.string().max(256).optional(),
14
+ temperature: z.number().min(0).max(2).optional(),
15
+ maxTokens: z.number().int().min(1).max(2e5).optional(),
16
+ topP: z.number().min(0).max(1).optional()
17
+ });
18
+ var PromptTemplate = z.object({
19
+ messages: z.array(PromptMessage).min(1).max(50),
20
+ params: ModelParams.default({})
21
+ });
22
+ var Prompt = z.object({
23
+ tenantId: z.string().min(1),
24
+ id: PromptId,
25
+ name: z.string().min(1).max(120),
26
+ description: z.string().max(2e3).optional(),
27
+ latestVersion: z.number().int().min(0),
28
+ createdAtIso: z.string().datetime(),
29
+ updatedAtIso: z.string().datetime()
30
+ });
31
+ var PromptVersion = z.object({
32
+ promptId: PromptId,
33
+ version: z.number().int().min(1),
34
+ template: PromptTemplate,
35
+ contentHash: z.string().regex(/^[a-f0-9]{64}$/),
36
+ createdAtIso: z.string().datetime(),
37
+ note: z.string().max(500).optional()
38
+ });
39
+ var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
40
+ function templateVariables(template) {
41
+ const seen = /* @__PURE__ */ new Set();
42
+ const out = [];
43
+ for (const m of template.messages) {
44
+ for (const match of m.content.matchAll(VARIABLE_RE)) {
45
+ const name = match[1];
46
+ if (!seen.has(name)) {
47
+ seen.add(name);
48
+ out.push(name);
49
+ }
50
+ }
51
+ }
52
+ return out;
53
+ }
54
+ function renderPrompt(template, variables) {
55
+ const missing = templateVariables(template).filter((v) => !(v in variables));
56
+ const messages = template.messages.map((m) => ({
57
+ role: m.role,
58
+ content: m.content.replace(VARIABLE_RE, (_, name) => variables[name] ?? "")
59
+ }));
60
+ return { messages, missing };
61
+ }
62
+ function hashTemplate(template) {
63
+ return sha256Hex(canonicalJson(template));
64
+ }
65
+
66
+ export { ModelParams, Prompt, PromptId, PromptMessage, PromptTemplate, PromptVersion, hashTemplate, renderPrompt, templateVariables };
67
+ //# sourceMappingURL=index.js.map
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/render.ts"],"names":[],"mappings":";;;;AAEO,IAAM,QAAA,GAAW,CAAA,CACrB,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,GAAA,CAAI,EAAE,CAAA,CACN,KAAA,CAAM,mBAAA,EAAqB,gDAAgD;AAGvE,IAAM,aAAA,GAAgB,EAAE,MAAA,CAAO;AAAA,EACpC,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,QAAA,EAAU,MAAA,EAAQ,WAAW,CAAC,CAAA;AAAA;AAAA,EAE5C,OAAA,EAAS,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,GAAM;AACvC,CAAC;AAGM,IAAM,WAAA,GAAc,EAAE,MAAA,CAAO;AAAA;AAAA,EAElC,OAAO,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,GAAG,EAAE,QAAA,EAAS;AAAA,EACpC,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA,EAAS;AAAA,EAC/C,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAM,CAAA,CAAE,QAAA,EAAS;AAAA,EACxD,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA;AACjC,CAAC;AAIM,IAAM,cAAA,GAAiB,EAAE,MAAA,CAAO;AAAA,EACrC,QAAA,EAAU,EAAE,KAAA,CAAM,aAAa,EAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA;AAAA,EAC9C,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,EAAE;AAChC,CAAC;AAGM,IAAM,MAAA,GAAS,EAAE,MAAA,CAAO;AAAA,EAC7B,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC1B,EAAA,EAAI,QAAA;AAAA,EACJ,IAAA,EAAM,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,GAAG,CAAA;AAAA,EAC/B,aAAa,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,GAAI,EAAE,QAAA,EAAS;AAAA,EAC3C,eAAe,CAAA,CAAE,MAAA,GAAS,GAAA,EAAI,CAAE,IAAI,CAAC,CAAA;AAAA,EACrC,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAClC,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAC3B,CAAC;AAQM,IAAM,aAAA,GAAgB,EAAE,MAAA,CAAO;AAAA,EACpC,QAAA,EAAU,QAAA;AAAA,EACV,SAAS,CAAA,CAAE,MAAA,GAAS,GAAA,EAAI,CAAE,IAAI,CAAC,CAAA;AAAA,EAC/B,QAAA,EAAU,cAAA;AAAA,EACV,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,MAAM,gBAAgB,CAAA;AAAA,EAC9C,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAClC,MAAM,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,GAAG,EAAE,QAAA;AAC5B,CAAC;ACnDD,IAAM,WAAA,GAAc,yCAAA;AAGb,SAAS,kBAAkB,QAAA,EAAoC;AACpE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,KAAA,MAAW,CAAA,IAAK,SAAS,QAAA,EAAU;AACjC,IAAA,KAAA,MAAW,KAAA,IAAS,CAAA,CAAE,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AACnB,QAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AACb,QAAA,GAAA,CAAI,KAAK,IAAI,CAAA;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAaO,SAAS,YAAA,CACd,UACA,SAAA,EACc;AACd,EAAA,MAAM,OAAA,GAAU,kBAAkB,QAAQ,CAAA,CAAE,OAAO,CAAC,CAAA,KAAM,EAAE,CAAA,IAAK,SAAA,CAAU,CAAA;AAC3E,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAC7C,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,OAAA,CAAQ,WAAA,EAAa,CAAC,CAAA,EAAG,IAAA,KAAiB,SAAA,CAAU,IAAI,CAAA,IAAK,EAAE;AAAA,GACpF,CAAE,CAAA;AACF,EAAA,OAAO,EAAE,UAAU,OAAA,EAAQ;AAC7B;AAGO,SAAS,aAAa,QAAA,EAAkC;AAC7D,EAAA,OAAO,SAAA,CAAU,aAAA,CAAc,QAAQ,CAAC,CAAA;AAC1C","file":"index.js","sourcesContent":["import { z } from 'zod';\n\nexport const PromptId = z\n .string()\n .min(2)\n .max(64)\n .regex(/^[a-z][a-z0-9-]*$/, 'lowercase kebab-case, must start with a letter');\nexport type PromptId = z.infer<typeof PromptId>;\n\nexport const PromptMessage = z.object({\n role: z.enum(['system', 'user', 'assistant']),\n /** Template text; {{variable}} placeholders are substituted at render time. */\n content: z.string().min(1).max(100000),\n});\nexport type PromptMessage = z.infer<typeof PromptMessage>;\n\nexport const ModelParams = z.object({\n /** Model Serving endpoint or model name; resolution happens in the control plane. */\n model: z.string().max(256).optional(),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().min(1).max(200000).optional(),\n topP: z.number().min(0).max(1).optional(),\n});\nexport type ModelParams = z.infer<typeof ModelParams>;\n\n/** The versionable content of a prompt — what the content hash covers. */\nexport const PromptTemplate = z.object({\n messages: z.array(PromptMessage).min(1).max(50),\n params: ModelParams.default({}),\n});\nexport type PromptTemplate = z.infer<typeof PromptTemplate>;\n\nexport const Prompt = z.object({\n tenantId: z.string().min(1),\n id: PromptId,\n name: z.string().min(1).max(120),\n description: z.string().max(2000).optional(),\n latestVersion: z.number().int().min(0),\n createdAtIso: z.string().datetime(),\n updatedAtIso: z.string().datetime(),\n});\nexport type Prompt = z.infer<typeof Prompt>;\n\n/**\n * Immutable prompt version. Content-addressed like dataset versions and the\n * edge manifest: identical templates always yield identical hashes, so a\n * judge's provenance promptHash can be traced back to a registry version.\n */\nexport const PromptVersion = z.object({\n promptId: PromptId,\n version: z.number().int().min(1),\n template: PromptTemplate,\n contentHash: z.string().regex(/^[a-f0-9]{64}$/),\n createdAtIso: z.string().datetime(),\n note: z.string().max(500).optional(),\n});\nexport type PromptVersion = z.infer<typeof PromptVersion>;\n","import { canonicalJson, sha256Hex } from '@fabricorg/experiments-datasets';\nimport type { PromptMessage, PromptTemplate } from './schema.js';\n\n/** {{variable}} — same placeholder syntax as the evals judge templates. */\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\n\n/** Distinct variable names referenced by a template, in first-appearance order. */\nexport function templateVariables(template: PromptTemplate): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const m of template.messages) {\n for (const match of m.content.matchAll(VARIABLE_RE)) {\n const name = match[1]!;\n if (!seen.has(name)) {\n seen.add(name);\n out.push(name);\n }\n }\n }\n return out;\n}\n\nexport interface RenderResult {\n messages: PromptMessage[];\n /** Variables referenced by the template but absent from the input. */\n missing: string[];\n}\n\n/**\n * Substitute variables into every message. Missing variables render as empty\n * strings and are reported — the playground surfaces them as a warning\n * rather than refusing to run (matching judge-template render semantics).\n */\nexport function renderPrompt(\n template: PromptTemplate,\n variables: Record<string, string>,\n): RenderResult {\n const missing = templateVariables(template).filter((v) => !(v in variables));\n const messages = template.messages.map((m) => ({\n role: m.role,\n content: m.content.replace(VARIABLE_RE, (_, name: string) => variables[name] ?? ''),\n }));\n return { messages, missing };\n}\n\n/** Content hash over the canonical template JSON — version identity. */\nexport function hashTemplate(template: PromptTemplate): string {\n return sha256Hex(canonicalJson(template));\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@fabricorg/experiments-prompts",
3
+ "version": "0.1.0",
4
+ "description": "Versioned prompt registry domain for Fabric Experiments: chat templates, variable rendering, content-hashed versions.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.cjs",
9
+ "types": "./dist/index.d.ts",
10
+ "module": "./dist/index.js",
11
+ "exports": {
12
+ ".": {
13
+ "import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
14
+ "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
15
+ }
16
+ },
17
+ "files": ["dist"],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "type-check": "tsc --noEmit",
21
+ "test": "vitest run",
22
+ "clean": "rm -rf dist"
23
+ },
24
+ "dependencies": {
25
+ "@fabricorg/experiments-datasets": "^0.1.0",
26
+ "zod": "^3.23.8"
27
+ },
28
+ "devDependencies": {
29
+ "tsup": "^8.3.5",
30
+ "typescript": "^5.8.3",
31
+ "vitest": "^3.2.7"
32
+ }
33
+ }