@vertesia/studio-utils 1.6.0-dev.20260918.115658Z → 1.6.0-dev.20261004.085740Z
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/lib/conditions/index.d.ts +1 -0
- package/lib/conditions/index.d.ts.map +1 -1
- package/lib/conditions/index.js +1 -0
- package/lib/conditions/index.js.map +1 -1
- package/lib/conditions/principal-context.d.ts +55 -0
- package/lib/conditions/principal-context.d.ts.map +1 -0
- package/lib/conditions/principal-context.js +81 -0
- package/lib/conditions/principal-context.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/prompts/extract-vars.d.ts +44 -12
- package/lib/prompts/extract-vars.d.ts.map +1 -1
- package/lib/prompts/extract-vars.js +165 -78
- package/lib/prompts/extract-vars.js.map +1 -1
- package/lib/prompts/render.d.ts +7 -9
- package/lib/prompts/render.d.ts.map +1 -1
- package/lib/prompts/render.js +12 -15
- package/lib/prompts/render.js.map +1 -1
- package/lib/prompts/validate.d.ts +8 -2
- package/lib/prompts/validate.d.ts.map +1 -1
- package/lib/prompts/validate.js +87 -51
- package/lib/prompts/validate.js.map +1 -1
- package/lib/roles/agent-runs.d.ts +8 -0
- package/lib/roles/agent-runs.d.ts.map +1 -0
- package/lib/roles/agent-runs.js +36 -0
- package/lib/roles/agent-runs.js.map +1 -0
- package/lib/roles/classes.d.ts +15 -1
- package/lib/roles/classes.d.ts.map +1 -1
- package/lib/roles/classes.js +10 -1
- package/lib/roles/classes.js.map +1 -1
- package/lib/roles/content.d.ts.map +1 -1
- package/lib/roles/content.js +14 -4
- package/lib/roles/content.js.map +1 -1
- package/lib/roles/index.d.ts +4 -3
- package/lib/roles/index.d.ts.map +1 -1
- package/lib/roles/index.js +7 -5
- package/lib/roles/index.js.map +1 -1
- package/lib/vertesia-studio-utils.js +2 -1
- package/lib/vertesia-studio-utils.js.map +1 -1
- package/package.json +12 -11
- package/src/conditions/index.ts +6 -0
- package/src/conditions/principal-context.ts +122 -0
- package/src/index.ts +20 -1
- package/src/prompts/extract-vars.ts +212 -71
- package/src/prompts/render.ts +24 -15
- package/src/prompts/validate.ts +113 -57
- package/src/roles/agent-runs.ts +41 -0
- package/src/roles/classes.ts +7 -0
- package/src/roles/content.ts +21 -5
- package/src/roles/index.ts +7 -5
- package/src/apps/index.test.ts +0 -166
- package/src/conditions/match.test.ts +0 -134
- package/src/prompts/render.test.ts +0 -110
- package/src/prompts/validate.test.ts +0 -309
- package/src/roles/index.test.ts +0 -221
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,eAAe,GAClB,MAAM,wBAAwB,CAAC"}
|
package/lib/conditions/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conditions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EACH,qBAAqB,EAGrB,eAAe,GAClB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { AbacPrincipalContext, PrincipalKind } from '@vertesia/common';
|
|
2
|
+
/**
|
|
3
|
+
* The shared principal-context builder, consumed by both the token server (JWT `$principal.*`
|
|
4
|
+
* resolution at mint time) and studio-server (the `/iam/users/identity` endpoint). It is the single
|
|
5
|
+
* home for logic that used to be duplicated in `apps/token-server` and `apps/studio-server` and kept
|
|
6
|
+
* in sync by hand; the produced {@link AbacPrincipalContext} is exactly the shape ABAC rules resolve
|
|
7
|
+
* against.
|
|
8
|
+
*
|
|
9
|
+
* Browser-safe (pure, no Node built-ins): the UI condition editor lives downstream of the same
|
|
10
|
+
* `@vertesia/common` shape, and this package must stay loadable in the browser bundle.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A user, group, or api-key record as it comes out of Mongo, where every optional field can be null
|
|
14
|
+
* as well as absent — which the inferred persistence types say out loud. The merge treats null and
|
|
15
|
+
* absent identically, so nothing about the resulting context changes; what changes is that the
|
|
16
|
+
* nullability is handled rather than asserted away at the call site.
|
|
17
|
+
*/
|
|
18
|
+
export interface MergeSource {
|
|
19
|
+
properties?: Record<string, unknown> | null;
|
|
20
|
+
clearance?: number | null;
|
|
21
|
+
compartments?: string[] | null;
|
|
22
|
+
tags?: string[] | null;
|
|
23
|
+
}
|
|
24
|
+
export interface MergedUserFields {
|
|
25
|
+
properties?: Record<string, unknown>;
|
|
26
|
+
clearance?: number;
|
|
27
|
+
compartments?: string[];
|
|
28
|
+
tags?: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Merge properties, clearance, compartments, and tags from groups + the principal.
|
|
32
|
+
*
|
|
33
|
+
* - properties: array values are deduplicated union, scalars use last-write-wins (principal wins)
|
|
34
|
+
* - clearance: max across all defined values (most permissive wins)
|
|
35
|
+
* - compartments / tags: deduplicated union of all arrays
|
|
36
|
+
*
|
|
37
|
+
* Used for the user token path (user + covering groups). The api-key path has no groups to merge and
|
|
38
|
+
* passes the key document straight to {@link buildPrincipalContext} as `fields`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function mergeUserFields(groups: MergeSource[], user: MergeSource): MergedUserFields;
|
|
41
|
+
/**
|
|
42
|
+
* Build the {@link AbacPrincipalContext} consumed by ResourceSet/PrincipalSet condition evaluation
|
|
43
|
+
* and mirrored into the JWT for runtime `$principal.*` resolution.
|
|
44
|
+
*
|
|
45
|
+
* - user: pass `mergeUserFields(groups, user)` as fields, the user's email, and the user id
|
|
46
|
+
* - apikey: pass the api key document itself (it carries optional properties/clearance/compartments)
|
|
47
|
+
* and the api key id
|
|
48
|
+
*
|
|
49
|
+
* Defaults are applied so condition operators have well-defined behaviour when the principal has no
|
|
50
|
+
* merged value: clearance → 0, compartments → [], tags → [], properties → {}, id → '', email → ''.
|
|
51
|
+
* `email` is published optional on the wire but defaulted to '' here so `$principal.email` resolves
|
|
52
|
+
* to a string rather than undefined during rule evaluation.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildPrincipalContext(kind: PrincipalKind, fields: MergeSource, email?: string | null, id?: string): AbacPrincipalContext;
|
|
55
|
+
//# sourceMappingURL=principal-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal-context.d.ts","sourceRoot":"","sources":["../../src/conditions/principal-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE5E;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAgD1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACjC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,EAAE,CAAC,EAAE,MAAM,GACZ,oBAAoB,CAUtB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge properties, clearance, compartments, and tags from groups + the principal.
|
|
3
|
+
*
|
|
4
|
+
* - properties: array values are deduplicated union, scalars use last-write-wins (principal wins)
|
|
5
|
+
* - clearance: max across all defined values (most permissive wins)
|
|
6
|
+
* - compartments / tags: deduplicated union of all arrays
|
|
7
|
+
*
|
|
8
|
+
* Used for the user token path (user + covering groups). The api-key path has no groups to merge and
|
|
9
|
+
* passes the key document straight to {@link buildPrincipalContext} as `fields`.
|
|
10
|
+
*/
|
|
11
|
+
export function mergeUserFields(groups, user) {
|
|
12
|
+
const mergedProps = {};
|
|
13
|
+
let maxClearance;
|
|
14
|
+
const allCompartments = new Set();
|
|
15
|
+
const allTags = new Set();
|
|
16
|
+
for (const source of [...groups, user]) {
|
|
17
|
+
if (source.properties) {
|
|
18
|
+
for (const [key, value] of Object.entries(source.properties)) {
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
const existing = mergedProps[key];
|
|
21
|
+
if (Array.isArray(existing)) {
|
|
22
|
+
const set = new Set([...existing, ...value]);
|
|
23
|
+
mergedProps[key] = Array.from(set);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
mergedProps[key] = [...value];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
mergedProps[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// `!= null` rather than `!== undefined`: a stored null means "no clearance recorded", the
|
|
35
|
+
// same as an absent field, and must not reach Math.max where it would read as 0.
|
|
36
|
+
if (source.clearance != null) {
|
|
37
|
+
maxClearance = maxClearance !== undefined ? Math.max(maxClearance, source.clearance) : source.clearance;
|
|
38
|
+
}
|
|
39
|
+
if (source.compartments) {
|
|
40
|
+
for (const c of source.compartments) {
|
|
41
|
+
allCompartments.add(c);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (source.tags) {
|
|
45
|
+
for (const t of source.tags) {
|
|
46
|
+
allTags.add(t);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
properties: Object.keys(mergedProps).length > 0 ? mergedProps : undefined,
|
|
52
|
+
clearance: maxClearance,
|
|
53
|
+
compartments: allCompartments.size > 0 ? Array.from(allCompartments) : undefined,
|
|
54
|
+
tags: allTags.size > 0 ? Array.from(allTags) : undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build the {@link AbacPrincipalContext} consumed by ResourceSet/PrincipalSet condition evaluation
|
|
59
|
+
* and mirrored into the JWT for runtime `$principal.*` resolution.
|
|
60
|
+
*
|
|
61
|
+
* - user: pass `mergeUserFields(groups, user)` as fields, the user's email, and the user id
|
|
62
|
+
* - apikey: pass the api key document itself (it carries optional properties/clearance/compartments)
|
|
63
|
+
* and the api key id
|
|
64
|
+
*
|
|
65
|
+
* Defaults are applied so condition operators have well-defined behaviour when the principal has no
|
|
66
|
+
* merged value: clearance → 0, compartments → [], tags → [], properties → {}, id → '', email → ''.
|
|
67
|
+
* `email` is published optional on the wire but defaulted to '' here so `$principal.email` resolves
|
|
68
|
+
* to a string rather than undefined during rule evaluation.
|
|
69
|
+
*/
|
|
70
|
+
export function buildPrincipalContext(kind, fields, email, id) {
|
|
71
|
+
return {
|
|
72
|
+
kind,
|
|
73
|
+
id: id ?? '',
|
|
74
|
+
clearance: fields.clearance ?? 0,
|
|
75
|
+
compartments: fields.compartments ?? [],
|
|
76
|
+
email: email ?? '',
|
|
77
|
+
tags: fields.tags ?? [],
|
|
78
|
+
properties: fields.properties ?? {},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=principal-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal-context.js","sourceRoot":"","sources":["../../src/conditions/principal-context.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export { describeTemplateSystemVariables, HANDLEBARS_HELPER_NAMES, isTemplateSystemVariable, TEMPLATE_SYSTEM_VARIABLE_NAMES, TEMPLATE_SYSTEM_VARIABLES, type TemplateSystemContext, type TemplateSystemVariable, type TemplateSystemVariableName, withTemplateSystemVariables, } from '@vertesia/jst';
|
|
1
2
|
export { substituteEndpoints } from './apps/index.js';
|
|
2
|
-
export { extractHandlebarsVariables } from './prompts/extract-vars.js';
|
|
3
|
+
export { analyzeHandlebarsTemplate, extractHandlebarsVariables, type HandlebarsHelperMisuse, type HandlebarsTemplateAnalysis, type HandlebarsVariableReference, } from './prompts/extract-vars.js';
|
|
3
4
|
export { generateMockData } from './prompts/mock-data.js';
|
|
4
5
|
export { executeHandlebars, executeJST, renderPrompt, renderSegments, renderSegmentsOrErrors, renderTemplate, type SegmentPreview, } from './prompts/render.js';
|
|
5
6
|
export { type PromptValidationInput, type PromptValidationIssue, type PromptValidationIssueSeverity, type PromptValidationIssueType, type PromptValidationResult, validatePrompt, } from './prompts/validate.js';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,+BAA+B,EAC/B,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,2BAA2B,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACH,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,KAAK,cAAc,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,cAAc,GACjB,MAAM,uBAAuB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
// The template runtime's registry, re-exported so consumers validating or documenting prompts
|
|
2
|
+
// read the same names the renderer uses.
|
|
3
|
+
export { describeTemplateSystemVariables, HANDLEBARS_HELPER_NAMES, isTemplateSystemVariable, TEMPLATE_SYSTEM_VARIABLE_NAMES, TEMPLATE_SYSTEM_VARIABLES, withTemplateSystemVariables, } from '@vertesia/jst';
|
|
1
4
|
export { substituteEndpoints } from './apps/index.js';
|
|
2
|
-
export { extractHandlebarsVariables } from './prompts/extract-vars.js';
|
|
5
|
+
export { analyzeHandlebarsTemplate, extractHandlebarsVariables, } from './prompts/extract-vars.js';
|
|
3
6
|
export { generateMockData } from './prompts/mock-data.js';
|
|
4
7
|
export { executeHandlebars, executeJST, renderPrompt, renderSegments, renderSegmentsOrErrors, renderTemplate, } from './prompts/render.js';
|
|
5
8
|
export { validatePrompt, } from './prompts/validate.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,yCAAyC;AACzC,OAAO,EACH,+BAA+B,EAC/B,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EAIzB,2BAA2B,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACH,yBAAyB,EACzB,0BAA0B,GAI7B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACH,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,cAAc,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAMH,cAAc,GACjB,MAAM,uBAAuB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
|
@@ -1,19 +1,51 @@
|
|
|
1
|
+
/** A read of a root-level template variable. */
|
|
2
|
+
export interface HandlebarsVariableReference {
|
|
3
|
+
/** Root identifier: `customer` for `{{customer.name}}`, `{{../customer}}` or `{{@root.customer}}`. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** The path as written, e.g. `customer.name`. */
|
|
6
|
+
expression: string;
|
|
7
|
+
/** True when the path reads a property of the variable (`customer.name`). */
|
|
8
|
+
hasPath: boolean;
|
|
9
|
+
/** Source of the tag that contains the read, e.g. `{{#if customer}}`. */
|
|
10
|
+
tag: string;
|
|
11
|
+
}
|
|
12
|
+
/** A helper name used where Handlebars will not call it. */
|
|
13
|
+
export interface HandlebarsHelperMisuse {
|
|
14
|
+
helper: string;
|
|
15
|
+
/**
|
|
16
|
+
* - `used_as_value`: passed as an argument (`{{#if stringify}}`), where Handlebars reads the data.
|
|
17
|
+
* - `missing_arguments`: called bare (`{{stringify}}`) with none of the arguments it needs.
|
|
18
|
+
*/
|
|
19
|
+
problem: 'used_as_value' | 'missing_arguments';
|
|
20
|
+
tag: string;
|
|
21
|
+
}
|
|
22
|
+
export interface HandlebarsTemplateAnalysis {
|
|
23
|
+
references: HandlebarsVariableReference[];
|
|
24
|
+
helperMisuses: HandlebarsHelperMisuse[];
|
|
25
|
+
}
|
|
1
26
|
/**
|
|
2
|
-
*
|
|
27
|
+
* Analyze the variables and helpers a Handlebars template uses, resolving names the way the
|
|
28
|
+
* prompt renderer does (helpers and system variables come from `@vertesia/jst`).
|
|
3
29
|
*
|
|
4
|
-
*
|
|
5
|
-
* - `{{
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - `
|
|
9
|
-
* - `{{@index}}
|
|
30
|
+
* Scoping rules:
|
|
31
|
+
* - Inside `{{#each}}` / `{{#with}}` (and `{{#section}}` over data), bare names read the current item,
|
|
32
|
+
* whose shape the input schema does not describe — they are not reported. `../x` and `@root.x`
|
|
33
|
+
* read the enclosing or root context and are reported.
|
|
34
|
+
* - `as |x|` block params are local bindings, not variables.
|
|
35
|
+
* - `{{@index}}` and other `@`-data (except `@root.x`) are runtime values, not variables.
|
|
10
36
|
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
37
|
+
* Returns null when the template does not parse; the render check reports the syntax error.
|
|
38
|
+
*/
|
|
39
|
+
export declare function analyzeHandlebarsTemplate(template: string): HandlebarsTemplateAnalysis | null;
|
|
40
|
+
/**
|
|
41
|
+
* Extract the set of root-level input variable names a Handlebars template reads.
|
|
42
|
+
*
|
|
43
|
+
* - `{{foo}}` → `foo`; `{{obj.bar.baz}}` → `obj`
|
|
44
|
+
* - `{{#each items as |item|}}{{item.name}}{{/each}}` → `items` (`item` is a block param)
|
|
45
|
+
* - `{{lookup obj key}}` → `obj`, `key` (helper name skipped)
|
|
46
|
+
* - `{{@index}}`, `{{this}}`, and bare names inside `#each`/`#with` → ignored
|
|
14
47
|
*
|
|
15
|
-
* Returns an empty set on parse failure
|
|
16
|
-
* (e.g. `executeHandlebars`) to surface parse errors separately.
|
|
48
|
+
* Returns an empty set on parse failure.
|
|
17
49
|
*/
|
|
18
50
|
export declare function extractHandlebarsVariables(template: string): Set<string>;
|
|
19
51
|
//# sourceMappingURL=extract-vars.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-vars.d.ts","sourceRoot":"","sources":["../../src/prompts/extract-vars.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extract-vars.d.ts","sourceRoot":"","sources":["../../src/prompts/extract-vars.ts"],"names":[],"mappings":"AAGA,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IACxC,sGAAsG;IACtG,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;CACf;AAED,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAC/C,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACvC,UAAU,EAAE,2BAA2B,EAAE,CAAC;IAC1C,aAAa,EAAE,sBAAsB,EAAE,CAAC;CAC3C;AAyCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,0BAA0B,GAAG,IAAI,CA2J7F;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAGxE"}
|
|
@@ -1,114 +1,201 @@
|
|
|
1
|
+
import { HANDLEBARS_CONTEXT_HELPERS, isHandlebarsHelper, isTemplateSystemVariable } from '@vertesia/jst';
|
|
1
2
|
import Handlebars from 'handlebars';
|
|
3
|
+
function isPath(node) {
|
|
4
|
+
return !!node && typeof node === 'object' && node.type === 'PathExpression';
|
|
5
|
+
}
|
|
6
|
+
/** `this.x`, `./x` and `this` read the context explicitly — Handlebars never treats them as helpers. */
|
|
7
|
+
function isScoped(path) {
|
|
8
|
+
return /^\.|this\b/.test(path.original);
|
|
9
|
+
}
|
|
10
|
+
/** A single bare identifier — the only form Handlebars may resolve to a helper. */
|
|
11
|
+
function isSimpleId(path) {
|
|
12
|
+
return path.parts.length === 1 && !isScoped(path) && !path.data && path.depth === 0;
|
|
13
|
+
}
|
|
14
|
+
function lineOffsets(template) {
|
|
15
|
+
const offsets = [0];
|
|
16
|
+
for (let i = 0; i < template.length; i++) {
|
|
17
|
+
if (template[i] === '\n')
|
|
18
|
+
offsets.push(i + 1);
|
|
19
|
+
}
|
|
20
|
+
return offsets;
|
|
21
|
+
}
|
|
2
22
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* - `{{foo}}` → `foo`
|
|
6
|
-
* - `{{obj.bar.baz}}` → `obj` (only the root identifier; nested access doesn't add `bar` or `baz`)
|
|
7
|
-
* - `{{#if cond}}{{name}}{{/if}}` → `cond`, `name`
|
|
8
|
-
* - `{{#each items as |item|}}{{item.name}}{{/each}}` → `items` (NOT `item` — bound by `as |item|`)
|
|
9
|
-
* - `{{lookup obj key}}` → `obj`, `key` (helper name skipped)
|
|
10
|
-
* - `{{@index}}`, `{{this}}` → ignored (built-in data vars / self)
|
|
23
|
+
* Analyze the variables and helpers a Handlebars template uses, resolving names the way the
|
|
24
|
+
* prompt renderer does (helpers and system variables come from `@vertesia/jst`).
|
|
11
25
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
26
|
+
* Scoping rules:
|
|
27
|
+
* - Inside `{{#each}}` / `{{#with}}` (and `{{#section}}` over data), bare names read the current item,
|
|
28
|
+
* whose shape the input schema does not describe — they are not reported. `../x` and `@root.x`
|
|
29
|
+
* read the enclosing or root context and are reported.
|
|
30
|
+
* - `as |x|` block params are local bindings, not variables.
|
|
31
|
+
* - `{{@index}}` and other `@`-data (except `@root.x`) are runtime values, not variables.
|
|
15
32
|
*
|
|
16
|
-
* Returns
|
|
17
|
-
* (e.g. `executeHandlebars`) to surface parse errors separately.
|
|
33
|
+
* Returns null when the template does not parse; the render check reports the syntax error.
|
|
18
34
|
*/
|
|
19
|
-
export function
|
|
35
|
+
export function analyzeHandlebarsTemplate(template) {
|
|
20
36
|
let ast;
|
|
21
37
|
try {
|
|
22
38
|
ast = Handlebars.parse(template);
|
|
23
39
|
}
|
|
24
40
|
catch {
|
|
25
|
-
return
|
|
41
|
+
return null;
|
|
26
42
|
}
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
43
|
+
const offsets = lineOffsets(template);
|
|
44
|
+
const tagAt = (loc) => {
|
|
45
|
+
if (!loc)
|
|
46
|
+
return '';
|
|
47
|
+
const start = (offsets[loc.start.line - 1] ?? 0) + loc.start.column;
|
|
48
|
+
const end = template.indexOf('}}', start);
|
|
49
|
+
if (end < 0)
|
|
50
|
+
return template.slice(start);
|
|
51
|
+
return template.slice(start, template[end + 2] === '}' ? end + 3 : end + 2);
|
|
52
|
+
};
|
|
53
|
+
const references = [];
|
|
54
|
+
const helperMisuses = [];
|
|
55
|
+
const contexts = ['root'];
|
|
56
|
+
const blockParams = [];
|
|
57
|
+
let tag = '';
|
|
58
|
+
const isBlockParam = (name) => blockParams.some((scope) => scope.has(name));
|
|
59
|
+
/** Record a data read of `path`, if it reads the root input. */
|
|
60
|
+
const readData = (path) => {
|
|
61
|
+
if (path.data) {
|
|
62
|
+
// `@root.x` reads the input root; `@index`, `@key`, ... are runtime values.
|
|
63
|
+
if (path.parts[0] === 'root' && path.parts.length > 1) {
|
|
64
|
+
references.push({
|
|
65
|
+
name: path.parts[1],
|
|
66
|
+
expression: path.original,
|
|
67
|
+
hasPath: path.parts.length > 2,
|
|
68
|
+
tag,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (path.parts.length === 0)
|
|
74
|
+
return; // `this` / `.`
|
|
75
|
+
const root = path.parts[0];
|
|
76
|
+
if (path.depth === 0 && !isScoped(path) && isBlockParam(root))
|
|
77
|
+
return;
|
|
78
|
+
// Handlebars stops at the root context when `../` goes past it.
|
|
79
|
+
const context = contexts[Math.max(0, contexts.length - 1 - path.depth)];
|
|
80
|
+
if (context !== 'root')
|
|
81
|
+
return;
|
|
82
|
+
references.push({ name: root, expression: path.original, hasPath: path.parts.length > 1, tag });
|
|
83
|
+
};
|
|
84
|
+
/** A path in argument position (params, hash values): Handlebars reads data, never calls a helper. */
|
|
85
|
+
const visitArgument = (node) => {
|
|
86
|
+
if (isPath(node)) {
|
|
87
|
+
const name = node.parts[0];
|
|
88
|
+
// System variables are injected as data too, so they resolve as arguments.
|
|
89
|
+
if (isSimpleId(node) &&
|
|
90
|
+
!isBlockParam(name) &&
|
|
91
|
+
isHandlebarsHelper(name) &&
|
|
92
|
+
!isTemplateSystemVariable(name)) {
|
|
93
|
+
helperMisuses.push({ helper: name, problem: 'used_as_value', tag });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
readData(node);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
visit(node);
|
|
100
|
+
};
|
|
101
|
+
const visitCall = (n) => {
|
|
102
|
+
const params = n.params ?? [];
|
|
103
|
+
for (const p of params)
|
|
104
|
+
visitArgument(p);
|
|
105
|
+
const pairs = n.hash?.pairs ?? [];
|
|
106
|
+
for (const pair of pairs)
|
|
107
|
+
visitArgument(pair.value);
|
|
108
|
+
};
|
|
109
|
+
const hasArguments = (n) => (n.params?.length ?? 0) > 0 ||
|
|
110
|
+
(n.hash?.pairs?.length ?? 0) > 0;
|
|
30
111
|
const visit = (node) => {
|
|
31
112
|
if (!node || typeof node !== 'object')
|
|
32
113
|
return;
|
|
33
114
|
const n = node;
|
|
34
115
|
switch (n.type) {
|
|
35
116
|
case 'Program': {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
117
|
+
for (const stmt of n.body ?? [])
|
|
118
|
+
visit(stmt);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case 'MustacheStatement': {
|
|
122
|
+
tag = tagAt(n.loc);
|
|
123
|
+
const path = n.path;
|
|
124
|
+
if (hasArguments(n)) {
|
|
125
|
+
// `{{helper arg}}`: the head is a helper name (a missing one fails the render check).
|
|
126
|
+
visitCall(n);
|
|
127
|
+
}
|
|
128
|
+
else if (isPath(path)) {
|
|
129
|
+
// A bare `{{name}}` calls a helper of that name when there is one, else reads data.
|
|
130
|
+
// System variables are helpers returning their injected value, meant to be used bare.
|
|
131
|
+
const name = path.parts[0];
|
|
132
|
+
if (isSimpleId(path) && !isBlockParam(name) && isHandlebarsHelper(name)) {
|
|
133
|
+
if (!isTemplateSystemVariable(name)) {
|
|
134
|
+
helperMisuses.push({ helper: name, problem: 'missing_arguments', tag });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
readData(path);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
visit(path);
|
|
143
|
+
}
|
|
40
144
|
break;
|
|
41
145
|
}
|
|
42
146
|
case 'BlockStatement': {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
147
|
+
tag = tagAt(n.loc);
|
|
148
|
+
const path = n.path;
|
|
149
|
+
const helper = isPath(path) && isSimpleId(path) ? path.parts[0] : undefined;
|
|
150
|
+
let itemContext;
|
|
151
|
+
if (hasArguments(n) || (helper && isHandlebarsHelper(helper))) {
|
|
152
|
+
visitCall(n);
|
|
153
|
+
itemContext = !!helper && HANDLEBARS_CONTEXT_HELPERS.includes(helper);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// `{{#section}}…{{/section}}` over data: iterates or enters `section`.
|
|
157
|
+
if (isPath(path))
|
|
158
|
+
readData(path);
|
|
159
|
+
itemContext = true;
|
|
160
|
+
}
|
|
51
161
|
const program = n.program;
|
|
52
162
|
const inverse = n.inverse;
|
|
53
|
-
|
|
54
|
-
|
|
163
|
+
blockParams.push(new Set(program?.blockParams ?? []));
|
|
164
|
+
contexts.push(itemContext ? 'item' : contexts[contexts.length - 1]);
|
|
55
165
|
visit(n.program);
|
|
166
|
+
contexts.pop();
|
|
167
|
+
blockParams.pop();
|
|
168
|
+
// `{{else}}` renders with the enclosing context.
|
|
169
|
+
blockParams.push(new Set(inverse?.blockParams ?? []));
|
|
56
170
|
visit(n.inverse);
|
|
57
|
-
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
case 'MustacheStatement': {
|
|
61
|
-
// Bare mustache (no params, no hash) → it's a variable reference.
|
|
62
|
-
// With params/hash, it's a helper call — skip the path (helper name), visit args.
|
|
63
|
-
const params = n.params;
|
|
64
|
-
const hash = n.hash;
|
|
65
|
-
const isHelperCall = (params?.length ?? 0) > 0 || (hash?.pairs?.length ?? 0) > 0;
|
|
66
|
-
// The renderer registers _now as a zero-argument helper. Only the bare
|
|
67
|
-
// helper invocation is implicit; paths such as this._now remain data reads.
|
|
68
|
-
const path = n.path;
|
|
69
|
-
if (!isHelperCall && path?.original !== '_now') {
|
|
70
|
-
visit(n.path);
|
|
71
|
-
}
|
|
72
|
-
if (params)
|
|
73
|
-
for (const p of params)
|
|
74
|
-
visit(p);
|
|
75
|
-
visit(hash);
|
|
171
|
+
blockParams.pop();
|
|
76
172
|
break;
|
|
77
173
|
}
|
|
78
174
|
case 'SubExpression': {
|
|
79
|
-
// (helper
|
|
80
|
-
|
|
81
|
-
if (params)
|
|
82
|
-
for (const p of params)
|
|
83
|
-
visit(p);
|
|
84
|
-
visit(n.hash);
|
|
175
|
+
// `(helper arg)`: the head is a call, like a bare `{{helper}}`.
|
|
176
|
+
visitCall(n);
|
|
85
177
|
break;
|
|
86
178
|
}
|
|
87
|
-
|
|
88
|
-
if (n.data)
|
|
89
|
-
break; // `@-data` references (@index, @key, etc.)
|
|
90
|
-
const parts = n.parts;
|
|
91
|
-
if (!parts || parts.length === 0)
|
|
92
|
-
break; // `this` / `.`
|
|
93
|
-
const root = parts[0];
|
|
94
|
-
if (isLocal(root))
|
|
95
|
-
break;
|
|
96
|
-
variables.add(root);
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
case 'Hash': {
|
|
100
|
-
const pairs = n.pairs;
|
|
101
|
-
if (pairs)
|
|
102
|
-
for (const pair of pairs)
|
|
103
|
-
visit(pair.value);
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
// ContentStatement, CommentStatement, *Literal, PartialStatement — no variables to extract.
|
|
179
|
+
// ContentStatement, CommentStatement, literals, partials — no variables.
|
|
107
180
|
default:
|
|
108
181
|
break;
|
|
109
182
|
}
|
|
110
183
|
};
|
|
111
184
|
visit(ast);
|
|
112
|
-
return
|
|
185
|
+
return { references, helperMisuses };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Extract the set of root-level input variable names a Handlebars template reads.
|
|
189
|
+
*
|
|
190
|
+
* - `{{foo}}` → `foo`; `{{obj.bar.baz}}` → `obj`
|
|
191
|
+
* - `{{#each items as |item|}}{{item.name}}{{/each}}` → `items` (`item` is a block param)
|
|
192
|
+
* - `{{lookup obj key}}` → `obj`, `key` (helper name skipped)
|
|
193
|
+
* - `{{@index}}`, `{{this}}`, and bare names inside `#each`/`#with` → ignored
|
|
194
|
+
*
|
|
195
|
+
* Returns an empty set on parse failure.
|
|
196
|
+
*/
|
|
197
|
+
export function extractHandlebarsVariables(template) {
|
|
198
|
+
const analysis = analyzeHandlebarsTemplate(template);
|
|
199
|
+
return new Set(analysis?.references.map((r) => r.name) ?? []);
|
|
113
200
|
}
|
|
114
201
|
//# sourceMappingURL=extract-vars.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-vars.js","sourceRoot":"","sources":["../../src/prompts/extract-vars.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"extract-vars.js","sourceRoot":"","sources":["../../src/prompts/extract-vars.ts"],"names":[],"mappings":"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"}
|
package/lib/prompts/render.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSONObject, JSONSchema, PromptSegment } from '@llumiverse/common';
|
|
2
2
|
import { type PromptSegmentDef, type PromptTemplate, TemplateType } from '@vertesia/common';
|
|
3
|
+
import { type TemplateSystemContext } from '@vertesia/jst';
|
|
3
4
|
export interface SegmentPreview {
|
|
4
5
|
error?: Error;
|
|
5
6
|
title: string;
|
|
@@ -9,21 +10,18 @@ export interface SegmentPreview {
|
|
|
9
10
|
/**
|
|
10
11
|
* Render a prompt template with the given input data.
|
|
11
12
|
*
|
|
12
|
-
* Handlebars templates use {{variable}} interpolation against `data`.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* studio-server executor
|
|
16
|
-
*
|
|
17
|
-
* and `apps/studio-server/src/executor/rendering/template.ts`). Listing it here keeps
|
|
18
|
-
* the Playground preview and `validatePrompt` in sync with runtime resolution — a JST
|
|
19
|
-
* template referencing `_model` validates fine here and renders fine in production.
|
|
13
|
+
* Handlebars templates use {{variable}} interpolation against `data`. JST (JavaScript template)
|
|
14
|
+
* bodies evaluate against `data` with the schema's top-level property names exposed as globals.
|
|
15
|
+
* Both see the system variables (`TEMPLATE_SYSTEM_VARIABLES` in `@vertesia/jst`), added here the
|
|
16
|
+
* same way the studio-server executor adds them, so a preview renders what an execution would.
|
|
17
|
+
* `_model` is only set when the caller passes `system.model` or the data already carries it.
|
|
20
18
|
*
|
|
21
19
|
* For `TemplateType.text`, the content is returned verbatim — it is static text, not a
|
|
22
20
|
* template — matching the studio-server executor (see `apps/studio-server/src/executor/
|
|
23
21
|
* rendering/template.ts`). Routing it through the JST evaluator would compile the prose as
|
|
24
22
|
* JavaScript and throw on any plain sentence (e.g. "You are a helpful assistant.").
|
|
25
23
|
*/
|
|
26
|
-
export declare function renderTemplate(code: string, contentType: TemplateType, schema: JSONSchema, data: JSONObject): string;
|
|
24
|
+
export declare function renderTemplate(code: string, contentType: TemplateType, schema: JSONSchema, data: JSONObject, system?: TemplateSystemContext): string;
|
|
27
25
|
/**
|
|
28
26
|
* Execute a JST (JavaScript Template) with given data.
|
|
29
27
|
* Returns a discriminated union to surface errors without throwing.
|