codedeck 0.4.0 → 0.4.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/dist/cli/commands/done.js +35 -0
- package/dist/cli/commands/done.js.map +1 -0
- package/dist/cli/commands/send.js +2 -0
- package/dist/cli/commands/send.js.map +1 -1
- package/dist/cli/commands/web.js +89 -6
- package/dist/cli/commands/web.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/events.js.map +1 -1
- package/dist/core/roles.js +28 -5
- package/dist/core/roles.js.map +1 -1
- package/dist/core/session.js.map +1 -1
- package/dist/daemon/daemon.js +289 -93
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/drivers/antigravity/driver.js +52 -38
- package/dist/drivers/antigravity/driver.js.map +1 -1
- package/dist/open/contract.js +6 -2
- package/dist/open/contract.js.map +1 -1
- package/dist/open/launchers/claude.js +8 -2
- package/dist/open/launchers/claude.js.map +1 -1
- package/dist/plugin/agents/auditor.md +13 -5
- package/dist/plugin/agents/general.md +355 -15
- package/dist/plugin/agents/orchestrator-edit.md +16 -5
- package/dist/plugin/agents/orchestrator-read.md +16 -5
- package/dist/plugin/agents/orchestrator.md +16 -5
- package/dist/plugin/agents/reviewer.md +6 -2
- package/dist/plugin/prompts/_partials/commit.md +145 -0
- package/dist/plugin/prompts/_partials/core.md +9 -0
- package/dist/plugin/prompts/_partials/dispatch.md +5 -0
- package/dist/plugin/prompts/_partials/pr-writer.md +186 -0
- package/dist/plugin/prompts/_partials/proof.md +2 -0
- package/dist/plugin/prompts/_partials/rename-run.md +1 -0
- package/dist/plugin/prompts/_partials/review-self.md +4 -0
- package/dist/plugin/prompts/_partials/worktree.md +2 -0
- package/dist/plugin/prompts/roles/auditor.md +35 -0
- package/dist/plugin/prompts/roles/general.md +29 -0
- package/dist/plugin/prompts/roles/orchestrator-edit.md +68 -0
- package/dist/plugin/prompts/roles/orchestrator-read.md +68 -0
- package/dist/plugin/prompts/roles/orchestrator.md +90 -0
- package/dist/plugin/prompts/roles/reviewer.md +37 -0
- package/dist/store/database.js +4 -0
- package/dist/store/database.js.map +1 -1
- package/dist/store/sessions.js +8 -3
- package/dist/store/sessions.js.map +1 -1
- package/dist/web/canvas-page.js +208 -57
- package/dist/web/canvas-page.js.map +1 -1
- package/package.json +1 -1
package/dist/web/canvas-page.js
CHANGED
|
@@ -50,7 +50,7 @@ export const CANVAS_PAGE = `<!doctype html>
|
|
|
50
50
|
#feed li.fresh { color: #f5f5f7; }
|
|
51
51
|
@keyframes feedIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; } }
|
|
52
52
|
#hint { left: 50%; transform: translateX(-50%); bottom: 16px; font-size: 12px; color: #98989f; white-space: nowrap; }
|
|
53
|
-
#detail { position: fixed; top: 0; right: 0; bottom: 0; width: min(
|
|
53
|
+
#detail { position: fixed; top: 0; right: 0; bottom: 0; width: min(400px, 94vw); z-index: 20;
|
|
54
54
|
background: rgba(10, 12, 16, 0.92); border-left: 1px solid rgba(255,255,255,0.1);
|
|
55
55
|
backdrop-filter: blur(14px); padding: 18px; overflow-y: auto; display: none; }
|
|
56
56
|
#detail.open { display: block; }
|
|
@@ -69,6 +69,28 @@ export const CANVAS_PAGE = `<!doctype html>
|
|
|
69
69
|
border: 1px solid rgba(255,255,255,0.12); background: transparent; color: #98989f;
|
|
70
70
|
cursor: pointer; font-size: 14px; line-height: 1; font-family: inherit; }
|
|
71
71
|
#detailClose:hover { color: #f5f5f7; border-color: rgba(255,255,255,0.25); }
|
|
72
|
+
#dChat { border: 1px solid rgba(255,255,255,0.08); border-radius: 10px; padding: 10px; max-height: 52vh; min-height: 140px; overflow-y: auto; display: flex; flex-direction: column; gap: 9px; }
|
|
73
|
+
/* Scroll fino escuro no painel e no chat (Firefox + WebKit): o padrao
|
|
74
|
+
claro do SO quebra o tema escuro da pagina. */
|
|
75
|
+
#detail, #dChat { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.24) transparent; }
|
|
76
|
+
#detail::-webkit-scrollbar, #dChat::-webkit-scrollbar { width: 10px; }
|
|
77
|
+
#detail::-webkit-scrollbar-track, #dChat::-webkit-scrollbar-track { background: transparent; }
|
|
78
|
+
#detail::-webkit-scrollbar-thumb, #dChat::-webkit-scrollbar-thumb { background-color: rgba(255,255,255,0.18); border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }
|
|
79
|
+
#detail::-webkit-scrollbar-thumb:hover, #dChat::-webkit-scrollbar-thumb:hover { background-color: rgba(255,255,255,0.32); }
|
|
80
|
+
#dChat .msg { font-size: 12.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; padding: 7px 9px; border-radius: 9px; }
|
|
81
|
+
#dChat .msg .who { display: block; font-size: 10.5px; letter-spacing: 0.04em; color: #98989f; margin-bottom: 2px; }
|
|
82
|
+
#dChat .msg.user { background: rgba(10,132,255,0.16); }
|
|
83
|
+
#dChat .msg.assistant { background: rgba(255,255,255,0.05); }
|
|
84
|
+
#dChat .evt { font-size: 11.5px; color: #636366; }
|
|
85
|
+
#dChat .empty { color: #636366; font-size: 12px; }
|
|
86
|
+
#dSend { display: flex; gap: 8px; margin-top: 10px; }
|
|
87
|
+
#dSendText { flex: 1; min-width: 0; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12); border-radius: 10px; color: #f5f5f7; padding: 8px 10px; font-size: 12.5px; font-family: inherit; }
|
|
88
|
+
#dSendText:focus { outline: none; border-color: rgba(255,255,255,0.3); }
|
|
89
|
+
#dSendText:disabled { opacity: 0.4; }
|
|
90
|
+
#dSendBtn, #dArchive { border: 1px solid rgba(255,255,255,0.14); background: rgba(10,132,255,0.25); color: #f5f5f7; border-radius: 10px; padding: 8px 12px; cursor: pointer; font-family: inherit; font-size: 12.5px; }
|
|
91
|
+
#dSendBtn:disabled, #dArchive:disabled { opacity: 0.4; cursor: default; }
|
|
92
|
+
#dArchive { width: 100%; margin-top: 8px; }
|
|
93
|
+
#dSendMsg { font-size: 11.5px; color: #98989f; margin: 6px 0 0; min-height: 15px; }
|
|
72
94
|
.node { position: absolute; width: 196px; background: #13161c; border: 1px solid rgba(255,255,255,.09);
|
|
73
95
|
border-radius: 14px; padding: 11px 13px; pointer-events: auto; cursor: grab; user-select: none;
|
|
74
96
|
box-shadow: 0 8px 28px rgba(0,0,0,.45); }
|
|
@@ -105,8 +127,14 @@ export const CANVAS_PAGE = `<!doctype html>
|
|
|
105
127
|
<h2 id="dTitle"></h2>
|
|
106
128
|
<p class="dsub" id="dSub"></p>
|
|
107
129
|
<dl id="dRows"></dl>
|
|
108
|
-
<h3>
|
|
109
|
-
<
|
|
130
|
+
<h3>CONVERSA</h3>
|
|
131
|
+
<div id="dChat"></div>
|
|
132
|
+
<form id="dSend">
|
|
133
|
+
<input id="dSendText" type="text" autocomplete="off" placeholder="mensagem para esta sessão">
|
|
134
|
+
<button id="dSendBtn" type="submit">Enviar</button>
|
|
135
|
+
</form>
|
|
136
|
+
<p id="dSendMsg" role="status"></p>
|
|
137
|
+
<button id="dArchive" type="button" style="display:none">Marcar como concluída</button>
|
|
110
138
|
</aside>
|
|
111
139
|
<script>
|
|
112
140
|
"use strict";
|
|
@@ -114,10 +142,11 @@ var LOGO_ANTHROPIC = '<svg viewBox="0 0 24 24"><path d="M17.304 3.541h-3.672l6.6
|
|
|
114
142
|
var LOGO_OPENAI = '<svg viewBox="0 0 24 24"><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>';
|
|
115
143
|
var LOGO_TERM = '<svg viewBox="0 0 24 24" fill="none" stroke="#f5f5f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="4" width="19" height="16" rx="4"/><path d="M7 9.5l3 3-3 3M12.5 15.5H17"/></svg>';
|
|
116
144
|
var LOGO_ORCH = '<svg viewBox="0 0 24 24" fill="none" stroke="#0a84ff" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="5" r="2.4" fill="#0a84ff" stroke="none"/><circle cx="5" cy="19" r="2.4" fill="#0a84ff" stroke="none"/><circle cx="19" cy="19" r="2.4" fill="#0a84ff" stroke="none"/><path d="M12 7.5 5.8 16.7M12 7.5l6.2 9.2M7.4 19h9.2"/></svg>';
|
|
145
|
+
var LOGO_OPENCODE = '<svg viewBox="0 0 24 24"><path fill-rule="evenodd" d="M16 6H8v12h8V6zm4 16H4V2h16v20z"/></svg>';
|
|
117
146
|
function logoFor(agent) {
|
|
118
147
|
if (agent === "claude") return LOGO_ANTHROPIC;
|
|
119
148
|
if (agent === "codex") return LOGO_OPENAI;
|
|
120
|
-
if (agent === "opencode") return
|
|
149
|
+
if (agent === "opencode") return LOGO_OPENCODE;
|
|
121
150
|
return LOGO_TERM;
|
|
122
151
|
}
|
|
123
152
|
var AGENT_NAME = { claude: "Claude", codex: "Codex", opencode: "OpenCode", omp: "OMP", antigravity: "Antigravity" };
|
|
@@ -253,7 +282,7 @@ function makeNodeEl(n) {
|
|
|
253
282
|
row.className = "row";
|
|
254
283
|
var logo = document.createElement("span");
|
|
255
284
|
logo.className = "logo";
|
|
256
|
-
logo.innerHTML = logoFor(n.agent);
|
|
285
|
+
logo.innerHTML = n.isOrch ? LOGO_ORCH : logoFor(n.agent);
|
|
257
286
|
row.appendChild(logo);
|
|
258
287
|
var dot = document.createElement("i");
|
|
259
288
|
row.appendChild(dot);
|
|
@@ -267,13 +296,14 @@ function makeNodeEl(n) {
|
|
|
267
296
|
var act = document.createElement("div");
|
|
268
297
|
act.className = "act";
|
|
269
298
|
el.appendChild(act);
|
|
270
|
-
n.el = el; n.dotEl = dot; n.nameEl = name; n.subEl = sub; n.actEl = act;
|
|
299
|
+
n.el = el; n.logoEl = logo; n.dotEl = dot; n.nameEl = name; n.subEl = sub; n.actEl = act;
|
|
271
300
|
el.addEventListener("mousedown", function (ev) { startDragNode(ev, n); });
|
|
272
301
|
nodesLayer.appendChild(el);
|
|
273
302
|
paintNode(n);
|
|
274
303
|
}
|
|
275
304
|
function paintNode(n) {
|
|
276
305
|
n.dotEl.className = "dot " + (STATUS_DOT[n.status] || "done");
|
|
306
|
+
if (n.logoEl) n.logoEl.innerHTML = n.isOrch ? LOGO_ORCH : logoFor(n.agent);
|
|
277
307
|
n.nameEl.textContent = n.isOrch ? "Orquestrador" : agentName(n.agent);
|
|
278
308
|
if (n.isOrch) {
|
|
279
309
|
n.subEl.style.display = "";
|
|
@@ -410,6 +440,11 @@ function reconcile(sessions) {
|
|
|
410
440
|
if (Date.now() > n.liveUntil) n.activity = baseActivity(s);
|
|
411
441
|
paintNode(n);
|
|
412
442
|
seen[s.id] = true;
|
|
443
|
+
if (detailId === s.id) {
|
|
444
|
+
detailStatus = s.status;
|
|
445
|
+
detailOrigin = s.origin || null;
|
|
446
|
+
paintSendState();
|
|
447
|
+
}
|
|
413
448
|
});
|
|
414
449
|
for (var id in nodesById) {
|
|
415
450
|
if (!seen[id]) {
|
|
@@ -538,6 +573,12 @@ function onEvent(n, ev) {
|
|
|
538
573
|
touch(n, "respondendo");
|
|
539
574
|
feed(agentName(n.agent), String(ev.content || "").slice(0, 90));
|
|
540
575
|
}
|
|
576
|
+
} else if (ev.type === "message.queued") {
|
|
577
|
+
touch(n, "mensagem na fila");
|
|
578
|
+
feed(agentName(n.agent), "mensagem na fila");
|
|
579
|
+
if (n.id && n.id === detailId) { detailPending = ev.prompt || true; paintSendState(); }
|
|
580
|
+
} else if (ev.type === "turn.started") {
|
|
581
|
+
if (n.id && n.id === detailId && detailPending) { detailPending = null; paintSendState(); }
|
|
541
582
|
} else if (ev.type === "turn.completed") {
|
|
542
583
|
feed(agentName(n.agent), "etapa concluída");
|
|
543
584
|
} else if (ev.type === "file.changed") {
|
|
@@ -553,6 +594,9 @@ function onEvent(n, ev) {
|
|
|
553
594
|
touch(n, ev.type === "session.failed" ? ("falhou: " + (ev.error || "")) : "concluída");
|
|
554
595
|
paintSummary();
|
|
555
596
|
feed(agentName(n.agent), ev.type === "session.failed" ? "falhou" : "concluída");
|
|
597
|
+
// Stop/release cancels the queue server-side: drop a stale "na fila"
|
|
598
|
+
// hint on the open detail, mirroring the turn.started branch.
|
|
599
|
+
if (n.id && n.id === detailId && detailPending) { detailPending = null; paintSendState(); }
|
|
556
600
|
if (n.es) { try { n.es.close(); } catch (e) {} n.es = null; }
|
|
557
601
|
}
|
|
558
602
|
}
|
|
@@ -754,6 +798,10 @@ window.addEventListener("keydown", function (ev) {
|
|
|
754
798
|
if (ev.key === "Escape") closeDetail();
|
|
755
799
|
});
|
|
756
800
|
window.addEventListener("wheel", function (ev) {
|
|
801
|
+
// O painel de detalhe tem scroll proprio (#detail e #dChat): o zoom do
|
|
802
|
+
// canvas so vale fora dele, senao rolar o chat daria zoom na cena.
|
|
803
|
+
var t = ev.target;
|
|
804
|
+
if (t && typeof t.closest === "function" && t.closest("#detail")) return;
|
|
757
805
|
ev.preventDefault();
|
|
758
806
|
var before = toWorld(ev.clientX, ev.clientY);
|
|
759
807
|
cam.zoom = Math.min(2.2, Math.max(0.45, cam.zoom * (ev.deltaY < 0 ? 1.1 : 0.9)));
|
|
@@ -764,17 +812,20 @@ window.addEventListener("wheel", function (ev) {
|
|
|
764
812
|
function syncUrl() {
|
|
765
813
|
try {
|
|
766
814
|
var qp = new URLSearchParams(window.location.search);
|
|
767
|
-
|
|
815
|
+
// Padrão é esconder concluídas: a URL limpa É o estado escondido, e
|
|
816
|
+
// quem quiser ver tudo marca hide=0 explicitamente.
|
|
817
|
+
if (hideDone) qp.delete("hide"); else qp.set("hide", "0");
|
|
768
818
|
if (!motion) qp.set("motion", "0"); else qp.delete("motion");
|
|
769
819
|
var qs = qp.toString();
|
|
770
820
|
window.history.replaceState(null, "", window.location.pathname + (qs ? "?" + qs : ""));
|
|
771
821
|
} catch (e) {}
|
|
772
822
|
}
|
|
773
|
-
// Filtros sobrevivem ao F5: o estado mora na query string (?hide=
|
|
774
|
-
|
|
823
|
+
// Filtros sobrevivem ao F5: o estado mora na query string (?hide=0&motion=0).
|
|
824
|
+
// hideDone nasce true: concluídas ficam fora até alguém pedir hide=0.
|
|
825
|
+
var urlHide = true, urlMotion = true;
|
|
775
826
|
try {
|
|
776
827
|
var qp0 = new URLSearchParams(window.location.search);
|
|
777
|
-
urlHide = qp0.get("hide")
|
|
828
|
+
urlHide = qp0.get("hide") !== "0";
|
|
778
829
|
urlMotion = qp0.get("motion") !== "0";
|
|
779
830
|
} catch (e) {}
|
|
780
831
|
motion = urlMotion;
|
|
@@ -808,31 +859,44 @@ document.getElementById("btnMotion").classList.toggle("on", motion);
|
|
|
808
859
|
document.getElementById("btnHide").classList.toggle("on", hideDone);
|
|
809
860
|
document.getElementById("btnHide").title = hideDone ? "Mostrar concluídas" : "Ocultar concluídas";
|
|
810
861
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
function
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
862
|
+
/* Transcrição da sessão: a mensagem do usuário mora em turn.started.prompt
|
|
863
|
+
(o daemon anexa no turno inicial e a cada send), a resposta em
|
|
864
|
+
message(role=assistant) com content completo. Ferramentas viram linhas
|
|
865
|
+
compactas para a conversa continuar legível. */
|
|
866
|
+
var detailId = null, detailStatus = null, detailOrigin = null, detailPending = null;
|
|
867
|
+
var sendInFlight = false, sendBlockedNote = false;
|
|
868
|
+
function chatMsg(who, text, cls) {
|
|
869
|
+
var d = document.createElement("div");
|
|
870
|
+
d.className = "msg " + cls;
|
|
871
|
+
var w = document.createElement("span");
|
|
872
|
+
w.className = "who";
|
|
873
|
+
w.textContent = who;
|
|
874
|
+
d.appendChild(w);
|
|
875
|
+
d.appendChild(document.createTextNode(text));
|
|
876
|
+
return d;
|
|
877
|
+
}
|
|
878
|
+
function chatEvt(text) {
|
|
879
|
+
var d = document.createElement("div");
|
|
880
|
+
d.className = "evt";
|
|
881
|
+
d.textContent = text;
|
|
882
|
+
return d;
|
|
883
|
+
}
|
|
884
|
+
/* Input e botão seguem o estado do daemon: ocupada trava, origin=open
|
|
885
|
+
(TUI interativa) trava sempre. Mensagem de sucesso não é apagada aqui. */
|
|
886
|
+
function paintSendState() {
|
|
887
|
+
var input = document.getElementById("dSendText");
|
|
888
|
+
var btn = document.getElementById("dSendBtn");
|
|
889
|
+
var msg = document.getElementById("dSendMsg");
|
|
890
|
+
if (!detailId) return;
|
|
891
|
+
// origin=open (TUI interativa) trava sempre; working/starting entra na
|
|
892
|
+
// fila em vez de travar. Mensagem de sucesso não é apagada aqui.
|
|
893
|
+
var reason = "";
|
|
894
|
+
if (detailOrigin === "open") reason = "sessão interativa não aceita mensagens";
|
|
895
|
+
input.disabled = sendInFlight || reason !== "";
|
|
896
|
+
btn.disabled = sendInFlight || reason !== "";
|
|
897
|
+
if (reason) { msg.textContent = reason; sendBlockedNote = true; }
|
|
898
|
+
else if (detailPending) { msg.textContent = "1 mensagem na fila — envia quando o turno terminar"; sendBlockedNote = true; }
|
|
899
|
+
else if (sendBlockedNote) { msg.textContent = ""; sendBlockedNote = false; }
|
|
836
900
|
}
|
|
837
901
|
function row(dt, dd) {
|
|
838
902
|
var d = document.createElement("dt");
|
|
@@ -842,20 +906,33 @@ function row(dt, dd) {
|
|
|
842
906
|
return [d, v];
|
|
843
907
|
}
|
|
844
908
|
function closeDetail() {
|
|
909
|
+
detailId = null;
|
|
910
|
+
detailStatus = null;
|
|
911
|
+
detailOrigin = null;
|
|
912
|
+
detailPending = null;
|
|
845
913
|
document.getElementById("detail").classList.remove("open");
|
|
846
914
|
}
|
|
847
915
|
document.getElementById("detailClose").onclick = closeDetail;
|
|
848
916
|
function selectSession(id) {
|
|
849
|
-
|
|
917
|
+
// /logs traz até 1000 eventos; /get limitaria a transcrição aos 10 últimos.
|
|
918
|
+
fetch("api/sessions/" + encodeURIComponent(id) + "/logs").then(function (r) { return r.json(); }).then(function (j) {
|
|
850
919
|
var s = j.session || j;
|
|
851
920
|
if (!s || !s.id) return;
|
|
921
|
+
detailId = s.id;
|
|
922
|
+
detailStatus = s.status;
|
|
923
|
+
detailOrigin = s.origin || null;
|
|
924
|
+
detailPending = s.pendingMessage || null;
|
|
925
|
+
// Interrupted rows are actionable again: offer archival. Every other
|
|
926
|
+
// status keeps the button hidden.
|
|
927
|
+
document.getElementById("dArchive").style.display = s.status === "interrupted" ? "" : "none";
|
|
852
928
|
var title = document.getElementById("dTitle");
|
|
853
929
|
title.innerHTML = "";
|
|
930
|
+
var isOrch = (nodesById[s.id] && nodesById[s.id].isOrch) || (s.id && s.id === s.runId);
|
|
854
931
|
var logo = document.createElement("span");
|
|
855
932
|
logo.className = "logo";
|
|
856
|
-
logo.innerHTML = logoFor(s.agent);
|
|
933
|
+
logo.innerHTML = isOrch ? LOGO_ORCH : logoFor(s.agent);
|
|
857
934
|
title.appendChild(logo);
|
|
858
|
-
title.appendChild(document.createTextNode(agentName(s.agent) + " · " + (s.name || s.id)));
|
|
935
|
+
title.appendChild(document.createTextNode((isOrch ? "Orquestrador" : agentName(s.agent)) + " · " + (s.name || s.id)));
|
|
859
936
|
document.getElementById("dSub").textContent = (STATUS_HUMAN[s.status] || s.status) +
|
|
860
937
|
(s.createdAt ? " · começou " + timeAgo(s.createdAt) : "");
|
|
861
938
|
var rows = document.getElementById("dRows");
|
|
@@ -870,8 +947,9 @@ function selectSession(id) {
|
|
|
870
947
|
];
|
|
871
948
|
if (s.pid) items.push(["PID", String(s.pid)]);
|
|
872
949
|
if (s.updatedAt) items.push(["Atualizado", timeAgo(s.updatedAt)]);
|
|
950
|
+
var events = j.events || [];
|
|
873
951
|
var tools = 0, msgs = 0;
|
|
874
|
-
|
|
952
|
+
events.forEach(function (ev) {
|
|
875
953
|
if (!ev) return;
|
|
876
954
|
if (ev.type === "tool.completed") tools++;
|
|
877
955
|
if (ev.type === "message" && ev.role === "assistant") msgs++;
|
|
@@ -881,29 +959,102 @@ function selectSession(id) {
|
|
|
881
959
|
items.forEach(function (kv) {
|
|
882
960
|
row(kv[0], kv[1]).forEach(function (el) { rows.appendChild(el); });
|
|
883
961
|
});
|
|
884
|
-
var
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
962
|
+
var chat = document.getElementById("dChat");
|
|
963
|
+
chat.innerHTML = "";
|
|
964
|
+
// Últimos 200 eventos bastam: render além disso só pesa o DOM.
|
|
965
|
+
var start = Math.max(0, events.length - 200);
|
|
966
|
+
for (var i = start; i < events.length; i++) {
|
|
967
|
+
var ev = events[i];
|
|
968
|
+
if (!ev || !ev.type) continue;
|
|
969
|
+
if (ev.type === "turn.started" && ev.prompt) {
|
|
970
|
+
chat.appendChild(chatMsg("você", String(ev.prompt), "user"));
|
|
971
|
+
} else if (ev.type === "message.queued" && ev.prompt) {
|
|
972
|
+
chat.appendChild(chatMsg("você", String(ev.prompt) + " (na fila)", "user"));
|
|
973
|
+
} else if (ev.type === "message" && ev.role === "assistant" && ev.content) {
|
|
974
|
+
chat.appendChild(chatMsg(agentName(s.agent), String(ev.content), "assistant"));
|
|
975
|
+
} else if (ev.type === "tool.started") {
|
|
976
|
+
chat.appendChild(chatEvt("começou: " + toolLabel(ev.tool)));
|
|
977
|
+
} else if (ev.type === "tool.completed") {
|
|
978
|
+
var bad = ev.tool && ev.tool.success === false;
|
|
979
|
+
chat.appendChild(chatEvt("terminou: " + toolLabel(ev.tool) + (bad ? " (com erro)" : "")));
|
|
980
|
+
} else if (ev.type === "permission.requested") {
|
|
981
|
+
chat.appendChild(chatEvt("pediu aprovação: " + (ev.tool || "uma ação")));
|
|
982
|
+
} else if (ev.type === "file.changed") {
|
|
983
|
+
chat.appendChild(chatEvt("mudou " + (ev.path || "um arquivo")));
|
|
984
|
+
}
|
|
898
985
|
}
|
|
899
|
-
if (!
|
|
900
|
-
var empty = document.createElement("
|
|
901
|
-
empty.
|
|
902
|
-
|
|
986
|
+
if (!chat.children.length) {
|
|
987
|
+
var empty = document.createElement("div");
|
|
988
|
+
empty.className = "empty";
|
|
989
|
+
empty.textContent = "Sem mensagens ainda.";
|
|
990
|
+
chat.appendChild(empty);
|
|
903
991
|
}
|
|
992
|
+
chat.scrollTop = chat.scrollHeight;
|
|
904
993
|
document.getElementById("detail").classList.add("open");
|
|
994
|
+
paintSendState();
|
|
905
995
|
}).catch(function () {});
|
|
906
996
|
}
|
|
997
|
+
document.getElementById("dSend").addEventListener("submit", function (ev) {
|
|
998
|
+
ev.preventDefault();
|
|
999
|
+
if (!detailId || sendInFlight) return;
|
|
1000
|
+
var input = document.getElementById("dSendText");
|
|
1001
|
+
var text = input.value.trim();
|
|
1002
|
+
if (!text) return;
|
|
1003
|
+
var msg = document.getElementById("dSendMsg");
|
|
1004
|
+
var btn = document.getElementById("dSendBtn");
|
|
1005
|
+
sendInFlight = true;
|
|
1006
|
+
input.disabled = true;
|
|
1007
|
+
btn.disabled = true;
|
|
1008
|
+
msg.textContent = "enviando...";
|
|
1009
|
+
fetch("api/sessions/" + encodeURIComponent(detailId) + "/send", {
|
|
1010
|
+
method: "POST",
|
|
1011
|
+
headers: { "content-type": "application/json" },
|
|
1012
|
+
body: JSON.stringify({ message: text })
|
|
1013
|
+
}).then(function (r) {
|
|
1014
|
+
return r.json().then(function (j) { return { ok: r.ok, body: j }; });
|
|
1015
|
+
}).then(function (out) {
|
|
1016
|
+
if (out.ok) {
|
|
1017
|
+
input.value = "";
|
|
1018
|
+
if (out.body && out.body.queued) {
|
|
1019
|
+
detailPending = text;
|
|
1020
|
+
msg.textContent = "mensagem na fila — envia quando o turno terminar";
|
|
1021
|
+
} else {
|
|
1022
|
+
detailPending = null;
|
|
1023
|
+
msg.textContent = "mensagem enviada — nova etapa começou";
|
|
1024
|
+
}
|
|
1025
|
+
poll();
|
|
1026
|
+
} else {
|
|
1027
|
+
msg.textContent = (out.body && out.body.error) || "não deu para enviar";
|
|
1028
|
+
}
|
|
1029
|
+
}).catch(function () {
|
|
1030
|
+
msg.textContent = "daemon fora do ar?";
|
|
1031
|
+
}).then(function () {
|
|
1032
|
+
sendInFlight = false;
|
|
1033
|
+
paintSendState();
|
|
1034
|
+
});
|
|
1035
|
+
});
|
|
1036
|
+
document.getElementById("dArchive").addEventListener("click", function () {
|
|
1037
|
+
if (!detailId) return;
|
|
1038
|
+
var msg = document.getElementById("dSendMsg");
|
|
1039
|
+
var btn = document.getElementById("dArchive");
|
|
1040
|
+
btn.disabled = true;
|
|
1041
|
+
msg.textContent = "arquivando...";
|
|
1042
|
+
fetch("api/sessions/" + encodeURIComponent(detailId) + "/release", { method: "POST" }).then(function (r) {
|
|
1043
|
+
return r.json().then(function (j) { return { ok: r.ok, body: j }; });
|
|
1044
|
+
}).then(function (out) {
|
|
1045
|
+
if (out.ok) {
|
|
1046
|
+
msg.textContent = "sessão arquivada como concluída";
|
|
1047
|
+
selectSession(detailId);
|
|
1048
|
+
poll();
|
|
1049
|
+
} else {
|
|
1050
|
+
msg.textContent = (out.body && out.body.error) || "não deu para arquivar";
|
|
1051
|
+
}
|
|
1052
|
+
}).catch(function () {
|
|
1053
|
+
msg.textContent = "daemon fora do ar?";
|
|
1054
|
+
}).then(function () {
|
|
1055
|
+
btn.disabled = false;
|
|
1056
|
+
});
|
|
1057
|
+
});
|
|
907
1058
|
|
|
908
1059
|
function poll() {
|
|
909
1060
|
fetch("api/sessions").then(function (r) { return r.json(); }).then(function (j) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-page.js","sourceRoot":"","sources":["../../src/web/canvas-page.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW
|
|
1
|
+
{"version":3,"file":"canvas-page.js","sourceRoot":"","sources":["../../src/web/canvas-page.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAuiC3B,CAAC"}
|
package/package.json
CHANGED