@wenathlan/extension 1.1.56 → 1.1.58

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 (40) hide show
  1. package/README.md +5 -3
  2. package/dist/agentmailbox.d.ts +42 -0
  3. package/dist/agentmailbox.d.ts.map +1 -0
  4. package/dist/blackboard.d.ts +55 -0
  5. package/dist/blackboard.d.ts.map +1 -0
  6. package/dist/index.d.ts +8 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4570 -3392
  9. package/dist/index.js.map +4 -4
  10. package/dist/llm.d.ts +238 -0
  11. package/dist/llm.d.ts.map +1 -0
  12. package/dist/memory.d.ts +112 -1
  13. package/dist/memory.d.ts.map +1 -1
  14. package/dist/modelroute.d.ts +43 -0
  15. package/dist/modelroute.d.ts.map +1 -0
  16. package/dist/multiagent.d.ts +151 -0
  17. package/dist/multiagent.d.ts.map +1 -0
  18. package/dist/policy.d.ts +67 -1
  19. package/dist/policy.d.ts.map +1 -1
  20. package/dist/promptlibrary.d.ts +33 -0
  21. package/dist/promptlibrary.d.ts.map +1 -0
  22. package/dist/protocol.d.ts +115 -1
  23. package/dist/protocol.d.ts.map +1 -1
  24. package/dist/taskqueue.d.ts +97 -0
  25. package/dist/taskqueue.d.ts.map +1 -0
  26. package/dist/types.d.ts +375 -2
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/version.d.ts +1 -1
  29. package/extension/dist/background.js +5421 -3808
  30. package/extension/dist/background.js.map +4 -4
  31. package/extension/dist/manifest.json +1 -1
  32. package/extension/dist/pagebridge.js.map +1 -1
  33. package/extension/dist/popup.html +1 -1
  34. package/extension/dist/popup.js +23 -0
  35. package/extension/dist/popup.js.map +2 -2
  36. package/extension/dist/sidepanel.html +3 -1
  37. package/extension/dist/sidepanel.js +713 -0
  38. package/extension/dist/sidepanel.js.map +2 -2
  39. package/extension/manifest.json +1 -1
  40. package/package.json +1 -1
@@ -393,6 +393,11 @@ var workflowsroot = document.querySelector("#workflows");
393
393
  var workfloweditorroot = document.querySelector("#workfloweditor");
394
394
  var triggersroot = document.querySelector("#triggers");
395
395
  var agentprotocolroot = document.querySelector("#agentprotocol");
396
+ var modelsroot = document.querySelector("#models");
397
+ var agentsroot = document.querySelector("#agents");
398
+ var commandinput = document.querySelector("#command");
399
+ var commandbutton = document.querySelector("#commandsend");
400
+ var intentbadge = document.querySelector("#intentbadge");
396
401
  var triggerview = { manual: void 0, history: void 0 };
397
402
  var sessionsview = { term: "", window: "all", diffselection: [], restorereview: void 0, importreview: void 0 };
398
403
  var workflowview = { review: void 0, selected: "" };
