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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/commands/doctor.js +24 -6
  3. package/dist/cli/commands/doctor.js.map +1 -1
  4. package/dist/cli/commands/profile.js +7 -2
  5. package/dist/cli/commands/profile.js.map +1 -1
  6. package/dist/cli/commands/ps.js +41 -6
  7. package/dist/cli/commands/ps.js.map +1 -1
  8. package/dist/cli/commands/setup.js +50 -22
  9. package/dist/cli/commands/setup.js.map +1 -1
  10. package/dist/cli/commands/web.js +1 -1
  11. package/dist/core/events.js.map +1 -1
  12. package/dist/core/pricing.js +51 -6
  13. package/dist/core/pricing.js.map +1 -1
  14. package/dist/daemon/daemon.js +30 -1
  15. package/dist/daemon/daemon.js.map +1 -1
  16. package/dist/drivers/antigravity/driver.js +105 -2
  17. package/dist/drivers/antigravity/driver.js.map +1 -1
  18. package/dist/drivers/antigravity/parser.js +108 -2
  19. package/dist/drivers/antigravity/parser.js.map +1 -1
  20. package/dist/drivers/claude/parser.js +3 -1
  21. package/dist/drivers/claude/parser.js.map +1 -1
  22. package/dist/drivers/opencode/parser.js +26 -1
  23. package/dist/drivers/opencode/parser.js.map +1 -1
  24. package/dist/open/launchers/opencode.js +1 -1
  25. package/dist/open/launchers/opencode.js.map +1 -1
  26. package/dist/open/runtime.js +8 -0
  27. package/dist/open/runtime.js.map +1 -1
  28. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  29. package/dist/plugin/agents/orchestrator-edit.md +11 -2
  30. package/dist/plugin/agents/orchestrator-read.md +11 -2
  31. package/dist/plugin/agents/orchestrator.md +4 -2
  32. package/dist/plugin/hooks/hooks.json +2 -0
  33. package/dist/plugin/hooks/register.tsx +251 -0
  34. package/dist/plugin/mods/agents/pane.ts +453 -0
  35. package/dist/plugin/mods/agents/parse.ts +29 -0
  36. package/dist/plugin/mods/agents/types.ts +43 -0
  37. package/dist/plugin/prompts/_partials/spec-gates.md +2 -0
  38. package/dist/plugin/prompts/roles/orchestrator-edit.md +2 -1
  39. package/dist/plugin/prompts/roles/orchestrator-read.md +2 -1
  40. package/dist/plugin/prompts/roles/orchestrator.md +2 -2
  41. package/dist/plugin/skills/tlc-spec-driven/SKILL.md +186 -0
  42. package/dist/plugin/skills/tlc-spec-driven/references/code-analysis.md +98 -0
  43. package/dist/plugin/skills/tlc-spec-driven/references/coding-principles.md +72 -0
  44. package/dist/plugin/skills/tlc-spec-driven/references/context-limits.md +31 -0
  45. package/dist/plugin/skills/tlc-spec-driven/references/design.md +199 -0
  46. package/dist/plugin/skills/tlc-spec-driven/references/discuss.md +159 -0
  47. package/dist/plugin/skills/tlc-spec-driven/references/implement.md +436 -0
  48. package/dist/plugin/skills/tlc-spec-driven/references/lessons.md +115 -0
  49. package/dist/plugin/skills/tlc-spec-driven/references/memory.md +144 -0
  50. package/dist/plugin/skills/tlc-spec-driven/references/specify.md +228 -0
  51. package/dist/plugin/skills/tlc-spec-driven/references/sub-agents.md +147 -0
  52. package/dist/plugin/skills/tlc-spec-driven/references/tasks.md +451 -0
  53. package/dist/plugin/skills/tlc-spec-driven/references/validate.md +355 -0
  54. package/dist/plugin/skills/tlc-spec-driven/scripts/check_commit.py +133 -0
  55. package/dist/plugin/skills/tlc-spec-driven/scripts/lessons.py +412 -0
  56. package/dist/plugin/skills/tlc-spec-driven/scripts/validate_spec.py +284 -0
  57. package/dist/plugin/skills/tlc-spec-driven/scripts/validate_state.py +196 -0
  58. package/dist/plugin/skills/tlc-spec-driven/scripts/validate_tasks.py +287 -0
  59. package/dist/plugin/statusline.sh +0 -1
  60. package/dist/web/canvas-page.js +82 -82
  61. package/package.json +1 -1
