@forwardimpact/pathway 0.10.0 → 0.11.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/pathway",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Career progression web app and CLI for exploring roles and generating agents",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -11,6 +11,10 @@
11
11
  import Mustache from "mustache";
12
12
 
13
13
  import { trimValue, trimRequired, trimFields } from "../shared.js";
14
+ import {
15
+ flattenToLine,
16
+ preprocessArrayFrontmatter,
17
+ } from "../template-preprocess.js";
14
18
 
15
19
  /**
16
20
  * @typedef {Object} WorkingStyleEntry
@@ -49,8 +53,14 @@ import { trimValue, trimRequired, trimFields } from "../shared.js";
49
53
  * @returns {Object} Data object ready for Mustache template
50
54
  */
51
55
  function prepareAgentProfileData({ frontmatter, bodyData }) {
52
- // Trim array fields using shared helpers
53
- const handoffs = trimFields(frontmatter.handoffs, { prompt: "required" });
56
+ // Preprocess handoffs - flatten prompt field for front matter compatibility
57
+ const preprocessedHandoffs = preprocessArrayFrontmatter(
58
+ frontmatter.handoffs,
59
+ ["prompt"],
60
+ );
61
+ // Then trim as before
62
+ const handoffs = trimFields(preprocessedHandoffs, { prompt: "required" });
63
+
54
64
  const constraints = (bodyData.constraints || []).map((c) => trimRequired(c));
55
65
  const skillIndex = trimFields(bodyData.skillIndex, {
56
66
  name: "required",
@@ -75,9 +85,9 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
75
85
  }));
76
86
 
77
87
  return {
78
- // Frontmatter
88
+ // Frontmatter - flatten description for single-line front matter
79
89
  name: frontmatter.name,
80
- description: trimRequired(frontmatter.description),
90
+ description: flattenToLine(frontmatter.description),
81
91
  infer: frontmatter.infer,
82
92
  handoffs,
83
93
 
@@ -11,6 +11,7 @@
11
11
  import Mustache from "mustache";
12
12
 
13
13
  import { trimValue, splitLines, trimFields } from "../shared.js";
14
+ import { flattenToLine } from "../template-preprocess.js";
14
15
 
15
16
  /**
16
17
  * Prepare agent skill data for template rendering
@@ -40,17 +41,25 @@ function prepareAgentSkillData({
40
41
  ready: "array",
41
42
  });
42
43
 
44
+ // Flatten multi-line strings to single line for front matter compatibility
45
+ const description = flattenToLine(frontmatter.description);
46
+ const useWhen = flattenToLine(frontmatter.useWhen);
47
+
48
+ // Keep line arrays for body rendering
43
49
  const descriptionLines = splitLines(frontmatter.description);
44
- const useWhenLines = splitLines(frontmatter.useWhen);
50
+
45
51
  const trimmedReference = trimValue(reference) || "";
46
52
  const tools = toolReferences || [];
47
53
 
48
54
  return {
49
55
  name: frontmatter.name,
56
+ // Single-line versions for front matter
57
+ description,
58
+ hasDescription: !!description,
59
+ useWhen,
60
+ hasUseWhen: !!useWhen,
61
+ // Line arrays for body content
50
62
  descriptionLines,
51
- hasDescription: descriptionLines.length > 0,
52
- useWhenLines,
53
- hasUseWhen: useWhenLines.length > 0,
54
63
  title,
55
64
  stages: processedStages,
56
65
  hasStages: processedStages.length > 0,
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Template Preprocessing Utilities
3
+ *
4
+ * Functions to prepare template data for front matter compatibility.
5
+ * Ensures all front matter values are single-line strings for maximum
6
+ * compatibility with coding agents that have limited YAML parsing.
7
+ */
8
+
9
+ /**
10
+ * Flatten a multi-line string into a single line
11
+ * Replaces newlines with spaces and collapses multiple spaces.
12
+ * @param {string|null|undefined} value - Value to flatten
13
+ * @returns {string} Single-line string (empty string if no value)
14
+ */
15
+ export function flattenToLine(value) {
16
+ if (value == null) return "";
17
+ return value
18
+ .replace(/\s*\n\s*/g, " ") // Replace newlines (with surrounding whitespace) with single space
19
+ .replace(/\s+/g, " ") // Collapse multiple spaces
20
+ .trim();
21
+ }
22
+
23
+ /**
24
+ * Join an array of strings into a single line
25
+ * @param {string[]|null|undefined} lines - Array of lines to join
26
+ * @param {string} separator - Separator between lines (default: single space)
27
+ * @returns {string} Single-line string
28
+ */
29
+ export function joinLines(lines, separator = " ") {
30
+ if (!lines || !Array.isArray(lines)) return "";
31
+ return lines.map((line) => line.trim()).join(separator);
32
+ }
33
+
34
+ /**
35
+ * Preprocess an object's string fields for front matter
36
+ * Flattens specified fields to single-line strings.
37
+ * @param {Object} obj - Object to preprocess
38
+ * @param {string[]} fields - Field names to flatten
39
+ * @returns {Object} New object with flattened fields
40
+ */
41
+ export function preprocessFrontmatter(obj, fields) {
42
+ const result = { ...obj };
43
+ for (const field of fields) {
44
+ if (result[field] != null) {
45
+ result[field] = flattenToLine(result[field]);
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+
51
+ /**
52
+ * Preprocess an array of objects, flattening specified fields in each
53
+ * @param {Array<Object>|null|undefined} array - Array to preprocess
54
+ * @param {string[]} fields - Field names to flatten in each object
55
+ * @returns {Array<Object>} Array with preprocessed objects
56
+ */
57
+ export function preprocessArrayFrontmatter(array, fields) {
58
+ if (!array) return [];
59
+ return array.map((item) => preprocessFrontmatter(item, fields));
60
+ }
@@ -1,10 +1,6 @@
1
1
  ---
2
2
  name: {{name}}
3
- description: |
4
- {{#descriptionLines}}{{{.}}} {{/descriptionLines}}
5
- {{#hasUseWhen}}
6
- Use When: {{#useWhenLines}}{{{.}}} {{/useWhenLines}}
7
- {{/hasUseWhen}}
3
+ description: {{{description}}}{{#hasUseWhen}} Use When: {{{useWhen}}}{{/hasUseWhen}}
8
4
  ---
9
5
 
10
6
  # {{{title}}}