codedeck 0.5.2 → 0.5.3
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/README.md +1 -1
- package/dist/cli/commands/doctor.js +24 -6
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/profile.js +7 -2
- package/dist/cli/commands/profile.js.map +1 -1
- package/dist/cli/commands/ps.js +41 -6
- package/dist/cli/commands/ps.js.map +1 -1
- package/dist/cli/commands/setup.js +50 -22
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/web.js +1 -1
- package/dist/core/events.js.map +1 -1
- package/dist/core/pricing.js +51 -6
- package/dist/core/pricing.js.map +1 -1
- package/dist/daemon/daemon.js +30 -1
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/drivers/antigravity/driver.js +105 -2
- package/dist/drivers/antigravity/driver.js.map +1 -1
- package/dist/drivers/antigravity/parser.js +108 -2
- package/dist/drivers/antigravity/parser.js.map +1 -1
- package/dist/drivers/claude/parser.js +3 -1
- package/dist/drivers/claude/parser.js.map +1 -1
- package/dist/drivers/opencode/parser.js +26 -1
- package/dist/drivers/opencode/parser.js.map +1 -1
- package/dist/open/launchers/opencode.js +1 -1
- package/dist/open/launchers/opencode.js.map +1 -1
- package/dist/open/runtime.js +8 -0
- package/dist/open/runtime.js.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/agents/orchestrator-edit.md +11 -2
- package/dist/plugin/agents/orchestrator-read.md +11 -2
- package/dist/plugin/agents/orchestrator.md +4 -2
- package/dist/plugin/hooks/hooks.json +2 -0
- package/dist/plugin/hooks/register.tsx +251 -0
- package/dist/plugin/mods/agents/pane.ts +453 -0
- package/dist/plugin/mods/agents/parse.ts +29 -0
- package/dist/plugin/mods/agents/types.ts +43 -0
- package/dist/plugin/prompts/_partials/spec-gates.md +2 -0
- package/dist/plugin/prompts/roles/orchestrator-edit.md +2 -1
- package/dist/plugin/prompts/roles/orchestrator-read.md +2 -1
- package/dist/plugin/prompts/roles/orchestrator.md +2 -2
- package/dist/plugin/skills/tlc-spec-driven/SKILL.md +186 -0
- package/dist/plugin/skills/tlc-spec-driven/references/code-analysis.md +98 -0
- package/dist/plugin/skills/tlc-spec-driven/references/coding-principles.md +72 -0
- package/dist/plugin/skills/tlc-spec-driven/references/context-limits.md +31 -0
- package/dist/plugin/skills/tlc-spec-driven/references/design.md +199 -0
- package/dist/plugin/skills/tlc-spec-driven/references/discuss.md +159 -0
- package/dist/plugin/skills/tlc-spec-driven/references/implement.md +436 -0
- package/dist/plugin/skills/tlc-spec-driven/references/lessons.md +115 -0
- package/dist/plugin/skills/tlc-spec-driven/references/memory.md +144 -0
- package/dist/plugin/skills/tlc-spec-driven/references/specify.md +228 -0
- package/dist/plugin/skills/tlc-spec-driven/references/sub-agents.md +147 -0
- package/dist/plugin/skills/tlc-spec-driven/references/tasks.md +451 -0
- package/dist/plugin/skills/tlc-spec-driven/references/validate.md +355 -0
- package/dist/plugin/skills/tlc-spec-driven/scripts/check_commit.py +133 -0
- package/dist/plugin/skills/tlc-spec-driven/scripts/lessons.py +412 -0
- package/dist/plugin/skills/tlc-spec-driven/scripts/validate_spec.py +284 -0
- package/dist/plugin/skills/tlc-spec-driven/scripts/validate_state.py +196 -0
- package/dist/plugin/skills/tlc-spec-driven/scripts/validate_tasks.py +287 -0
- package/dist/plugin/statusline.sh +0 -1
- package/dist/web/canvas-page.js +82 -82
- package/package.json +1 -1
package/dist/web/canvas-page.js
CHANGED
|
@@ -119,28 +119,28 @@ export const CANVAS_PAGE = `<!doctype html>
|
|
|
119
119
|
<body>
|
|
120
120
|
<canvas id="scene"></canvas>
|
|
121
121
|
<div id="nodes"></div>
|
|
122
|
-
<div class="hud" id="title"><h1><span class="live"></span>
|
|
122
|
+
<div class="hud" id="title"><h1><span class="live"></span>Run canvas</h1><p id="summary">connecting...</p></div>
|
|
123
123
|
<div class="hud" id="tools">
|
|
124
|
-
<button id="btnMotion" class="on" type="button" title="
|
|
125
|
-
<button id="btnReset" type="button" title="
|
|
126
|
-
<button id="btnHide" type="button" title="
|
|
124
|
+
<button id="btnMotion" class="on" type="button" title="Pause motion"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12h3l2.5-6 3.5 12 3-9 2 3H22"/></svg></button>
|
|
125
|
+
<button id="btnReset" type="button" title="Recenter" aria-label="Recenter"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="7"/><circle cx="12" cy="12" r="1.5" fill="currentColor" stroke="none"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3"/></svg></button>
|
|
126
|
+
<button id="btnHide" type="button" title="Hide completed" aria-label="Hide completed"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l18 18"/><path d="M10.6 5.1A9.8 9.8 0 0 1 12 5c7 0 10 7 10 7a17 17 0 0 1-2.9 3.6M6.6 6.6C3.6 8.2 2 12 2 12s3 7 10 7c1.5 0 2.8-.3 4-.8"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/></svg></button>
|
|
127
127
|
</div>
|
|
128
|
-
<div class="hud" id="legend"><span><i class="dot working"></i>
|
|
129
|
-
<div class="hud" id="feed"><h2>
|
|
130
|
-
<div class="hud" id="hint">
|
|
131
|
-
<aside id="detail" aria-label="
|
|
132
|
-
<button id="detailClose" type="button" aria-label="
|
|
128
|
+
<div class="hud" id="legend"><span><i class="dot working"></i>Working</span><span><i class="dot waiting"></i>Waiting for you</span><span><i class="dot resting"></i>Paused</span><span><i class="dot done"></i>Completed</span></div>
|
|
129
|
+
<div class="hud" id="feed"><h2>RIGHT NOW</h2><ul id="feedList"></ul></div>
|
|
130
|
+
<div class="hud" id="hint">drag to arrange · scroll to zoom · click an agent for details</div>
|
|
131
|
+
<aside id="detail" aria-label="Session details">
|
|
132
|
+
<button id="detailClose" type="button" aria-label="Close">×</button>
|
|
133
133
|
<h2 id="dTitle"></h2>
|
|
134
134
|
<p class="dsub" id="dSub"></p>
|
|
135
135
|
<dl id="dRows"></dl>
|
|
136
|
-
<h3>
|
|
136
|
+
<h3>CONVERSATION</h3>
|
|
137
137
|
<div id="dChat"></div>
|
|
138
138
|
<form id="dSend">
|
|
139
|
-
<input id="dSendText" type="text" autocomplete="off" placeholder="
|
|
140
|
-
<button id="dSendBtn" type="submit">
|
|
139
|
+
<input id="dSendText" type="text" autocomplete="off" placeholder="message for this session">
|
|
140
|
+
<button id="dSendBtn" type="submit">Send</button>
|
|
141
141
|
</form>
|
|
142
142
|
<p id="dSendMsg" role="status"></p>
|
|
143
|
-
<button id="dArchive" type="button" style="display:none">
|
|
143
|
+
<button id="dArchive" type="button" style="display:none">Mark as completed</button>
|
|
144
144
|
</aside>
|
|
145
145
|
<script>
|
|
146
146
|
"use strict";
|
|
@@ -157,9 +157,9 @@ function logoFor(agent) {
|
|
|
157
157
|
}
|
|
158
158
|
var AGENT_NAME = { claude: "Claude", codex: "Codex", opencode: "OpenCode", omp: "OMP", antigravity: "Antigravity" };
|
|
159
159
|
function agentName(a) { return AGENT_NAME[a] || a || "?"; }
|
|
160
|
-
var STATUS_HUMAN = { working: "
|
|
161
|
-
idle: "
|
|
162
|
-
orphaned: "
|
|
160
|
+
var STATUS_HUMAN = { working: "Working now", starting: "Working now", needs_input: "Waiting for you",
|
|
161
|
+
idle: "Paused", completed: "Completed", failed: "Failed", stopped: "Stopped",
|
|
162
|
+
orphaned: "Interrupted", interrupted: "Interrupted", dead: "Died" };
|
|
163
163
|
var STATUS_DOT = { working: "working", starting: "working", needs_input: "waiting", idle: "resting",
|
|
164
164
|
completed: "done", failed: "failed", stopped: "done", orphaned: "waiting", interrupted: "waiting", dead: "done" };
|
|
165
165
|
var STATUS_COLOR = { working: "#30d158", starting: "#30d158", needs_input: "#ff9f0a", idle: "#636366",
|
|
@@ -167,18 +167,18 @@ var STATUS_COLOR = { working: "#30d158", starting: "#30d158", needs_input: "#ff9
|
|
|
167
167
|
dead: "#3a3a3c" };
|
|
168
168
|
function lastEventHuman(last) {
|
|
169
169
|
if (!last) return "";
|
|
170
|
-
if (last === "exit 0") return "
|
|
171
|
-
if (last === "agent_end") return "
|
|
170
|
+
if (last === "exit 0") return "finished successfully";
|
|
171
|
+
if (last === "agent_end") return "finished its response";
|
|
172
172
|
if (last.indexOf("tool: ") === 0) {
|
|
173
173
|
var tool = last.slice(6);
|
|
174
|
-
if (tool === "bash") return "
|
|
175
|
-
return "
|
|
174
|
+
if (tool === "bash") return "running terminal commands";
|
|
175
|
+
return "using " + tool;
|
|
176
176
|
}
|
|
177
|
-
if (last.indexOf("send: ") === 0) return "
|
|
177
|
+
if (last.indexOf("send: ") === 0) return "received your message";
|
|
178
178
|
return "";
|
|
179
179
|
}
|
|
180
180
|
function toolHuman(name) {
|
|
181
|
-
if (!name) return "
|
|
181
|
+
if (!name) return "a task";
|
|
182
182
|
if (name === "bash" || name === "Bash") return "terminal";
|
|
183
183
|
return name;
|
|
184
184
|
}
|
|
@@ -195,7 +195,7 @@ function inputSnippet(input) {
|
|
|
195
195
|
if (!input) return "";
|
|
196
196
|
if (typeof input === "string") return clip(input);
|
|
197
197
|
if (typeof input !== "object") return "";
|
|
198
|
-
if (Array.isArray(input.todos)) return "(" + input.todos.length + "
|
|
198
|
+
if (Array.isArray(input.todos)) return "(" + input.todos.length + " tasks)";
|
|
199
199
|
var pathKeys = ["filePath", "file_path", "filename", "file", "path", "target", "dest", "directory", "dir"];
|
|
200
200
|
for (var p = 0; p < pathKeys.length; p++) {
|
|
201
201
|
var pv = input[pathKeys[p]];
|
|
@@ -215,7 +215,7 @@ function clip(s) {
|
|
|
215
215
|
function toolLabel(tool) {
|
|
216
216
|
var name = (tool && tool.name) || "";
|
|
217
217
|
var snip = (tool && tool.title && typeof tool.title === "string") ? clip(tool.title) : inputSnippet(tool && tool.input);
|
|
218
|
-
if (!name) return snip || "
|
|
218
|
+
if (!name) return snip || "task";
|
|
219
219
|
if (name === "bash" || name === "Bash") return snip ? "$ " + snip : "terminal";
|
|
220
220
|
return snip ? name + " " + snip : name;
|
|
221
221
|
}
|
|
@@ -223,11 +223,11 @@ function timeAgo(iso) {
|
|
|
223
223
|
var t = new Date(iso).getTime();
|
|
224
224
|
if (!t) return "";
|
|
225
225
|
var m = Math.max(0, Math.round((Date.now() - t) / 60000));
|
|
226
|
-
if (m < 1) return "
|
|
227
|
-
if (m < 60) return
|
|
226
|
+
if (m < 1) return "just now";
|
|
227
|
+
if (m < 60) return m + " min ago";
|
|
228
228
|
var h = Math.floor(m / 60);
|
|
229
|
-
if (h < 24) return
|
|
230
|
-
return
|
|
229
|
+
if (h < 24) return h + " hr ago";
|
|
230
|
+
return Math.floor(h / 24) + " days ago";
|
|
231
231
|
}
|
|
232
232
|
function ringSlot(wi) {
|
|
233
233
|
var j = 0, start = 0;
|
|
@@ -323,23 +323,23 @@ function makeNodeEl(n) {
|
|
|
323
323
|
function paintNode(n) {
|
|
324
324
|
n.dotEl.className = "dot " + (STATUS_DOT[n.status] || "done");
|
|
325
325
|
if (n.logoEl) n.logoEl.innerHTML = n.isOrch ? LOGO_ORCH : logoFor(n.agent);
|
|
326
|
-
n.nameEl.textContent = n.isOrch ? "
|
|
326
|
+
n.nameEl.textContent = n.isOrch ? "Orchestrator" : agentName(n.agent);
|
|
327
327
|
if (n.isOrch) {
|
|
328
328
|
n.subEl.style.display = "";
|
|
329
|
-
n.subEl.textContent = n.count + (n.count === 1 ? "
|
|
329
|
+
n.subEl.textContent = n.count + (n.count === 1 ? " session" : " sessions");
|
|
330
330
|
} else {
|
|
331
331
|
n.subEl.style.display = "none";
|
|
332
332
|
n.subEl.textContent = "";
|
|
333
333
|
}
|
|
334
334
|
n.actEl.innerHTML = "";
|
|
335
335
|
var b = document.createElement("b");
|
|
336
|
-
b.textContent = STATUS_HUMAN[n.status] || "
|
|
336
|
+
b.textContent = STATUS_HUMAN[n.status] || "Completed";
|
|
337
337
|
n.actEl.appendChild(b);
|
|
338
338
|
n.actEl.appendChild(document.createTextNode(" · " + n.activity));
|
|
339
339
|
n.actEl.title = (STATUS_HUMAN[n.status] || "") + (n.activity ? " · " + n.activity : "");
|
|
340
340
|
n.el.classList.toggle("orch", !!n.isOrch);
|
|
341
341
|
n.el.classList.toggle("alert", n.status === "needs_input");
|
|
342
|
-
n.el.title = "
|
|
342
|
+
n.el.title = "session " + n.id + (n.label ? " · " + n.label : "");
|
|
343
343
|
}
|
|
344
344
|
function feed(agent, text, kind) {
|
|
345
345
|
if (!text) return;
|
|
@@ -386,24 +386,24 @@ function paintSummary() {
|
|
|
386
386
|
});
|
|
387
387
|
var el = document.getElementById("summary");
|
|
388
388
|
el.innerHTML = "";
|
|
389
|
-
el.appendChild(document.createTextNode(nodes.length + "
|
|
390
|
-
var b1 = document.createElement("b"); b1.textContent = working + "
|
|
389
|
+
el.appendChild(document.createTextNode(nodes.length + " sessions · "));
|
|
390
|
+
var b1 = document.createElement("b"); b1.textContent = working + " working"; el.appendChild(b1);
|
|
391
391
|
el.appendChild(document.createTextNode(" · "));
|
|
392
|
-
var b2 = document.createElement("b"); b2.textContent = waiting + "
|
|
393
|
-
if (hidden > 0) el.appendChild(document.createTextNode(" · " + hidden + "
|
|
392
|
+
var b2 = document.createElement("b"); b2.textContent = waiting + " waiting for you"; el.appendChild(b2);
|
|
393
|
+
if (hidden > 0) el.appendChild(document.createTextNode(" · " + hidden + " hidden"));
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
/* Reconcilia o poll com os nos: preserva posicao arrastada, atualiza status. */
|
|
397
397
|
var streams = {};
|
|
398
398
|
function baseActivity(s) {
|
|
399
|
-
if (s.status === "needs_input") return "
|
|
399
|
+
if (s.status === "needs_input") return "waiting for your approval";
|
|
400
400
|
var last = lastEventHuman(s.lastEvent);
|
|
401
|
-
if (s.status === "failed") return last ? "
|
|
402
|
-
if (s.status === "dead") return last ? "
|
|
403
|
-
if (s.status === "completed") return last ? "
|
|
404
|
-
if (s.status === "working" || s.status === "starting") return last || "
|
|
405
|
-
if (last) return "
|
|
406
|
-
return "
|
|
401
|
+
if (s.status === "failed") return last ? "failed while " + last : "failed, check the logs";
|
|
402
|
+
if (s.status === "dead") return last ? "died while " + last : "died, the process disappeared";
|
|
403
|
+
if (s.status === "completed") return last ? "completed, " + last : "completed";
|
|
404
|
+
if (s.status === "working" || s.status === "starting") return last || "processing...";
|
|
405
|
+
if (last) return "last: " + last;
|
|
406
|
+
return "no recent activity";
|
|
407
407
|
}
|
|
408
408
|
var lastSessions = [];
|
|
409
409
|
function visibleNodes() {
|
|
@@ -602,7 +602,7 @@ function onEvent(n, ev) {
|
|
|
602
602
|
if (!ev || !ev.type) return;
|
|
603
603
|
if (ev.type === "text.delta") {
|
|
604
604
|
spawnFlow(n, "#30d158", 1);
|
|
605
|
-
touch(n, "
|
|
605
|
+
touch(n, "writing a response");
|
|
606
606
|
} else if (ev.type === "tool.started") {
|
|
607
607
|
spawnRing(n, "#0a84ff");
|
|
608
608
|
spawnFlow(n, "#0a84ff", 1);
|
|
@@ -610,35 +610,35 @@ function onEvent(n, ev) {
|
|
|
610
610
|
feed(agentName(n.agent), toolLabel(ev.tool));
|
|
611
611
|
} else if (ev.type === "tool.completed") {
|
|
612
612
|
var bad = ev.tool && ev.tool.success === false;
|
|
613
|
-
touch(n, toolLabel(ev.tool) + (bad ? " (
|
|
614
|
-
if (bad) feed(agentName(n.agent), "
|
|
613
|
+
touch(n, toolLabel(ev.tool) + (bad ? " (failed)" : " ✓"));
|
|
614
|
+
if (bad) feed(agentName(n.agent), "failed: " + toolLabel(ev.tool), "bad");
|
|
615
615
|
} else if (ev.type === "message") {
|
|
616
616
|
if (ev.role === "assistant") {
|
|
617
|
-
touch(n, "
|
|
617
|
+
touch(n, "responding");
|
|
618
618
|
var textSnippet = clip(ev.content || "");
|
|
619
619
|
if (textSnippet) feed(agentName(n.agent), textSnippet);
|
|
620
620
|
}
|
|
621
621
|
} else if (ev.type === "message.queued") {
|
|
622
|
-
touch(n, "
|
|
623
|
-
feed(agentName(n.agent), "
|
|
622
|
+
touch(n, "message queued");
|
|
623
|
+
feed(agentName(n.agent), "message queued");
|
|
624
624
|
if (n.id && n.id === detailId) { detailPending = ev.prompt || true; paintSendState(); }
|
|
625
625
|
} else if (ev.type === "turn.started") {
|
|
626
626
|
if (n.id && n.id === detailId && detailPending) { detailPending = null; paintSendState(); }
|
|
627
627
|
} else if (ev.type === "turn.completed") {
|
|
628
628
|
// turn completion is recorded on node activity
|
|
629
629
|
} else if (ev.type === "file.changed") {
|
|
630
|
-
feed(agentName(n.agent), "
|
|
630
|
+
feed(agentName(n.agent), "saved " + (shortPath(ev.path === "unknown" ? "" : ev.path) || "file"));
|
|
631
631
|
} else if (ev.type === "permission.requested") {
|
|
632
632
|
n.status = "needs_input";
|
|
633
|
-
touch(n, "
|
|
633
|
+
touch(n, "waiting for your approval");
|
|
634
634
|
paintSummary();
|
|
635
635
|
spawnRing(n, "#ff9f0a");
|
|
636
|
-
feed(agentName(n.agent), "
|
|
636
|
+
feed(agentName(n.agent), "needs approval", "warn");
|
|
637
637
|
} else if (ev.type === "session.completed" || ev.type === "session.failed") {
|
|
638
638
|
n.status = ev.type === "session.failed" ? "failed" : "completed";
|
|
639
|
-
touch(n, ev.type === "session.failed" ? ("
|
|
639
|
+
touch(n, ev.type === "session.failed" ? ("failed: " + (ev.error || "")) : "completed");
|
|
640
640
|
paintSummary();
|
|
641
|
-
feed(agentName(n.agent), ev.type === "session.failed" ? "
|
|
641
|
+
feed(agentName(n.agent), ev.type === "session.failed" ? "failed" : "completed", ev.type === "session.failed" ? "bad" : "");
|
|
642
642
|
// Stop/release cancels the queue server-side: drop a stale "na fila"
|
|
643
643
|
// hint on the open detail, mirroring the turn.started branch.
|
|
644
644
|
if (n.id && n.id === detailId && detailPending) { detailPending = null; paintSendState(); }
|
|
@@ -893,7 +893,7 @@ var hideDone = urlHide;
|
|
|
893
893
|
document.getElementById("btnHide").onclick = function (ev) {
|
|
894
894
|
hideDone = !hideDone;
|
|
895
895
|
ev.currentTarget.classList.toggle("on", hideDone);
|
|
896
|
-
ev.currentTarget.title = hideDone ? "
|
|
896
|
+
ev.currentTarget.title = hideDone ? "Show completed" : "Hide completed";
|
|
897
897
|
// Trocar o filtro reempacota o mundo e reenquadra: sem isso os nos
|
|
898
898
|
// visiveis ficam presos nos slots antigos, a um oceano de distancia.
|
|
899
899
|
layoutVisible();
|
|
@@ -903,7 +903,7 @@ document.getElementById("btnHide").onclick = function (ev) {
|
|
|
903
903
|
};
|
|
904
904
|
document.getElementById("btnMotion").classList.toggle("on", motion);
|
|
905
905
|
document.getElementById("btnHide").classList.toggle("on", hideDone);
|
|
906
|
-
document.getElementById("btnHide").title = hideDone ? "
|
|
906
|
+
document.getElementById("btnHide").title = hideDone ? "Show completed" : "Hide completed";
|
|
907
907
|
|
|
908
908
|
/* Transcrição da sessão: a mensagem do usuário mora em turn.started.prompt
|
|
909
909
|
(o daemon anexa no turno inicial e a cada send), a resposta em
|
|
@@ -937,11 +937,11 @@ function paintSendState() {
|
|
|
937
937
|
// origin=open (TUI interativa) trava sempre; working/starting entra na
|
|
938
938
|
// fila em vez de travar. Mensagem de sucesso não é apagada aqui.
|
|
939
939
|
var reason = "";
|
|
940
|
-
if (detailOrigin === "open") reason = "
|
|
940
|
+
if (detailOrigin === "open") reason = "interactive sessions do not accept messages";
|
|
941
941
|
input.disabled = sendInFlight || reason !== "";
|
|
942
942
|
btn.disabled = sendInFlight || reason !== "";
|
|
943
943
|
if (reason) { msg.textContent = reason; sendBlockedNote = true; }
|
|
944
|
-
else if (detailPending) { msg.textContent = "1
|
|
944
|
+
else if (detailPending) { msg.textContent = "1 message queued - sends when the turn ends"; sendBlockedNote = true; }
|
|
945
945
|
else if (sendBlockedNote) { msg.textContent = ""; sendBlockedNote = false; }
|
|
946
946
|
}
|
|
947
947
|
function row(dt, dd) {
|
|
@@ -978,21 +978,21 @@ function selectSession(id) {
|
|
|
978
978
|
logo.className = "logo";
|
|
979
979
|
logo.innerHTML = isOrch ? LOGO_ORCH : logoFor(s.agent);
|
|
980
980
|
title.appendChild(logo);
|
|
981
|
-
title.appendChild(document.createTextNode((isOrch ? "
|
|
981
|
+
title.appendChild(document.createTextNode((isOrch ? "Orchestrator" : agentName(s.agent)) + " · " + (s.name || s.id)));
|
|
982
982
|
document.getElementById("dSub").textContent = (STATUS_HUMAN[s.status] || s.status) +
|
|
983
|
-
(s.createdAt ? " ·
|
|
983
|
+
(s.createdAt ? " · started " + timeAgo(s.createdAt) : "");
|
|
984
984
|
var rows = document.getElementById("dRows");
|
|
985
985
|
rows.innerHTML = "";
|
|
986
986
|
var repo = s.repository ? String(s.repository).split("/").pop() : "";
|
|
987
987
|
var items = [
|
|
988
|
-
["
|
|
988
|
+
["Model", s.model || "—"],
|
|
989
989
|
// effort chega sempre para claude/codex/omp/antigravity; ausente = opencode (ignora) ou sessão legada.
|
|
990
|
-
["
|
|
990
|
+
["Effort", s.effort || "n/a"],
|
|
991
991
|
["Repo", repo || "—"],
|
|
992
|
-
["
|
|
992
|
+
["Activity", s.lastEvent ? (lastEventHuman(s.lastEvent) || s.lastEvent) : "—"],
|
|
993
993
|
];
|
|
994
994
|
if (s.pid) items.push(["PID", String(s.pid)]);
|
|
995
|
-
if (s.updatedAt) items.push(["
|
|
995
|
+
if (s.updatedAt) items.push(["Updated", timeAgo(s.updatedAt)]);
|
|
996
996
|
var events = j.events || [];
|
|
997
997
|
var tools = 0, msgs = 0;
|
|
998
998
|
events.forEach(function (ev) {
|
|
@@ -1000,8 +1000,8 @@ function selectSession(id) {
|
|
|
1000
1000
|
if (ev.type === "tool.completed") tools++;
|
|
1001
1001
|
if (ev.type === "message" && ev.role === "assistant") msgs++;
|
|
1002
1002
|
});
|
|
1003
|
-
items.push(["
|
|
1004
|
-
items.push(["
|
|
1003
|
+
items.push(["Tools", String(tools)]);
|
|
1004
|
+
items.push(["Replies", String(msgs)]);
|
|
1005
1005
|
items.forEach(function (kv) {
|
|
1006
1006
|
row(kv[0], kv[1]).forEach(function (el) { rows.appendChild(el); });
|
|
1007
1007
|
});
|
|
@@ -1013,26 +1013,26 @@ function selectSession(id) {
|
|
|
1013
1013
|
var ev = events[i];
|
|
1014
1014
|
if (!ev || !ev.type) continue;
|
|
1015
1015
|
if (ev.type === "turn.started" && ev.prompt) {
|
|
1016
|
-
chat.appendChild(chatMsg("
|
|
1016
|
+
chat.appendChild(chatMsg("you", String(ev.prompt), "user"));
|
|
1017
1017
|
} else if (ev.type === "message.queued" && ev.prompt) {
|
|
1018
|
-
chat.appendChild(chatMsg("
|
|
1018
|
+
chat.appendChild(chatMsg("you", String(ev.prompt) + " (queued)", "user"));
|
|
1019
1019
|
} else if (ev.type === "message" && ev.role === "assistant" && ev.content) {
|
|
1020
1020
|
chat.appendChild(chatMsg(agentName(s.agent), String(ev.content), "assistant"));
|
|
1021
1021
|
} else if (ev.type === "tool.started") {
|
|
1022
1022
|
chat.appendChild(chatEvt(toolLabel(ev.tool)));
|
|
1023
1023
|
} else if (ev.type === "tool.completed") {
|
|
1024
1024
|
var bad = ev.tool && ev.tool.success === false;
|
|
1025
|
-
if (bad) chat.appendChild(chatEvt("
|
|
1025
|
+
if (bad) chat.appendChild(chatEvt("failed: " + toolLabel(ev.tool)));
|
|
1026
1026
|
} else if (ev.type === "permission.requested") {
|
|
1027
|
-
chat.appendChild(chatEvt("
|
|
1027
|
+
chat.appendChild(chatEvt("needs approval: " + (ev.tool || "an action")));
|
|
1028
1028
|
} else if (ev.type === "file.changed") {
|
|
1029
|
-
chat.appendChild(chatEvt("
|
|
1029
|
+
chat.appendChild(chatEvt("saved " + (shortPath(ev.path === "unknown" ? "" : ev.path) || "file")));
|
|
1030
1030
|
}
|
|
1031
1031
|
}
|
|
1032
1032
|
if (!chat.children.length) {
|
|
1033
1033
|
var empty = document.createElement("div");
|
|
1034
1034
|
empty.className = "empty";
|
|
1035
|
-
empty.textContent = "
|
|
1035
|
+
empty.textContent = "No messages yet.";
|
|
1036
1036
|
chat.appendChild(empty);
|
|
1037
1037
|
}
|
|
1038
1038
|
chat.scrollTop = chat.scrollHeight;
|
|
@@ -1051,7 +1051,7 @@ document.getElementById("dSend").addEventListener("submit", function (ev) {
|
|
|
1051
1051
|
sendInFlight = true;
|
|
1052
1052
|
input.disabled = true;
|
|
1053
1053
|
btn.disabled = true;
|
|
1054
|
-
msg.textContent = "
|
|
1054
|
+
msg.textContent = "sending...";
|
|
1055
1055
|
fetch("api/sessions/" + encodeURIComponent(detailId) + "/send", {
|
|
1056
1056
|
method: "POST",
|
|
1057
1057
|
headers: { "content-type": "application/json" },
|
|
@@ -1063,17 +1063,17 @@ document.getElementById("dSend").addEventListener("submit", function (ev) {
|
|
|
1063
1063
|
input.value = "";
|
|
1064
1064
|
if (out.body && out.body.queued) {
|
|
1065
1065
|
detailPending = text;
|
|
1066
|
-
msg.textContent = "
|
|
1066
|
+
msg.textContent = "message queued - sends when the turn ends";
|
|
1067
1067
|
} else {
|
|
1068
1068
|
detailPending = null;
|
|
1069
|
-
msg.textContent = "
|
|
1069
|
+
msg.textContent = "message sent - new turn started";
|
|
1070
1070
|
}
|
|
1071
1071
|
poll();
|
|
1072
1072
|
} else {
|
|
1073
|
-
msg.textContent = (out.body && out.body.error) || "
|
|
1073
|
+
msg.textContent = (out.body && out.body.error) || "could not send";
|
|
1074
1074
|
}
|
|
1075
1075
|
}).catch(function () {
|
|
1076
|
-
msg.textContent = "daemon
|
|
1076
|
+
msg.textContent = "daemon is offline?";
|
|
1077
1077
|
}).then(function () {
|
|
1078
1078
|
sendInFlight = false;
|
|
1079
1079
|
paintSendState();
|
|
@@ -1084,19 +1084,19 @@ document.getElementById("dArchive").addEventListener("click", function () {
|
|
|
1084
1084
|
var msg = document.getElementById("dSendMsg");
|
|
1085
1085
|
var btn = document.getElementById("dArchive");
|
|
1086
1086
|
btn.disabled = true;
|
|
1087
|
-
msg.textContent = "
|
|
1087
|
+
msg.textContent = "archiving...";
|
|
1088
1088
|
fetch("api/sessions/" + encodeURIComponent(detailId) + "/release", { method: "POST" }).then(function (r) {
|
|
1089
1089
|
return r.json().then(function (j) { return { ok: r.ok, body: j }; });
|
|
1090
1090
|
}).then(function (out) {
|
|
1091
1091
|
if (out.ok) {
|
|
1092
|
-
msg.textContent = "
|
|
1092
|
+
msg.textContent = "session archived as completed";
|
|
1093
1093
|
selectSession(detailId);
|
|
1094
1094
|
poll();
|
|
1095
1095
|
} else {
|
|
1096
|
-
msg.textContent = (out.body && out.body.error) || "
|
|
1096
|
+
msg.textContent = (out.body && out.body.error) || "could not archive";
|
|
1097
1097
|
}
|
|
1098
1098
|
}).catch(function () {
|
|
1099
|
-
msg.textContent = "daemon
|
|
1099
|
+
msg.textContent = "daemon is offline?";
|
|
1100
1100
|
}).then(function () {
|
|
1101
1101
|
btn.disabled = false;
|
|
1102
1102
|
});
|
|
@@ -1106,7 +1106,7 @@ function poll() {
|
|
|
1106
1106
|
fetch("api/sessions").then(function (r) { return r.json(); }).then(function (j) {
|
|
1107
1107
|
reconcile(j.sessions || []);
|
|
1108
1108
|
}).catch(function () {
|
|
1109
|
-
document.getElementById("summary").textContent = "daemon
|
|
1109
|
+
document.getElementById("summary").textContent = "daemon is offline?";
|
|
1110
1110
|
});
|
|
1111
1111
|
}
|
|
1112
1112
|
poll();
|
package/package.json
CHANGED