@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 +1 -1
- package/dist/src/agent-runner.js +97 -42
- package/package.json +2 -2
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-
|
|
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",
|
package/dist/src/agent-runner.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
12
|
-
|
|
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 (
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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",
|