@wenathlan/extension 1.1.58 → 1.1.60

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 (44) hide show
  1. package/README.md +6 -4
  2. package/dist/cli.js +19 -2
  3. package/dist/coordination.d.ts +139 -0
  4. package/dist/coordination.d.ts.map +1 -0
  5. package/dist/environments.d.ts +96 -0
  6. package/dist/environments.d.ts.map +1 -0
  7. package/dist/index.d.ts +6 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1080 -1
  10. package/dist/index.js.map +4 -4
  11. package/dist/memory.d.ts +119 -1
  12. package/dist/memory.d.ts.map +1 -1
  13. package/dist/multiagent.d.ts +1 -1
  14. package/dist/multiagent.d.ts.map +1 -1
  15. package/dist/orchestration.d.ts +174 -0
  16. package/dist/orchestration.d.ts.map +1 -0
  17. package/dist/policy.d.ts +76 -1
  18. package/dist/policy.d.ts.map +1 -1
  19. package/dist/protocol.d.ts +82 -3
  20. package/dist/protocol.d.ts.map +1 -1
  21. package/dist/runstate.d.ts +127 -0
  22. package/dist/runstate.d.ts.map +1 -0
  23. package/dist/sandboxframe.d.ts +45 -0
  24. package/dist/sandboxframe.d.ts.map +1 -0
  25. package/dist/types.d.ts +444 -4
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/version.d.ts +1 -1
  28. package/extension/dist/background.js +1837 -58
  29. package/extension/dist/background.js.map +4 -4
  30. package/extension/dist/manifest.json +16 -2
  31. package/extension/dist/offscreen.html +7 -0
  32. package/extension/dist/offscreen.js +87 -0
  33. package/extension/dist/offscreen.js.map +7 -0
  34. package/extension/dist/pagebridge.js +7 -0
  35. package/extension/dist/pagebridge.js.map +2 -2
  36. package/extension/dist/popup.html +1 -1
  37. package/extension/dist/popup.js +39 -1
  38. package/extension/dist/popup.js.map +2 -2
  39. package/extension/dist/sandbox.html +28 -0
  40. package/extension/dist/sidepanel.html +1 -1
  41. package/extension/dist/sidepanel.js +848 -3
  42. package/extension/dist/sidepanel.js.map +4 -4
  43. package/extension/manifest.json +16 -2
  44. package/package.json +1 -1
@@ -319,6 +319,12 @@ function redoedit(model) {
319
319
  return { ...next, redo: redo.slice(0, -1), undo: [...model.undo ?? [], current] };
320
320
  }
321
321
 
322
+ // progress.ts
323
+ function environmentof(progress, planid, stepid) {
324
+ if (!progress || progress.planid !== planid) return void 0;
325
+ return (progress.environments ?? {})[stepid];
326
+ }
327
+
322
328
  // extension/tabscommand.ts
