@cccarv82/freya 1.0.18 → 1.0.19
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/cli/web.js +55 -3
- package/package.json +1 -1
package/cli/web.js
CHANGED
|
@@ -182,6 +182,52 @@ function postTeamsWebhook(url, text) {
|
|
|
182
182
|
return postJson(url, { text });
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
function escapeJsonControlChars(jsonText) {
|
|
186
|
+
// Replace unescaped control chars inside JSON string literals with safe escapes.
|
|
187
|
+
// Handles Copilot outputs where newlines/tabs leak into string values.
|
|
188
|
+
const out = [];
|
|
189
|
+
let inString = false;
|
|
190
|
+
let esc = false;
|
|
191
|
+
|
|
192
|
+
for (let i = 0; i < jsonText.length; i++) {
|
|
193
|
+
const ch = jsonText[i];
|
|
194
|
+
const code = ch.charCodeAt(0);
|
|
195
|
+
|
|
196
|
+
if (esc) {
|
|
197
|
+
out.push(ch);
|
|
198
|
+
esc = false;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (ch === '\\') {
|
|
203
|
+
out.push(ch);
|
|
204
|
+
esc = true;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (ch === '"') {
|
|
209
|
+
out.push(ch);
|
|
210
|
+
inString = !inString;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (inString) {
|
|
215
|
+
if (code === 10) { out.push('\\n'); continue; }
|
|
216
|
+
if (code === 13) { out.push('\\r'); continue; }
|
|
217
|
+
if (code === 9) { out.push('\\t'); continue; }
|
|
218
|
+
if (code >= 0 && code < 32) {
|
|
219
|
+
const hex = code.toString(16).padStart(2, '0');
|
|
220
|
+
out.push('\\u00' + hex);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
out.push(ch);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return out.join('');
|
|
229
|
+
}
|
|
230
|
+
|
|
185
231
|
async function publishRobust(webhookUrl, text, opts = {}) {
|
|
186
232
|
const u = new URL(webhookUrl);
|
|
187
233
|
const isDiscord = u.hostname.includes('discord.com') || u.hostname.includes('discordapp.com');
|
|
@@ -353,9 +399,7 @@ function buildHtml(safeDefault) {
|
|
|
353
399
|
<div class="sideGroup">
|
|
354
400
|
<div class="sideTitle">Workspace</div>
|
|
355
401
|
<button class="btn sideBtn" onclick="pickDir()">Select workspace…</button>
|
|
356
|
-
<button class="btn primary sideBtn" onclick="doInit()">Init workspace</button>
|
|
357
402
|
<button class="btn sideBtn" onclick="doUpdate()">Update (preserve data/logs)</button>
|
|
358
|
-
<button class="btn sideBtn" onclick="doHealth()">Health</button>
|
|
359
403
|
<button class="btn sideBtn" onclick="doMigrate()">Migrate</button>
|
|
360
404
|
<div style="height:10px"></div>
|
|
361
405
|
<div class="help">Dica: se você já tem uma workspace antiga, use Update. Por padrão, data/logs não são sobrescritos.</div>
|
|
@@ -836,7 +880,15 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
836
880
|
try {
|
|
837
881
|
plan = JSON.parse(jsonText);
|
|
838
882
|
} catch (e) {
|
|
839
|
-
|
|
883
|
+
try {
|
|
884
|
+
plan = JSON.parse(escapeJsonControlChars(jsonText));
|
|
885
|
+
} catch (e2) {
|
|
886
|
+
return safeJson(res, 400, {
|
|
887
|
+
error: 'Plan is not valid JSON',
|
|
888
|
+
details: (e2 && e2.message) ? e2.message : (e && e.message ? e.message : String(e)),
|
|
889
|
+
hint: 'O planner gerou caracteres de controle dentro de strings (ex.: quebra de linha). Reexecute o planner ou escape quebras de linha como \\n.'
|
|
890
|
+
});
|
|
891
|
+
}
|
|
840
892
|
}
|
|
841
893
|
|
|
842
894
|
const actions = Array.isArray(plan.actions) ? plan.actions : [];
|