@mistralys/persona-builder 2.2.0 → 2.4.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 +8 -2
- package/dist/cli.cjs +75 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +75 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +77 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +222 -27
- package/dist/index.d.ts +222 -27
- package/dist/index.js +76 -10
- package/dist/index.js.map +1 -1
- package/package.json +53 -53
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,12 @@
|
|
|
22
22
|
*
|
|
23
23
|
* @param text - Template string potentially containing {{> name}} markers
|
|
24
24
|
* @param partialsMap - Map of partial name → partial content
|
|
25
|
-
* @param depth -
|
|
25
|
+
* @param depth - **Internal recursion counter — callers must always omit this
|
|
26
|
+
* parameter.** It exists solely so the function can track its own
|
|
27
|
+
* nesting level across recursive calls. Passing a non-zero value
|
|
28
|
+
* bypasses the depth guard (e.g. `resolvePartials(text, map, 5)`
|
|
29
|
+
* expands nothing). This parameter will be removed from the public
|
|
30
|
+
* signature and marked `@internal` in a future release.
|
|
26
31
|
* @returns The template string with partial markers replaced
|
|
27
32
|
*/
|
|
28
33
|
declare function resolvePartials(text: string, partialsMap: Record<string, string>, depth?: number): string;
|
|
@@ -31,7 +36,8 @@ declare function resolvePartials(text: string, partialsMap: Record<string, strin
|
|
|
31
36
|
* conditionals.ts
|
|
32
37
|
*
|
|
33
38
|
* Pure template-engine function for resolving conditional blocks.
|
|
34
|
-
* Handles {{#if flag}}…{{/if}}
|
|
39
|
+
* Handles {{#if flag}}…{{/if}}, {{#if flag}}…{{else}}…{{/if}}, and
|
|
40
|
+
* {{#if flag}}…{{else if flag2}}…{{else}}…{{/if}} (chain) syntax,
|
|
35
41
|
* including nested {{#if}} blocks inside {{else}} branches.
|
|
36
42
|
* No file-system I/O.
|
|
37
43
|
*/
|
|
@@ -41,10 +47,15 @@ declare function resolvePartials(text: string, partialsMap: Record<string, strin
|
|
|
41
47
|
* Syntax:
|
|
42
48
|
* `{{#if flag}}content{{/if}}`
|
|
43
49
|
* `{{#if flag}}truthy-content{{else}}falsy-content{{/if}}`
|
|
50
|
+
* `{{#if flag}}truthy-content{{else if flag2}}branch2{{else}}falsy-content{{/if}}`
|
|
44
51
|
*
|
|
45
52
|
* Nested conditionals inside `{{else}}` branches are supported:
|
|
46
53
|
* `{{#if a}}A{{else}}{{#if b}}B{{else}}C{{/if}}{{/if}}`
|
|
47
54
|
*
|
|
55
|
+
* `{{else if}}` chains are normalised into nested `{{#if}}` blocks before
|
|
56
|
+
* resolution, so they work transparently alongside — and can be combined
|
|
57
|
+
* with — traditional nested `{{#if}}` syntax.
|
|
58
|
+
*
|
|
48
59
|
* Behaviour:
|
|
49
60
|
* - When `context[flag]` is truthy: the delimiters are stripped and the
|
|
50
61
|
* content before `{{else}}` (or the entire inner block if no `{{else}}`)
|
|
@@ -309,6 +320,26 @@ interface SuiteConfig {
|
|
|
309
320
|
metaSubdir?: string;
|
|
310
321
|
/** Sub-directory within srcDir that contains content Markdown files. Default: 'content' */
|
|
311
322
|
contentSubdir?: string;
|
|
323
|
+
/**
|
|
324
|
+
* Optional map of suite-level template variables.
|
|
325
|
+
*
|
|
326
|
+
* These form the **second-lowest** layer (layer 2 of 7) in the merge chain
|
|
327
|
+
* used by `buildContext()`:
|
|
328
|
+
*
|
|
329
|
+
* 1. `BuildConfig.variables` — global defaults (lowest priority)
|
|
330
|
+
* 2. `SuiteConfig.variables` ← this field
|
|
331
|
+
* 3. `_shared.yaml` fields — shared metadata
|
|
332
|
+
* 4. Per-persona YAML fields — per-persona metadata
|
|
333
|
+
* 5. Derived fields — version fallback, tools serialisation, etc.
|
|
334
|
+
* 6. Cross-suite agent map — `agent_<slug>` entries
|
|
335
|
+
* 7. Target flags — `target_<name>` booleans (highest priority)
|
|
336
|
+
*
|
|
337
|
+
* Suite variables override any same-named entry in `BuildConfig.variables`,
|
|
338
|
+
* but are themselves overridden by `_shared.yaml` fields and per-persona
|
|
339
|
+
* YAML metadata. Use this field to inject suite-scoped defaults that apply
|
|
340
|
+
* to every persona in the suite without modifying shared YAML files.
|
|
341
|
+
*/
|
|
342
|
+
variables?: Record<string, unknown>;
|
|
312
343
|
}
|
|
313
344
|
/**
|
|
314
345
|
* A single validation outcome returned by a plugin's `onValidate` hook.
|
|
@@ -327,10 +358,12 @@ interface ValidationResult {
|
|
|
327
358
|
* identification.
|
|
328
359
|
*
|
|
329
360
|
* Hook invocation order (per persona):
|
|
330
|
-
* 1. onSuiteInit
|
|
331
|
-
* 2.
|
|
332
|
-
* 3.
|
|
333
|
-
* 4.
|
|
361
|
+
* 1. onSuiteInit — once per suite, before any persona is built
|
|
362
|
+
* 2. onPartials — once per suite, after partials are loaded
|
|
363
|
+
* 3. onBuildContext — per persona, before template rendering
|
|
364
|
+
* 4. onPersonaPartials — per persona, before template rendering (after onBuildContext)
|
|
365
|
+
* 5. onPostRender — per persona, after body rendering
|
|
366
|
+
* 6. onValidate — per persona, during the validation phase
|
|
334
367
|
*/
|
|
335
368
|
interface PersonaBuildPlugin {
|
|
336
369
|
/**
|
|
@@ -347,6 +380,21 @@ interface PersonaBuildPlugin {
|
|
|
347
380
|
* @param sharedMeta Shared metadata merged from `_shared.yaml` (mutate in place if needed)
|
|
348
381
|
*/
|
|
349
382
|
onSuiteInit?(suite: SuiteConfig, sharedMeta: Record<string, unknown>): void;
|
|
383
|
+
/**
|
|
384
|
+
* Called once per suite after partials are loaded from disk (and after any
|
|
385
|
+
* `BuildConfig.partials` inline map has been applied), but before any persona
|
|
386
|
+
* is rendered.
|
|
387
|
+
*
|
|
388
|
+
* Plugins are chained: each plugin receives the accumulated partials map
|
|
389
|
+
* returned by the previous plugin. Return the (possibly mutated or extended)
|
|
390
|
+
* map to pass it to the next plugin.
|
|
391
|
+
*
|
|
392
|
+
* @param partialsMap The current map of partial name → partial content
|
|
393
|
+
* @param suiteName The identifier of the current suite
|
|
394
|
+
* @param suite The suite configuration object
|
|
395
|
+
* @returns Updated partials map (must include all original keys)
|
|
396
|
+
*/
|
|
397
|
+
onPartials?(partialsMap: Record<string, string>, suiteName: string, suite: SuiteConfig): Record<string, string>;
|
|
350
398
|
/**
|
|
351
399
|
* Called for each persona before template rendering.
|
|
352
400
|
*
|
|
@@ -360,6 +408,34 @@ interface PersonaBuildPlugin {
|
|
|
360
408
|
* @returns Updated rendering context (must include all original keys)
|
|
361
409
|
*/
|
|
362
410
|
onBuildContext?(context: Record<string, unknown>, persona: PersonaMetadata, suite: SuiteConfig, target?: TargetType): Record<string, unknown>;
|
|
411
|
+
/**
|
|
412
|
+
* Called for each persona (and target) after `onBuildContext`, before
|
|
413
|
+
* template rendering.
|
|
414
|
+
*
|
|
415
|
+
* Allows plugins to inject or override partials on a per-persona basis.
|
|
416
|
+
* Plugins are chained: each plugin receives the accumulated partials map
|
|
417
|
+
* returned by the previous plugin. Return the (possibly mutated or extended)
|
|
418
|
+
* map to pass it to the next plugin.
|
|
419
|
+
*
|
|
420
|
+
* **Isolation guarantee:** The builder creates a shallow copy of the
|
|
421
|
+
* suite-level partials map before invoking the first plugin in the chain.
|
|
422
|
+
* The `partialsMap` argument you receive is already persona-scoped — changes
|
|
423
|
+
* to it (or to the map you return) are invisible to other personas in the
|
|
424
|
+
* same suite. Do **not** mutate `partialsMap` in place; instead, return a
|
|
425
|
+
* new map (e.g. `{ ...partialsMap, myPartial: '...' }`) so that each plugin
|
|
426
|
+
* in the chain receives an independent copy of the previous plugin's output.
|
|
427
|
+
*
|
|
428
|
+
* @param partialsMap The current persona-scoped map of partial name → content
|
|
429
|
+
* (a shallow copy of the suite-level map, isolated per persona)
|
|
430
|
+
* @param persona Typed metadata for the persona being built
|
|
431
|
+
* @param context The post-`onBuildContext` rendering context; persona
|
|
432
|
+
* metadata and any context keys injected by `onBuildContext`
|
|
433
|
+
* plugins are accessible here
|
|
434
|
+
* @param suite The suite configuration object
|
|
435
|
+
* @param target The current build target (optional)
|
|
436
|
+
* @returns Updated partials map (must include all original keys)
|
|
437
|
+
*/
|
|
438
|
+
onPersonaPartials?(partialsMap: Record<string, string>, persona: PersonaMetadata, context: Record<string, unknown>, suite: SuiteConfig, target?: TargetType): Record<string, string>;
|
|
363
439
|
/**
|
|
364
440
|
* Called for each persona after body rendering.
|
|
365
441
|
*
|
|
@@ -489,8 +565,9 @@ declare function loadContent(mdPath: string): Promise<string>;
|
|
|
489
565
|
* PersonaBuildPlugin. The runner:
|
|
490
566
|
* - Skips plugins that do not implement the requested hook (hook is optional)
|
|
491
567
|
* - Invokes hooks in the order plugins are registered (first-in first-called)
|
|
492
|
-
* - For accumulating hooks (onBuildContext,
|
|
493
|
-
* receives the output of the previous plugin
|
|
568
|
+
* - For accumulating hooks (onBuildContext, onPartials, onPersonaPartials,
|
|
569
|
+
* onPostRender), each plugin receives the output of the previous plugin
|
|
570
|
+
* as its first argument
|
|
494
571
|
* - For collecting hooks (onValidate), results are concatenated into a
|
|
495
572
|
* flat array
|
|
496
573
|
*
|
|
@@ -541,6 +618,44 @@ declare function runBuildContext(plugins: PersonaBuildPlugin[], ctx: Record<stri
|
|
|
541
618
|
* @returns Final output string after all plugins have run
|
|
542
619
|
*/
|
|
543
620
|
declare function runPostRender(plugins: PersonaBuildPlugin[], rendered: string, persona: PersonaMetadata, target: TargetType): string;
|
|
621
|
+
/**
|
|
622
|
+
* Invoke the `onPartials` hook on every registered plugin, accumulating
|
|
623
|
+
* partials map mutations sequentially.
|
|
624
|
+
*
|
|
625
|
+
* Each plugin receives the partials map returned by the previous plugin. If a
|
|
626
|
+
* plugin does not implement `onPartials`, the map passes through unchanged.
|
|
627
|
+
* The final accumulated map is returned.
|
|
628
|
+
*
|
|
629
|
+
* Called once per suite after partials are loaded from disk, before any
|
|
630
|
+
* persona is rendered.
|
|
631
|
+
*
|
|
632
|
+
* @param plugins Ordered list of registered plugins
|
|
633
|
+
* @param partialsMap Initial map of partial name → partial content
|
|
634
|
+
* @param suiteName The identifier of the current suite
|
|
635
|
+
* @param suite The suite configuration object
|
|
636
|
+
* @returns Accumulated partials map after all plugins have run
|
|
637
|
+
*/
|
|
638
|
+
declare function runPartials(plugins: PersonaBuildPlugin[], partialsMap: Record<string, string>, suiteName: string, suite: SuiteConfig): Record<string, string>;
|
|
639
|
+
/**
|
|
640
|
+
* Invoke the `onPersonaPartials` hook on every registered plugin, accumulating
|
|
641
|
+
* partials map mutations sequentially.
|
|
642
|
+
*
|
|
643
|
+
* Each plugin receives the partials map returned by the previous plugin. If a
|
|
644
|
+
* plugin does not implement `onPersonaPartials`, the map passes through
|
|
645
|
+
* unchanged. The final accumulated map is returned.
|
|
646
|
+
*
|
|
647
|
+
* Called for each persona (and target) after `onBuildContext`, before
|
|
648
|
+
* template rendering.
|
|
649
|
+
*
|
|
650
|
+
* @param plugins Ordered list of registered plugins
|
|
651
|
+
* @param partialsMap Initial map of partial name → partial content
|
|
652
|
+
* @param persona Typed metadata for the persona being built
|
|
653
|
+
* @param context The rendering context built by `onBuildContext`
|
|
654
|
+
* @param suite The suite configuration object
|
|
655
|
+
* @param target The current build target (optional)
|
|
656
|
+
* @returns Accumulated partials map after all plugins have run
|
|
657
|
+
*/
|
|
658
|
+
declare function runPersonaPartials(plugins: PersonaBuildPlugin[], partialsMap: Record<string, string>, persona: PersonaMetadata, context: Record<string, unknown>, suite: SuiteConfig, target?: TargetType): Record<string, string>;
|
|
544
659
|
/**
|
|
545
660
|
* Invoke the `onValidate` hook on every registered plugin and collect all
|
|
546
661
|
* returned ValidationResult objects into a single flat array.
|
|
@@ -739,9 +854,19 @@ interface BuildConfig {
|
|
|
739
854
|
*/
|
|
740
855
|
suites: Record<string, SuiteConfig>;
|
|
741
856
|
/**
|
|
742
|
-
* Absolute path to the shared partials directory.
|
|
743
|
-
*
|
|
744
|
-
* partials
|
|
857
|
+
* Absolute path to the shared partials directory.
|
|
858
|
+
*
|
|
859
|
+
* When provided, partials from this directory form the **second** layer in
|
|
860
|
+
* the five-layer partials resolution order:
|
|
861
|
+
*
|
|
862
|
+
* 1. `BuildConfig.partials` — lowest precedence (inline map)
|
|
863
|
+
* 2. `sharedPartialsDir` — overlaid on top of inline partials (this field)
|
|
864
|
+
* 3. Suite-local partials — overlaid on top of shared partials
|
|
865
|
+
* 4. `onPartials` hooks — suite-level plugin-injected partials
|
|
866
|
+
* 5. `onPersonaPartials` — per-persona overrides (highest precedence)
|
|
867
|
+
*
|
|
868
|
+
* Later layers overlay earlier ones; a key present in multiple layers uses
|
|
869
|
+
* the value from the highest-precedence layer.
|
|
745
870
|
*/
|
|
746
871
|
sharedPartialsDir?: string;
|
|
747
872
|
/**
|
|
@@ -788,6 +913,43 @@ interface BuildConfig {
|
|
|
788
913
|
* `TargetDefinition.defaultFrontmatter` are used.
|
|
789
914
|
*/
|
|
790
915
|
frontmatter?: Record<string, string>;
|
|
916
|
+
/**
|
|
917
|
+
* Optional map of global template variables made available to every persona
|
|
918
|
+
* during rendering.
|
|
919
|
+
*
|
|
920
|
+
* These form the **lowest-priority** layer (layer 1 of 7) in the merge chain
|
|
921
|
+
* used by `buildContext()`:
|
|
922
|
+
*
|
|
923
|
+
* 1. `BuildConfig.variables` ← this field (lowest priority)
|
|
924
|
+
* 2. `SuiteConfig.variables` — suite-level overrides
|
|
925
|
+
* 3. `_shared.yaml` fields — shared metadata
|
|
926
|
+
* 4. Per-persona YAML fields — per-persona metadata
|
|
927
|
+
* 5. Derived fields — version fallback, tools serialisation, etc.
|
|
928
|
+
* 6. Cross-suite agent map — `agent_<slug>` entries
|
|
929
|
+
* 7. Target flags — `target_<name>` booleans (highest priority)
|
|
930
|
+
*
|
|
931
|
+
* Any key set here that also appears in a higher-priority layer will be
|
|
932
|
+
* overridden. Use this field for project-wide defaults that individual suites
|
|
933
|
+
* or personas can selectively override via `SuiteConfig.variables` or their
|
|
934
|
+
* own YAML metadata.
|
|
935
|
+
*/
|
|
936
|
+
variables?: Record<string, unknown>;
|
|
937
|
+
/**
|
|
938
|
+
* Optional map of inline partials, keyed by partial name.
|
|
939
|
+
*
|
|
940
|
+
* These form the **lowest** layer in the five-layer partials resolution
|
|
941
|
+
* order:
|
|
942
|
+
*
|
|
943
|
+
* 1. `BuildConfig.partials` — lowest precedence (this field)
|
|
944
|
+
* 2. `sharedPartialsDir` — overlaid on top of inline partials
|
|
945
|
+
* 3. Suite-local partials — overlaid on top of shared partials
|
|
946
|
+
* 4. `onPartials` hooks — suite-level plugin-injected partials
|
|
947
|
+
* 5. `onPersonaPartials` — per-persona overrides (highest precedence)
|
|
948
|
+
*
|
|
949
|
+
* Later layers overlay earlier ones; a key present in multiple layers uses
|
|
950
|
+
* the value from the highest-precedence layer.
|
|
951
|
+
*/
|
|
952
|
+
partials?: Record<string, string>;
|
|
791
953
|
/**
|
|
792
954
|
* Optional target registry to use for this build.
|
|
793
955
|
*
|
|
@@ -909,6 +1071,21 @@ declare function renderFrontmatter(template: string, context: Record<string, unk
|
|
|
909
1071
|
* agent name map, then iterates all suites × targets, calls
|
|
910
1072
|
* buildSuite() for each combination, and returns a BuildSummary.
|
|
911
1073
|
* Respects --check (no writes) and --strict (fail on warnings/errors).
|
|
1074
|
+
*
|
|
1075
|
+
* Template variable injection (7-layer merge order, later layers win):
|
|
1076
|
+
*
|
|
1077
|
+
* 1. BuildConfig.variables — global defaults; available to every suite
|
|
1078
|
+
* 2. SuiteConfig.variables — suite-level overrides
|
|
1079
|
+
* 3. _shared.yaml fields — shared metadata for the suite
|
|
1080
|
+
* 4. Per-persona YAML fields — per-persona metadata
|
|
1081
|
+
* 5. Derived fields — version fallback, tools serialisation, etc.
|
|
1082
|
+
* 6. Cross-suite agent map — agent_<slug> / agent_slug_<slug> entries
|
|
1083
|
+
* 7. Target flags — target_<name> booleans; always highest precedence
|
|
1084
|
+
*
|
|
1085
|
+
* Callers inject global or suite-scoped variables via `BuildConfig.variables`
|
|
1086
|
+
* and `SuiteConfig.variables` respectively. Both fields are forwarded by
|
|
1087
|
+
* buildPersona() to the internal buildContext() function as the two
|
|
1088
|
+
* lowest-priority layers in the merge chain.
|
|
912
1089
|
*/
|
|
913
1090
|
|
|
914
1091
|
/**
|
|
@@ -918,22 +1095,39 @@ declare function renderFrontmatter(template: string, context: Record<string, unk
|
|
|
918
1095
|
* 1. Load sharedMeta + personaMeta (callers supply pre-loaded values)
|
|
919
1096
|
* 2. Build merged context
|
|
920
1097
|
* 3. Run onBuildContext plugin hooks (context accumulation)
|
|
921
|
-
* 4.
|
|
922
|
-
* 5.
|
|
923
|
-
* 6.
|
|
924
|
-
* 7.
|
|
925
|
-
* 8.
|
|
926
|
-
* 9. Run
|
|
927
|
-
* 10.
|
|
928
|
-
* 11.
|
|
929
|
-
* 12.
|
|
1098
|
+
* 4. Run onPersonaPartials plugin hooks (shallow-copy partials map, persona-scoped)
|
|
1099
|
+
* 5. Render frontmatter template → render frontmatter
|
|
1100
|
+
* 6. Load content template
|
|
1101
|
+
* 7. Render body: partials → conditionals → variables → post-process
|
|
1102
|
+
* 8. Assemble final output (frontmatter + body)
|
|
1103
|
+
* 9. Run onPostRender plugin hooks (output chain)
|
|
1104
|
+
* 10. Run onValidate plugin hooks (validation collection)
|
|
1105
|
+
* 11. Determine output file path
|
|
1106
|
+
* 12. Write output file (unless check mode)
|
|
1107
|
+
* 13. Return BuildResult
|
|
930
1108
|
*
|
|
931
1109
|
* @param personaYamlPath Absolute path to the persona YAML source file
|
|
932
1110
|
* @param suiteName Identifier for the suite this persona belongs to
|
|
933
|
-
* @param suiteConfig Suite configuration object
|
|
1111
|
+
* @param suiteConfig Suite configuration object. `suiteConfig.variables`
|
|
1112
|
+
* is forwarded to `buildContext()` as the
|
|
1113
|
+
* `suiteVariables` layer (layer 2 of 7) — these values
|
|
1114
|
+
* override any `config.variables` but are themselves
|
|
1115
|
+
* overridden by `_shared.yaml` and per-persona fields.
|
|
934
1116
|
* @param sharedMeta Pre-loaded `_shared.yaml` contents
|
|
935
|
-
* @param partialsMap Pre-loaded partials map (shared + suite-local merged)
|
|
936
|
-
*
|
|
1117
|
+
* @param partialsMap Pre-loaded partials map (shared + suite-local merged).
|
|
1118
|
+
* This map is **not** passed directly to rendering.
|
|
1119
|
+
* Instead, a shallow copy (`{ ...partialsMap }`) is
|
|
1120
|
+
* created at step 3b and passed to the `onPersonaPartials`
|
|
1121
|
+
* plugin hooks — the hooks' accumulated output map is what
|
|
1122
|
+
* reaches `resolvePartials`, not `partialsMap` itself.
|
|
1123
|
+
* This ensures that persona-level overrides or injections
|
|
1124
|
+
* do not leak back into the caller's reference or into
|
|
1125
|
+
* subsequent personas in the same suite.
|
|
1126
|
+
* @param config Top-level BuildConfig. `config.variables` is
|
|
1127
|
+
* forwarded to `buildContext()` as the
|
|
1128
|
+
* `configVariables` layer (layer 1 of 7, lowest
|
|
1129
|
+
* priority) — global defaults available to every
|
|
1130
|
+
* persona across all suites.
|
|
937
1131
|
* @param plugins Registered plugins
|
|
938
1132
|
* @param target Target output format
|
|
939
1133
|
* @param agentMap Pre-built cross-suite agent name map
|
|
@@ -952,10 +1146,11 @@ declare function buildPersona(personaYamlPath: string, suiteName: string, suiteC
|
|
|
952
1146
|
*
|
|
953
1147
|
* Pipeline:
|
|
954
1148
|
* 1. Load `_shared.yaml` for the suite
|
|
955
|
-
* 2. Load merged partials (shared → suite-local)
|
|
1149
|
+
* 2. Load merged partials (config.partials → shared → suite-local)
|
|
956
1150
|
* 3. Run `onSuiteInit` on all plugins
|
|
957
|
-
* 4.
|
|
958
|
-
* 5.
|
|
1151
|
+
* 4. Run `onPartials` on all plugins (highest priority: may override any file-based partial)
|
|
1152
|
+
* 5. Discover all persona YAML files
|
|
1153
|
+
* 6. Call `buildPersona()` for each
|
|
959
1154
|
*
|
|
960
1155
|
* @param suiteName Identifier for this suite
|
|
961
1156
|
* @param suiteConfig Suite configuration
|
|
@@ -1113,4 +1308,4 @@ declare const defaultRegistry: TargetRegistry;
|
|
|
1113
1308
|
|
|
1114
1309
|
declare const VERSION: string;
|
|
1115
1310
|
|
|
1116
|
-
export { type BuildConfig, type BuildResult, type BuildSummary, DEFAULT_FRONTMATTER_CLAUDE_CODE, DEFAULT_FRONTMATTER_DEEP_AGENTS, DEFAULT_FRONTMATTER_VSCODE, type PersonaBuildPlugin, type PersonaMetadata, type SuiteConfig, TARGET_CLAUDE_CODE, TARGET_DEEP_AGENTS, TARGET_VSCODE, type TargetDefinition, TargetRegistry, type TargetType, VERSION, type ValidationResult, build, buildPersona, buildSuite, collapseBlankLines, defaultRegistry, discoverPersonaYamls, ensureBlankLineBeforeHeadings, escapeRegExp, loadContent, loadMetadata, loadPartials, normalizeNewlines, renderFrontmatter, resolveConditionals, resolveFrontmatterTemplate, resolvePartials, resolveVariables, runBuildContext, runPostRender, runSuiteInit, runValidate, serializeTools, serializeToolsList, validateFileName, validateStrictMarkers };
|
|
1311
|
+
export { type BuildConfig, type BuildResult, type BuildSummary, DEFAULT_FRONTMATTER_CLAUDE_CODE, DEFAULT_FRONTMATTER_DEEP_AGENTS, DEFAULT_FRONTMATTER_VSCODE, type PersonaBuildPlugin, type PersonaMetadata, type SuiteConfig, TARGET_CLAUDE_CODE, TARGET_DEEP_AGENTS, TARGET_VSCODE, type TargetDefinition, TargetRegistry, type TargetType, VERSION, type ValidationResult, build, buildPersona, buildSuite, collapseBlankLines, defaultRegistry, discoverPersonaYamls, ensureBlankLineBeforeHeadings, escapeRegExp, loadContent, loadMetadata, loadPartials, normalizeNewlines, renderFrontmatter, resolveConditionals, resolveFrontmatterTemplate, resolvePartials, resolveVariables, runBuildContext, runPartials, runPersonaPartials, runPostRender, runSuiteInit, runValidate, serializeTools, serializeToolsList, validateFileName, validateStrictMarkers };
|
package/dist/index.js
CHANGED
|
@@ -19,10 +19,30 @@ function resolvePartials(text, partialsMap, depth = 0) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// src/engine/conditionals.ts
|
|
22
|
+
var NO_NESTED_IF = String.raw`(?:(?!\{\{#if\b)[\s\S])*?`;
|
|
23
|
+
var ELSE_IF_PATTERN = new RegExp(
|
|
24
|
+
String.raw`\{\{else if (\w+)\}\}(${NO_NESTED_IF})\{\{\/if\}\}`,
|
|
25
|
+
"g"
|
|
26
|
+
);
|
|
27
|
+
function resolveElseIf(text) {
|
|
28
|
+
if (!text.includes("{{else if ")) {
|
|
29
|
+
return text;
|
|
30
|
+
}
|
|
31
|
+
let result = text;
|
|
32
|
+
let prev;
|
|
33
|
+
do {
|
|
34
|
+
prev = result;
|
|
35
|
+
result = result.replace(
|
|
36
|
+
ELSE_IF_PATTERN,
|
|
37
|
+
(_match, flag, content) => `{{else}}{{#if ${flag}}}${content}{{/if}}{{/if}}`
|
|
38
|
+
);
|
|
39
|
+
} while (result !== prev);
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
22
42
|
function resolveConditionals(text, context) {
|
|
23
|
-
const
|
|
43
|
+
const normalized = resolveElseIf(text);
|
|
24
44
|
const pattern = new RegExp(
|
|
25
|
-
String.raw`\n*\{\{#if (\w+)\}\}(${
|
|
45
|
+
String.raw`\n*\{\{#if (\w+)\}\}(${NO_NESTED_IF})` + String.raw`(?:\{\{else\}\}(${NO_NESTED_IF}))?\{\{\/if\}\}\n*`,
|
|
26
46
|
"g"
|
|
27
47
|
);
|
|
28
48
|
const resolve = (_match, flag, inner, elseInner) => {
|
|
@@ -34,7 +54,7 @@ function resolveConditionals(text, context) {
|
|
|
34
54
|
}
|
|
35
55
|
return "\n";
|
|
36
56
|
};
|
|
37
|
-
let result =
|
|
57
|
+
let result = normalized;
|
|
38
58
|
let prev;
|
|
39
59
|
do {
|
|
40
60
|
prev = result;
|
|
@@ -129,7 +149,7 @@ function runBuildContext(plugins, ctx, persona, suite, target) {
|
|
|
129
149
|
let accumulated = ctx;
|
|
130
150
|
for (const plugin of plugins) {
|
|
131
151
|
if (typeof plugin.onBuildContext === "function") {
|
|
132
|
-
accumulated = plugin.onBuildContext(accumulated, persona, suite, target);
|
|
152
|
+
accumulated = plugin.onBuildContext(accumulated, persona, suite, target) ?? accumulated;
|
|
133
153
|
}
|
|
134
154
|
}
|
|
135
155
|
return accumulated;
|
|
@@ -138,11 +158,29 @@ function runPostRender(plugins, rendered, persona, target) {
|
|
|
138
158
|
let output = rendered;
|
|
139
159
|
for (const plugin of plugins) {
|
|
140
160
|
if (typeof plugin.onPostRender === "function") {
|
|
141
|
-
output = plugin.onPostRender(output, persona, target);
|
|
161
|
+
output = plugin.onPostRender(output, persona, target) ?? output;
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
164
|
return output;
|
|
145
165
|
}
|
|
166
|
+
function runPartials(plugins, partialsMap, suiteName, suite) {
|
|
167
|
+
let accumulated = partialsMap;
|
|
168
|
+
for (const plugin of plugins) {
|
|
169
|
+
if (typeof plugin.onPartials === "function") {
|
|
170
|
+
accumulated = plugin.onPartials(accumulated, suiteName, suite) ?? accumulated;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return accumulated;
|
|
174
|
+
}
|
|
175
|
+
function runPersonaPartials(plugins, partialsMap, persona, context, suite, target) {
|
|
176
|
+
let accumulated = partialsMap;
|
|
177
|
+
for (const plugin of plugins) {
|
|
178
|
+
if (typeof plugin.onPersonaPartials === "function") {
|
|
179
|
+
accumulated = plugin.onPersonaPartials(accumulated, persona, context, suite, target) ?? accumulated;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return accumulated;
|
|
183
|
+
}
|
|
146
184
|
function runValidate(plugins, persona, suite, target) {
|
|
147
185
|
const results = [];
|
|
148
186
|
for (const plugin of plugins) {
|
|
@@ -365,9 +403,20 @@ async function buildAgentNameMap(config) {
|
|
|
365
403
|
}
|
|
366
404
|
return agentMap;
|
|
367
405
|
}
|
|
368
|
-
function buildContext(
|
|
406
|
+
function buildContext(options) {
|
|
407
|
+
const {
|
|
408
|
+
personaMeta,
|
|
409
|
+
sharedMeta,
|
|
410
|
+
agentMap = {},
|
|
411
|
+
target,
|
|
412
|
+
registry,
|
|
413
|
+
configVariables,
|
|
414
|
+
suiteVariables
|
|
415
|
+
} = options;
|
|
369
416
|
const version = typeof personaMeta["version"] === "string" ? personaMeta["version"] : typeof sharedMeta["default_version"] === "string" ? sharedMeta["default_version"] : "0.0.0";
|
|
370
417
|
const merged = {
|
|
418
|
+
...configVariables ?? {},
|
|
419
|
+
...suiteVariables ?? {},
|
|
371
420
|
...sharedMeta,
|
|
372
421
|
...personaMeta,
|
|
373
422
|
version
|
|
@@ -422,16 +471,32 @@ function buildContext(personaMeta, sharedMeta, agentMap = {}, target, registry)
|
|
|
422
471
|
}
|
|
423
472
|
async function buildPersona(personaYamlPath, suiteName, suiteConfig, sharedMeta, partialsMap, config, plugins, target, agentMap = {}, registry = defaultRegistry) {
|
|
424
473
|
const personaMeta = await loadPersonaYaml(personaYamlPath);
|
|
425
|
-
let context = buildContext(
|
|
474
|
+
let context = buildContext({
|
|
475
|
+
personaMeta,
|
|
476
|
+
sharedMeta,
|
|
477
|
+
agentMap,
|
|
478
|
+
target,
|
|
479
|
+
registry,
|
|
480
|
+
configVariables: config.variables,
|
|
481
|
+
suiteVariables: suiteConfig.variables
|
|
482
|
+
});
|
|
426
483
|
const personaMetaTyped = personaMeta;
|
|
427
484
|
context = runBuildContext(plugins, context, personaMetaTyped, suiteConfig, target);
|
|
485
|
+
const personaPartialsMap = runPersonaPartials(
|
|
486
|
+
plugins,
|
|
487
|
+
{ ...partialsMap },
|
|
488
|
+
personaMetaTyped,
|
|
489
|
+
context,
|
|
490
|
+
suiteConfig,
|
|
491
|
+
target
|
|
492
|
+
);
|
|
428
493
|
const fmTemplate = resolveFrontmatterTemplate(target, plugins, config.frontmatter, registry);
|
|
429
494
|
const contentBasename = path4.basename(personaYamlPath, ".yaml") + ".md";
|
|
430
495
|
const frontmatter = renderFrontmatter(fmTemplate, context, contentBasename);
|
|
431
496
|
const contentSubdir = suiteConfig.contentSubdir ?? "content";
|
|
432
497
|
const contentPath = path4.join(suiteConfig.srcDir, contentSubdir, contentBasename);
|
|
433
498
|
const bodyTemplate = normalizeNewlines(await readFile(contentPath, "utf8"));
|
|
434
|
-
let body = resolvePartials(bodyTemplate,
|
|
499
|
+
let body = resolvePartials(bodyTemplate, personaPartialsMap);
|
|
435
500
|
body = resolveConditionals(body, context);
|
|
436
501
|
body = resolveVariables(body, context, contentBasename);
|
|
437
502
|
body = collapseBlankLines(body);
|
|
@@ -469,7 +534,7 @@ async function buildSuite(suiteName, suiteConfig, config, plugins, target, agent
|
|
|
469
534
|
const metaSubdir = suiteConfig.metaSubdir ?? "meta";
|
|
470
535
|
const sharedYamlPath = path4.join(suiteConfig.srcDir, metaSubdir, "_shared.yaml");
|
|
471
536
|
const sharedMeta = await loadRawYaml(sharedYamlPath);
|
|
472
|
-
let partialsMap = {};
|
|
537
|
+
let partialsMap = { ...config.partials ?? {} };
|
|
473
538
|
if (config.sharedPartialsDir && existsSync(config.sharedPartialsDir)) {
|
|
474
539
|
partialsMap = { ...partialsMap, ...await loadPartials(config.sharedPartialsDir) };
|
|
475
540
|
}
|
|
@@ -479,6 +544,7 @@ async function buildSuite(suiteName, suiteConfig, config, plugins, target, agent
|
|
|
479
544
|
partialsMap = { ...partialsMap, ...await loadPartials(suitePartialsDir) };
|
|
480
545
|
}
|
|
481
546
|
runSuiteInit(plugins, suiteConfig, sharedMeta);
|
|
547
|
+
partialsMap = runPartials(plugins, partialsMap, suiteName, suiteConfig);
|
|
482
548
|
const personaYamlPaths = await discoverSuitePersonaYamls(suiteConfig);
|
|
483
549
|
const results = [];
|
|
484
550
|
for (const yamlPath of personaYamlPaths) {
|
|
@@ -594,6 +660,6 @@ function escapeRegExp(str) {
|
|
|
594
660
|
var _pkgRequire = createRequire(import.meta.url);
|
|
595
661
|
var VERSION = _pkgRequire("../package.json").version;
|
|
596
662
|
|
|
597
|
-
export { DEFAULT_FRONTMATTER_CLAUDE_CODE, DEFAULT_FRONTMATTER_DEEP_AGENTS, DEFAULT_FRONTMATTER_VSCODE, TARGET_CLAUDE_CODE, TARGET_DEEP_AGENTS, TARGET_VSCODE, TargetRegistry, VERSION, build, buildPersona, buildSuite, collapseBlankLines, defaultRegistry, discoverPersonaYamls, ensureBlankLineBeforeHeadings, escapeRegExp, loadContent, loadMetadata, loadPartials, normalizeNewlines, renderFrontmatter, resolveConditionals, resolveFrontmatterTemplate, resolvePartials, resolveVariables, runBuildContext, runPostRender, runSuiteInit, runValidate, serializeTools, serializeToolsList, validateFileName, validateStrictMarkers };
|
|
663
|
+
export { DEFAULT_FRONTMATTER_CLAUDE_CODE, DEFAULT_FRONTMATTER_DEEP_AGENTS, DEFAULT_FRONTMATTER_VSCODE, TARGET_CLAUDE_CODE, TARGET_DEEP_AGENTS, TARGET_VSCODE, TargetRegistry, VERSION, build, buildPersona, buildSuite, collapseBlankLines, defaultRegistry, discoverPersonaYamls, ensureBlankLineBeforeHeadings, escapeRegExp, loadContent, loadMetadata, loadPartials, normalizeNewlines, renderFrontmatter, resolveConditionals, resolveFrontmatterTemplate, resolvePartials, resolveVariables, runBuildContext, runPartials, runPersonaPartials, runPostRender, runSuiteInit, runValidate, serializeTools, serializeToolsList, validateFileName, validateStrictMarkers };
|
|
598
664
|
//# sourceMappingURL=index.js.map
|
|
599
665
|
//# sourceMappingURL=index.js.map
|