@@ -2876,6 +2881,8 @@ async function refresh() {
2876
2881
  renderworkfloweditor(context);
2877
2882
  rendertriggers(context);
2878
2883
  renderagentprotocol(context);
2884
+ rendermodels(context);
2885
+ renderagents(context);
2879
2886
  renderconsolediff();
2880
2887
  renderaudit(context.audit);
2881
2888
  rendercapabilities(context.capabilities);
@@ -2889,6 +2896,13 @@ async function create(kind) {
2889
2896
  localbutton?.addEventListener("click", () => create("proposelocal").catch((error) => status(error instanceof Error ? error.message : String(error), true)));
2890
2897
  remotebutton?.addEventListener("click", () => create("proposeremote").catch((error) => status(error instanceof Error ? error.message : String(error), true)));
2891
2898
  diagnosticbutton?.addEventListener("click", () => request({ kind: "diagnostic" }).then(() => refresh()).catch((error) => status(error instanceof Error ? error.message : String(error), true)));
2899
+ commandbutton?.addEventListener("click", () => request({ kind: "llmcommand", text: commandinput?.value ?? "" }).then(() => {
2900
+ status("The model parsed the command; the intent badge shows the classification.");
2901
+ return refresh();
2902
+ }).catch((error) => status(error instanceof Error ? error.message : String(error), true)));
2903
+ commandinput?.addEventListener("keydown", (event) => {
2904
+ if (event.key === "Enter") commandbutton?.click();
2905
+ });
2892
2906
  refresh().catch((error) => status(error instanceof Error ? error.message : String(error), true));
2893
2907
  function renderprofiling(context) {
2894
2908
  if (!profilingroot) return;
@@ -5165,4 +5179,703 @@ function renderagentprotocol(context) {
5165
5179
  }
5166
5180
  agentprotocolroot.append(callsbox);
5167
5181
  }
5182
+ function rendermodels(context) {
5183
+ if (!modelsroot) return;
5184
+ modelsroot.replaceChildren();
5185
+ const llm = context.llm;
5186
+ if (!llm) {
5187
+ const empty = document.createElement("p");
5188
+ empty.textContent = "The models state is unknown.";
5189
+ modelsroot.append(empty);
5190
+ return;
5191
+ }
5192
+ const head = document.createElement("p");
5193
+ head.textContent = `${llm.providers.length} provider${llm.providers.length === 1 ? "" : "s"} \xB7 ${llm.routes.length} route${llm.routes.length === 1 ? "" : "s"} \xB7 ${llm.usage.calls} model call${llm.usage.calls === 1 ? "" : "s"} with ${llm.usage.totaltokens} tokens${llm.budget !== void 0 ? ` against the ceiling` : " and no ceiling"}.`;
5194
+ modelsroot.append(head);
5195
+ const providersbox = document.createElement("details");
5196
+ providersbox.className = "sessiongroup";
5197
+ providersbox.open = true;
5198
+ const providersummary = document.createElement("summary");
5199
+ providersummary.textContent = `Providers (${llm.providers.length})`;
5200
+ providersbox.append(providersummary);
5201
+ for (const provider of llm.providers) {
5202
+ const row = document.createElement("div");
5203
+ row.className = "sessionrow";
5204
+ const info = document.createElement("p");
5205
+ info.textContent = `${provider.name} \xB7 ${provider.style} \xB7 ${provider.status}${provider.lastcheckedat !== void 0 ? ` (checked ${new Date(provider.lastcheckedat).toLocaleTimeString()})` : ""}${provider.authref !== void 0 ? ` \xB7 key ${provider.authref.name}` : " \xB7 no key"}${provider.costpermilliontokens !== void 0 ? ` \xB7 ${provider.costpermilliontokens} per million tokens` : ""}.`;
5206
+ row.append(info);
5207
+ const actions = document.createElement("div");
5208
+ actions.className = "actions";
5209
+ const nameinput = document.createElement("input");
5210
+ nameinput.value = provider.name;
5211
+ nameinput.placeholder = "name";
5212
+ const endpointinput = document.createElement("input");
5213
+ endpointinput.value = provider.endpoint;
5214
+ endpointinput.placeholder = "endpoint url";
5215
+ const styleselect = document.createElement("select");
5216
+ for (const style of ["chatcompletions", "responses", "messages", "gemini"]) {
5217
+ const option = document.createElement("option");
5218
+ option.value = style;
5219
+ option.textContent = style;
5220
+ option.selected = provider.style === style;
5221
+ styleselect.append(option);
5222
+ }
5223
+ const modelsinput = document.createElement("input");
5224
+ modelsinput.value = provider.models.join(", ");
5225
+ modelsinput.placeholder = "models, comma separated";
5226
+ const keyinput = document.createElement("input");
5227
+ keyinput.placeholder = "stored key name";
5228
+ actions.append(nameinput, " ", endpointinput, " ", styleselect, " ", modelsinput, " ", keyinput, " ", button("Save", async () => {
5229
+ await request({ kind: "llmproviders", id: provider.id, name: nameinput.value, endpoint: endpointinput.value, style: styleselect.value, models: modelsinput.value.split(",").map((model) => model.trim()).filter((model) => model !== ""), ...keyinput.value.trim() !== "" ? { authrefname: keyinput.value.trim() } : {} });
5230
+ status(`Saved the provider ${nameinput.value}.`);
5231
+ await refresh();
5232
+ }), " ", button("Test call", async () => {
5233
+ await request({ kind: "llmtestprovider", id: provider.id });
5234
+ status(`The test call of ${provider.name} answered.`);
5235
+ await refresh();
5236
+ }), " ", button("Remove", async () => {
5237
+ await request({ kind: "llmproviders", id: provider.id, remove: true });
5238
+ status(`Removed the provider ${provider.name}.`);
5239
+ await refresh();
5240
+ }));
5241
+ row.append(actions);
5242
+ providersbox.append(row);
5243
+ }
5244
+ const addrow = document.createElement("div");
5245
+ addrow.className = "actions";
5246
+ const addname = document.createElement("input");
5247
+ addname.placeholder = "new provider name";
5248
+ const addendpoint = document.createElement("input");
5249
+ addendpoint.placeholder = "endpoint url";
5250
+ const addstyle = document.createElement("select");
5251
+ for (const style of ["chatcompletions", "responses", "messages", "gemini"]) {
5252
+ const option = document.createElement("option");
5253
+ option.value = style;
5254
+ option.textContent = style;
5255
+ addstyle.append(option);
5256
+ }
5257
+ const addmodels = document.createElement("input");
5258
+ addmodels.placeholder = "models, comma separated";
5259
+ const addkey = document.createElement("input");
5260
+ addkey.placeholder = "stored key name";
5261
+ addrow.append(addname, " ", addendpoint, " ", addstyle, " ", addmodels, " ", addkey, " ", button("Add provider", async () => {
5262
+ await request({ kind: "llmproviders", name: addname.value, endpoint: addendpoint.value, style: addstyle.value, models: addmodels.value.split(",").map((model) => model.trim()).filter((model) => model !== ""), ...addkey.value.trim() !== "" ? { authrefname: addkey.value.trim() } : {} });
5263
+ status(`Added the provider ${addname.value}; nothing is hardcoded so any gateway works.`);
5264
+ await refresh();
5265
+ }));
5266
+ providersbox.append(addrow);
5267
+ modelsroot.append(providersbox);
5268
+ const localbox = document.createElement("details");
5269
+ localbox.className = "sessiongroup";
5270
+ localbox.open = true;
5271
+ const localsummary = document.createElement("summary");
5272
+ localsummary.textContent = "Local model endpoint";
5273
+ localbox.append(localsummary);
5274
+ const localinfo = document.createElement("p");
5275
+ localinfo.textContent = llm.local !== void 0 ? `${llm.local.endpoint} with ${llm.local.model} (${llm.local.style})${llm.local.health !== void 0 ? ` \xB7 health ${llm.local.health.ok ? "ok" : `failing: ${llm.local.health.detail ?? "unknown"}`}` : " \xB7 no health check yet"}.` : "No local endpoint configured; local inference keeps sensitive extractions on the machine.";
5276
+ localbox.append(localinfo);
5277
+ const localactions = document.createElement("div");
5278
+ localactions.className = "actions";
5279
+ const localendpoint = document.createElement("input");
5280
+ localendpoint.placeholder = "local endpoint url";
5281
+ localendpoint.value = llm.local?.endpoint ?? "";
5282
+ const localmodel = document.createElement("input");
5283
+ localmodel.placeholder = "model name";
5284
+ localmodel.value = llm.local?.model ?? "";
5285
+ const localstyle = document.createElement("select");
5286
+ for (const style of ["chatcompletions", "responses", "messages", "gemini"]) {
5287
+ const option = document.createElement("option");
5288
+ option.value = style;
5289
+ option.textContent = style;
5290
+ option.selected = llm.local?.style === style;
5291
+ localstyle.append(option);
5292
+ }
5293
+ localactions.append(localendpoint, " ", localmodel, " ", localstyle, " ", button("Save local", async () => {
5294
+ await request({ kind: "llmlocal", endpoint: localendpoint.value, model: localmodel.value, style: localstyle.value });
5295
+ status("Saved the local model endpoint; the calls never leave the machine.");
5296
+ await refresh();
5297
+ }), " ", button("Health check", async () => {
5298
+ await request({ kind: "llmlocal", check: true });
5299
+ status("The local health check ran; the result rides the endpoint line.");
5300
+ await refresh();
5301
+ }));
5302
+ localbox.append(localactions);
5303
+ modelsroot.append(localbox);
5304
+ const routesbox = document.createElement("details");
5305
+ routesbox.className = "sessiongroup";
5306
+ routesbox.open = true;
5307
+ const routesummary = document.createElement("summary");
5308
+ routesummary.textContent = `Model routes (${llm.routes.length})`;
5309
+ routesbox.append(routesummary);
5310
+ for (const task of llm.tasks) {
5311
+ const row = document.createElement("div");
5312
+ row.className = "sessionrow";
5313
+ const info = document.createElement("p");
5314
+ info.textContent = `${task.kind}: ${task.provider !== void 0 ? `${task.provider} with ${task.model}` : "unrouted; the user picks the pair"}.`;
5315
+ row.append(info);
5316
+ const actions = document.createElement("div");
5317
+ actions.className = "actions";
5318
+ const providerselect = document.createElement("select");
5319
+ for (const provider of llm.providers) {
5320
+ const option = document.createElement("option");
5321
+ option.value = provider.id;
5322
+ option.textContent = provider.name;
5323
+ providerselect.append(option);
5324
+ }
5325
+ const modelinput = document.createElement("input");
5326
+ modelinput.placeholder = "model";
5327
+ const fallbackselect = document.createElement("select");
5328
+ const noneoption = document.createElement("option");
5329
+ noneoption.value = "";
5330
+ noneoption.textContent = "no fallback";
5331
+ fallbackselect.append(noneoption);
5332
+ for (const provider of llm.providers) {
5333
+ const option = document.createElement("option");
5334
+ option.value = provider.id;
5335
+ option.textContent = provider.name;
5336
+ fallbackselect.append(option);
5337
+ }
5338
+ const fallbackmodel = document.createElement("input");
5339
+ fallbackmodel.placeholder = "fallback model";
5340
+ actions.append(providerselect, " ", modelinput, " ", fallbackselect, " ", fallbackmodel, " ", button("Route", async () => {
5341
+ await request({ kind: "llmroutes", taskkind: task.kind, providerid: providerselect.value, model: modelinput.value, ...fallbackselect.value !== "" ? { fallbackproviderid: fallbackselect.value, fallbackmodel: fallbackmodel.value } : {} });
5342
+ status(`Routed the ${task.kind} task kind.`);
5343
+ await refresh();
5344
+ }), " ", button("Unroute", async () => {
5345
+ await request({ kind: "llmroutes", taskkind: task.kind, remove: true });
5346
+ status(`Removed the route of the ${task.kind} task kind.`);
5347
+ await refresh();
5348
+ }));
5349
+ row.append(actions);
5350
+ routesbox.append(row);
5351
+ }
5352
+ if (llm.routehistory.length > 0) {
5353
+ const history = document.createElement("p");
5354
+ history.textContent = `Route revisions: ${llm.routehistory.slice(0, 5).map((entry) => `${entry.kind} r${entry.revision} ${entry.providerid}/${entry.model}`).join(" \xB7 ")}.`;
5355
+ routesbox.append(history);
5356
+ }
5357
+ modelsroot.append(routesbox);
5358
+ if (llm.parse !== void 0) {
5359
+ const badge = document.createElement("p");
5360
+ badge.textContent = `Last command: ${llm.parse.intent} at confidence ${Math.round(llm.parse.confidence * 100)}%${llm.parse.entities.length > 0 ? ` with ${llm.parse.entities.map((entity) => `${entity.name}=${entity.value}`).join(", ")}` : ""}${llm.parse.model !== void 0 ? ` parsed by ${llm.parse.model}` : " parsed locally"}.`;
5361
+ modelsroot.append(badge);
5362
+ if (intentbadge) intentbadge.textContent = `${llm.parse.intent} ${Math.round(llm.parse.confidence * 100)}%`;
5363
+ } else if (intentbadge) intentbadge.textContent = "";
5364
+ const draftsbox = document.createElement("details");
5365
+ draftsbox.className = "sessiongroup";
5366
+ draftsbox.open = true;
5367
+ const draftsummary = document.createElement("summary");
5368
+ draftsummary.textContent = `Model drafted plans (${llm.drafts.length})`;
5369
+ draftsbox.append(draftsummary);
5370
+ for (const draft of llm.drafts.slice(0, 5)) {
5371
+ const card = document.createElement("div");
5372
+ card.className = "sessionrow";
5373
+ const info = document.createElement("p");
5374
+ info.textContent = `${draft.goal} \xB7 ${draft.steps.length} steps \xB7 ${draft.state}${draft.lintfindings.length > 0 ? ` \xB7 ${draft.lintfindings.length} grammar finding${draft.lintfindings.length === 1 ? "" : "s"}` : " \xB7 clean grammar"} \xB7 by ${draft.model}.`;
5375
+ card.append(info);
5376
+ const edits = [];
5377
+ for (const step of draft.steps) {
5378
+ const steprow = document.createElement("div");
5379
+ steprow.className = "actions";
5380
+ const kindinput = document.createElement("input");
5381
+ kindinput.value = step.kind;
5382
+ kindinput.placeholder = "kind";
5383
+ const targetinput = document.createElement("input");
5384
+ targetinput.value = step.target ?? "";
5385
+ targetinput.placeholder = "target";
5386
+ const valueinput = document.createElement("input");
5387
+ valueinput.value = step.value ?? "";
5388
+ valueinput.placeholder = "value";
5389
+ const summaryinput = document.createElement("input");
5390
+ summaryinput.value = step.summary;
5391
+ summaryinput.placeholder = "summary";
5392
+ steprow.append(kindinput, " ", targetinput, " ", valueinput, " ", summaryinput);
5393
+ card.append(steprow);
5394
+ edits.push({ id: step.id, kind: kindinput, target: targetinput, value: valueinput, summary: summaryinput });
5395
+ }
5396
+ if (draft.openquestions.length > 0) {
5397
+ const questions = document.createElement("p");
5398
+ questions.textContent = `Open questions: ${draft.openquestions.join(" | ")}`;
5399
+ card.append(questions);
5400
+ }
5401
+ if (draft.lintfindings.length > 0) {
5402
+ const findings = document.createElement("p");
5403
+ findings.textContent = `Grammar findings: ${draft.lintfindings.join(" ")}`;
5404
+ card.append(findings);
5405
+ }
5406
+ const actions = document.createElement("div");
5407
+ actions.className = "actions";
5408
+ actions.append(button("Approve draft", async () => {
5409
+ await request({ kind: "llmdraftdecision", draftid: draft.id, approve: true, steps: edits.map((edit) => ({ id: edit.id, kind: edit.kind.value, ...edit.target.value.trim() !== "" ? { target: edit.target.value } : {}, ...edit.value.value.trim() !== "" ? { value: edit.value.value } : {}, summary: edit.summary.value })) });
5410
+ status("The approved draft became a pending plan that still passes the same plan review.");
5411
+ await refresh();
5412
+ }), " ", button("Reject draft", async () => {
5413
+ await request({ kind: "llmdraftdecision", draftid: draft.id });
5414
+ status("The draft is rejected and stays for the audit trail.");
5415
+ await refresh();
5416
+ }), " ", button("Replan failed tail", async () => {
5417
+ await request({ kind: "llmreplan", draftid: draft.id, failedstepids: edits.slice(-1).map((edit) => edit.id), reason: "The last step failed and the model replans the tail." });
5418
+ status("The model replanned the failed tail; the fresh review waits.");
5419
+ await refresh();
5420
+ }));
5421
+ card.append(actions);
5422
+ draftsbox.append(card);
5423
+ }
5424
+ modelsroot.append(draftsbox);
5425
+ const replansbox = document.createElement("details");
5426
+ replansbox.className = "sessiongroup";
5427
+ replansbox.open = true;
5428
+ const replansummary = document.createElement("summary");
5429
+ replansummary.textContent = `Replans (${llm.replans.length})`;
5430
+ replansbox.append(replansummary);
5431
+ for (const replan of llm.replans.slice(0, 5)) {
5432
+ const card = document.createElement("div");
5433
+ card.className = "sessionrow";
5434
+ const info = document.createElement("p");
5435
+ info.textContent = `${replan.reason} \xB7 keeps ${replan.completedstepids.length} completed step${replan.completedstepids.length === 1 ? "" : "s"} \xB7 ${replan.state}.`;
5436
+ card.append(info);
5437
+ for (const step of replan.tail) {
5438
+ const tail = document.createElement("p");
5439
+ tail.textContent = `\u21BB ${step.id} ${step.kind}: ${step.summary} \u2014 fresh review required`;
5440
+ card.append(tail);
5441
+ }
5442
+ const actions = document.createElement("div");
5443
+ actions.className = "actions";
5444
+ actions.append(button("Approve fresh review", async () => {
5445
+ await request({ kind: "llmreplandecision", replanid: replan.id, approve: true });
5446
+ status("The approved replan became a pending plan with the changed tail under the same plan review.");
5447
+ await refresh();
5448
+ }), " ", button("Reject replan", async () => {
5449
+ await request({ kind: "llmreplandecision", replanid: replan.id });
5450
+ status("The replan is rejected and stays for the audit trail.");
5451
+ await refresh();
5452
+ }));
5453
+ card.append(actions);
5454
+ replansbox.append(card);
5455
+ }
5456
+ modelsroot.append(replansbox);
5457
+ const notesbox = document.createElement("details");
5458
+ notesbox.className = "sessiongroup";
5459
+ const notesummary = document.createElement("summary");
5460
+ notesummary.textContent = `Reflection notes (${llm.notes.length})`;
5461
+ notesbox.append(notesummary);
5462
+ for (const note of llm.notes.slice(0, 5)) {
5463
+ const row = document.createElement("p");
5464
+ row.textContent = `Step ${note.stepid} (${note.runid}): ${note.outcome} \u2014 lesson ${note.lesson} \u2014 next ${note.advice} \xB7 by ${note.model}.`;
5465
+ notesbox.append(row);
5466
+ }
5467
+ modelsroot.append(notesbox);
5468
+ const budgetbox = document.createElement("details");
5469
+ budgetbox.className = "sessiongroup";
5470
+ budgetbox.open = true;
5471
+ const budgetsummary = document.createElement("summary");
5472
+ budgetsummary.textContent = "Cost budget";
5473
+ budgetbox.append(budgetsummary);
5474
+ const meter = document.createElement("progress");
5475
+ meter.max = llm.budget?.maxtokens ?? (llm.usage.totaltokens || 1);
5476
+ meter.value = Math.min(llm.usage.totaltokens, Number(meter.max));
5477
+ budgetbox.append(meter);
5478
+ const budgetinfo = document.createElement("p");
5479
+ budgetinfo.textContent = `${llm.usage.totaltokens} tokens (${llm.usage.prompttokens} prompt and ${llm.usage.completiontokens} completion) and ${llm.usage.cost.toFixed(4)} cost over ${llm.usage.calls} call${llm.usage.calls === 1 ? "" : "s"}${llm.budget?.maxtokens !== void 0 ? ` against the ${llm.budget.maxtokens} token ceiling` : " with no token ceiling"}${llm.budget?.maxcost !== void 0 ? ` and the ${llm.budget.maxcost} ${llm.budget.currency ?? ""} cost ceiling` : ""}; a reached ceiling halts and asks.`;
5480
+ budgetbox.append(budgetinfo);
5481
+ const budgetactions = document.createElement("div");
5482
+ budgetactions.className = "actions";
5483
+ const tokensinput = document.createElement("input");
5484
+ tokensinput.placeholder = "token ceiling";
5485
+ const costinput = document.createElement("input");
5486
+ costinput.placeholder = "cost ceiling";
5487
+ const currencyinput = document.createElement("input");
5488
+ currencyinput.placeholder = "currency";
5489
+ budgetactions.append(tokensinput, " ", costinput, " ", currencyinput, " ", button("Set budget", async () => {
5490
+ await request({ kind: "llmbudget", ...tokensinput.value.trim() !== "" ? { maxtokens: Number(tokensinput.value) } : {}, ...costinput.value.trim() !== "" ? { maxcost: Number(costinput.value) } : {}, ...currencyinput.value.trim() !== "" ? { currency: currencyinput.value } : {} });
5491
+ status("Saved the cost budget; every ceiling stays the user choice.");
5492
+ await refresh();
5493
+ }), " ", button("Remove budget", async () => {
5494
+ await request({ kind: "llmbudget", remove: true });
5495
+ status("The cost budget is gone; the runs stay unbounded.");
5496
+ await refresh();
5497
+ }));
5498
+ budgetbox.append(budgetactions);
5499
+ modelsroot.append(budgetbox);
5500
+ const templatesbox = document.createElement("details");
5501
+ templatesbox.className = "sessiongroup";
5502
+ const templatesummary = document.createElement("summary");
5503
+ templatesummary.textContent = `Prompt library (${llm.templates.length})`;
5504
+ templatesbox.append(templatesummary);
5505
+ for (const template of llm.templates.slice(0, 8)) {
5506
+ const row = document.createElement("p");
5507
+ row.textContent = `${template.name} v${template.version} \xB7 variables ${template.variables.join(", ") || "none"}${template.notes !== void 0 ? ` \xB7 ${template.notes}` : ""}: ${template.body.slice(0, 120)}${template.body.length > 120 ? "\u2026" : ""}`;
5508
+ templatesbox.append(row);
5509
+ }
5510
+ const templateactions = document.createElement("div");
5511
+ templateactions.className = "actions";
5512
+ const templatename = document.createElement("input");
5513
+ templatename.placeholder = "template name";
5514
+ const templatebody = document.createElement("input");
5515
+ templatebody.placeholder = "body with {{variables}}";
5516
+ const templatenotes = document.createElement("input");
5517
+ templatenotes.placeholder = "change notes";
5518
+ templateactions.append(templatename, " ", templatebody, " ", templatenotes, " ", button("Save template", async () => {
5519
+ await request({ kind: "llmtemplate", name: templatename.value, body: templatebody.value, ...templatenotes.value.trim() !== "" ? { notes: templatenotes.value } : {} });
5520
+ status("Saved the template version with its change notes.");
5521
+ await refresh();
5522
+ }), " ", button("Remove template", async () => {
5523
+ await request({ kind: "llmtemplate", name: templatename.value, remove: true });
5524
+ status("Removed every version of the template.");
5525
+ await refresh();
5526
+ }));
5527
+ templatesbox.append(templateactions);
5528
+ modelsroot.append(templatesbox);
5529
+ const guardbox = document.createElement("details");
5530
+ guardbox.className = "sessiongroup";
5531
+ const guardsummary = document.createElement("summary");
5532
+ guardsummary.textContent = `Guard refusals (${llm.guardnotices.length})`;
5533
+ guardbox.append(guardsummary);
5534
+ for (const notice of llm.guardnotices.slice(0, 5)) {
5535
+ const row = document.createElement("p");
5536
+ row.textContent = `${notice.verdict} after ${notice.attempts} attempt${notice.attempts === 1 ? "" : "s"}: ${notice.reason ?? "the output failed its guard"}.`;
5537
+ guardbox.append(row);
5538
+ }
5539
+ if (llm.guardnotices.length === 0) {
5540
+ const row = document.createElement("p");
5541
+ row.textContent = "No guard refusal yet; invalid model output never executes.";
5542
+ guardbox.append(row);
5543
+ }
5544
+ modelsroot.append(guardbox);
5545
+ }
5546
+ function renderagents(context) {
5547
+ if (!agentsroot) return;
5548
+ agentsroot.replaceChildren();
5549
+ const swarm = context.swarm;
5550
+ if (!swarm) {
5551
+ const empty = document.createElement("p");
5552
+ empty.textContent = "The swarm state is unknown.";
5553
+ agentsroot.append(empty);
5554
+ return;
5555
+ }
5556
+ const head = document.createElement("p");
5557
+ head.textContent = `${swarm.overview.agents} agent${swarm.overview.agents === 1 ? "" : "s"} (${swarm.overview.active} active, ${swarm.overview.paused} paused, ${swarm.overview.stopped} stopped) \xB7 ${swarm.overview.tasks} task${swarm.overview.tasks === 1 ? "" : "s"} (${swarm.overview.claimed} claimed, ${swarm.overview.queued} queued, ${swarm.overview.done} done) \xB7 ${swarm.overview.messages} message${swarm.overview.messages === 1 ? "" : "s"} with ${swarm.overview.unread} unread \xB7 queue policy ${swarm.queue.completionpolicy}${swarm.queue.complete ? " \xB7 queue complete" : ""}.`;
5558
+ agentsroot.append(head);
5559
+ const switchbox = document.createElement("div");
5560
+ switchbox.className = "actions";
5561
+ if (swarm.killswitch.engaged) {
5562
+ const state = document.createElement("span");
5563
+ state.className = "muted";
5564
+ state.textContent = `Killswitch engaged${swarm.killswitch.reason !== void 0 ? `: ${swarm.killswitch.reason}` : ""}; every agent halted.`;
5565
+ switchbox.append(state, " ", button("Disarm killswitch", async () => {
5566
+ await request({ kind: "swarmagent", disarm: true });
5567
+ status("The killswitch disarmed; the stopped agents stay stopped until resumed.");
5568
+ await refresh();
5569
+ }));
5570
+ } else {
5571
+ switchbox.append(button("Halt every agent (killswitch)", async () => {
5572
+ if (window.confirm("Halt every agent of the swarm at once?")) {
5573
+ await request({ kind: "swarmagent", killall: true, reason: "The user halted the swarm from the panel." });
5574
+ status("The killswitch engaged: every agent halted at once and the claims returned to the queue.");
5575
+ await refresh();
5576
+ }
5577
+ }));
5578
+ }
5579
+ agentsroot.append(switchbox);
5580
+ const agentsbox = document.createElement("details");
5581
+ agentsbox.className = "sessiongroup";
5582
+ agentsbox.open = true;
5583
+ const agentsummary = document.createElement("summary");
5584
+ agentsummary.textContent = `Agent cards (${swarm.agents.length})`;
5585
+ agentsbox.append(agentsummary);
5586
+ for (const agent of swarm.agents) {
5587
+ const row = document.createElement("div");
5588
+ row.className = "sessionrow";
5589
+ const info = document.createElement("p");
5590
+ 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` : ""}.`;
5592
+ row.append(info);
5593
+ const actions = document.createElement("div");
5594
+ actions.className = "actions";
5595
+ actions.append(button("Pause", async () => {
5596
+ await request({ kind: "swarmagent", agentid: agent.id, action: "pause" });
5597
+ status(`Paused the agent ${agent.name}; the others keep running.`);
5598
+ await refresh();
5599
+ }), " ", button("Resume", async () => {
5600
+ await request({ kind: "swarmagent", agentid: agent.id, action: "resume" });
5601
+ status(`Resumed the agent ${agent.name}.`);
5602
+ await refresh();
5603
+ }), " ", button("Stop", async () => {
5604
+ await request({ kind: "swarmagent", agentid: agent.id, action: "stop" });
5605
+ status(`Stopped the agent ${agent.name}.`);
5606
+ await refresh();
5607
+ }), " ", button("Claim task", async () => {
5608
+ await request({ kind: "swarmqueue", agentid: agent.id, claim: true });
5609
+ status(`The agent ${agent.name} claimed the highest priority task; the proposal still passes the plan review.`);
5610
+ await refresh();
5611
+ }), " ", button("Heartbeat", async () => {
5612
+ await request({ kind: "swarmagent", agentid: agent.id, heartbeat: true });
5613
+ status(`The agent ${agent.name} refreshed its heartbeat.`);
5614
+ await refresh();
5615
+ }));
5616
+ const budgetrow = document.createElement("div");
5617
+ budgetrow.className = "actions";
5618
+ const tokensinput = document.createElement("input");
5619
+ tokensinput.placeholder = "token ceiling";
5620
+ const costinput = document.createElement("input");
5621
+ costinput.placeholder = "cost ceiling";
5622
+ const stepsinput = document.createElement("input");
5623
+ stepsinput.placeholder = "step ceiling";
5624
+ const currencyinput = document.createElement("input");
5625
+ currencyinput.placeholder = "currency";
5626
+ budgetrow.append(tokensinput, " ", costinput, " ", currencyinput, " ", stepsinput, " ", button("Set budget", async () => {
5627
+ await request({ kind: "swarmagent", agentid: agent.id, budget: { ...tokensinput.value.trim() !== "" ? { maxtokens: Number(tokensinput.value) } : {}, ...costinput.value.trim() !== "" ? { maxcost: Number(costinput.value) } : {}, ...stepsinput.value.trim() !== "" ? { maxsteps: Number(stepsinput.value) } : {}, ...currencyinput.value.trim() !== "" ? { currency: currencyinput.value.trim() } : {} } });
5628
+ status(`Saved the budget of the agent ${agent.name}.`);
5629
+ await refresh();
5630
+ }));
5631
+ row.append(actions, budgetrow);
5632
+ agentsbox.append(row);
5633
+ }
5634
+ const addrow = document.createElement("div");
5635
+ addrow.className = "actions";
5636
+ const nameinput = document.createElement("input");
5637
+ nameinput.placeholder = "new agent name";
5638
+ const roleselect = document.createElement("select");
5639
+ for (const role of ["worker", "planner", "observer"]) {
5640
+ const option = document.createElement("option");
5641
+ option.value = role;
5642
+ option.textContent = role;
5643
+ roleselect.append(option);
5644
+ }
5645
+ const customrole = document.createElement("input");
5646
+ customrole.placeholder = "custom role";
5647
+ const tabinput = document.createElement("input");
5648
+ tabinput.placeholder = "tab id";
5649
+ addrow.append(nameinput, " ", roleselect, " ", customrole, " ", tabinput, " ", button("Register agent", async () => {
5650
+ await request({ kind: "swarmagent", register: { name: nameinput.value, role: customrole.value.trim() !== "" ? customrole.value.trim() : roleselect.value, ...tabinput.value.trim() !== "" ? { tabid: Number(tabinput.value) } : {} } });
5651
+ status(`Registered the agent ${nameinput.value}; one tab holds at most one agent.`);
5652
+ await refresh();
5653
+ }));
5654
+ agentsbox.append(addrow);
5655
+ const spawnrow = document.createElement("div");
5656
+ spawnrow.className = "actions";
5657
+ const parentselect = document.createElement("select");
5658
+ for (const agent of swarm.agents) {
5659
+ const option = document.createElement("option");
5660
+ option.value = agent.id;
5661
+ option.textContent = agent.name;
5662
+ parentselect.append(option);
5663
+ }
5664
+ const spawnrole = document.createElement("select");
5665
+ for (const role of ["worker", "planner", "observer"]) {
5666
+ const option = document.createElement("option");
5667
+ option.value = role;
5668
+ option.textContent = role;
5669
+ spawnrole.append(option);
5670
+ }
5671
+ const spawntask = document.createElement("input");
5672
+ spawntask.placeholder = "sub agent task";
5673
+ const spawndepth = document.createElement("input");
5674
+ spawndepth.placeholder = "depth";
5675
+ spawndepth.value = "1";
5676
+ const spawnname = document.createElement("input");
5677
+ spawnname.placeholder = "sub agent name";
5678
+ spawnrow.append(parentselect, " ", spawnrole, " ", spawntask, " ", spawndepth, " ", spawnname, " ", button("Spawn sub agent", async () => {
5679
+ await request({ kind: "swarmagent", spawn: { parentid: parentselect.value, role: spawnrole.value, task: spawntask.value, depth: Number(spawndepth.value || "1"), ...spawnname.value.trim() !== "" ? { name: spawnname.value } : {} } });
5680
+ status("Spawned the sub agent; the depth history records the recursion.");
5681
+ await refresh();
5682
+ }));
5683
+ agentsbox.append(spawnrow);
5684
+ if (swarm.spawns.length > 0) {
5685
+ const history = document.createElement("p");
5686
+ history.textContent = `Spawn history: ${swarm.spawns.slice(0, 5).map((record) => `${record.parentid} \u2192 ${record.childid} (${record.role}, depth ${record.depth})`).join("; ")}.`;
5687
+ agentsbox.append(history);
5688
+ }
5689
+ agentsroot.append(agentsbox);
5690
+ const queuebox = document.createElement("details");
5691
+ queuebox.className = "sessiongroup";
5692
+ queuebox.open = true;
5693
+ const queuesummary = document.createElement("summary");
5694
+ queuesummary.textContent = `Task queue (${swarm.queue.items.length})`;
5695
+ queuebox.append(queuesummary);
5696
+ for (const lane of swarm.queue.lanesreport) {
5697
+ const row = document.createElement("p");
5698
+ const claims = swarm.queue.claims.filter((claim) => swarm.queue.items.some((item) => item.id === claim.taskid && item.lane === lane.lane && item.state === "claimed"));
5699
+ row.textContent = `Lane ${lane.lane}: ${lane.queued} queued \xB7 ${lane.claimed} claimed \xB7 ${lane.done} done \xB7 ${lane.cancelled} cancelled${claims.length > 0 ? ` \xB7 held by ${claims.map((claim) => claim.agentid).join(", ")}` : ""}.`;
5700
+ queuebox.append(row);
5701
+ }
5702
+ const list = document.createElement("ol");
5703
+ list.className = "audit";
5704
+ for (const item of swarm.queue.items.slice(0, 12)) {
5705
+ const entry = document.createElement("li");
5706
+ entry.textContent = `${item.payload} \u2014 lane ${item.lane}, priority ${item.priority}, ${item.state}.`;
5707
+ const actions = document.createElement("div");
5708
+ actions.className = "actions";
5709
+ actions.append(button("Complete", async () => {
5710
+ await request({ kind: "swarmqueue", taskid: item.id, complete: true });
5711
+ status("The task completed and released its claim.");
5712
+ await refresh();
5713
+ }), " ", button("Cancel", async () => {
5714
+ await request({ kind: "swarmqueue", taskid: item.id, cancel: true });
5715
+ status("The task left the queue.");
5716
+ await refresh();
5717
+ }));
5718
+ entry.append(actions);
5719
+ list.append(entry);
5720
+ }
5721
+ queuebox.append(list);
5722
+ const enqueuerow = document.createElement("div");
5723
+ enqueuerow.className = "actions";
5724
+ const laneinput = document.createElement("input");
5725
+ laneinput.placeholder = "lane";
5726
+ const priorityinput = document.createElement("input");
5727
+ priorityinput.placeholder = "priority";
5728
+ const payloadinput = document.createElement("input");
5729
+ payloadinput.placeholder = "task in plain language";
5730
+ const lanesinput = document.createElement("input");
5731
+ lanesinput.placeholder = "configured lanes, comma separated";
5732
+ lanesinput.value = swarm.queue.lanes.join(", ");
5733
+ enqueuerow.append(laneinput, " ", priorityinput, " ", payloadinput, " ", button("Enqueue", async () => {
5734
+ await request({ kind: "swarmqueue", enqueue: { lane: laneinput.value, priority: Number(priorityinput.value || "0"), payload: payloadinput.value } });
5735
+ status("The task entered the lane; nothing runs before the plan review.");
5736
+ await refresh();
5737
+ }), " ", button("Requeue orphans", async () => {
5738
+ await request({ kind: "swarmqueue", requeue: true });
5739
+ status("The requeue pass returned the orphaned tasks to their lanes.");
5740
+ await refresh();
5741
+ }), " ", button("Save lanes", async () => {
5742
+ await request({ kind: "swarmqueue", lanes: lanesinput.value.split(",").map((lane) => lane.trim()).filter((lane) => lane !== "") });
5743
+ status("Saved the configured lanes.");
5744
+ await refresh();
5745
+ }));
5746
+ queuebox.append(enqueuerow);
5747
+ agentsroot.append(queuebox);
5748
+ const mailboxbox = document.createElement("details");
5749
+ mailboxbox.className = "sessiongroup";
5750
+ const mailboxsummary = document.createElement("summary");
5751
+ mailboxsummary.textContent = `Mailboxes (${swarm.mailboxes.length})`;
5752
+ mailboxbox.append(mailboxsummary);
5753
+ for (const mailbox of swarm.mailboxes) {
5754
+ if (mailbox.inbox.length === 0 && mailbox.outbox.length === 0) continue;
5755
+ const row = document.createElement("div");
5756
+ row.className = "sessionrow";
5757
+ const info = document.createElement("p");
5758
+ info.textContent = `Agent ${mailbox.agentid}: ${mailbox.inbox.length} in, ${mailbox.outbox.length} out, ${mailbox.unread} unread.`;
5759
+ row.append(info);
5760
+ const feed = document.createElement("ul");
5761
+ feed.className = "audit";
5762
+ for (const message of [...mailbox.inbox, ...mailbox.outbox].slice(0, 6)) {
5763
+ const entry = document.createElement("li");
5764
+ entry.textContent = `${message.senderid} \u2192 ${message.recipient} (${message.routing}): ${message.payload}`;
5765
+ feed.append(entry);
5766
+ }
5767
+ row.append(feed, button("Receive", async () => {
5768
+ await request({ kind: "swarmmailbox", agentid: mailbox.agentid, receive: true });
5769
+ status(`The agent ${mailbox.agentid} drained its inbox.`);
5770
+ await refresh();
5771
+ }));
5772
+ mailboxbox.append(row);
5773
+ }
5774
+ const composerow = document.createElement("div");
5775
+ composerow.className = "actions";
5776
+ const recipientselect = document.createElement("select");
5777
+ const broadcastoption = document.createElement("option");
5778
+ broadcastoption.value = "*";
5779
+ broadcastoption.textContent = "broadcast (every agent)";
5780
+ recipientselect.append(broadcastoption);
5781
+ for (const agent of swarm.agents) {
5782
+ const option = document.createElement("option");
5783
+ option.value = agent.id;
5784
+ option.textContent = `${agent.name} (${agent.id})`;
5785
+ recipientselect.append(option);
5786
+ }
5787
+ const routingselect = document.createElement("select");
5788
+ for (const routing of ["direct", "broadcast", "role"]) {
5789
+ const option = document.createElement("option");
5790
+ option.value = routing;
5791
+ option.textContent = routing;
5792
+ routingselect.append(option);
5793
+ }
5794
+ const messageinput = document.createElement("input");
5795
+ messageinput.placeholder = "message to the agents";
5796
+ composerow.append(recipientselect, " ", routingselect, " ", messageinput, " ", button("Send user message", async () => {
5797
+ await request({ kind: "swarmmailbox", send: { senderid: "user", recipient: recipientselect.value, routing: routingselect.value, payload: messageinput.value } });
5798
+ status("The user message was delivered to the swarm.");
5799
+ await refresh();
5800
+ }));
5801
+ mailboxbox.append(composerow);
5802
+ agentsroot.append(mailboxbox);
5803
+ const boardbox = document.createElement("details");
5804
+ boardbox.className = "sessiongroup";
5805
+ const boardsummary = document.createElement("summary");
5806
+ boardsummary.textContent = "Blackboard";
5807
+ boardbox.append(boardsummary);
5808
+ for (const section of swarm.blackboard.sections) {
5809
+ const row = document.createElement("p");
5810
+ row.textContent = `Section ${section.section}: ${section.entries} live entr${section.entries === 1 ? "y" : "ies"}${section.authors.length > 0 ? ` by ${section.authors.join(", ")}` : ""}${section.freshestat !== void 0 ? ` \xB7 freshest ${new Date(section.freshestat).toLocaleTimeString()}` : ""}.`;
5811
+ boardbox.append(row);
5812
+ }
5813
+ const entries = document.createElement("ol");
5814
+ entries.className = "audit";
5815
+ for (const entry of swarm.blackboard.entries.slice(0, 12)) {
5816
+ const item = document.createElement("li");
5817
+ item.textContent = `[${entry.section}] ${entry.key} = ${entry.value} \u2014 ${entry.author}, ${entry.consentclass}, posted ${new Date(entry.postedat).toLocaleTimeString()}.`;
5818
+ const actions = document.createElement("div");
5819
+ actions.className = "actions";
5820
+ actions.append(button("Retire", async () => {
5821
+ await request({ kind: "swarmblackboard", retire: entry.id });
5822
+ status(`Retired the entry ${entry.key}.`);
5823
+ await refresh();
5824
+ }));
5825
+ item.append(actions);
5826
+ entries.append(item);
5827
+ }
5828
+ boardbox.append(entries);
5829
+ const postrow = document.createElement("div");
5830
+ postrow.className = "actions";
5831
+ const keyinput = document.createElement("input");
5832
+ keyinput.placeholder = "key";
5833
+ const valueinput = document.createElement("input");
5834
+ valueinput.placeholder = "value";
5835
+ const sectionselect = document.createElement("select");
5836
+ for (const section of ["goals", "facts", "findings", "scratch"]) {
5837
+ const option = document.createElement("option");
5838
+ option.value = section;
5839
+ option.textContent = section;
5840
+ sectionselect.append(option);
5841
+ }
5842
+ const authorselect = document.createElement("select");
5843
+ const useroption = document.createElement("option");
5844
+ useroption.value = "user";
5845
+ useroption.textContent = "user";
5846
+ authorselect.append(useroption);
5847
+ for (const agent of swarm.agents) {
5848
+ const option = document.createElement("option");
5849
+ option.value = agent.id;
5850
+ option.textContent = agent.name;
5851
+ authorselect.append(option);
5852
+ }
5853
+ postrow.append(keyinput, " ", valueinput, " ", sectionselect, " ", authorselect, " ", button("Post entry", async () => {
5854
+ await request({ kind: "swarmblackboard", post: { key: keyinput.value, value: valueinput.value, section: sectionselect.value, author: authorselect.value } });
5855
+ status("The entry landed on the shared board; every agent reads it.");
5856
+ await refresh();
5857
+ }), " ", button("Retirement sweep", async () => {
5858
+ await request({ kind: "swarmblackboard", sweep: true });
5859
+ status("The retirement pass expired the stale entries.");
5860
+ await refresh();
5861
+ }));
5862
+ boardbox.append(postrow);
5863
+ agentsroot.append(boardbox);
5864
+ if (swarm.events.length > 0) {
5865
+ const eventbox = document.createElement("details");
5866
+ eventbox.className = "sessiongroup";
5867
+ const eventsummary = document.createElement("summary");
5868
+ eventsummary.textContent = `Lifecycle events (${swarm.events.length})`;
5869
+ eventbox.append(eventsummary);
5870
+ const feed = document.createElement("ul");
5871
+ feed.className = "audit";
5872
+ for (const event of swarm.events.slice(0, 10)) {
5873
+ const entry = document.createElement("li");
5874
+ entry.textContent = `${event.kind}: ${event.summary}`;
5875
+ feed.append(entry);
5876
+ }
5877
+ eventbox.append(feed);
5878
+ agentsroot.append(eventbox);
5879
+ }
5880
+ }
5168
5881
  //# sourceMappingURL=sidepanel.js.map