@cccarv82/freya 1.0.19 → 1.0.21

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.
Files changed (2) hide show
  1. package/cli/web.js +32 -11
  2. package/package.json +1 -1
package/cli/web.js CHANGED
@@ -399,10 +399,11 @@ function buildHtml(safeDefault) {
399
399
  <div class="sideGroup">
400
400
  <div class="sideTitle">Workspace</div>
401
401
  <button class="btn sideBtn" onclick="pickDir()">Select workspace…</button>
402
- <button class="btn sideBtn" onclick="doUpdate()">Update (preserve data/logs)</button>
403
- <button class="btn sideBtn" onclick="doMigrate()">Migrate</button>
402
+ <button class="btn sideBtn" onclick="doUpdate()">Sync workspace</button>
403
+ <button class="btn sideBtn" onclick="doMigrate()">Migrate data</button>
404
404
  <div style="height:10px"></div>
405
- <div class="help">Dica: se você tem uma workspace antiga, use Update. Por padrão, data/logs não são sobrescritos.</div>
405
+ <div class="help"><b>Sync workspace</b>: atualiza scripts/templates/agents na pasta <code>freya</code> sem sobrescrever <code>data/</code> e <code>logs/</code>.</div>
406
+ <div class="help"><b>Migrate data</b>: ajusta formatos/schemaVersion quando uma versão nova exige.</div>
406
407
  </div>
407
408
 
408
409
  <div class="sideGroup">
@@ -837,7 +838,7 @@ async function cmdWeb({ port, dir, open, dev }) {
837
838
  ]
838
839
  };
839
840
 
840
- const prompt = `Você é o planner do sistema F.R.E.Y.A.\n\nContexto: vamos receber um input bruto do usuário e propor ações estruturadas.\nRegras: siga os arquivos de regras abaixo.\nSaída: retorne APENAS JSON válido no formato: ${JSON.stringify(schema)}\n\nREGRAS:${rulesText}\n\nINPUT DO USUÁRIO:\n${text}\n`;
841
+ const prompt = `Você é o planner do sistema F.R.E.Y.A.\n\nContexto: vamos receber um input bruto do usuário e propor ações estruturadas.\nRegras: siga os arquivos de regras abaixo.\nSaída: retorne APENAS JSON válido no formato: ${JSON.stringify(schema)}\n\nRestrições:\n- NÃO use code fences (\`\`\`)\n- NÃO inclua texto extra antes/depois do JSON\n- NÃO use quebras de linha dentro de strings (transforme em uma frase única)\n\nREGRAS:${rulesText}\n\nINPUT DO USUÁRIO:\n${text}\n`;
841
842
 
842
843
  // Prefer COPILOT_CMD if provided, otherwise try 'copilot'
843
844
  const cmd = process.env.COPILOT_CMD || 'copilot';
@@ -966,15 +967,35 @@ async function cmdWeb({ port, dir, open, dev }) {
966
967
  }
967
968
 
968
969
  const jsonText = extractJson(planRaw) || planRaw;
970
+
971
+ function errorSnippet(text, pos) {
972
+ const p = Number.isFinite(pos) ? pos : 0;
973
+ const start = Math.max(0, p - 60);
974
+ const end = Math.min(text.length, p + 60);
975
+ const slice = text.slice(start, end);
976
+ const codes = Array.from(slice).map((ch) => ch.charCodeAt(0));
977
+ return { start, end, slice, codes };
978
+ }
979
+
969
980
  let plan;
970
981
  try {
971
982
  plan = JSON.parse(jsonText);
972
983
  } catch (e) {
973
- return safeJson(res, 400, {
974
- error: 'Plan is not valid JSON',
975
- details: (e && e.message) ? e.message : String(e),
976
- hint: 'O planner precisa retornar APENAS JSON. Se vier com texto extra, revise o prompt ou use apenas o bloco JSON.'
977
- });
984
+ // Attempt repair for common control-character issues
985
+ try {
986
+ plan = JSON.parse(escapeJsonControlChars(jsonText));
987
+ } catch (e2) {
988
+ return safeJson(res, 400, {
989
+ error: 'Plan is not valid JSON',
990
+ details: (e2 && e2.message) ? e2.message : ((e && e.message) ? e.message : String(e)),
991
+ hint: 'O planner gerou caracteres de controle dentro de strings (ex.: quebra de linha literal). Reexecute o planner; ou escape quebras de linha como \\n.',
992
+ snippet: (() => {
993
+ const m2 = /position (\d+)/.exec(((e2 && e2.message) ? e2.message : ((e && e.message) ? e.message : '')));
994
+ const pos = m2 ? Number(m2[1]) : NaN;
995
+ return errorSnippet(jsonText, pos);
996
+ })()
997
+ });
998
+ }
978
999
  }
979
1000
 
980
1001
  const actions = Array.isArray(plan.actions) ? plan.actions : [];
@@ -994,7 +1015,7 @@ async function cmdWeb({ port, dir, open, dev }) {
994
1015
  if (typeof blockerLog.schemaVersion !== 'number') blockerLog.schemaVersion = 1;
995
1016
 
996
1017
  function normalizeTextForKey(t) {
997
- return String(t || '').toLowerCase().replace(/s+/g, ' ').trim();
1018
+ return String(t || '').toLowerCase().replace(/\s+/g, ' ').trim();
998
1019
  }
999
1020
 
1000
1021
  function sha1(text) {
@@ -1025,7 +1046,7 @@ async function cmdWeb({ port, dir, open, dev }) {
1025
1046
 
1026
1047
  const now = new Date().toISOString();
1027
1048
  const applyMode = String(payload.mode || 'all').trim();
1028
- undefined
1049
+ const applied = { tasks: 0, blockers: 0, tasksSkipped: 0, blockersSkipped: 0, reportsSuggested: [], oracleQueries: [], mode: applyMode };
1029
1050
 
1030
1051
  function makeId(prefix) {
1031
1052
  const rand = Math.random().toString(16).slice(2, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cccarv82/freya",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Personal AI Assistant with local-first persistence",
5
5
  "scripts": {
6
6
  "health": "node scripts/validate-data.js",