@loompad/cli 1.1.1 → 1.2.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/CHANGELOG.md +37 -0
- package/README.md +20 -5
- package/dist/adapters/antigravity-cli.d.ts +2 -0
- package/dist/adapters/antigravity-cli.js +20 -1
- package/dist/adapters/antigravity-cli.js.map +1 -1
- package/dist/adapters/model.js +1 -1
- package/dist/adapters/model.js.map +1 -1
- package/dist/cli/doctor.d.ts +30 -1
- package/dist/cli/doctor.js +117 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.js +294 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/ui.js +11 -7
- package/dist/cli/ui.js.map +1 -1
- package/dist/core/auto-policy.d.ts +46 -0
- package/dist/core/auto-policy.js +181 -0
- package/dist/core/auto-policy.js.map +1 -0
- package/dist/core/council.d.ts +55 -0
- package/dist/core/council.js +71 -0
- package/dist/core/council.js.map +1 -0
- package/dist/core/permissions.js +2 -2
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/prices.d.ts +55 -0
- package/dist/core/prices.js +99 -0
- package/dist/core/prices.js.map +1 -0
- package/dist/core/proof.d.ts +2 -0
- package/dist/core/proof.js +33 -10
- package/dist/core/proof.js.map +1 -1
- package/dist/core/providers.d.ts +13 -0
- package/dist/core/providers.js +17 -0
- package/dist/core/providers.js.map +1 -1
- package/dist/core/replay.js +14 -0
- package/dist/core/replay.js.map +1 -1
- package/dist/core/review.d.ts +60 -0
- package/dist/core/review.js +121 -0
- package/dist/core/review.js.map +1 -0
- package/dist/core/setup.d.ts +13 -0
- package/dist/core/setup.js +17 -1
- package/dist/core/setup.js.map +1 -1
- package/dist/core/turn-wait.d.ts +20 -0
- package/dist/core/turn-wait.js +39 -0
- package/dist/core/turn-wait.js.map +1 -0
- package/dist/core/usage.d.ts +7 -1
- package/dist/core/usage.js +11 -3
- package/dist/core/usage.js.map +1 -1
- package/dist/daemon/client.d.ts +46 -0
- package/dist/daemon/client.js +34 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/council.d.ts +98 -0
- package/dist/daemon/council.js +248 -0
- package/dist/daemon/council.js.map +1 -0
- package/dist/daemon/proof.d.ts +6 -0
- package/dist/daemon/proof.js +22 -3
- package/dist/daemon/proof.js.map +1 -1
- package/dist/daemon/push.js +7 -0
- package/dist/daemon/push.js.map +1 -1
- package/dist/daemon/review.d.ts +89 -0
- package/dist/daemon/review.js +136 -0
- package/dist/daemon/review.js.map +1 -0
- package/dist/daemon/routes/council.d.ts +4 -0
- package/dist/daemon/routes/council.js +29 -0
- package/dist/daemon/routes/council.js.map +1 -0
- package/dist/daemon/routes/review.d.ts +4 -0
- package/dist/daemon/routes/review.js +40 -0
- package/dist/daemon/routes/review.js.map +1 -0
- package/dist/daemon/routes/routing.js +2 -1
- package/dist/daemon/routes/routing.js.map +1 -1
- package/dist/daemon/routes/setup.d.ts +2 -1
- package/dist/daemon/routes/setup.js +13 -5
- package/dist/daemon/routes/setup.js.map +1 -1
- package/dist/daemon/runtime/accounting.d.ts +6 -0
- package/dist/daemon/runtime/accounting.js +37 -1
- package/dist/daemon/runtime/accounting.js.map +1 -1
- package/dist/daemon/runtime/briefings.d.ts +8 -3
- package/dist/daemon/runtime/briefings.js +26 -14
- package/dist/daemon/runtime/briefings.js.map +1 -1
- package/dist/daemon/runtime.d.ts +40 -1
- package/dist/daemon/runtime.js +171 -2
- package/dist/daemon/runtime.js.map +1 -1
- package/dist/daemon/server.js +5 -1
- package/dist/daemon/server.js.map +1 -1
- package/dist/providers/agent.js +3 -0
- package/dist/providers/agent.js.map +1 -1
- package/dist/providers/claude/adapter.d.ts +3 -0
- package/dist/providers/claude/adapter.js +20 -1
- package/dist/providers/claude/adapter.js.map +1 -1
- package/dist/types.d.ts +19 -1
- package/dist/types.js.map +1 -1
- package/dist/web/app.css +48 -1
- package/dist/web/app.js +143 -12
- package/dist/web/app.js.map +3 -3
- package/docs/release-notes/v1.1.2.md +21 -0
- package/docs/release-notes/v1.2.0.md +48 -0
- package/package.json +1 -1
package/dist/web/app.js
CHANGED
|
@@ -751,8 +751,10 @@
|
|
|
751
751
|
return v.length > 24 ? v.slice(0, 23) + "\u2026" : v;
|
|
752
752
|
}
|
|
753
753
|
__name(shortModel, "shortModel");
|
|
754
|
-
function permBadge(mode, agentId) {
|
|
755
|
-
|
|
754
|
+
function permBadge(mode, agentId, kind) {
|
|
755
|
+
var cell = kind && permProfile(kind).modes ? permProfile(kind).modes[mode] : null;
|
|
756
|
+
var what = cell && cell.label ? cell.label : "permissions: " + (PERM_NAMES[mode] || mode);
|
|
757
|
+
return '<span class="pbdg ' + esc(mode) + '"' + (agentId ? ' data-permof="' + esc(agentId) + '"' : "") + ' title="' + esc(what) + (agentId ? " \u2014 click to change" : "") + '">' + esc(mode) + "</span>";
|
|
756
758
|
}
|
|
757
759
|
__name(permBadge, "permBadge");
|
|
758
760
|
var KMOD = /Mac|iPhone|iPad/.test(navigator.platform || "") ? "\u2318" : "Ctrl+";
|
|
@@ -1845,6 +1847,93 @@
|
|
|
1845
1847
|
return '<div class="shiftcard"><div class="shh">\u{1F319} <b>Night shift report</b><span class="shsum">' + esc(String(p.summary || "")) + '</span><span class="shmeta">' + (took ? took + " min" : "") + (p.costUsd ? " \xB7 " + money(p.costUsd) : "") + "</span></div>" + (p.stopped ? '<div class="shstop">Stopped early: ' + esc(String(p.stopped)) + "</div>" : "") + '<ul class="shl">' + rows + "</ul></div>";
|
|
1846
1848
|
}
|
|
1847
1849
|
__name(shiftCard, "shiftCard");
|
|
1850
|
+
var SEV_WORD = { high: "high", medium: "medium", low: "low" };
|
|
1851
|
+
function reviewCard(e) {
|
|
1852
|
+
var p = e.payload || {}, t = p.target || {};
|
|
1853
|
+
var what = t.kind === "file" ? t.file : t.kind === "diff" ? "the uncommitted changes" : t.label || "your request";
|
|
1854
|
+
if (p.phase === "started") {
|
|
1855
|
+
return '<div class="sys reviewline">\u{1F50D} ' + esc((p.agents || []).map(labelOf).join(", ")) + " reviewing " + esc(what) + " \u2014 read-only, nobody takes the baton" + (p.focus ? " \xB7 focus: " + esc(p.focus) : "") + "</div>";
|
|
1856
|
+
}
|
|
1857
|
+
if (p.phase !== "done") return "";
|
|
1858
|
+
var rows = (p.findings || []).map(function(f) {
|
|
1859
|
+
var loc = f.file ? '<code class="rvloc">' + esc(f.file + (f.line ? ":" + f.line : "")) + "</code>" : "";
|
|
1860
|
+
return '<li class="rvf" data-finding="' + esc(f.id) + '"><span class="rvsev sev-' + esc(f.severity || "note") + '">' + esc(SEV_WORD[f.severity] || "note") + "</span>" + avatarFor(f.agent) + (f.agreed || []).map(function(a) {
|
|
1861
|
+
return avatarFor(a.agent);
|
|
1862
|
+
}).join("") + (f.agreed && f.agreed.length ? '<span class="rvagree" title="' + esc((f.agreed || []).map(function(a) {
|
|
1863
|
+
return labelOf(a.agent) + ": " + a.text;
|
|
1864
|
+
}).join("\n")) + '">' + (f.agreed.length + 1) + " agree</span>" : "") + loc + '<span class="rvtext">' + esc(f.text) + '</span><span class="rvact"><button type="button" class="btn xs outline" data-finding-decide="' + esc(f.id) + '" data-decision="accepted" title="accept: it becomes a project decision every agent is briefed with">Accept</button><button type="button" class="btn xs ghost" data-finding-decide="' + esc(f.id) + '" data-decision="rejected">Reject</button></span><span class="rvdone"></span></li>';
|
|
1865
|
+
}).join("");
|
|
1866
|
+
var quiet = (p.results || []).map(function(r) {
|
|
1867
|
+
var wrote = r.edited && r.edited.length ? '<div class="rvquiet err">\u26A0 ' + esc(labelOf(r.agent)) + " changed files in a read-only review: " + esc(r.edited.slice(0, 6).join(", ")) + (r.edited.length > 6 ? ", \u2026" : "") + "</div>" : "";
|
|
1868
|
+
return wrote + reviewQuiet(r);
|
|
1869
|
+
}).join("");
|
|
1870
|
+
function reviewQuiet(r) {
|
|
1871
|
+
if (r.status === "failed") return '<div class="rvquiet err">' + esc(labelOf(r.agent)) + " didn\u2019t finish: " + esc(String(r.error || "").slice(0, 200)) + "</div>";
|
|
1872
|
+
if ((p.findings || []).some(function(f) {
|
|
1873
|
+
return f.agent === r.agent || (f.agreed || []).some(function(a) {
|
|
1874
|
+
return a.agent === r.agent;
|
|
1875
|
+
});
|
|
1876
|
+
})) return "";
|
|
1877
|
+
var first = String(r.reply || "").split("\n").filter(function(l) {
|
|
1878
|
+
return l.trim();
|
|
1879
|
+
})[0] || "(no reply)";
|
|
1880
|
+
return '<div class="rvquiet">' + esc(labelOf(r.agent)) + ": " + esc(first.slice(0, 220)) + "</div>";
|
|
1881
|
+
}
|
|
1882
|
+
__name(reviewQuiet, "reviewQuiet");
|
|
1883
|
+
return '<div class="reviewcard" data-review="' + esc(p.reviewId) + '"><div class="rvh">\u{1F50D} <b>Review</b><span class="rvsum">' + esc(p.summary || "") + '</span><span class="rvwhat">' + esc(what) + "</span></div>" + (rows ? '<ul class="rvl">' + rows + "</ul>" : "") + quiet + "</div>";
|
|
1884
|
+
}
|
|
1885
|
+
__name(reviewCard, "reviewCard");
|
|
1886
|
+
var CSTAGE_MARK = { waiting: "\xB7", running: "\u25D0", done: "\u2713", skipped: "\u2013", failed: "\u2717" };
|
|
1887
|
+
function councilCard(e) {
|
|
1888
|
+
var p = e.payload || {};
|
|
1889
|
+
if (p.phase !== "started") return "";
|
|
1890
|
+
var rows = (p.stages || []).map(function(st) {
|
|
1891
|
+
return '<li class="cst cs-waiting" data-cstage="' + esc(st.key) + '"><span class="csm">' + CSTAGE_MARK.waiting + '</span><span class="csn">' + esc(st.name) + '</span><span class="csd" title="' + esc(st.what || "") + '">' + esc(st.what || "") + "</span></li>";
|
|
1892
|
+
}).join("");
|
|
1893
|
+
return '<div class="councilcard cc-running" data-council="' + esc(p.councilId) + '"><div class="cch">\u{1F3DB} <b>Council</b><span class="ccgoal">' + esc(p.goal || "") + '</span><button type="button" class="btn xs outline" data-council-stop="' + esc(p.councilId) + '">Stop</button></div><div class="ccwho">' + avatarFor(p.planner) + " " + esc(labelOf(p.planner)) + " plans and builds \xB7 " + (p.reviewers || []).map(function(r) {
|
|
1894
|
+
return avatarFor(r) + " " + esc(labelOf(r));
|
|
1895
|
+
}).join(" ") + ' review</div><ol class="ccl">' + rows + '</ol><div class="ccsum"></div></div>';
|
|
1896
|
+
}
|
|
1897
|
+
__name(councilCard, "councilCard");
|
|
1898
|
+
function settleCouncil(root2, p) {
|
|
1899
|
+
var cards = (root2 || document).querySelectorAll('.councilcard[data-council="' + String(p.councilId).replace(/"/g, "") + '"]');
|
|
1900
|
+
Array.prototype.forEach.call(cards, function(card) {
|
|
1901
|
+
if (p.phase === "stage") {
|
|
1902
|
+
var row = card.querySelector('[data-cstage="' + String(p.stage).replace(/"/g, "") + '"]');
|
|
1903
|
+
if (!row) return;
|
|
1904
|
+
row.className = "cst cs-" + p.status;
|
|
1905
|
+
row.querySelector(".csm").textContent = CSTAGE_MARK[p.status] || "\xB7";
|
|
1906
|
+
if (p.detail || p.status !== "running") {
|
|
1907
|
+
var d = row.querySelector(".csd");
|
|
1908
|
+
d.textContent = p.detail || (p.status === "running" ? d.textContent : "");
|
|
1909
|
+
}
|
|
1910
|
+
} else if (p.phase === "done") {
|
|
1911
|
+
card.classList.remove("cc-running");
|
|
1912
|
+
card.classList.add("cc-" + p.status);
|
|
1913
|
+
var btn = card.querySelector("[data-council-stop]");
|
|
1914
|
+
if (btn) btn.remove();
|
|
1915
|
+
card.querySelector(".ccsum").textContent = p.summary || "";
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1918
|
+
return cards.length > 0;
|
|
1919
|
+
}
|
|
1920
|
+
__name(settleCouncil, "settleCouncil");
|
|
1921
|
+
function settleFinding(root2, findingId, decision) {
|
|
1922
|
+
var done = false;
|
|
1923
|
+
Array.prototype.forEach.call((root2 || document).querySelectorAll('.rvf[data-finding="' + String(findingId).replace(/"/g, "") + '"]'), function(row) {
|
|
1924
|
+
row.classList.remove("fd-accepted", "fd-rejected");
|
|
1925
|
+
row.classList.add("fd-" + decision);
|
|
1926
|
+
var lbl = row.querySelector(".rvdone");
|
|
1927
|
+
if (lbl) lbl.textContent = decision === "accepted" ? "\u2713 accepted \u2014 recorded as a decision" : "\u2715 rejected";
|
|
1928
|
+
Array.prototype.forEach.call(row.querySelectorAll("[data-finding-decide]"), function(b) {
|
|
1929
|
+
b.disabled = false;
|
|
1930
|
+
b.hidden = b.getAttribute("data-decision") === decision;
|
|
1931
|
+
});
|
|
1932
|
+
done = true;
|
|
1933
|
+
});
|
|
1934
|
+
return done;
|
|
1935
|
+
}
|
|
1936
|
+
__name(settleFinding, "settleFinding");
|
|
1848
1937
|
function avatarFor(id) {
|
|
1849
1938
|
var s = String(id || "?"), k = kindOf(s) || (AGENT_LABELS[s] ? s : null);
|
|
1850
1939
|
var mine = state.project && (state.project.agents || []).filter(function(a) {
|
|
@@ -2087,6 +2176,8 @@
|
|
|
2087
2176
|
}
|
|
2088
2177
|
if (e.kind === "proof") return proofCard(e);
|
|
2089
2178
|
if (e.kind === "shift") return shiftCard(e);
|
|
2179
|
+
if (e.kind === "review") return reviewCard(e);
|
|
2180
|
+
if (e.kind === "council") return councilCard(e);
|
|
2090
2181
|
if (e.kind === "checkpoint") {
|
|
2091
2182
|
if (p.reason !== "rewound") return tview() === "verbose" ? '<div class="sys" style="opacity:.6">\u21BA checkpoint \xB7 ' + esc(p.label || p.id) + "</div>" : "";
|
|
2092
2183
|
return '<div class="sys ok">\u21BA Rewound to \u201C' + esc(String(p.label || p.id).slice(0, 80)) + "\u201D \xB7 " + Number(p.files || 0) + " file" + (Number(p.files || 0) === 1 ? "" : "s") + (p.undo ? ' <button class="btn xs outline" type="button" data-rewind="' + esc(p.undo) + '">Undo the rewind</button>' : "") + "</div>";
|
|
@@ -10947,7 +11038,8 @@
|
|
|
10947
11038
|
else adapters.forEach(function(a) {
|
|
10948
11039
|
var hh = hue(a.id);
|
|
10949
11040
|
var curA = a.id === state.selected;
|
|
10950
|
-
html += '<div class="frow agentrow' + (curA ? " cur" : "") + '" data-agent="' + esc(a.id) + '" title="click to aim your next message at ' + esc(a.id) + '"><span class="adot' + (a.busy ? " busy" : "") + '"></span>' + brandMark(a.kind) + '<span class="fp" style="color:hsl(' + hh + ',55%,var(--agent-l))">' + esc(a.id) + "</span>" + (a.id === p.holder ? ' <span class="abadge">baton</span>' : "") + //
|
|
11041
|
+
html += '<div class="frow agentrow' + (curA ? " cur" : "") + '" data-agent="' + esc(a.id) + '" title="click to aim your next message at ' + esc(a.id) + '"><span class="adot' + (a.busy ? " busy" : "") + '"></span>' + brandMark(a.kind) + '<span class="fp" style="color:hsl(' + hh + ',55%,var(--agent-l))">' + esc(a.id) + "</span>" + (a.id === p.holder ? ' <span class="abadge">baton</span>' : "") + // its effective mode, and on hover what that mode lets this agent do (#261)
|
|
11042
|
+
permBadge(permOf(a), void 0, a.kind) + (a.signedOut ? ' <span class="abadge err" title="' + esc(a.signedOut) + '">signed out</span>' : "") + (a.readOnly ? ' <span class="abadge" title="can answer, can\u2019t change files">read-only</span>' : "") + // your project decides what jobs exist — click and type
|
|
10951
11043
|
'<span class="role edit' + (!a.role || a.role === a.id || a.role === a.kind ? " same" : "") + '" data-role-p="' + esc(view.pid) + '" data-role-a="' + esc(a.id) + '" title="click to rename this job">' + esc(a.role || "\u2026") + "</span></div>";
|
|
10952
11044
|
});
|
|
10953
11045
|
var bridges = p ? p.agents.filter(function(a) {
|
|
@@ -11201,7 +11293,7 @@
|
|
|
11201
11293
|
var lbl = agentLabel(a.kind, a.id), last = a.last;
|
|
11202
11294
|
var sub = [a.id !== lbl ? a.id : "", a.role || ""].filter(Boolean).join(" \xB7 ");
|
|
11203
11295
|
var chatName = a.chatTitle || (a.chat === "main" ? "Main thread" : a.chat);
|
|
11204
|
-
return '<div class="frow' + (a.busy ? " busy" : "") + '" data-fagent="' + esc(a.id) + '"><span class="fg">' + agentGlyph(a.kind, a.id) + '</span><span class="fn"><b>' + esc(lbl) + "</b>" + (sub ? "<small>" + esc(sub) + "</small>" : "") + '</span><span class="fs">' + (a.busy ? '<span class="fspin"></span>working' + (a.since ? " \xB7 " + fleetSince(a.since) : "") : '<span class="fidle"></span>idle') + '</span><span class="fa">' + (a.chat ? '<button class="fthr" type="button" data-fchat="' + esc(a.chat) + '" data-fpid="' + esc(info.id) + '" title="open this thread">' + ICONS.thread + "<span>" + esc(chatName) + "</span></button>" : "") + (last && last.line ? '<span class="fline">' + esc(last.line) + '<span class="ft">' + rel(last.ts) + "</span></span>" : a.chat ? "" : '<span class="fline">no activity yet</span>') + '</span><span class="fb">' + (a.holdsBaton ? '<span class="fbaton" title="holds the baton">baton</span>' : "") + permBadge(a.permissions || "auto") + "</span></div>";
|
|
11296
|
+
return '<div class="frow' + (a.busy ? " busy" : "") + '" data-fagent="' + esc(a.id) + '"><span class="fg">' + agentGlyph(a.kind, a.id) + '</span><span class="fn"><b>' + esc(lbl) + "</b>" + (sub ? "<small>" + esc(sub) + "</small>" : "") + '</span><span class="fs">' + (a.busy ? '<span class="fspin"></span>working' + (a.since ? " \xB7 " + fleetSince(a.since) : "") : '<span class="fidle"></span>idle') + '</span><span class="fa">' + (a.chat ? '<button class="fthr" type="button" data-fchat="' + esc(a.chat) + '" data-fpid="' + esc(info.id) + '" title="open this thread">' + ICONS.thread + "<span>" + esc(chatName) + "</span></button>" : "") + (last && last.line ? '<span class="fline">' + esc(last.line) + '<span class="ft">' + rel(last.ts) + "</span></span>" : a.chat ? "" : '<span class="fline">no activity yet</span>') + '</span><span class="fb">' + (a.holdsBaton ? '<span class="fbaton" title="holds the baton">baton</span>' : "") + permBadge(a.permissions || "auto", void 0, a.kind) + "</span></div>";
|
|
11205
11297
|
}
|
|
11206
11298
|
__name(fleetAgentRow, "fleetAgentRow");
|
|
11207
11299
|
function openFleetThread(toPid, chat) {
|
|
@@ -11327,7 +11419,7 @@
|
|
|
11327
11419
|
canvas: "<b>Right now.</b> Who is running this second, who is idle, and where the " + fx + "baton</b> is \u2014 the ring pulses on whoever holds it. Every agent hangs off the <b>one shared brain</b> in the middle: that is the memory they all read and write, which is the whole point of the fleet. Updates live as turns start and finish. " + drag,
|
|
11328
11420
|
graph: "<b>What already happened.</b> The baton\u2019s actual route through the fleet, left to right, oldest handoff first. Each " + fx + "\u2192</b> is one real handoff from the event log; <code>19t</code> under a name is turns that agent took. Live view is the <b>Live fleet</b> tab \u2014 this one is history. " + drag,
|
|
11329
11421
|
timeline: "<b>The run, in the order it happened.</b> Every turn, handoff, route, memory fold, budget pause and self-heal line on one spine \u2014 so \u201Cwhy did it do that?\u201D is answered by scrolling rather than by guessing. The \u{1F4A1} lines are <b>decisions</b>; click one to read the reasoning behind it.",
|
|
11330
|
-
usage: "<b>What it cost, and what it used.</b> Spend and tokens split by agent, model, chat, day and tool, beside the turn metrics. Each turn\u2019s dollars are counted once, on the turn that spent them. An agent that reports no price (a subscription CLI, a free model) shows its tokens at $0 and is flagged, so the total is the least you spent,
|
|
11422
|
+
usage: "<b>What it cost, and what it used.</b> Spend and tokens split by agent, model, chat, day and tool, beside the turn metrics. Each turn\u2019s dollars are counted once, on the turn that spent them. An agent that reports no price (a subscription CLI, a free model) shows its tokens at $0 and is flagged, so the total is the least you spent; beside it, \u201Cest.\u201D is what those tokens would cost at the model\u2019s API price, when Loom knows it \u2014 an estimate, never added to the total.",
|
|
11331
11423
|
metrics: "<b>Where the run\u2019s time and money actually went.</b> Nothing here is estimated: tokens and cost are what each agent\u2019s own CLI reported for the turn, and the durations are the spans Loom exports. Every agent carries a 0\u2013100 <b>health score</b>, and <b>\u26A0 Triage</b> root-causes a bad one from that agent\u2019s own spans.",
|
|
11332
11424
|
decisions: "<b>The reasoning, not just the result.</b> Every choice an agent made, with what it weighed and rejected \u2014 mined out of its own prose after each turn, so it survives the agent that made it. A confidence it actually measured and one merely pattern-matched are labelled differently, because a number you cannot source is worse than no number.",
|
|
11333
11425
|
alerts: "<b>What your monitoring told Loom, and what Loom did about it.</b> A firing alert takes the named agent out of rotation \u2014 it is refused the baton until the alert resolves \u2014 and a resolved one puts it back. This is the part your dashboards cannot show you: they know the alert fired, only Loom knows the fleet reacted.",
|
|
@@ -11856,7 +11948,7 @@
|
|
|
11856
11948
|
var tile = /* @__PURE__ */ __name(function(label, val2, sub) {
|
|
11857
11949
|
return '<div class="obminicard"><div class="obcl">' + esc(label) + '</div><div class="obcv sm">' + val2 + "</div>" + (sub ? '<div class="usub">' + sub + "</div>" : "") + "</div>";
|
|
11858
11950
|
}, "tile");
|
|
11859
|
-
var tiles = tile("Spend", money(t.usd || 0), t.unpriced ? t.unpriced + " unpriced turn" + (t.unpriced === 1 ? "" : "s") : "every turn priced") + tile("Per turn", money(t.usdPerTurn || 0), (t.turns || 0) + " turns") + tile("Tokens in", tok(t.tokensIn), pct(t.cachedIn, t.tokensIn) + " from cache") + tile("Tokens out", tok(t.tokensOut), t.reasoning ? tok(t.reasoning) + " thinking" : "") + tile("Avg turn", durfmt(t.avgTurnMs || 0), durfmt(t.ms || 0) + " in all") + tile("Tool calls", String(t.toolCalls || 0), (t.toolFailures || 0) + " failed") + tile("Errors", String(t.errors || 0), (t.questions || 0) + " questions asked") + tile("Changed", String(t.filesChanged || 0) + " files", '<span class="cadd">+' + (t.linesAdded || 0) + '</span> <span class="cdel">\u2212' + (t.linesRemoved || 0) + "</span>");
|
|
11951
|
+
var tiles = tile("Spend", money(t.usd || 0), t.unpriced ? (t.estUsd ? '<span title="tokens at the model\u2019s API price, for agents that report tokens but no cost">+ ~' + money(t.estUsd) + " est.</span> \xB7 " : "") + t.unpriced + " unpriced turn" + (t.unpriced === 1 ? "" : "s") : "every turn priced") + tile("Per turn", money(t.usdPerTurn || 0), (t.turns || 0) + " turns") + tile("Tokens in", tok(t.tokensIn), pct(t.cachedIn, t.tokensIn) + " from cache") + tile("Tokens out", tok(t.tokensOut), t.reasoning ? tok(t.reasoning) + " thinking" : "") + tile("Avg turn", durfmt(t.avgTurnMs || 0), durfmt(t.ms || 0) + " in all") + tile("Tool calls", String(t.toolCalls || 0), (t.toolFailures || 0) + " failed") + tile("Errors", String(t.errors || 0), (t.questions || 0) + " questions asked") + tile("Changed", String(t.filesChanged || 0) + " files", '<span class="cadd">+' + (t.linesAdded || 0) + '</span> <span class="cdel">\u2212' + (t.linesRemoved || 0) + "</span>");
|
|
11860
11952
|
var seen = {};
|
|
11861
11953
|
(u.byDay || []).forEach(function(d) {
|
|
11862
11954
|
seen[d.day] = d;
|
|
@@ -11887,11 +11979,14 @@
|
|
|
11887
11979
|
var v = t.usd > 0 ? x.usd / t.usd : (x.tokensIn + x.tokensOut) / ((t.tokensIn || 0) + (t.tokensOut || 0) || 1);
|
|
11888
11980
|
return '<span class="ushare"><i style="width:' + Math.round(v * 100) + '%"></i></span>';
|
|
11889
11981
|
}, "shareBar");
|
|
11982
|
+
var estNote = /* @__PURE__ */ __name(function(x) {
|
|
11983
|
+
return x.estUsd ? ' <span class="uest" title="tokens at the model\u2019s API price \u2014 this agent reports tokens but no cost">~' + money(x.estUsd) + " est.</span>" : "";
|
|
11984
|
+
}, "estNote");
|
|
11890
11985
|
var agentRows = (u.byAgent || []).map(function(a) {
|
|
11891
|
-
return "<tr><td>" + avatarFor(a.agentId) + " " + esc(labelOf(a.agentId)) + (a.unpriced ? ' <span class="uflag" title="reports tokens but no price">unpriced</span>' : "") + '</td><td class="num">' + money(a.usd) + "</td><td>" + shareBar(a) + " " + share(a) + '</td><td class="num">' + a.turns + '</td><td class="num">' + tok(a.tokensIn) + '</td><td class="num">' + tok(a.tokensOut) + '</td><td class="num">' + pct(a.cachedIn, a.tokensIn) + '</td><td class="num">' + (a.turns ? durfmt(a.ms / a.turns) : "\u2014") + '</td><td class="num">' + a.toolCalls + (a.toolFailures ? ' <span class="cdel">(' + a.toolFailures + ")</span>" : "") + '</td><td class="num">' + a.errors + '</td><td class="umodels">' + esc((a.models || []).join(", ")) + "</td></tr>";
|
|
11986
|
+
return "<tr><td>" + avatarFor(a.agentId) + " " + esc(labelOf(a.agentId)) + (a.unpriced ? ' <span class="uflag" title="reports tokens but no price">unpriced</span>' : "") + '</td><td class="num">' + money(a.usd) + estNote(a) + "</td><td>" + shareBar(a) + " " + share(a) + '</td><td class="num">' + a.turns + '</td><td class="num">' + tok(a.tokensIn) + '</td><td class="num">' + tok(a.tokensOut) + '</td><td class="num">' + pct(a.cachedIn, a.tokensIn) + '</td><td class="num">' + (a.turns ? durfmt(a.ms / a.turns) : "\u2014") + '</td><td class="num">' + a.toolCalls + (a.toolFailures ? ' <span class="cdel">(' + a.toolFailures + ")</span>" : "") + '</td><td class="num">' + a.errors + '</td><td class="umodels">' + esc((a.models || []).join(", ")) + "</td></tr>";
|
|
11892
11987
|
}).join("");
|
|
11893
11988
|
var modelRows = (u.byModel || []).map(function(m) {
|
|
11894
|
-
return "<tr><td><code>" + esc(m.model) + '</code></td><td class="num">' + money(m.usd) + "</td><td>" + shareBar(m) + " " + share(m) + '</td><td class="num">' + m.turns + '</td><td class="num">' + tok(m.tokensIn) + '</td><td class="num">' + tok(m.tokensOut) + '</td><td class="num">' + money(m.turns ? m.usd / m.turns : 0) + "</td></tr>";
|
|
11989
|
+
return "<tr><td><code>" + esc(m.model) + '</code></td><td class="num">' + money(m.usd) + estNote(m) + "</td><td>" + shareBar(m) + " " + share(m) + '</td><td class="num">' + m.turns + '</td><td class="num">' + tok(m.tokensIn) + '</td><td class="num">' + tok(m.tokensOut) + '</td><td class="num">' + money(m.turns ? m.usd / m.turns : 0) + "</td></tr>";
|
|
11895
11990
|
}).join("");
|
|
11896
11991
|
var chatRows = (u.byChat || []).map(function(c) {
|
|
11897
11992
|
return '<tr class="uclick" data-uchat="' + esc(c.chat) + '"><td>' + esc(c.title || c.chat) + '</td><td class="num">' + money(c.usd) + '</td><td class="num">' + c.turns + '</td><td class="num">' + tok(c.tokensIn + c.tokensOut) + "</td></tr>";
|
|
@@ -12898,7 +12993,7 @@
|
|
|
12898
12993
|
if (c.race) {
|
|
12899
12994
|
el.innerHTML = modeSeg + '<span class="colbl" title="each gets the same prompt, in its own worktree">Racers</span><span class="cowk" id="cowk">' + roster.map(function(a) {
|
|
12900
12995
|
var on = !c.off[a.id];
|
|
12901
|
-
return '<button type="button" class="cowchip' + (on ? " on" : "") + '" data-wk="' + esc(a.id) + '" aria-pressed="' + on + '"><span class="cwon">' + (on ? ICONS.check : "") + "</span>" + agentGlyph(a.kind, a.id) + '<span class="cwn">' + esc(agentLabel(a.kind, a.id)) + '</span><span class="cwset">' + modelBadge(a) + permBadge(permOf(a), a.id) + "</span></button>";
|
|
12996
|
+
return '<button type="button" class="cowchip' + (on ? " on" : "") + '" data-wk="' + esc(a.id) + '" aria-pressed="' + on + '"><span class="cwon">' + (on ? ICONS.check : "") + "</span>" + agentGlyph(a.kind, a.id) + '<span class="cwn">' + esc(agentLabel(a.kind, a.id)) + '</span><span class="cwset">' + modelBadge(a) + permBadge(permOf(a), a.id, a.kind) + "</span></button>";
|
|
12902
12997
|
}).join("") + "</span>";
|
|
12903
12998
|
Array.prototype.forEach.call(el.querySelectorAll("[data-wk]"), function(b) {
|
|
12904
12999
|
b.onclick = function() {
|
|
@@ -12919,9 +13014,9 @@
|
|
|
12919
13014
|
if (osb) osb.title = "start the race";
|
|
12920
13015
|
return;
|
|
12921
13016
|
}
|
|
12922
|
-
el.innerHTML = modeSeg + '<span class="colbl" title="plans the goal, splits it into tasks, reviews the results">Lead</span><button class="cagent" id="corchpick" type="button" title="who plans the goal and reviews the results">' + agentGlyph(lead.kind, lead.id) + '<span class="can">' + esc(agentLabel(lead.kind, lead.id)) + "</span>" + permBadge(permOf(lead), lead.id) + modelBadge(lead) + '<span class="cchev">' + ICONS.chevron + '</span></button><span class="colbl" title="who can be given tasks \u2014 click to include or leave out">Team</span><span class="cowk" id="cowk">' + roster.map(function(a) {
|
|
13017
|
+
el.innerHTML = modeSeg + '<span class="colbl" title="plans the goal, splits it into tasks, reviews the results">Lead</span><button class="cagent" id="corchpick" type="button" title="who plans the goal and reviews the results">' + agentGlyph(lead.kind, lead.id) + '<span class="can">' + esc(agentLabel(lead.kind, lead.id)) + "</span>" + permBadge(permOf(lead), lead.id, lead.kind) + modelBadge(lead) + '<span class="cchev">' + ICONS.chevron + '</span></button><span class="colbl" title="who can be given tasks \u2014 click to include or leave out">Team</span><span class="cowk" id="cowk">' + roster.map(function(a) {
|
|
12923
13018
|
var on = !c.off[a.id];
|
|
12924
|
-
return '<button type="button" class="cowchip' + (on ? " on" : "") + '" data-wk="' + esc(a.id) + '" aria-pressed="' + on + '" title="' + esc((on ? "included \u2014 click to leave out" : "left out \u2014 click to include") + " \xB7 " + a.id) + '"><span class="cwon">' + (on ? ICONS.check : "") + "</span>" + agentGlyph(a.kind, a.id) + '<span class="cwn">' + esc(agentLabel(a.kind, a.id)) + '</span><span class="cwset">' + modelBadge(a) + permBadge(permOf(a), a.id) + "</span></button>";
|
|
13019
|
+
return '<button type="button" class="cowchip' + (on ? " on" : "") + '" data-wk="' + esc(a.id) + '" aria-pressed="' + on + '" title="' + esc((on ? "included \u2014 click to leave out" : "left out \u2014 click to include") + " \xB7 " + a.id) + '"><span class="cwon">' + (on ? ICONS.check : "") + "</span>" + agentGlyph(a.kind, a.id) + '<span class="cwn">' + esc(agentLabel(a.kind, a.id)) + '</span><span class="cwset">' + modelBadge(a) + permBadge(permOf(a), a.id, a.kind) + "</span></button>";
|
|
12925
13020
|
}).join("") + // A roster of CLIs is whatever you happen to have installed. An API
|
|
12926
13021
|
// model is a name off a list, so it can be added here, in the row
|
|
12927
13022
|
// where you are already deciding who runs the goal.
|
|
@@ -13043,7 +13138,7 @@
|
|
|
13043
13138
|
m.innerHTML = '<div class="cmhead">who orchestrates</div>' + roster.map(function(a, i) {
|
|
13044
13139
|
var lbl = agentLabel(a.kind, a.id);
|
|
13045
13140
|
var sub = agentSub(a, lbl);
|
|
13046
|
-
return '<div class="cmi" data-oi="' + i + '"><span class="ic">' + agentGlyph(a.kind, a.id) + "</span><span>" + esc(lbl) + "</span>" + permBadge(permOf(a), a.id) + (a.busy ? '<span class="cmbusy">working</span>' : "") + (a.id === c.orchestrator ? '<span class="tick"' + (a.busy ? ' style="margin-left:6px"' : "") + ">" + ICONS.info + "</span>" : sub && !a.busy ? '<span class="sub">' + esc(sub) + "</span>" : "") + "</div>";
|
|
13141
|
+
return '<div class="cmi" data-oi="' + i + '"><span class="ic">' + agentGlyph(a.kind, a.id) + "</span><span>" + esc(lbl) + "</span>" + permBadge(permOf(a), a.id, a.kind) + (a.busy ? '<span class="cmbusy">working</span>' : "") + (a.id === c.orchestrator ? '<span class="tick"' + (a.busy ? ' style="margin-left:6px"' : "") + ">" + ICONS.info + "</span>" : sub && !a.busy ? '<span class="sub">' + esc(sub) + "</span>" : "") + "</div>";
|
|
13047
13142
|
}).join("");
|
|
13048
13143
|
Array.prototype.forEach.call(m.querySelectorAll("[data-oi]"), function(row) {
|
|
13049
13144
|
row.onmousedown = function(ev) {
|
|
@@ -17530,6 +17625,14 @@
|
|
|
17530
17625
|
if (c.getAttribute("data-niwho") === e.agentId) settleQuestionCard(c, null);
|
|
17531
17626
|
});
|
|
17532
17627
|
}
|
|
17628
|
+
if (e.kind === "review" && pl.phase === "decided") {
|
|
17629
|
+
settleFinding(feed, pl.findingId, pl.decision);
|
|
17630
|
+
return;
|
|
17631
|
+
}
|
|
17632
|
+
if (e.kind === "council" && (pl.phase === "stage" || pl.phase === "done")) {
|
|
17633
|
+
settleCouncil(feed, pl);
|
|
17634
|
+
return;
|
|
17635
|
+
}
|
|
17533
17636
|
if (e.kind === "approval" && e.payload && e.payload.phase === "decided") {
|
|
17534
17637
|
if (settleApprovalCards(e.payload.approvalId, e.payload.behavior, e.payload.message)) return;
|
|
17535
17638
|
}
|
|
@@ -19354,6 +19457,34 @@
|
|
|
19354
19457
|
});
|
|
19355
19458
|
return;
|
|
19356
19459
|
}
|
|
19460
|
+
var cst = ev.target.closest && ev.target.closest("[data-council-stop]");
|
|
19461
|
+
if (cst) {
|
|
19462
|
+
ev.preventDefault();
|
|
19463
|
+
ev.stopPropagation();
|
|
19464
|
+
cst.disabled = true;
|
|
19465
|
+
api("/api/projects/" + pid + "/councils", { method: "DELETE" }).then(function() {
|
|
19466
|
+
cst.textContent = "Stopping\u2026";
|
|
19467
|
+
}).catch(function(err) {
|
|
19468
|
+
cst.disabled = false;
|
|
19469
|
+
toast(err.message);
|
|
19470
|
+
});
|
|
19471
|
+
return;
|
|
19472
|
+
}
|
|
19473
|
+
var fdb = ev.target.closest && ev.target.closest("[data-finding-decide]");
|
|
19474
|
+
if (fdb) {
|
|
19475
|
+
ev.preventDefault();
|
|
19476
|
+
ev.stopPropagation();
|
|
19477
|
+
var fid = fdb.getAttribute("data-finding-decide"), dec = fdb.getAttribute("data-decision");
|
|
19478
|
+
fdb.disabled = true;
|
|
19479
|
+
api("/api/projects/" + pid + "/findings/" + encodeURIComponent(fid), { method: "POST", body: JSON.stringify({ decision: dec }) }).then(function() {
|
|
19480
|
+
settleFinding(document, fid, dec);
|
|
19481
|
+
if (dec === "accepted") toast("recorded as a decision \u2014 every agent is briefed with it");
|
|
19482
|
+
}).catch(function(err) {
|
|
19483
|
+
fdb.disabled = false;
|
|
19484
|
+
toast(err.message);
|
|
19485
|
+
});
|
|
19486
|
+
return;
|
|
19487
|
+
}
|
|
19357
19488
|
var shs = ev.target.closest && ev.target.closest("[data-shift-stop]");
|
|
19358
19489
|
if (shs) {
|
|
19359
19490
|
ev.preventDefault();
|