@@ -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>Canvas das runs</h1><p id="summary">conectando...</p></div>
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="Pausar movimento"><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="Recentralizar" aria-label="Recentralizar"><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="Ocultar concluídas" aria-label="Ocultar concluídas"><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>
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>Trabalhando</span><span><i class="dot waiting"></i>Esperando você</span><span><i class="dot resting"></i>Em pausa</span><span><i class="dot done"></i>Concluída</span></div>
129
- <div class="hud" id="feed"><h2>AGORA MESMO</h2><ul id="feedList"></ul></div>
130
- <div class="hud" id="hint">arraste para organizar · scroll dá zoom · clique num agente para o detalhe</div>
131
- <aside id="detail" aria-label="Detalhe da sessão">
132
- <button id="detailClose" type="button" aria-label="Fechar">×</button>
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>CONVERSA</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="mensagem para esta sessão">
140
- <button id="dSendBtn" type="submit">Enviar</button>
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">Marcar como concluída</button>
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: "Trabalhando agora", starting: "Trabalhando agora", needs_input: "Esperando você",
161
- idle: "Em pausa", completed: "Concluída", failed: "Falhou", stopped: "Parada",
162
- orphaned: "Interrompida", interrupted: "Interrompida", dead: "Morreu" };
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 "terminou bem";
171
- if (last === "agent_end") return "terminou a resposta";
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 "rodando comandos no terminal";
175
- return "usando " + tool;
174
+ if (tool === "bash") return "running terminal commands";
175
+ return "using " + tool;
176
176
  }
177
- if (last.indexOf("send: ") === 0) return "recebeu sua mensagem";
177
+ if (last.indexOf("send: ") === 0) return "received your message";
178
178
  return "";
179
179
  }
180
180
  function toolHuman(name) {
181
- if (!name) return "uma tarefa";
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 + " tarefas)";
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 || "tarefa";
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 "agora mesmo";
227
- if (m < 60) return "há " + m + " min";
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 "há " + h + " h";
230
- return "há " + Math.floor(h / 24) + " dias";
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 ? "Orquestrador" : agentName(n.agent);
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 ? " sessão" : " sessões");
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] || "Encerrada";
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 = "sessão " + n.id + (n.label ? " · " + n.label : "");
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 + " sessões · "));
390
- var b1 = document.createElement("b"); b1.textContent = working + " trabalhando"; el.appendChild(b1);
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 + " esperando você"; el.appendChild(b2);
393
- if (hidden > 0) el.appendChild(document.createTextNode(" · " + hidden + " ocultas"));
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 "quer sua aprovação para continuar";
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 ? "falhou quando estava " + last : "falhou, abra os logs para ver";
402
- if (s.status === "dead") return last ? "morreu quando estava " + last : "morreu, o processo sumiu";
403
- if (s.status === "completed") return last ? "concluída, " + last : "concluída";
404
- if (s.status === "working" || s.status === "starting") return last || "processando...";
405
- if (last) return "por último: " + last;
406
- return "sem atividade recente";
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, "escrevendo resposta");
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 ? " (com erro)" : " ✓"));
614
- if (bad) feed(agentName(n.agent), "falhou: " + toolLabel(ev.tool), "bad");
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, "respondendo");
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, "mensagem na fila");
623
- feed(agentName(n.agent), "mensagem na fila");
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), "salvou " + (shortPath(ev.path === "unknown" ? "" : ev.path) || "arquivo"));
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, "quer sua aprovação para continuar");
633
+ touch(n, "waiting for your approval");
634
634
  paintSummary();
