@cccarv82/freya 1.0.31 → 1.0.33
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.js +64 -2
- package/cli/web.js +55 -1
- package/package.json +2 -1
package/cli/web-ui.js
CHANGED
|
@@ -325,7 +325,7 @@
|
|
|
325
325
|
async function refreshReports(opts = {}) {
|
|
326
326
|
try {
|
|
327
327
|
const r = await api('/api/reports/list', { dir: dirOrDefault() });
|
|
328
|
-
state.reports = (r.reports || []).slice(0,
|
|
328
|
+
state.reports = (r.reports || []).slice(0, 10);
|
|
329
329
|
renderReportsList();
|
|
330
330
|
|
|
331
331
|
const latest = state.reports && state.reports[0] ? state.reports[0] : null;
|
|
@@ -344,6 +344,44 @@
|
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
+
async function editTask(t) {
|
|
348
|
+
try {
|
|
349
|
+
const currentSlug = t.projectSlug ? String(t.projectSlug) : '';
|
|
350
|
+
const slug = prompt('projectSlug (ex: vivo/fidelizacao/chg0178682):', currentSlug);
|
|
351
|
+
if (slug === null) return;
|
|
352
|
+
|
|
353
|
+
const currentCat = String(t.category || 'DO_NOW');
|
|
354
|
+
const cat = prompt('category (DO_NOW|SCHEDULE|DELEGATE|IGNORE):', currentCat);
|
|
355
|
+
if (cat === null) return;
|
|
356
|
+
|
|
357
|
+
setPill('run', 'updating…');
|
|
358
|
+
await api('/api/tasks/update', { dir: dirOrDefault(), id: t.id, patch: { projectSlug: slug, category: cat } });
|
|
359
|
+
await refreshToday();
|
|
360
|
+
setPill('ok', 'updated');
|
|
361
|
+
setTimeout(() => setPill('ok', 'idle'), 800);
|
|
362
|
+
} catch (e) {
|
|
363
|
+
setPill('err', 'update failed');
|
|
364
|
+
setOut(String(e && e.message ? e.message : e));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function editBlocker(b) {
|
|
369
|
+
try {
|
|
370
|
+
const currentSlug = b.projectSlug ? String(b.projectSlug) : '';
|
|
371
|
+
const slug = prompt('projectSlug (ex: vivo/bnpl/dpgc):', currentSlug);
|
|
372
|
+
if (slug === null) return;
|
|
373
|
+
|
|
374
|
+
setPill('run', 'updating…');
|
|
375
|
+
await api('/api/blockers/update', { dir: dirOrDefault(), id: b.id, patch: { projectSlug: slug } });
|
|
376
|
+
await refreshToday();
|
|
377
|
+
setPill('ok', 'updated');
|
|
378
|
+
setTimeout(() => setPill('ok', 'idle'), 800);
|
|
379
|
+
} catch (e) {
|
|
380
|
+
setPill('err', 'update failed');
|
|
381
|
+
setOut(String(e && e.message ? e.message : e));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
347
385
|
function renderTasks(list) {
|
|
348
386
|
const el = $('tasksList');
|
|
349
387
|
if (!el) return;
|
|
@@ -357,9 +395,14 @@
|
|
|
357
395
|
+ '<div style="opacity:.7; font-size:11px; margin-top:4px">' + escapeHtml(String(t.category || ''))
|
|
358
396
|
+ (t.projectSlug ? (' · <span style="font-family:var(--mono); opacity:.9">[' + escapeHtml(String(t.projectSlug)) + ']</span>') : '')
|
|
359
397
|
+ (pri ? (' · ' + escapeHtml(pri)) : '') + '</div></div>'
|
|
398
|
+
+ '<div style="display:flex; gap:8px">'
|
|
360
399
|
+ '<button class="btn small" type="button">Complete</button>'
|
|
400
|
+
+ '<button class="btn small" type="button">Edit</button>'
|
|
401
|
+
+ '</div>'
|
|
361
402
|
+ '</div>';
|
|
362
|
-
const
|
|
403
|
+
const btns = row.querySelectorAll('button');
|
|
404
|
+
const btn = btns[0];
|
|
405
|
+
if (btns[1]) btns[1].onclick = () => editTask(t);
|
|
363
406
|
btn.onclick = async () => {
|
|
364
407
|
try {
|
|
365
408
|
setPill('run', 'completing…');
|
|
@@ -396,8 +439,13 @@
|
|
|
396
439
|
+ (b.projectSlug ? (' <span style="font-family:var(--mono); opacity:.8">[' + escapeHtml(String(b.projectSlug)) + ']</span>') : '')
|
|
397
440
|
+ '</div>'
|
|
398
441
|
+ '</div>'
|
|
442
|
+
+ '<div style="display:flex; gap:8px; align-items:center">'
|
|
399
443
|
+ '<div style="opacity:.7; font-size:11px; white-space:nowrap">' + escapeHtml(fmtWhen(new Date(b.createdAt || Date.now()).getTime())) + '</div>'
|
|
444
|
+
+ '<button class="btn small" type="button">Edit</button>'
|
|
445
|
+
+ '</div>'
|
|
400
446
|
+ '</div>';
|
|
447
|
+
const ebtn = row.querySelector('button');
|
|
448
|
+
if (ebtn) ebtn.onclick = () => editBlocker(b);
|
|
401
449
|
el.appendChild(row);
|
|
402
450
|
}
|
|
403
451
|
if (!el.childElementCount) {
|
|
@@ -526,6 +574,19 @@
|
|
|
526
574
|
}
|
|
527
575
|
}
|
|
528
576
|
|
|
577
|
+
async function exportObsidian() {
|
|
578
|
+
try {
|
|
579
|
+
setPill('run', 'exporting…');
|
|
580
|
+
const r = await api('/api/obsidian/export', { dir: dirOrDefault() });
|
|
581
|
+
setOut('## Obsidian export\n\n' + (r.output || 'ok'));
|
|
582
|
+
setPill('ok', 'exported');
|
|
583
|
+
setTimeout(() => setPill('ok', 'idle'), 800);
|
|
584
|
+
} catch (e) {
|
|
585
|
+
setPill('err', 'export failed');
|
|
586
|
+
setOut(String(e && e.message ? e.message : e));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
529
590
|
async function reloadSlugRules() {
|
|
530
591
|
try {
|
|
531
592
|
const r = await api('/api/project-slug-map/get', { dir: dirOrDefault() });
|
|
@@ -807,6 +868,7 @@
|
|
|
807
868
|
window.refreshToday = refreshToday;
|
|
808
869
|
window.reloadSlugRules = reloadSlugRules;
|
|
809
870
|
window.saveSlugRules = saveSlugRules;
|
|
871
|
+
window.exportObsidian = exportObsidian;
|
|
810
872
|
window.renderReportsList = renderReportsList;
|
|
811
873
|
window.copyOut = copyOut;
|
|
812
874
|
window.copyPath = copyPath;
|
package/cli/web.js
CHANGED
|
@@ -675,7 +675,6 @@ function buildHtml(safeDefault) {
|
|
|
675
675
|
<textarea id="inboxText" rows="6" placeholder="Cole aqui updates do dia (status, blockers, decisões, ideias)…" style="width:100%; padding:10px 12px; border-radius:12px; border:1px solid var(--line); background: rgba(255,255,255,.72); color: var(--text); outline:none; resize: vertical;"></textarea>
|
|
676
676
|
<div style="height:10px"></div>
|
|
677
677
|
<div class="stack">
|
|
678
|
-
<button class="btn sideBtn" onclick="saveInbox()">Save to Daily Log</button>
|
|
679
678
|
<button class="btn primary sideBtn" onclick="saveAndPlan()">Save + Process (Agents)</button>
|
|
680
679
|
<button class="btn sideBtn" onclick="runSuggestedReports()">Run suggested reports</button>
|
|
681
680
|
</div>
|
|
@@ -775,6 +774,7 @@ function buildHtml(safeDefault) {
|
|
|
775
774
|
<div class="stack" style="margin-top:10px">
|
|
776
775
|
<button class="btn" onclick="reloadSlugRules()">Reload rules</button>
|
|
777
776
|
<button class="btn" onclick="saveSlugRules()">Save rules</button>
|
|
777
|
+
<button class="btn" onclick="exportObsidian()">Export Obsidian notes</button>
|
|
778
778
|
</div>
|
|
779
779
|
</div>
|
|
780
780
|
</div>
|
|
@@ -1553,6 +1553,13 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
1553
1553
|
}
|
|
1554
1554
|
|
|
1555
1555
|
|
|
1556
|
+
|
|
1557
|
+
if (req.url === '/api/obsidian/export') {
|
|
1558
|
+
const r = await run(npmCmd, ['run', 'export-obsidian'], workspaceDir);
|
|
1559
|
+
const out = (r.stdout + r.stderr).trim();
|
|
1560
|
+
return safeJson(res, r.code === 0 ? 200 : 400, r.code === 0 ? { ok: true, output: out } : { error: out || 'export failed', output: out });
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1556
1563
|
if (req.url === '/api/tasks/list') {
|
|
1557
1564
|
const limit = Math.max(1, Math.min(50, Number(payload.limit || 10)));
|
|
1558
1565
|
const cat = payload.category ? String(payload.category).trim() : null;
|
|
@@ -1606,6 +1613,30 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
1606
1613
|
return safeJson(res, 200, { ok: true, task: updated });
|
|
1607
1614
|
}
|
|
1608
1615
|
|
|
1616
|
+
|
|
1617
|
+
if (req.url === '/api/tasks/update') {
|
|
1618
|
+
const id = String(payload.id || '').trim();
|
|
1619
|
+
if (!id) return safeJson(res, 400, { error: 'Missing id' });
|
|
1620
|
+
const patch = payload.patch && typeof payload.patch === 'object' ? payload.patch : {};
|
|
1621
|
+
|
|
1622
|
+
const file = path.join(workspaceDir, 'data', 'tasks', 'task-log.json');
|
|
1623
|
+
const doc = readJsonOrNull(file) || { schemaVersion: 1, tasks: [] };
|
|
1624
|
+
const tasks = Array.isArray(doc.tasks) ? doc.tasks : [];
|
|
1625
|
+
|
|
1626
|
+
let updated = null;
|
|
1627
|
+
for (const t of tasks) {
|
|
1628
|
+
if (t && t.id === id) {
|
|
1629
|
+
if (typeof patch.projectSlug === 'string') t.projectSlug = patch.projectSlug.trim() || undefined;
|
|
1630
|
+
if (typeof patch.category === 'string') t.category = patch.category.trim();
|
|
1631
|
+
updated = t;
|
|
1632
|
+
break;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
if (!updated) return safeJson(res, 404, { error: 'Task not found' });
|
|
1636
|
+
writeJson(file, doc);
|
|
1637
|
+
return safeJson(res, 200, { ok: true, task: updated });
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1609
1640
|
if (req.url === '/api/blockers/list') {
|
|
1610
1641
|
const limit = Math.max(1, Math.min(50, Number(payload.limit || 10)));
|
|
1611
1642
|
const status = payload.status ? String(payload.status).trim() : 'OPEN';
|
|
@@ -1639,6 +1670,29 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
1639
1670
|
|
|
1640
1671
|
return safeJson(res, 200, { ok: true, blockers: filtered });
|
|
1641
1672
|
}
|
|
1673
|
+
|
|
1674
|
+
if (req.url === '/api/blockers/update') {
|
|
1675
|
+
const id = String(payload.id || '').trim();
|
|
1676
|
+
if (!id) return safeJson(res, 400, { error: 'Missing id' });
|
|
1677
|
+
const patch = payload.patch && typeof payload.patch === 'object' ? payload.patch : {};
|
|
1678
|
+
|
|
1679
|
+
const file = path.join(workspaceDir, 'data', 'blockers', 'blocker-log.json');
|
|
1680
|
+
const doc = readJsonOrNull(file) || { schemaVersion: 1, blockers: [] };
|
|
1681
|
+
const blockers = Array.isArray(doc.blockers) ? doc.blockers : [];
|
|
1682
|
+
|
|
1683
|
+
let updated = null;
|
|
1684
|
+
for (const b of blockers) {
|
|
1685
|
+
if (b && b.id === id) {
|
|
1686
|
+
if (typeof patch.projectSlug === 'string') b.projectSlug = patch.projectSlug.trim() || undefined;
|
|
1687
|
+
updated = b;
|
|
1688
|
+
break;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
if (!updated) return safeJson(res, 404, { error: 'Blocker not found' });
|
|
1692
|
+
writeJson(file, doc);
|
|
1693
|
+
return safeJson(res, 200, { ok: true, blocker: updated });
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1642
1696
|
if (req.url === '/api/report') {
|
|
1643
1697
|
const script = payload.script;
|
|
1644
1698
|
if (!script) return safeJson(res, 400, { error: 'Missing script' });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cccarv82/freya",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"description": "Personal AI Assistant with local-first persistence",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"health": "node scripts/validate-data.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"daily": "node scripts/generate-daily-summary.js",
|
|
11
11
|
"status": "node scripts/generate-executive-report.js",
|
|
12
12
|
"blockers": "node scripts/generate-blockers-report.js",
|
|
13
|
+
"export-obsidian": "node scripts/export-obsidian.js",
|
|
13
14
|
"test": "node tests/unit/test-package-config.js && node tests/unit/test-cli-init.js && node tests/unit/test-cli-web-help.js && node tests/unit/test-web-static-assets.js && node tests/unit/test-fs-utils.js && node tests/unit/test-task-schema.js && node tests/unit/test-daily-generation.js && node tests/unit/test-report-generation.js && node tests/unit/test-oracle-retrieval.js && node tests/unit/test-task-completion.js && node tests/unit/test-migrate-data.js && node tests/unit/test-blockers-validation.js && node tests/unit/test-blockers-report.js && node tests/unit/test-sm-weekly-report.js && node tests/integration/test-ingestor-task.js"
|
|
14
15
|
},
|
|
15
16
|
"keywords": [],
|