@contentful/experience-design-system-generation 2.26.7-dev-build-ccb2aff.0 → 2.26.7-dev-build-6f3b072.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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-generation",
3
- "version": "2.26.7-dev-build-ccb2aff.0",
3
+ "version": "2.26.7-dev-build-6f3b072.0",
4
4
  "description": "Agent-invocation and skill-prompt engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,24 +1,107 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  export { AGENT_NAMES, DEFAULT_AGENT_NAME, isAgentName } from './agent-names.js';
3
3
  const VALID_SELECT_TOOL_NAMES = new Set(['select_component', 'reject_component']);
4
- export function parseSelectToolCallLines(stdout) {
5
- const calls = [];
4
+ /**
5
+ * Scans one line for the complete JSON objects it contains.
6
+ *
7
+ * The agents are asked for one object per line and mostly comply, but a line
8
+ * that carries anything after a valid object used to lose the whole tool call:
9
+ * `JSON.parse` is all-or-nothing, so a single stray character discarded a
10
+ * fully-formed classification. Scanning for balanced objects and parsing each
11
+ * one keeps the call and reports the leftovers instead.
12
+ *
13
+ * Every candidate still goes through `JSON.parse`, so nothing is reconstructed
14
+ * or guessed — an object that is genuinely malformed is still rejected.
15
+ */
16
+ function scanJsonObjects(line) {
17
+ const objects = [];
18
+ let i = 0;
19
+ while (i < line.length) {
20
+ while (i < line.length && /\s/.test(line[i]))
21
+ i++;
22
+ if (i >= line.length)
23
+ break;
24
+ if (line[i] !== '{')
25
+ return { objects, trailing: line.slice(i), malformed: objects.length === 0 };
26
+ // Walk to the matching brace, ignoring braces inside string literals so a
27
+ // description such as "renders `<Text>{title}</Text>`" cannot end the
28
+ // object early.
29
+ let depth = 0;
30
+ let inString = false;
31
+ let escaped = false;
32
+ let end = -1;
33
+ for (let j = i; j < line.length; j++) {
34
+ const ch = line[j];
35
+ if (escaped) {
36
+ escaped = false;
37
+ continue;
38
+ }
39
+ if (ch === '\\') {
40
+ if (inString)
41
+ escaped = true;
42
+ continue;
43
+ }
44
+ if (ch === '"') {
45
+ inString = !inString;
46
+ continue;
47
+ }
48
+ if (inString)
49
+ continue;
50
+ if (ch === '{')
51
+ depth++;
52
+ else if (ch === '}') {
53
+ depth--;
54
+ if (depth === 0) {
55
+ end = j;
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ if (end === -1)
61
+ return { objects, trailing: '', malformed: true };
62
+ let parsed;
63
+ try {
64
+ parsed = JSON.parse(line.slice(i, end + 1));
65
+ }
66
+ catch {
67
+ return { objects, trailing: '', malformed: true };
68
+ }
69
+ if (typeof parsed === 'object' && parsed !== null)
70
+ objects.push(parsed);
71
+ i = end + 1;
72
+ }
73
+ return { objects, trailing: '', malformed: false };
74
+ }
75
+ /**
76
+ * Reads an agent's stdout into the tool-call objects it carries. Lines that do
77
+ * not start with `{` are the agent's prose and are skipped silently, as before.
78
+ */
79
+ function readToolCallObjects(stdout) {
80
+ const objects = [];
6
81
  const warnings = [];
7
82
  for (const raw of stdout.split('\n')) {
8
83
  const line = raw.trim();
9
84
  if (!line.startsWith('{'))
10
85
  continue;
11
- let obj;
12
- try {
13
- obj = JSON.parse(line);
14
- }
15
- catch {
86
+ const { objects: found, trailing, malformed } = scanJsonObjects(line);
87
+ if (malformed) {
16
88
  warnings.push(`unparseable line: ${line.slice(0, 120)}`);
17
89
  continue;
18
90
  }
19
- if (typeof obj !== 'object' || obj === null || !('tool' in obj))
20
- continue;
21
- const rec = obj;
91
+ if (trailing.trim()) {
92
+ warnings.push(`ignored trailing content after JSON: ${trailing.trim().slice(0, 120)}`);
93
+ }
94
+ for (const obj of found) {
95
+ if ('tool' in obj)
96
+ objects.push(obj);
97
+ }
98
+ }
99
+ return { objects, warnings };
100
+ }
101
+ export function parseSelectToolCallLines(stdout) {
102
+ const calls = [];
103
+ const { objects, warnings } = readToolCallObjects(stdout);
104
+ for (const rec of objects) {
22
105
  if (!VALID_SELECT_TOOL_NAMES.has(rec.tool))
23
106
  continue;
24
107
  if (typeof rec.name !== 'string' || !rec.name) {
@@ -49,22 +132,8 @@ const VALID_CDF_TYPES = new Set(['string', 'richtext', 'media', 'enum', 'token',
49
132
  const VALID_CATEGORIES = new Set(['content', 'design', 'state']);
50
133
  export function parseToolCallLines(stdout) {
51
134
  const calls = [];
52
- const warnings = [];
53
- for (const raw of stdout.split('\n')) {
54
- const line = raw.trim();
55
- if (!line.startsWith('{'))
56
- continue;
57
- let obj;
58
- try {
59
- obj = JSON.parse(line);
60
- }
61
- catch {
62
- warnings.push(`unparseable line: ${line.slice(0, 120)}`);
63
- continue;
64
- }
65
- if (typeof obj !== 'object' || obj === null || !('tool' in obj))
66
- continue;
67
- const rec = obj;
135
+ const { objects, warnings } = readToolCallObjects(stdout);
136
+ for (const rec of objects) {
68
137
  if (!VALID_TOOL_NAMES.has(rec.tool)) {
69
138
  warnings.push(`unknown tool: ${String(rec.tool)}`);
70
139
  continue;
@@ -155,22 +224,8 @@ export function parseToolCallLines(stdout) {
155
224
  }
156
225
  export function parseTokenToolCallLines(stdout) {
157
226
  const calls = [];
158
- const warnings = [];
159
- for (const raw of stdout.split('\n')) {
160
- const line = raw.trim();
161
- if (!line.startsWith('{'))
162
- continue;
163
- let obj;
164
- try {
165
- obj = JSON.parse(line);
166
- }
167
- catch {
168
- warnings.push(`unparseable line: ${line.slice(0, 120)}`);
169
- continue;
170
- }
171
- if (typeof obj !== 'object' || obj === null || !('tool' in obj))
172
- continue;
173
- const rec = obj;
227
+ const { objects, warnings } = readToolCallObjects(stdout);
228
+ for (const rec of objects) {
174
229
  if (!VALID_TOKEN_TOOL_NAMES.has(rec.tool))
175
230
  continue; // not a token call — skip silently
176
231
  if (rec.tool === 'set_token') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-generation",
3
- "version": "2.26.7-dev-build-ccb2aff.0",
3
+ "version": "2.26.7-dev-build-6f3b072.0",
4
4
  "description": "Agent-invocation and skill-prompt engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  "skills/"
23
23
  ],
24
24
  "dependencies": {
25
- "@contentful/experience-design-system-types": "2.26.7-dev-build-ccb2aff.0"
25
+ "@contentful/experience-design-system-types": "2.26.7-dev-build-6f3b072.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@tsconfig/node24": "^24.0.4",