@cccarv82/freya 2.13.1 → 2.13.2
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-ui.css +1 -0
- package/cli/web-ui.js +118 -19
- package/cli/web.js +18 -3
- package/package.json +1 -1
package/cli/web-ui.css
CHANGED
package/cli/web-ui.js
CHANGED
|
@@ -162,6 +162,70 @@
|
|
|
162
162
|
return html;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
function formatPlanForDisplay(rawPlan) {
|
|
166
|
+
try {
|
|
167
|
+
const text = String(rawPlan || '');
|
|
168
|
+
const start = text.indexOf('{');
|
|
169
|
+
if (start === -1) return null;
|
|
170
|
+
let depth = 0, inStr = false, esc = false, jsonStr = null;
|
|
171
|
+
for (let i = start; i < text.length; i++) {
|
|
172
|
+
const ch = text[i];
|
|
173
|
+
if (esc) { esc = false; continue; }
|
|
174
|
+
if (ch === '\\') { esc = true; continue; }
|
|
175
|
+
if (ch === '"') { inStr = !inStr; continue; }
|
|
176
|
+
if (inStr) continue;
|
|
177
|
+
if (ch === '{') depth++;
|
|
178
|
+
if (ch === '}') { depth--; if (depth === 0) { jsonStr = text.slice(start, i + 1); break; } }
|
|
179
|
+
}
|
|
180
|
+
if (!jsonStr) return null;
|
|
181
|
+
const plan = JSON.parse(jsonStr);
|
|
182
|
+
const actions = Array.isArray(plan.actions) ? plan.actions : [];
|
|
183
|
+
if (actions.length === 0) return null;
|
|
184
|
+
|
|
185
|
+
const icons = {
|
|
186
|
+
append_daily_log: '\u{1F4DD}', appenddailylog: '\u{1F4DD}',
|
|
187
|
+
create_task: '\u2705', createtask: '\u2705',
|
|
188
|
+
create_blocker: '\u{1F6A7}', createblocker: '\u{1F6A7}',
|
|
189
|
+
suggest_report: '\u{1F4CA}', suggestreport: '\u{1F4CA}',
|
|
190
|
+
oracle_query: '\u{1F50D}', oraclequery: '\u{1F50D}'
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const lines = actions.map(function(a, i) {
|
|
194
|
+
var type = String(a.type || '').trim().toLowerCase().replace(/_/g, '');
|
|
195
|
+
var icon = icons[type] || icons[String(a.type || '').trim()] || '\u2022';
|
|
196
|
+
var num = i + 1;
|
|
197
|
+
var typeNorm = type.replace(/_/g, '');
|
|
198
|
+
|
|
199
|
+
if (typeNorm === 'appenddailylog') {
|
|
200
|
+
var t = String(a.text || '').slice(0, 140);
|
|
201
|
+
return num + '. ' + icon + ' **Registrar no log:** ' + t + (String(a.text || '').length > 140 ? '...' : '');
|
|
202
|
+
}
|
|
203
|
+
if (typeNorm === 'createtask') {
|
|
204
|
+
var desc = String(a.description || '').slice(0, 120);
|
|
205
|
+
var pri = a.priority ? ' (prioridade: **' + String(a.priority).toUpperCase() + '**)' : '';
|
|
206
|
+
var cat = a.category ? ' [' + a.category + ']' : '';
|
|
207
|
+
return num + '. ' + icon + ' **Criar tarefa:** ' + desc + pri + cat;
|
|
208
|
+
}
|
|
209
|
+
if (typeNorm === 'createblocker') {
|
|
210
|
+
var title = String(a.title || a.description || '').slice(0, 120);
|
|
211
|
+
var sev = a.severity ? ' (severidade: **' + String(a.severity).toUpperCase() + '**)' : '';
|
|
212
|
+
return num + '. ' + icon + ' **Registrar blocker:** ' + title + sev;
|
|
213
|
+
}
|
|
214
|
+
if (typeNorm === 'suggestreport') {
|
|
215
|
+
return num + '. ' + icon + ' **Sugerir relatorio:** ' + String(a.name || a.reportType || '');
|
|
216
|
+
}
|
|
217
|
+
if (typeNorm === 'oraclequery') {
|
|
218
|
+
return num + '. ' + icon + ' **Consultar oracle:** ' + String(a.query || '').slice(0, 120);
|
|
219
|
+
}
|
|
220
|
+
return num + '. \u2022 **' + String(a.type || 'acao') + ':** ' + JSON.stringify(a).slice(0, 100);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return lines.join('\n');
|
|
224
|
+
} catch (e) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
165
229
|
function ensureChatSession() {
|
|
166
230
|
if (state.chatSessionId) return state.chatSessionId;
|
|
167
231
|
try {
|
|
@@ -1507,29 +1571,63 @@
|
|
|
1507
1571
|
+ (t.category ? ' · <span style="font-family:var(--mono);">' + escapeHtml(t.category) + '</span>' : '')
|
|
1508
1572
|
+ '</div>'
|
|
1509
1573
|
+ '</div></div>'
|
|
1510
|
-
+ '<div style="display:flex; gap:6px; flex-shrink:0;">'
|
|
1574
|
+
+ '<div class="task-actions" style="display:flex; gap:6px; flex-shrink:0; align-items:center;">'
|
|
1511
1575
|
+ '<button class="btn small complete-btn" type="button" style="padding:3px 10px; font-size:11px;" title="Marcar como concluída">✓ Concluir</button>'
|
|
1512
1576
|
+ '<button class="btn small edit-btn" type="button" style="padding:3px 8px; font-size:11px;">✎</button>'
|
|
1513
1577
|
+ '</div>';
|
|
1514
1578
|
row.querySelector('.edit-btn').onclick = () => editTask(t);
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1579
|
+
|
|
1580
|
+
var attachCompleteHandler = function() {
|
|
1581
|
+
var cBtn = row.querySelector('.complete-btn');
|
|
1582
|
+
if (!cBtn) return;
|
|
1583
|
+
cBtn.onclick = function() {
|
|
1584
|
+
var actionsDiv = row.querySelector('.task-actions');
|
|
1585
|
+
actionsDiv.innerHTML =
|
|
1586
|
+
'<input type="text" class="comment-input" placeholder="Comentario (opcional)" '
|
|
1587
|
+
+ 'style="font-size:11px; padding:3px 8px; background:var(--bg); border:1px solid var(--border); '
|
|
1588
|
+
+ 'color:var(--text); width:180px; outline:none; font-family:var(--mono);" />'
|
|
1589
|
+
+ '<button class="btn small confirm-btn" type="button" style="padding:3px 10px; font-size:11px; '
|
|
1590
|
+
+ 'background:var(--accent); color:#000; font-weight:700;">Confirmar</button>'
|
|
1591
|
+
+ '<button class="btn small cancel-btn" type="button" style="padding:3px 8px; font-size:11px; '
|
|
1592
|
+
+ 'color:var(--muted);">\u2715</button>';
|
|
1593
|
+
|
|
1594
|
+
var input = actionsDiv.querySelector('.comment-input');
|
|
1595
|
+
input.focus();
|
|
1596
|
+
|
|
1597
|
+
var doComplete = async function() {
|
|
1598
|
+
var comment = input.value.trim();
|
|
1599
|
+
actionsDiv.querySelector('.confirm-btn').disabled = true;
|
|
1600
|
+
actionsDiv.querySelector('.confirm-btn').textContent = '\u2026';
|
|
1601
|
+
try {
|
|
1602
|
+
setPill('run', 'concluindo\u2026');
|
|
1603
|
+
var body = { dir: dirOrDefault(), id: t.id };
|
|
1604
|
+
if (comment) body.comment = comment;
|
|
1605
|
+
await api('/api/tasks/complete', body);
|
|
1606
|
+
row.style.opacity = '0.4';
|
|
1607
|
+
row.style.pointerEvents = 'none';
|
|
1608
|
+
await refreshToday();
|
|
1609
|
+
setPill('ok', 'conclu\u00edda');
|
|
1610
|
+
setTimeout(function() { setPill('ok', 'pronto'); }, 800);
|
|
1611
|
+
} catch (e) {
|
|
1612
|
+
actionsDiv.querySelector('.confirm-btn').disabled = false;
|
|
1613
|
+
actionsDiv.querySelector('.confirm-btn').textContent = 'Confirmar';
|
|
1614
|
+
setPill('err', 'falhou');
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
|
|
1618
|
+
actionsDiv.querySelector('.confirm-btn').onclick = doComplete;
|
|
1619
|
+
input.onkeydown = function(e) { if (e.key === 'Enter') doComplete(); };
|
|
1620
|
+
actionsDiv.querySelector('.cancel-btn').onclick = function() {
|
|
1621
|
+
actionsDiv.innerHTML =
|
|
1622
|
+
'<button class="btn small complete-btn" type="button" style="padding:3px 10px; font-size:11px;" '
|
|
1623
|
+
+ 'title="Marcar como conclu\u00edda">\u2713 Concluir</button>'
|
|
1624
|
+
+ '<button class="btn small edit-btn" type="button" style="padding:3px 8px; font-size:11px;">\u270E</button>';
|
|
1625
|
+
actionsDiv.querySelector('.edit-btn').onclick = function() { editTask(t); };
|
|
1626
|
+
attachCompleteHandler();
|
|
1627
|
+
};
|
|
1628
|
+
};
|
|
1532
1629
|
};
|
|
1630
|
+
attachCompleteHandler();
|
|
1533
1631
|
return row;
|
|
1534
1632
|
};
|
|
1535
1633
|
|
|
@@ -2328,7 +2426,8 @@
|
|
|
2328
2426
|
|
|
2329
2427
|
// Show plan output in Preview panel
|
|
2330
2428
|
const header = r.ok === false ? '## Agent Plan (planner unavailable)\n\n' : '## Agent Plan (draft)\n\n';
|
|
2331
|
-
const
|
|
2429
|
+
const formatted = r.ok !== false ? formatPlanForDisplay(r.plan) : null;
|
|
2430
|
+
const planOut = header + (formatted || r.plan || '');
|
|
2332
2431
|
setOut(planOut);
|
|
2333
2432
|
chatAppend('assistant', planOut, { markdown: true });
|
|
2334
2433
|
ta.value = '';
|
package/cli/web.js
CHANGED
|
@@ -3620,7 +3620,8 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
3620
3620
|
completedAt: t.completed_at,
|
|
3621
3621
|
projectSlug: t.project_slug,
|
|
3622
3622
|
priority: meta.priority,
|
|
3623
|
-
streamSlug: meta.streamSlug
|
|
3623
|
+
streamSlug: meta.streamSlug,
|
|
3624
|
+
comments: Array.isArray(meta.comments) ? meta.comments : []
|
|
3624
3625
|
};
|
|
3625
3626
|
});
|
|
3626
3627
|
|
|
@@ -3631,10 +3632,24 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
3631
3632
|
const id = String(payload.id || '').trim();
|
|
3632
3633
|
if (!id) return safeJson(res, 400, { error: 'Missing id' });
|
|
3633
3634
|
|
|
3635
|
+
const comment = typeof payload.comment === 'string' ? payload.comment.trim() : '';
|
|
3634
3636
|
const now = new Date().toISOString();
|
|
3635
|
-
const info = dl.db.prepare(`UPDATE tasks SET status = 'COMPLETED', completed_at = ? WHERE id = ?`).run(now, id);
|
|
3636
3637
|
|
|
3637
|
-
if (
|
|
3638
|
+
if (comment) {
|
|
3639
|
+
const row = dl.db.prepare('SELECT metadata FROM tasks WHERE id = ?').get(id);
|
|
3640
|
+
if (!row) return safeJson(res, 404, { error: 'Task not found' });
|
|
3641
|
+
let meta = {};
|
|
3642
|
+
try { meta = row.metadata ? JSON.parse(row.metadata) : {}; } catch (_) { meta = {}; }
|
|
3643
|
+
if (!Array.isArray(meta.comments)) meta.comments = [];
|
|
3644
|
+
meta.comments.push({ text: comment, createdAt: now });
|
|
3645
|
+
const info = dl.db.prepare(`UPDATE tasks SET status = 'COMPLETED', completed_at = ?, metadata = ? WHERE id = ?`)
|
|
3646
|
+
.run(now, JSON.stringify(meta), id);
|
|
3647
|
+
if (info.changes === 0) return safeJson(res, 404, { error: 'Task not found' });
|
|
3648
|
+
} else {
|
|
3649
|
+
const info = dl.db.prepare(`UPDATE tasks SET status = 'COMPLETED', completed_at = ? WHERE id = ?`).run(now, id);
|
|
3650
|
+
if (info.changes === 0) return safeJson(res, 404, { error: 'Task not found' });
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3638
3653
|
return safeJson(res, 200, { ok: true, task: { id, status: 'COMPLETED', completedAt: now } });
|
|
3639
3654
|
}
|
|
3640
3655
|
|
package/package.json
CHANGED