635
635
  spawnRing(n, "#ff9f0a");
636
- feed(agentName(n.agent), "precisa de aprovação", "warn");
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" ? ("falhou: " + (ev.error || "")) : "concluída");
639
+ touch(n, ev.type === "session.failed" ? ("failed: " + (ev.error || "")) : "completed");
640
640
  paintSummary();
641
- feed(agentName(n.agent), ev.type === "session.failed" ? "falhou" : "concluída", ev.type === "session.failed" ? "bad" : "");
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 ? "Mostrar concluídas" : "Ocultar concluídas";
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 ? "Mostrar concluídas" : "Ocultar concluídas";
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 = "sessão interativa não aceita mensagens";
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 mensagem na fila — envia quando o turno terminar"; sendBlockedNote = true; }
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 ? "Orquestrador" : agentName(s.agent)) + " · " + (s.name || s.id)));
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 ? " · começou " + timeAgo(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
- ["Modelo", s.model || "—"],
988
+ ["Model", s.model || "—"],
989
989
  // effort chega sempre para claude/codex/omp/antigravity; ausente = opencode (ignora) ou sessão legada.
990
- ["Esforço", s.effort || "n/a"],
990
+ ["Effort", s.effort || "n/a"],
991
991
  ["Repo", repo || "—"],
992
- ["Atividade", s.lastEvent ? (lastEventHuman(s.lastEvent) || s.lastEvent) : "—"],
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(["Atualizado", timeAgo(s.updatedAt)]);
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(["Ferramentas", String(tools)]);
1004
- items.push(["Respostas", String(msgs)]);
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("você", String(ev.prompt), "user"));
1016
+ chat.appendChild(chatMsg("you", String(ev.prompt), "user"));
1017
1017
  } else if (ev.type === "message.queued" && ev.prompt) {
1018
- chat.appendChild(chatMsg("você", String(ev.prompt) + " (na fila)", "user"));
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("falhou: " + toolLabel(ev.tool)));
1025
+ if (bad) chat.appendChild(chatEvt("failed: " + toolLabel(ev.tool)));
1026
1026
  } else if (ev.type === "permission.requested") {
1027
- chat.appendChild(chatEvt("precisa de aprovação: " + (ev.tool || "uma ação")));
1027
+ chat.appendChild(chatEvt("needs approval: " + (ev.tool || "an action")));
1028
1028
  } else if (ev.type === "file.changed") {
1029
- chat.appendChild(chatEvt("salvou " + (shortPath(ev.path === "unknown" ? "" : ev.path) || "arquivo")));
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 = "Sem mensagens ainda.";
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 = "enviando...";
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 = "mensagem na fila — envia quando o turno terminar";
1066
+ msg.textContent = "message queued - sends when the turn ends";
1067
1067
  } else {
1068
1068
  detailPending = null;
1069
- msg.textContent = "mensagem enviada — nova etapa começou";
1069
+ msg.textContent = "message sent - new turn started";
1070
1070
  }
1071
1071
  poll();
1072
1072
  } else {
1073
- msg.textContent = (out.body && out.body.error) || "não deu para enviar";
1073
+ msg.textContent = (out.body && out.body.error) || "could not send";
1074
1074
  }
1075
1075
  }).catch(function () {
1076
- msg.textContent = "daemon fora do ar?";
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 = "arquivando...";
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 = "sessão arquivada como concluída";
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) || "não deu para arquivar";
1096
+ msg.textContent = (out.body && out.body.error) || "could not archive";
1097
1097
  }
1098
1098
  }).catch(function () {
1099
- msg.textContent = "daemon fora do ar?";
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 fora do ar?";
1109
+ document.getElementById("summary").textContent = "daemon is offline?";
1110
1110
  });
1111
1111
  }
1112
1112
  poll();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codedeck",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "CodeDeck, a local runtime for coding agents with session management, process supervision, event normalization, and git isolation",
5
5
  "type": "module",
6
6
  "bin": {