323
329
  function switcherlist(tabs, recency, filter) {
324
330
  const needle = filter.trim().toLowerCase();
@@ -395,6 +401,7 @@ var triggersroot = document.querySelector("#triggers");
395
401
  var agentprotocolroot = document.querySelector("#agentprotocol");
396
402
  var modelsroot = document.querySelector("#models");
397
403
  var agentsroot = document.querySelector("#agents");
404
+ var environmentsroot = document.querySelector("#environments");
398
405
  var commandinput = document.querySelector("#command");
399
406
  var commandbutton = document.querySelector("#commandsend");
400
407
  var intentbadge = document.querySelector("#intentbadge");
@@ -585,6 +592,13 @@ function stepitem(plan, step, completed, outcomes, retries, progress) {
585
592
  const item = document.createElement("li");
586
593
  const done = completed.includes(step.id);
587
594
  item.textContent = `${done ? "\u2713" : ""} ${step.summary}${holddetail(step)}`;
595
+ const environmentbadge = progress?.planid === plan.id ? environmentof(progress, plan.id, step.id) ?? step.environment : step.environment;
596
+ if (environmentbadge !== void 0) {
597
+ const badge = document.createElement("span");
598
+ badge.className = "muted";
599
+ badge.textContent = ` [${environmentbadge}]`;
600
+ item.append(badge);
601
+ }
588
602
  const outcome = renderoutcome(step, outcomes);
589
603
  if (outcome) item.append(outcome);
590
604
  const timeline = step.kind === "retryaction" ? retrydetail(step, retries) : quietdetail(step, outcomes);
@@ -2883,6 +2897,7 @@ async function refresh() {
2883
2897
  renderagentprotocol(context);
2884
2898
  rendermodels(context);
2885
2899
  renderagents(context);
2900
+ renderenvironments(context);
2886
2901
  renderconsolediff();
2887
2902
  renderaudit(context.audit);
2888
2903
  rendercapabilities(context.capabilities);
@@ -5543,6 +5558,257 @@ function rendermodels(context) {
5543
5558
  }
5544
5559
  modelsroot.append(guardbox);
5545
5560
  }
5561
+ function renderenvironments(context) {
5562
+ if (!environmentsroot) return;
5563
+ environmentsroot.replaceChildren();
5564
+ const view = context.environments;
5565
+ if (!view) {
5566
+ environmentsroot.textContent = "The execution environment state is unknown.";
5567
+ return;
5568
+ }
5569
+ const head = document.createElement("p");
5570
+ head.textContent = `Steps by environment: ${view.report.environments.length} executed \xB7 offscreen ${view.offscreengranted ? "granted" : "not granted"} \xB7 parse offload ${view.parseoffload ? "on" : "off"} \xB7 workers ${view.report.workers} \xB7 sandbox origins ${view.sandboxorigins?.length ?? 0} configured.`;
5571
+ environmentsroot.append(head);
5572
+ const keepalive = view.report.keepalive;
5573
+ const keepbox = document.createElement("div");
5574
+ keepbox.className = "actions";
5575
+ const beatinfo = document.createElement("span");
5576
+ beatinfo.textContent = keepalive ? `Keepalive ${keepalive.state}: ${keepalive.beats} beat${keepalive.beats === 1 ? "" : "s"}, port ${keepalive.portopen ? "open" : "closed"}, last beat ${new Date(keepalive.lastbeatat).toLocaleTimeString()}${view.workerpoolsize !== void 0 ? ` \xB7 pool size ${view.workerpoolsize}` : ""}.` : "No run state holds a keepalive port.";
5577
+ keepbox.append(beatinfo);
5578
+ if (keepalive?.state === "active") {
5579
+ keepbox.append(button("Beat now", async () => {
5580
+ await request({ kind: "runstate", beat: true });
5581
+ await refresh();
5582
+ }), button("Close run state", async () => {
5583
+ await request({ kind: "runstate", stop: true });
5584
+ await refresh();
5585
+ }));
5586
+ }
5587
+ environmentsroot.append(keepbox);
5588
+ const keepnote = document.createElement("p");
5589
+ keepnote.className = "muted";
5590
+ keepnote.textContent = "Keepalive runs only during active reviewed plans: the port opens behind an approved plan of an active session and closes at every terminal state.";
5591
+ environmentsroot.append(keepnote);
5592
+ if (view.restartnotice !== void 0 || view.recovery !== void 0) {
5593
+ const notice = document.createElement("p");
5594
+ notice.textContent = view.restartnotice ?? view.recovery?.reason ?? "";
5595
+ if (view.recovery?.recoverable === true) notice.append(" ", button("Resume pending step", async () => {
5596
+ const result = await request({ kind: "runstate", recover: true });
5597
+ status(result.resumed ?? result.recovery?.reason ?? "The recovery finished.");
5598
+ await refresh();
5599
+ }));
5600
+ environmentsroot.append(notice);
5601
+ }
5602
+ if (view.zombies.length > 0) {
5603
+ const warning = document.createElement("p");
5604
+ warning.textContent = `Zombie run${view.zombies.length === 1 ? "" : "s"} whose heartbeat fell silent: ${view.zombies.join(", ")}.`;
5605
+ warning.append(" ", button("Reap zombie runs", async () => {
5606
+ const result = await request({ kind: "runstate", reap: true });
5607
+ status(`The reaper closed ${result.reaped?.length ?? 0} zombie run${result.reaped?.length === 1 ? "" : "s"}.`);
5608
+ await refresh();
5609
+ }));
5610
+ environmentsroot.append(warning);
5611
+ }
5612
+ const grouped = /* @__PURE__ */ new Map();
5613
+ for (const entry of view.report.environments) grouped.set(entry.environment, [...grouped.get(entry.environment) ?? [], entry.stepid]);
5614
+ const groupbox = document.createElement("details");
5615
+ groupbox.className = "sessiongroup";
5616
+ const groupsummary = document.createElement("summary");
5617
+ groupsummary.textContent = "Steps grouped by execution environment";
5618
+ groupbox.append(groupsummary);
5619
+ if (grouped.size === 0) {
5620
+ const none = document.createElement("p");
5621
+ none.textContent = "No step of the open run has executed yet.";
5622
+ groupbox.append(none);
5623
+ }
5624
+ for (const [environment, stepids] of grouped) {
5625
+ const line = document.createElement("p");
5626
+ line.textContent = `${environment}: ${stepids.length} step${stepids.length === 1 ? "" : "s"}${view.report.turnarounds.filter((entry) => stepids.includes(entry.stepid)).length > 0 ? ` \xB7 worker turnaround ${view.report.turnarounds.filter((entry) => stepids.includes(entry.stepid)).map((entry) => `${entry.stepid}: ${entry.milliseconds} ms`).join(", ")}` : ""}`;
5627
+ groupbox.append(line);
5628
+ }
5629
+ environmentsroot.append(groupbox);
5630
+ const grantbox = document.createElement("div");
5631
+ grantbox.className = "actions";
5632
+ const grantinfo = document.createElement("span");
5633
+ grantinfo.textContent = view.grants !== void 0 ? `Session environment grants: ${view.grants.length > 0 ? view.grants.join(", ") : "the documented default posture"}.` : "Session environment grants: the documented default posture (no grant list configured).";
5634
+ grantbox.append(grantinfo);
5635
+ const allenvironments = ["pagecontext", "isolatedworld", "offscreenworker", "sandboxframe"];
5636
+ for (const environment of allenvironments) {
5637
+ const active = view.grants?.includes(environment) ?? false;
5638
+ grantbox.append(" ", button(`${active ? "Revoke" : "Grant"} ${environment}`, async () => {
5639
+ const current = view.grants ?? [];
5640
+ const next = active ? current.filter((entry) => entry !== environment) : [...current, environment];
5641
+ await request({ kind: "environments", grants: next });
5642
+ await refresh();
5643
+ }));
5644
+ }
5645
+ environmentsroot.append(grantbox);
5646
+ const grantnote = document.createElement("p");
5647
+ grantnote.className = "muted";
5648
+ grantnote.textContent = "Environment grants join the origin grants of the session record: a configured list narrows every step to its entries and the request links to the same consent flow the origins use.";
5649
+ environmentsroot.append(grantnote);
5650
+ const capabilitybox = document.createElement("div");
5651
+ capabilitybox.className = "actions";
5652
+ const capabilityinfo = document.createElement("span");
5653
+ capabilityinfo.textContent = `Offscreen capability: ${view.offscreengranted ? "granted" : "absent \u2014 heavy parses keep their inline fallback inside the page"}.`;
5654
+ capabilitybox.append(capabilityinfo);
5655
+ if (!view.offscreengranted) capabilitybox.append(" ", button("Request offscreen capability", async () => {
5656
+ const result = await request({ kind: "environments", requestcapability: true });
5657
+ status(result.requested === true ? "The offscreen capability was granted; the worker pool may spawn." : "The capability request stayed refused; the inline fallback holds.");
5658
+ await refresh();
5659
+ }));
5660
+ else capabilitybox.append(" ", button("Close offscreen document", async () => {
5661
+ await request({ kind: "environments", offscreenclose: true });
5662
+ await refresh();
5663
+ }));
5664
+ environmentsroot.append(capabilitybox);
5665
+ const optionsbox = document.createElement("details");
5666
+ optionsbox.className = "sessiongroup";
5667
+ const optionssummary = document.createElement("summary");
5668
+ optionssummary.textContent = "Environment options";
5669
+ optionsbox.append(optionssummary);
5670
+ const offloadrow = document.createElement("div");
5671
+ offloadrow.className = "actions";
5672
+ offloadrow.append(button(`Parse offload: ${view.parseoffload ? "on" : "off"}`, async () => {
5673
+ await request({ kind: "environments", settings: { parseoffload: !view.parseoffload } });
5674
+ await refresh();
5675
+ }));
5676
+ const poolinput = document.createElement("input");
5677
+ poolinput.type = "number";
5678
+ poolinput.min = "1";
5679
+ poolinput.placeholder = "worker pool size (no cap)";
5680
+ poolinput.value = view.workerpoolsize !== void 0 ? String(view.workerpoolsize) : "";
5681
+ offloadrow.append(" ", poolinput, " ", button("Set pool size", async () => {
5682
+ const value = poolinput.value.trim();
5683
+ await request({ kind: "environments", settings: { ...value !== "" ? { workerpoolsize: Number(value) } : {} } });
5684
+ await refresh();
5685
+ }));
5686
+ optionsbox.append(offloadrow);
5687
+ const origininput = document.createElement("input");
5688
+ origininput.type = "url";
5689
+ origininput.placeholder = "https://origin.example to allow sandbox renders";
5690
+ const originrow = document.createElement("div");
5691
+ originrow.className = "actions";
5692
+ originrow.append(origininput, " ", button("Add sandbox origin", async () => {
5693
+ const value = origininput.value.trim();
5694
+ if (value === "") return;
5695
+ const next = [...view.sandboxorigins ?? [], value];
5696
+ await request({ kind: "environments", settings: { sandboxorigins: next } });
5697
+ await refresh();
5698
+ }));
5699
+ optionsbox.append(originrow);
5700
+ if ((view.sandboxorigins ?? []).length > 0) {
5701
+ const originlist = document.createElement("ul");
5702
+ originlist.className = "audit";
5703
+ for (const origin of view.sandboxorigins ?? []) {
5704
+ const item = document.createElement("li");
5705
+ item.textContent = origin;
5706
+ item.append(" ", button("Remove", async () => {
5707
+ await request({ kind: "environments", settings: { sandboxorigins: (view.sandboxorigins ?? []).filter((entry) => entry !== origin) } });
5708
+ await refresh();
5709
+ }));
5710
+ originlist.append(item);
5711
+ }
5712
+ optionsbox.append(originlist);
5713
+ }
5714
+ const intervalinput = document.createElement("input");
5715
+ intervalinput.type = "number";
5716
+ intervalinput.min = "1";
5717
+ intervalinput.placeholder = "keepalive interval ms (roadmap: 30000)";
5718
+ const intervalrow = document.createElement("div");
5719
+ intervalrow.className = "actions";
5720
+ intervalrow.append(intervalinput, " ", button("Set interval", async () => {
5721
+ const value = intervalinput.value.trim();
5722
+ if (value === "") return;
5723
+ await request({ kind: "environments", settings: { keepaliveinterval: Number(value) } });
5724
+ await refresh();
5725
+ }));
5726
+ optionsbox.append(intervalrow);
5727
+ environmentsroot.append(optionsbox);
5728
+ if (view.registry.length > 0) {
5729
+ const registrybox = document.createElement("details");
5730
+ registrybox.className = "sessiongroup";
5731
+ const registrysummary = document.createElement("summary");
5732
+ registrysummary.textContent = "Executor registry";
5733
+ registrybox.append(registrysummary);
5734
+ const registrylist = document.createElement("ul");
5735
+ registrylist.className = "audit";
5736
+ for (const adapter of view.registry) {
5737
+ const item = document.createElement("li");
5738
+ item.textContent = `${adapter.environment} \u2192 ${adapter.adapter}: ${adapter.description}`;
5739
+ registrylist.append(item);
5740
+ }
5741
+ registrybox.append(registrylist);
5742
+ environmentsroot.append(registrybox);
5743
+ }
5744
+ if (view.report.offscreen.length > 0) {
5745
+ const offbox = document.createElement("details");
5746
+ offbox.className = "sessiongroup";
5747
+ const offsummary = document.createElement("summary");
5748
+ offsummary.textContent = `Offscreen documents (${view.report.offscreen.length})`;
5749
+ offbox.append(offsummary);
5750
+ const offlist = document.createElement("ul");
5751
+ offlist.className = "audit";
5752
+ for (const entry of view.report.offscreen) {
5753
+ const item = document.createElement("li");
5754
+ item.textContent = `${entry.document} for the run ${entry.runid}: ${entry.reasons.join(", ")}${entry.closedat !== void 0 ? ` \xB7 closed ${new Date(entry.closedat).toLocaleTimeString()}` : " \xB7 open"} \u2014 ${entry.justification}`;
5755
+ offlist.append(item);
5756
+ }
5757
+ offbox.append(offlist);
5758
+ environmentsroot.append(offbox);
5759
+ }
5760
+ if (view.workerevents.length > 0) {
5761
+ const workerbox = document.createElement("details");
5762
+ workerbox.className = "sessiongroup";
5763
+ const workersummary = document.createElement("summary");
5764
+ workersummary.textContent = `Worker activity (${view.workerevents.length})`;
5765
+ workerbox.append(workersummary);
5766
+ const workerlist = document.createElement("ul");
5767
+ workerlist.className = "audit";
5768
+ for (const event of view.workerevents.slice(0, 10)) {
5769
+ const item = document.createElement("li");
5770
+ item.textContent = `${event.kind} ${event.workers} worker${event.workers === 1 ? "" : "s"}: ${event.reason}`;
5771
+ workerlist.append(item);
5772
+ }
5773
+ workerbox.append(workerlist);
5774
+ environmentsroot.append(workerbox);
5775
+ }
5776
+ if (view.urls.length > 0) {
5777
+ const urlbox = document.createElement("details");
5778
+ urlbox.className = "sessiongroup";
5779
+ const urlsummary = document.createElement("summary");
5780
+ urlsummary.textContent = `Url history of the open run (${view.urls.length})`;
5781
+ urlbox.append(urlsummary);
5782
+ const urllist = document.createElement("ol");
5783
+ urllist.className = "audit";
5784
+ for (const entry of view.urls) {
5785
+ const item = document.createElement("li");
5786
+ item.textContent = `${new Date(entry.at).toLocaleTimeString()} ${entry.url} (step ${entry.stepid})`;
5787
+ urllist.append(item);
5788
+ }
5789
+ urlbox.append(urllist);
5790
+ environmentsroot.append(urlbox);
5791
+ }
5792
+ const locksbox = document.createElement("details");
5793
+ locksbox.className = "sessiongroup";
5794
+ const lockssummary = document.createElement("summary");
5795
+ lockssummary.textContent = `Run locks (${view.locks.length})`;
5796
+ locksbox.append(lockssummary);
5797
+ if (view.locks.length === 0) {
5798
+ const none = document.createElement("p");
5799
+ none.textContent = "No session holds a run lock; one session never carries two concurrent runs.";
5800
+ locksbox.append(none);
5801
+ }
5802
+ const locklist = document.createElement("ul");
5803
+ locklist.className = "audit";
5804
+ for (const lock of view.locks) {
5805
+ const item = document.createElement("li");
5806
+ item.textContent = `Session ${lock.sessionid} \u2192 run ${lock.runid} (${lock.holder})${lock.expiresat !== void 0 ? ` \xB7 expires ${new Date(lock.expiresat).toLocaleTimeString()}` : " \xB7 no expiry"}`;
5807
+ locklist.append(item);
5808
+ }
5809
+ locksbox.append(locklist);
5810
+ environmentsroot.append(locksbox);
5811
+ }
5546
5812
  function renderagents(context) {
5547
5813
  if (!agentsroot) return;
5548
5814
  agentsroot.replaceChildren();
@@ -5588,7 +5854,7 @@ function renderagents(context) {
5588
5854
  row.className = "sessionrow";
5589
5855
  const info = document.createElement("p");
5590
5856
  const budgettext = agent.budget === void 0 ? "no ceiling" : [agent.budget.maxtokens !== void 0 ? `${agent.usage?.tokens ?? 0}/${agent.budget.maxtokens} tokens` : "", agent.budget.maxcost !== void 0 ? `${agent.usage?.cost ?? 0}/${agent.budget.maxcost} ${agent.budget.currency ?? ""}` : "", agent.budget.maxsteps !== void 0 ? `${agent.usage?.steps ?? 0}/${agent.budget.maxsteps} steps` : ""].filter((part) => part !== "").join(", ") || "no ceiling set";
5591
- info.textContent = `${agent.name} \xB7 ${agent.role} \xB7 ${agent.state}${agent.tabid !== void 0 ? ` \xB7 tab ${agent.tabid}` : ""}${agent.parentid !== void 0 ? ` \xB7 sub of ${agent.parentid} at depth ${agent.depth}` : ""}${agent.currenttask !== void 0 ? ` \xB7 working: ${agent.currenttask}` : " \xB7 idle"} \xB7 budget ${budgettext}${agent.heartbeatat !== void 0 ? ` \xB7 heartbeat ${new Date(agent.heartbeatat).toLocaleTimeString()}` : ""}${agent.unread > 0 ? ` \xB7 ${agent.unread} unread` : ""}.`;
5857
+ info.textContent = `${agent.name} \xB7 ${agent.role} \xB7 ${agent.state}${agent.tabid !== void 0 ? ` \xB7 tab ${agent.tabid}` : ""}${agent.parentid !== void 0 ? ` \xB7 sub of ${agent.parentid} at depth ${agent.depth}` : ""}${agent.currenttask !== void 0 ? ` \xB7 working: ${agent.currenttask}` : " \xB7 idle"} \xB7 budget ${budgettext}${agent.heartbeatat !== void 0 ? ` \xB7 heartbeat ${new Date(agent.heartbeatat).toLocaleTimeString()}` : ""}${agent.unread > 0 ? ` \xB7 ${agent.unread} unread` : ""}${agent.reviewstatus !== void 0 ? ` \xB7 review: ${agent.reviewstatus}` : ""}${agent.handoffarrows.length > 0 ? ` \xB7 handoffs: ${agent.handoffarrows.join(", ")}` : ""}.`;
5592
5858
  row.append(info);
5593
5859
  const actions = document.createElement("div");
5594
5860
  actions.className = "actions";
@@ -5636,7 +5902,7 @@ function renderagents(context) {
5636
5902
  const nameinput = document.createElement("input");
5637
5903
  nameinput.placeholder = "new agent name";
5638
5904
  const roleselect = document.createElement("select");
5639
- for (const role of ["worker", "planner", "observer"]) {
5905
+ for (const role of ["worker", "planner", "observer", "critic", "verifier"]) {
5640
5906
  const option = document.createElement("option");
5641
5907
  option.value = role;
5642
5908
  option.textContent = role;
@@ -5662,7 +5928,7 @@ function renderagents(context) {
5662
5928
  parentselect.append(option);
5663
5929
  }
5664
5930
  const spawnrole = document.createElement("select");
5665
- for (const role of ["worker", "planner", "observer"]) {
5931
+ for (const role of ["worker", "planner", "observer", "critic", "verifier"]) {
5666
5932
  const option = document.createElement("option");
5667
5933
  option.value = role;
5668
5934
  option.textContent = role;
@@ -5861,6 +6127,558 @@ function renderagents(context) {
5861
6127
  }));
5862
6128
  boardbox.append(postrow);
5863
6129
  agentsroot.append(boardbox);
6130
+ const orchestrationbox = document.createElement("details");
6131
+ orchestrationbox.className = "sessiongroup";
6132
+ const orchestrationsummary = document.createElement("summary");
6133
+ orchestrationsummary.textContent = "Leader worker topology";
6134
+ orchestrationbox.append(orchestrationsummary);
6135
+ if (swarm.topology !== void 0) {
6136
+ const lead = swarm.agents.find((agent) => agent.id === swarm.topology?.leaderid);
6137
+ const topinfo = document.createElement("p");
6138
+ topinfo.textContent = `Leader ${swarm.topology.leaderid}${lead !== void 0 ? ` (${lead.name})` : ""} by the ${swarm.topology.rule.kind} rule \xB7 ${swarm.topology.workerids.length} workers, ${swarm.topology.criticids.length} critics, ${swarm.topology.verifierids.length} verifiers \xB7 ${swarm.topology.assignments.length} assignment${swarm.topology.assignments.length === 1 ? "" : "s"}.`;
6139
+ orchestrationbox.append(topinfo);
6140
+ const assignments = document.createElement("ul");
6141
+ assignments.className = "audit";
6142
+ for (const assignment of swarm.topology.assignments.slice(0, 8)) {
6143
+ const entry = document.createElement("li");
6144
+ entry.textContent = `${assignment.workerid} \u2192 task ${assignment.taskid}: ${assignment.slice}.`;
6145
+ assignments.append(entry);
6146
+ }
6147
+ orchestrationbox.append(assignments);
6148
+ for (const split of swarm.splits.slice(0, 4)) {
6149
+ const row = document.createElement("p");
6150
+ row.textContent = `Planner executor split: ${split.planownerid} plans, ${split.runownerid} runs${split.taskid !== void 0 ? ` task ${split.taskid}` : ""} with ${split.stepreports.length} step report${split.stepreports.length === 1 ? "" : "s"} (${split.stepreports.filter((report) => report.outcome === "done").length} done).`;
6151
+ orchestrationbox.append(row);
6152
+ }
6153
+ } else {
6154
+ const none = document.createElement("p");
6155
+ none.textContent = "No leader is elected yet; the user elects one by the first or named rule.";
6156
+ orchestrationbox.append(none);
6157
+ }
6158
+ const electionrow = document.createElement("div");
6159
+ electionrow.className = "actions";
6160
+ const leaderselect = document.createElement("select");
6161
+ const firstoption = document.createElement("option");
6162
+ firstoption.value = "first";
6163
+ firstoption.textContent = "first registration";
6164
+ leaderselect.append(firstoption);
6165
+ for (const agent of swarm.agents) {
6166
+ const option = document.createElement("option");
6167
+ option.value = agent.id;
6168
+ option.textContent = `named: ${agent.name}`;
6169
+ leaderselect.append(option);
6170
+ }
6171
+ const splitplan = document.createElement("select");
6172
+ const splitrun = document.createElement("select");
6173
+ const splittask = document.createElement("input");
6174
+ splittask.placeholder = "task id";
6175
+ for (const agent of swarm.agents) {
6176
+ const plan = document.createElement("option");
6177
+ plan.value = agent.id;
6178
+ plan.textContent = agent.name;
6179
+ splitplan.append(plan);
6180
+ const run = document.createElement("option");
6181
+ run.value = agent.id;
6182
+ run.textContent = agent.name;
6183
+ splitrun.append(run);
6184
+ }
6185
+ electionrow.append(leaderselect, " ", button("Elect leader", async () => {
6186
+ await request({ kind: "swarmleader", elect: leaderselect.value === "first" ? { rule: "first" } : { rule: "named", agentid: leaderselect.value } });
6187
+ status("The leader election recorded the topology; the leader only organizes reviewed work.");
6188
+ await refresh();
6189
+ }), " ", button("Assign work", async () => {
6190
+ await request({ kind: "swarmleader", assign: {} });
6191
+ status("The leader sliced the tasks across the workers; every slice still passes the plan review.");
6192
+ await refresh();
6193
+ }), " ", button("Scale workers", async () => {
6194
+ await request({ kind: "swarmleader", scale: { pending: swarm.queue.counts.queued + swarm.queue.counts.claimed } });
6195
+ status("The worker lane scaled by the load under the user configured bound.");
6196
+ await refresh();
6197
+ }), " ", splitplan, " ", splitrun, " ", splittask, " ", button("Split plan and run", async () => {
6198
+ if (splitplan.value === splitrun.value) {
6199
+ status("The planner executor split needs two different agents.");
6200
+ return;
6201
+ }
6202
+ await request({ kind: "swarmleader", split: { planownerid: splitplan.value, runownerid: splitrun.value, ...splittask.value.trim() !== "" ? { taskid: splittask.value } : {} } });
6203
+ status("The task split between the planner and the executor; the executor reports every step back.");
6204
+ await refresh();
6205
+ }));
6206
+ orchestrationbox.append(electionrow);
6207
+ agentsroot.append(orchestrationbox);
6208
+ const boardbox2 = document.createElement("details");
6209
+ boardbox2.className = "sessiongroup";
6210
+ const board2summary = document.createElement("summary");
6211
+ board2summary.textContent = `Progressboard (${swarm.board.lanes.length} lanes)`;
6212
+ boardbox2.append(board2summary);
6213
+ for (const lane of swarm.board.lanes) {
6214
+ const row = document.createElement("p");
6215
+ row.textContent = `${lane.name} (${lane.role}, ${lane.state}) \xB7 lane ${lane.lane}${lane.currenttask !== void 0 ? ` \xB7 working: ${lane.currenttask}` : ""}${lane.milestones.length > 0 ? ` \xB7 ${lane.milestones.filter((milestone) => milestone.done).length}/${lane.milestones.length} milestones (${lane.milestones.map((milestone) => milestone.done ? milestone.label : `${milestone.label} (open)`).join(", ")})` : ""}.`;
6216
+ boardbox2.append(row);
6217
+ }
6218
+ const milestonerow = document.createElement("div");
6219
+ milestonerow.className = "actions";
6220
+ const milestoneagent = document.createElement("select");
6221
+ for (const agent of swarm.agents) {
6222
+ const option = document.createElement("option");
6223
+ option.value = agent.id;
6224
+ option.textContent = agent.name;
6225
+ milestoneagent.append(option);
6226
+ }
6227
+ const milestonelabel = document.createElement("input");
6228
+ milestonelabel.placeholder = "milestone label";
6229
+ milestonerow.append(milestoneagent, " ", milestonelabel, " ", button("Report milestone", async () => {
6230
+ await request({ kind: "swarmleader", milestone: { agentid: milestoneagent.value, label: milestonelabel.value, done: true } });
6231
+ status("The milestone landed on the progressboard snapshot.");
6232
+ await refresh();
6233
+ }), " ", button("Snapshot board", async () => {
6234
+ await request({ kind: "swarmmerge", snapshot: true });
6235
+ status("The progressboard snapshot was stored under the user configured retention.");
6236
+ await refresh();
6237
+ }));
6238
+ boardbox2.append(milestonerow);
6239
+ agentsroot.append(boardbox2);
6240
+ const reviewbox = document.createElement("details");
6241
+ reviewbox.className = "sessiongroup";
6242
+ const reviewsummary = document.createElement("summary");
6243
+ reviewsummary.textContent = `Reviews and verifications (${swarm.reviews.length} verdicts, ${swarm.verifications.length} checks)`;
6244
+ reviewbox.append(reviewsummary);
6245
+ for (const request2 of swarm.reviewrequests.slice(0, 8)) {
6246
+ const row = document.createElement("p");
6247
+ row.textContent = `Review request ${request2.subject}: ${request2.fromagentid} \u2192 ${request2.toagentid}, ${request2.state}${request2.timeoutat !== void 0 ? ` \xB7 deadline ${new Date(request2.timeoutat).toLocaleTimeString()}` : ""}.`;
6248
+ const actions = document.createElement("div");
6249
+ actions.className = "actions";
6250
+ actions.append(button("Ack", async () => {
6251
+ await request({ kind: "swarmreview", ack: request2.id });
6252
+ status("The review request was acked.");
6253
+ await refresh();
6254
+ }));
6255
+ row.append(actions);
6256
+ reviewbox.append(row);
6257
+ }
6258
+ for (const review of swarm.reviews.slice(0, 8)) {
6259
+ const row = document.createElement("p");
6260
+ row.textContent = `Critic verdict ${review.verdict} by ${review.reviewerid} over the output of ${review.subjectagentid}${review.issues.length > 0 ? ` \xB7 issues: ${review.issues.join("; ")}` : ""}${review.requiredchanges.length > 0 ? ` \xB7 required: ${review.requiredchanges.join("; ")}` : ""}.`;
6261
+ reviewbox.append(row);
6262
+ }
6263
+ for (const check of swarm.verifications.slice(0, 8)) {
6264
+ const row = document.createElement("p");
6265
+ const badge = document.createElement("strong");
6266
+ badge.textContent = check.outcome === "pass" ? "PASS" : "FAIL";
6267
+ row.append(`Verifier ${check.verifierid} checked the claim of ${check.claimagentid} by the ${check.method} method: `, badge, ` \u2014 ${check.claim}${check.evidence !== void 0 ? ` (${check.evidence})` : ""}.`);
6268
+ reviewbox.append(row);
6269
+ }
6270
+ const reviewrow = document.createElement("div");
6271
+ reviewrow.className = "actions";
6272
+ const reviewfrom = document.createElement("select");
6273
+ const reviewto = document.createElement("select");
6274
+ for (const agent of swarm.agents) {
6275
+ const one = document.createElement("option");
6276
+ one.value = agent.id;
6277
+ one.textContent = agent.name;
6278
+ reviewfrom.append(one);
6279
+ const two = document.createElement("option");
6280
+ two.value = agent.id;
6281
+ two.textContent = agent.name;
6282
+ reviewto.append(two);
6283
+ }
6284
+ const reviewsubject = document.createElement("input");
6285
+ reviewsubject.placeholder = "review subject";
6286
+ const reviewpayload = document.createElement("input");
6287
+ reviewpayload.placeholder = "output payload";
6288
+ const reviewverdict = document.createElement("select");
6289
+ for (const verdict of ["approve", "changes", "reject"]) {
6290
+ const option = document.createElement("option");
6291
+ option.value = verdict;
6292
+ option.textContent = verdict;
6293
+ reviewverdict.append(option);
6294
+ }
6295
+ const reviewchanges = document.createElement("input");
6296
+ reviewchanges.placeholder = "required changes, semicolon separated";
6297
+ reviewrow.append(reviewfrom, " ", reviewto, " ", reviewsubject, " ", reviewpayload, " ", button("Request review", async () => {
6298
+ await request({ kind: "swarmreview", request: { fromagentid: reviewfrom.value, toagentid: reviewto.value, subject: reviewsubject.value, payload: reviewpayload.value } });
6299
+ status("The review request was routed; the critic reads only.");
6300
+ await refresh();
6301
+ }), " ", reviewverdict, " ", reviewchanges, " ", button("Apply verdict", async () => {
6302
+ const open = swarm.reviewrequests.find((entry) => entry.state === "open" && entry.toagentid === reviewto.value);
6303
+ if (open === void 0) {
6304
+ status("No open review request for the selected reviewer; request one first.");
6305
+ return;
6306
+ }
6307
+ await request({ kind: "swarmreview", apply: { id: open.id, reviewerid: reviewto.value, verdict: reviewverdict.value, issues: [], requiredchanges: reviewchanges.value.split(";").map((change) => change.trim()).filter((change) => change !== "") } });
6308
+ status("The critic verdict was applied; the rework still passes the human review.");
6309
+ await refresh();
6310
+ }), " ", button("Sweep timeouts", async () => {
6311
+ await request({ kind: "swarmreview", sweep: true });
6312
+ status("The review sweep timed out the unanswered requests.");
6313
+ await refresh();
6314
+ }));
6315
+ const verifyrow = document.createElement("div");
6316
+ verifyrow.className = "actions";
6317
+ const verifierselect = document.createElement("select");
6318
+ for (const agent of swarm.agents) {
6319
+ const option = document.createElement("option");
6320
+ option.value = agent.id;
6321
+ option.textContent = agent.name;
6322
+ verifierselect.append(option);
6323
+ }
6324
+ const claimagent = document.createElement("select");
6325
+ for (const agent of swarm.agents) {
6326
+ const option = document.createElement("option");
6327
+ option.value = agent.id;
6328
+ option.textContent = agent.name;
6329
+ claimagent.append(option);
6330
+ }
6331
+ const claimtext = document.createElement("input");
6332
+ claimtext.placeholder = "claim to verify";
6333
+ const claimmethod = document.createElement("input");
6334
+ claimmethod.placeholder = "method";
6335
+ const claimoutcome = document.createElement("select");
6336
+ for (const outcome of ["pass", "fail"]) {
6337
+ const option = document.createElement("option");
6338
+ option.value = outcome;
6339
+ option.textContent = outcome;
6340
+ claimoutcome.append(option);
6341
+ }
6342
+ verifyrow.append(verifierselect, " ", claimagent, " ", claimtext, " ", claimmethod, " ", claimoutcome, " ", button("Verify claim", async () => {
6343
+ await request({ kind: "swarmreview", verify: { verifierid: verifierselect.value, claimagentid: claimagent.value, claim: claimtext.value, method: claimmethod.value, outcome: claimoutcome.value } });
6344
+ status(`The verifier marked the claim ${claimoutcome.value} with the method it used.`);
6345
+ await refresh();
6346
+ }));
6347
+ reviewbox.append(reviewrow, verifyrow);
6348
+ agentsroot.append(reviewbox);
6349
+ const escalationbox = document.createElement("details");
6350
+ escalationbox.className = "sessiongroup";
6351
+ const escalationsummary = document.createElement("summary");
6352
+ escalationsummary.textContent = `Escalation inbox (${swarm.escalations.filter((escalation) => escalation.state === "open").length} open)`;
6353
+ escalationbox.append(escalationsummary);
6354
+ for (const escalation of swarm.escalations.slice(0, 8)) {
6355
+ const row = document.createElement("div");
6356
+ row.className = "sessionrow";
6357
+ const info = document.createElement("p");
6358
+ info.textContent = `${escalation.state === "open" ? "AWAITS THE USER" : "decided"} \xB7 ${escalation.agentid} lifted ${escalation.subject} \u2014 ${escalation.context}${escalation.decision !== void 0 ? ` \xB7 decision: ${escalation.decision}` : ""}.`;
6359
+ row.append(info);
6360
+ if (escalation.state === "open") {
6361
+ const actions = document.createElement("div");
6362
+ actions.className = "actions";
6363
+ const decision = document.createElement("input");
6364
+ decision.placeholder = "the decision the user writes";
6365
+ actions.append(decision, " ", button("Decide", async () => {
6366
+ await request({ kind: "swarmreview", decide: { id: escalation.id, decision: decision.value } });
6367
+ status("The user decision was recorded; the agent continues from it.");
6368
+ await refresh();
6369
+ }));
6370
+ row.append(actions);
6371
+ }
6372
+ escalationbox.append(row);
6373
+ }
6374
+ const escalaterow = document.createElement("div");
6375
+ escalaterow.className = "actions";
6376
+ const escalateagent = document.createElement("select");
6377
+ for (const agent of swarm.agents) {
6378
+ const option = document.createElement("option");
6379
+ option.value = agent.id;
6380
+ option.textContent = agent.name;
6381
+ escalateagent.append(option);
6382
+ }
6383
+ const escalatesubject = document.createElement("input");
6384
+ escalatesubject.placeholder = "stalled subject";
6385
+ const escalatecontext = document.createElement("input");
6386
+ escalatecontext.placeholder = "full context for the user";
6387
+ escalaterow.append(escalateagent, " ", escalatesubject, " ", escalatecontext, " ", button("Escalate to user", async () => {
6388
+ await request({ kind: "swarmreview", escalate: { agentid: escalateagent.value, subject: escalatesubject.value, context: escalatecontext.value } });
6389
+ status("The stalled decision was lifted to the user; the agent waits.");
6390
+ await refresh();
6391
+ }));
6392
+ escalationbox.append(escalaterow);
6393
+ agentsroot.append(escalationbox);
6394
+ const consensusbox = document.createElement("details");
6395
+ consensusbox.className = "sessiongroup";
6396
+ const consensussummary = document.createElement("summary");
6397
+ consensussummary.textContent = `Consensus rounds (${swarm.consensus.length})`;
6398
+ consensusbox.append(consensussummary);
6399
+ for (const round of swarm.consensus.slice(0, 6)) {
6400
+ const yes = round.votes.filter((vote) => vote.vote === "yes").length;
6401
+ const no = round.votes.filter((vote) => vote.vote === "no").length;
6402
+ const abstain = round.votes.filter((vote) => vote.vote === "abstain").length;
6403
+ const row = document.createElement("p");
6404
+ row.textContent = `${round.subject}: ${round.state} \xB7 ${yes} yes, ${no} no, ${abstain} abstain against the quorum ${round.quorum}${round.votes.length > 0 ? ` \xB7 voted by ${round.votes.map((vote) => vote.agentid).join(", ")}` : ""}.`;
6405
+ const actions = document.createElement("div");
6406
+ actions.className = "actions";
6407
+ const voterselect = document.createElement("select");
6408
+ for (const agent of swarm.agents) {
6409
+ const option = document.createElement("option");
6410
+ option.value = agent.id;
6411
+ option.textContent = agent.name;
6412
+ voterselect.append(option);
6413
+ }
6414
+ const voteselect = document.createElement("select");
6415
+ for (const vote of ["yes", "no", "abstain"]) {
6416
+ const option = document.createElement("option");
6417
+ option.value = vote;
6418
+ option.textContent = vote;
6419
+ voteselect.append(option);
6420
+ }
6421
+ actions.append(voterselect, " ", voteselect, " ", button("Vote", async () => {
6422
+ await request({ kind: "swarmreview", vote: { id: round.id, agentid: voterselect.value, vote: voteselect.value } });
6423
+ status(`The vote landed on the round ${round.subject}.`);
6424
+ await refresh();
6425
+ }));
6426
+ row.append(actions);
6427
+ consensusbox.append(row);
6428
+ }
6429
+ const consensusrow = document.createElement("div");
6430
+ consensusrow.className = "actions";
6431
+ const subjectinput2 = document.createElement("input");
6432
+ subjectinput2.placeholder = "consensus subject";
6433
+ const quoruminput = document.createElement("input");
6434
+ quoruminput.placeholder = "quorum";
6435
+ consensusrow.append(subjectinput2, " ", quoruminput, " ", button("Open round", async () => {
6436
+ await request({ kind: "swarmreview", consensus: { subject: subjectinput2.value, ...quoruminput.value.trim() !== "" ? { quorum: Number(quoruminput.value) } : {} } });
6437
+ status("The consensus round opened with the user configured quorum.");
6438
+ await refresh();
6439
+ }));
6440
+ consensusbox.append(consensusrow);
6441
+ agentsroot.append(consensusbox);
6442
+ const handoffbox = document.createElement("details");
6443
+ handoffbox.className = "sessiongroup";
6444
+ const handoffsummary = document.createElement("summary");
6445
+ handoffsummary.textContent = `Handoffs and locks (${swarm.handoffs.length} handoffs, ${swarm.locks.length} locks)`;
6446
+ handoffbox.append(handoffsummary);
6447
+ for (const record of swarm.handoffs.slice(0, 8)) {
6448
+ const row = document.createElement("p");
6449
+ row.textContent = `${record.fromagentid} \u2192 ${record.toagentid}${record.tabid !== void 0 ? ` \xB7 tab ${record.tabid}` : ""} \xB7 ${record.state} \xB7 packaged state: ${record.taskstate}.`;
6450
+ const actions = document.createElement("div");
6451
+ actions.className = "actions";
6452
+ if (record.state === "prepared") actions.append(button("Transfer", async () => {
6453
+ await request({ kind: "swarmhandoff", transfer: record.id });
6454
+ status("The tab moved between the agents under the one agent per tab rule.");
6455
+ await refresh();
6456
+ }), " ");
6457
+ if (record.state === "transferred") actions.append(button("Resume", async () => {
6458
+ await request({ kind: "swarmhandoff", resume: record.id });
6459
+ status("The receiving agent resumed the task from the packaged state.");
6460
+ await refresh();
6461
+ }));
6462
+ row.append(actions);
6463
+ handoffbox.append(row);
6464
+ }
6465
+ const handoffrow = document.createElement("div");
6466
+ handoffrow.className = "actions";
6467
+ const handofffrom = document.createElement("select");
6468
+ const handoffto = document.createElement("select");
6469
+ for (const agent of swarm.agents) {
6470
+ const one = document.createElement("option");
6471
+ one.value = agent.id;
6472
+ one.textContent = agent.name;
6473
+ handofffrom.append(one);
6474
+ const two = document.createElement("option");
6475
+ two.value = agent.id;
6476
+ two.textContent = agent.name;
6477
+ handoffto.append(two);
6478
+ }
6479
+ const handoffstate = document.createElement("input");
6480
+ handoffstate.placeholder = "packaged task state";
6481
+ handoffrow.append(handofffrom, " ", handoffto, " ", handoffstate, " ", button("Prepare handoff", async () => {
6482
+ await request({ kind: "swarmhandoff", prepare: { fromagentid: handofffrom.value, toagentid: handoffto.value, taskstate: handoffstate.value } });
6483
+ status("The handoff was prepared with the packaged task state.");
6484
+ await refresh();
6485
+ }));
6486
+ handoffbox.append(handoffrow);
6487
+ for (const lock of swarm.locks.slice(0, 8)) {
6488
+ const row = document.createElement("p");
6489
+ row.textContent = `Lock ${lock.key} \xB7 ${lock.kind} \xB7 holder ${lock.holder} \xB7 acquired ${new Date(lock.acquiredat).toLocaleTimeString()}${lock.expiresat !== void 0 ? ` \xB7 expires in ${Math.max(Math.round((lock.expiresat - Date.now()) / 1e3), 0)}s` : " \xB7 no expiry"}.`;
6490
+ const actions = document.createElement("div");
6491
+ actions.className = "actions";
6492
+ actions.append(button("Release", async () => {
6493
+ await request({ kind: "swarmlocks", release: { key: lock.key, holder: lock.holder } });
6494
+ status("The lock released and the resource returned to the pool.");
6495
+ await refresh();
6496
+ }));
6497
+ row.append(actions);
6498
+ handoffbox.append(row);
6499
+ }
6500
+ const lockrow = document.createElement("div");
6501
+ lockrow.className = "actions";
6502
+ const lockholder = document.createElement("select");
6503
+ for (const agent of swarm.agents) {
6504
+ const option = document.createElement("option");
6505
+ option.value = agent.id;
6506
+ option.textContent = agent.name;
6507
+ lockholder.append(option);
6508
+ }
6509
+ const lockorigin = document.createElement("input");
6510
+ lockorigin.placeholder = "origin";
6511
+ const lockselector = document.createElement("input");
6512
+ lockselector.placeholder = "selector";
6513
+ const lockkindselect = document.createElement("select");
6514
+ for (const kind of ["exclusive", "shared"]) {
6515
+ const option = document.createElement("option");
6516
+ option.value = kind;
6517
+ option.textContent = kind;
6518
+ lockkindselect.append(option);
6519
+ }
6520
+ lockrow.append(lockholder, " ", lockorigin, " ", lockselector, " ", lockkindselect, " ", button("Acquire lock", async () => {
6521
+ await request({ kind: "swarmlocks", acquire: { holder: lockholder.value, origin: lockorigin.value, selector: lockselector.value, kind: lockkindselect.value } });
6522
+ status("The lock went to the holder; it serializes reviewed work only.");
6523
+ await refresh();
6524
+ }), " ", button("Sweep expired", async () => {
6525
+ await request({ kind: "swarmlocks", sweep: true });
6526
+ status("The expiry sweep returned the abandoned locks to the pool.");
6527
+ await refresh();
6528
+ }));
6529
+ handoffbox.append(lockrow);
6530
+ agentsroot.append(handoffbox);
6531
+ const conflictbox = document.createElement("details");
6532
+ conflictbox.className = "sessiongroup";
6533
+ const conflictsummary = document.createElement("summary");
6534
+ conflictsummary.textContent = `Conflicts and merges (${swarm.conflicts.length} scans)`;
6535
+ conflictbox.append(conflictsummary);
6536
+ for (const scan of swarm.conflicts.slice(0, 6)) {
6537
+ const row = document.createElement("p");
6538
+ row.textContent = scan.clean ? `Scan of ${scan.writers.length} writers: clean, no overlapping write.` : `Scan of ${scan.writers.length} writers: ${scan.overlaps.map((overlap) => `${overlap.origin}|${overlap.selector} by ${overlap.writers.join(", ")}`).join("; ")} \u2014 suggested order ${scan.suggestedorder.join(" \u2192 ")}.`;
6539
+ conflictbox.append(row);
6540
+ }
6541
+ const conflictrow = document.createElement("div");
6542
+ conflictrow.className = "actions";
6543
+ const scanorigin = document.createElement("input");
6544
+ scanorigin.placeholder = "origin";
6545
+ const scanselector = document.createElement("input");
6546
+ scanselector.placeholder = "selector";
6547
+ const scanagents = document.createElement("input");
6548
+ scanagents.placeholder = "writer agent ids, comma separated";
6549
+ conflictrow.append(scanorigin, " ", scanselector, " ", scanagents, " ", button("Scan conflicts", async () => {
6550
+ const writers = scanagents.value.split(",").map((id) => id.trim()).filter((id) => id !== "").map((id) => ({ agentid: id, origin: scanorigin.value, selector: scanselector.value }));
6551
+ await request({ kind: "swarmlocks", scan: { writers } });
6552
+ status("The conflict scan checked the overlapping writes before the parallel runs.");
6553
+ await refresh();
6554
+ }));
6555
+ conflictbox.append(conflictrow);
6556
+ if (swarm.report !== void 0) {
6557
+ const reportinfo = document.createElement("p");
6558
+ reportinfo.textContent = `Merged report ${swarm.report.title}: ${swarm.report.sections.length} section${swarm.report.sections.length === 1 ? "" : "s"} from ${swarm.report.sources.join(", ")}${swarm.report.confidence !== void 0 ? ` \xB7 confidence: ${swarm.report.confidence}` : ""}.`;
6559
+ conflictbox.append(reportinfo);
6560
+ const reportlist = document.createElement("ol");
6561
+ reportlist.className = "audit";
6562
+ for (const section of swarm.report.sections.slice(0, 3)) {
6563
+ const item = document.createElement("li");
6564
+ item.textContent = `${section.title}: ${section.entries.slice(0, 5).map((entry) => `${entry.key} = ${entry.value} (${entry.agentid}${entry.conflict !== void 0 ? `; ${entry.conflict}` : ""})`).join("; ")}.`;
6565
+ reportlist.append(item);
6566
+ }
6567
+ conflictbox.append(reportlist);
6568
+ const exportrow = document.createElement("div");
6569
+ exportrow.className = "actions";
6570
+ exportrow.append(button("Export report", async () => {
6571
+ await request({ kind: "swarmmerge", export: { carriespagecontent: true } });
6572
+ status("The merged report was exported; the page content it carries grades as a data egress event.");
6573
+ await refresh();
6574
+ }));
6575
+ conflictbox.append(exportrow);
6576
+ }
6577
+ const mergerow = document.createElement("div");
6578
+ mergerow.className = "actions";
6579
+ const reporttitle = document.createElement("input");
6580
+ reporttitle.placeholder = "report title";
6581
+ const mergeruleselect = document.createElement("select");
6582
+ for (const rule of ["first", "last", "preferagent", "fail"]) {
6583
+ const option = document.createElement("option");
6584
+ option.value = rule;
6585
+ option.textContent = rule;
6586
+ mergeruleselect.append(option);
6587
+ }
6588
+ const mergeoutputs = document.createElement("input");
6589
+ mergeoutputs.placeholder = "agent:task:key:value triples, semicolon separated";
6590
+ mergerow.append(reporttitle, " ", mergeruleselect, " ", mergeoutputs, " ", button("Build report", async () => {
6591
+ const entries2 = mergeoutputs.value.split(";").map((triple) => triple.split(":")).filter((parts) => parts.length === 4).map((parts) => ({ agentid: parts[0]?.trim() ?? "", taskid: parts[1]?.trim(), key: parts[2]?.trim() ?? "", value: parts[3]?.trim() ?? "" }));
6592
+ await request({ kind: "swarmmerge", entries: entries2, report: { title: reporttitle.value, rule: mergeruleselect.value } });
6593
+ status("The parallel outputs folded into one report with their provenance.");
6594
+ await refresh();
6595
+ }));
6596
+ conflictbox.append(mergerow);
6597
+ const comparerow = document.createElement("div");
6598
+ comparerow.className = "actions";
6599
+ const comparesubject = document.createElement("input");
6600
+ comparesubject.placeholder = "compare subject";
6601
+ const comparefirst = document.createElement("select");
6602
+ const comparesecond = document.createElement("select");
6603
+ for (const agent of swarm.agents) {
6604
+ const one = document.createElement("option");
6605
+ one.value = agent.id;
6606
+ one.textContent = agent.name;
6607
+ comparefirst.append(one);
6608
+ const two = document.createElement("option");
6609
+ two.value = agent.id;
6610
+ two.textContent = agent.name;
6611
+ comparesecond.append(two);
6612
+ }
6613
+ const comparevalue = document.createElement("input");
6614
+ comparevalue.placeholder = "output of the first agent";
6615
+ const comparevalue2 = document.createElement("input");
6616
+ comparevalue2.placeholder = "output of the second agent";
6617
+ comparerow.append(comparesubject, " ", comparefirst, " ", comparevalue, " ", comparesecond, " ", comparevalue2, " ", button("Compare outputs", async () => {
6618
+ await request({ kind: "swarmmerge", compare: { subject: comparesubject.value, outputs: [{ agentid: comparefirst.value, value: comparevalue.value }, { agentid: comparesecond.value, value: comparevalue2.value }] } });
6619
+ status("The competing outputs were contrasted for the user.");
6620
+ await refresh();
6621
+ }));
6622
+ conflictbox.append(comparerow);
6623
+ const lessonrow = document.createElement("div");
6624
+ lessonrow.className = "actions";
6625
+ const lessonagent = document.createElement("select");
6626
+ for (const agent of swarm.agents) {
6627
+ const option = document.createElement("option");
6628
+ option.value = agent.id;
6629
+ option.textContent = agent.name;
6630
+ lessonagent.append(option);
6631
+ }
6632
+ const lessonstatement = document.createElement("input");
6633
+ lessonstatement.placeholder = "verified lesson";
6634
+ const lessonverifier = document.createElement("input");
6635
+ lessonverifier.placeholder = "verified by";
6636
+ lessonrow.append(lessonagent, " ", lessonstatement, " ", lessonverifier, " ", button("Share lesson", async () => {
6637
+ await request({ kind: "swarmmerge", lesson: { agentid: lessonagent.value, statement: lessonstatement.value, verifiedby: lessonverifier.value } });
6638
+ status("The verified lesson landed on the findings section for every agent.");
6639
+ await refresh();
6640
+ }), " ", button("Recompute costs", async () => {
6641
+ await request({ kind: "swarmmerge", costs: true });
6642
+ status("The shared cost accounting summed the per agent usage into the swarm totals.");
6643
+ await refresh();
6644
+ }));
6645
+ conflictbox.append(lessonrow);
6646
+ agentsroot.append(conflictbox);
6647
+ const timelinebox = document.createElement("details");
6648
+ timelinebox.className = "sessiongroup";
6649
+ const timelinesummary = document.createElement("summary");
6650
+ timelinesummary.textContent = `Swarm timeline and costs (${swarm.timeline.length} actions)`;
6651
+ timelinebox.append(timelinesummary);
6652
+ const feed2 = document.createElement("ul");
6653
+ feed2.className = "audit";
6654
+ for (const action of swarm.timeline.slice(-12).reverse()) {
6655
+ const entry = document.createElement("li");
6656
+ entry.textContent = `${new Date(action.at).toLocaleTimeString()} ${action.kind}${action.agentid !== void 0 ? ` (${action.agentid})` : ""}: ${action.summary}`;
6657
+ feed2.append(entry);
6658
+ }
6659
+ timelinebox.append(feed2);
6660
+ const replayrow = document.createElement("div");
6661
+ replayrow.className = "actions";
6662
+ const replayselect = document.createElement("select");
6663
+ for (const agent of swarm.agents) {
6664
+ const option = document.createElement("option");
6665
+ option.value = agent.id;
6666
+ option.textContent = agent.name;
6667
+ replayselect.append(option);
6668
+ }
6669
+ replayrow.append(replayselect, " ", button("Replay agent run", async () => {
6670
+ const replayed = await request({ kind: "swarmmerge", replay: replayselect.value });
6671
+ status(replayed.replay !== void 0 && replayed.replay.length > 0 ? `The replay rebuilt ${replayed.replay.length} recorded actions of the agent.` : "The audit trail holds no recorded action of that agent yet.");
6672
+ await refresh();
6673
+ }));
6674
+ timelinebox.append(replayrow);
6675
+ const latestcost = swarm.costs[0];
6676
+ if (latestcost !== void 0) {
6677
+ const costinfo = document.createElement("p");
6678
+ costinfo.textContent = `Shared costs of ${latestcost.agents} agent${latestcost.agents === 1 ? "" : "s"}: ${latestcost.tokens} tokens \xB7 ${latestcost.cost} ${latestcost.currency ?? ""} \xB7 ${latestcost.steps} steps.`;
6679
+ timelinebox.append(costinfo);
6680
+ }
6681
+ agentsroot.append(timelinebox);
5864
6682
  if (swarm.events.length > 0) {
5865
6683
  const eventbox = document.createElement("details");
5866
6684
  eventbox.className = "sessiongroup";
@@ -5878,4 +6696,31 @@ function renderagents(context) {
5878
6696
  agentsroot.append(eventbox);
5879
6697
  }
5880
6698
  }
6699
+ {
6700
+ let sandboxframe;
6701
+ chrome.runtime.onMessage.addListener((message, _sender, sendresponse) => {
6702
+ if (!message || message.kind !== "environments" || message.action !== "sandboxhost" || !message.render?.nonce) return false;
6703
+ try {
6704
+ if (!sandboxframe) {
6705
+ sandboxframe = document.createElement("iframe");
6706
+ sandboxframe.src = chrome.runtime.getURL("sandbox.html");
6707
+ sandboxframe.style.display = "none";
6708
+ sandboxframe.setAttribute("aria-hidden", "true");
6709
+ document.body.append(sandboxframe);
6710
+ }
6711
+ sandboxframe.contentWindow?.postMessage({ channel: "devthinksandbox", type: "render", nonce: message.render.nonce, markup: message.render.markup ?? "" }, "*");
6712
+ const waitfor = (event) => {
6713
+ const data = event.data;
6714
+ if (data?.channel !== "devthinksandbox" || data.type !== "renderresult" || data.nonce !== message.render?.nonce) return;
6715
+ window.removeEventListener("message", waitfor);
6716
+ sendresponse({ ok: data.ok !== false, text: data.text ?? "", summary: data.summary ?? "The sandbox frame returned its render result." });
6717
+ };
6718
+ window.addEventListener("message", waitfor);
6719
+ return true;
6720
+ } catch {
6721
+ sendresponse({ ok: false, text: "", summary: "The sandbox host could not open the sandboxed page." });
6722
+ return true;
6723
+ }
6724
+ });
6725
+ }
5881
6726
  //# sourceMappingURL=sidepanel.js.map