@wenathlan/extension 1.1.62 → 1.1.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/environments.d.ts +10 -0
- package/dist/environments.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +956 -1
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +126 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/planreview.d.ts +87 -0
- package/dist/planreview.d.ts.map +1 -0
- package/dist/policy.d.ts +101 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +135 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/sessioninterface.d.ts +213 -0
- package/dist/sessioninterface.d.ts.map +1 -0
- package/dist/surfaces.d.ts +59 -0
- package/dist/surfaces.d.ts.map +1 -0
- package/dist/types.d.ts +376 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1394 -2
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/dashboardpage.html +13 -0
- package/extension/dist/dashboardpage.js +129 -0
- package/extension/dist/dashboardpage.js.map +7 -0
- package/extension/dist/manifest.json +5 -2
- package/extension/dist/offscreen.js +5 -0
- package/extension/dist/offscreen.js.map +2 -2
- package/extension/dist/optionspage.html +14 -0
- package/extension/dist/optionspage.js +118 -0
- package/extension/dist/optionspage.js.map +7 -0
- package/extension/dist/pagebridge.js.map +1 -1
- package/extension/dist/popup.html +4 -1
- package/extension/dist/popup.js +193 -0
- package/extension/dist/popup.js.map +3 -3
- package/extension/dist/sidepanel.html +7 -2
- package/extension/dist/sidepanel.js +693 -219
- package/extension/dist/sidepanel.js.map +3 -3
- package/extension/dist/transparencypage.html +1 -0
- package/extension/dist/transparencypage.js +42 -0
- package/extension/dist/transparencypage.js.map +2 -2
- package/extension/manifest.json +5 -2
- package/package.json +1 -1
|
@@ -781,10 +781,10 @@ function renderreader(capture) {
|
|
|
781
781
|
title.textContent = `${capture.article.title || "Untitled"}${capture.article.byline ? ` \xB7 ${capture.article.byline}` : ""} \xB7 ${capture.article.words} words \xB7 ${capture.article.blocks.length} blocks`;
|
|
782
782
|
readerroot.append(title);
|
|
783
783
|
for (const block of capture.article.blocks.slice(0, 40)) {
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
readerroot.append(
|
|
784
|
+
const line2 = document.createElement("p");
|
|
785
|
+
line2.className = /^h\d$/.test(block.kind) ? "readerblock heading" : "readerblock";
|
|
786
|
+
line2.textContent = `${block.kind}: ${block.text.slice(0, 200)}`;
|
|
787
|
+
readerroot.append(line2);
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
function renderdetections(plan, outcomes) {
|
|
@@ -978,9 +978,9 @@ function rendernavigation(context) {
|
|
|
978
978
|
title.textContent = `${list.links.length} curated url${list.links.length === 1 ? "" : "s"}${list.reviewedat ? " \xB7 opened after review" : " \xB7 waiting for review"}`;
|
|
979
979
|
card.append(title);
|
|
980
980
|
for (const link of list.links.slice(0, 8)) {
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
card.append(
|
|
981
|
+
const line2 = document.createElement("p");
|
|
982
|
+
line2.textContent = `${link.verdict === "safe" ? "\u2713" : "\u2717"} ${link.url}${link.reasons.length > 0 ? ` \xB7 ${link.reasons.join("; ")}` : ""}`;
|
|
983
|
+
card.append(line2);
|
|
984
984
|
}
|
|
985
985
|
navigationroot.append(card);
|
|
986
986
|
}
|
|
@@ -1471,13 +1471,13 @@ function renderdatasets(context) {
|
|
|
1471
1471
|
const sorted = sortrows(datasetvalue.rows.slice(0, 5), column.key, cell.dataset.sorted === "asc" ? "desc" : "asc");
|
|
1472
1472
|
cell.dataset.sorted = cell.dataset.sorted === "asc" ? "desc" : "asc";
|
|
1473
1473
|
body2.replaceChildren(...sorted.map((row) => {
|
|
1474
|
-
const
|
|
1474
|
+
const line2 = document.createElement("tr");
|
|
1475
1475
|
for (const columnspec of datasetvalue.columns.slice(0, 6)) {
|
|
1476
1476
|
const value = document.createElement("td");
|
|
1477
1477
|
value.textContent = row[columnspec.key] ?? "";
|
|
1478
|
-
|
|
1478
|
+
line2.append(value);
|
|
1479
1479
|
}
|
|
1480
|
-
return
|
|
1480
|
+
return line2;
|
|
1481
1481
|
}));
|
|
1482
1482
|
});
|
|
1483
1483
|
headerrow.append(cell);
|
|
@@ -1485,13 +1485,13 @@ function renderdatasets(context) {
|
|
|
1485
1485
|
grid.append(headerrow);
|
|
1486
1486
|
const body = document.createElement("tbody");
|
|
1487
1487
|
for (const row of datasetvalue.rows.slice(0, 5)) {
|
|
1488
|
-
const
|
|
1488
|
+
const line2 = document.createElement("tr");
|
|
1489
1489
|
for (const column of datasetvalue.columns.slice(0, 6)) {
|
|
1490
1490
|
const cell = document.createElement("td");
|
|
1491
1491
|
cell.textContent = row[column.key] ?? "";
|
|
1492
|
-
|
|
1492
|
+
line2.append(cell);
|
|
1493
1493
|
}
|
|
1494
|
-
body.append(
|
|
1494
|
+
body.append(line2);
|
|
1495
1495
|
}
|
|
1496
1496
|
grid.append(body);
|
|
1497
1497
|
card.append(grid);
|
|
@@ -2618,10 +2618,10 @@ function renderconsolediff() {
|
|
|
2618
2618
|
headline.textContent = `Run ${lastdiff.base} became run ${lastdiff.target}: ${lastdiff.added} added, ${lastdiff.removed} removed and ${lastdiff.repeated} repeated.`;
|
|
2619
2619
|
const list = document.createElement("ul");
|
|
2620
2620
|
list.className = "audit";
|
|
2621
|
-
for (const
|
|
2621
|
+
for (const line2 of lastdiff.lines.slice(0, 80)) {
|
|
2622
2622
|
const item = document.createElement("li");
|
|
2623
|
-
item.className = `diffrow ${
|
|
2624
|
-
item.textContent = `${
|
|
2623
|
+
item.className = `diffrow ${line2.kind}`;
|
|
2624
|
+
item.textContent = `${line2.kind}${line2.count !== void 0 ? ` \xD7${line2.count}` : ""}: ${line2.text}`;
|
|
2625
2625
|
list.append(item);
|
|
2626
2626
|
}
|
|
2627
2627
|
consolediffroot.append(headline, list);
|
|
@@ -2794,9 +2794,9 @@ function renderemulation(context) {
|
|
|
2794
2794
|
const row = document.createElement("div");
|
|
2795
2795
|
row.className = "emulationrow";
|
|
2796
2796
|
row.dataset.stacked = active.length > 1 ? "true" : "false";
|
|
2797
|
-
const
|
|
2798
|
-
|
|
2799
|
-
row.append(
|
|
2797
|
+
const line2 = document.createElement("p");
|
|
2798
|
+
line2.textContent = `${layer.family} layer ${layer.name} on ${layer.originscope} applied ${new Date(layer.appliedat).toLocaleTimeString()} with the revert plan ${layer.revertplan.join(", ")}.`;
|
|
2799
|
+
row.append(line2, button("Revert now", () => request({ kind: "revertemulation" }).then(() => {
|
|
2800
2800
|
status("Reverted every active emulation layer of the run on review panel demand.");
|
|
2801
2801
|
return refresh();
|
|
2802
2802
|
})));
|
|
@@ -2826,9 +2826,9 @@ function renderemulation(context) {
|
|
|
2826
2826
|
continue;
|
|
2827
2827
|
}
|
|
2828
2828
|
for (const preset of family.presets) {
|
|
2829
|
-
const
|
|
2830
|
-
|
|
2831
|
-
emulationroot.append(
|
|
2829
|
+
const line2 = document.createElement("p");
|
|
2830
|
+
line2.textContent = preset.label;
|
|
2831
|
+
emulationroot.append(line2);
|
|
2832
2832
|
}
|
|
2833
2833
|
}
|
|
2834
2834
|
const editor = document.createElement("details");
|
|
@@ -2888,9 +2888,9 @@ function renderemulation(context) {
|
|
|
2888
2888
|
head.textContent = "blackboxed patterns of the run";
|
|
2889
2889
|
emulationroot.append(head);
|
|
2890
2890
|
for (const entry of blackbox) {
|
|
2891
|
-
const
|
|
2892
|
-
|
|
2893
|
-
emulationroot.append(
|
|
2891
|
+
const line2 = document.createElement("p");
|
|
2892
|
+
line2.textContent = `${entry.origin}: ${entry.rules.flatMap((rule) => rule.urlpatterns).join(", ")} (${entry.rules.map((rule) => rule.tracescope).join(", ")} scope)`;
|
|
2893
|
+
emulationroot.append(line2);
|
|
2894
2894
|
}
|
|
2895
2895
|
}
|
|
2896
2896
|
const restored = emulation.permissions.filter((record) => record.restoredat === void 0);
|
|
@@ -2899,9 +2899,9 @@ function renderemulation(context) {
|
|
|
2899
2899
|
head.textContent = "permission overrides pending restore";
|
|
2900
2900
|
emulationroot.append(head);
|
|
2901
2901
|
for (const record of restored) {
|
|
2902
|
-
const
|
|
2903
|
-
|
|
2904
|
-
emulationroot.append(
|
|
2902
|
+
const line2 = document.createElement("p");
|
|
2903
|
+
line2.textContent = `${record.name} of ${record.origin} answered ${record.state} for run ${record.runid}; the prior ${record.priorstate} state restores at run end.`;
|
|
2904
|
+
emulationroot.append(line2);
|
|
2905
2905
|
}
|
|
2906
2906
|
}
|
|
2907
2907
|
const retentionrow = document.createElement("p");
|
|
@@ -2945,6 +2945,7 @@ async function refresh() {
|
|
|
2945
2945
|
renderagents(context);
|
|
2946
2946
|
renderenvironments(context);
|
|
2947
2947
|
rendersecurity(context);
|
|
2948
|
+
rendersessioninterface(context);
|
|
2948
2949
|
renderconsolediff();
|
|
2949
2950
|
renderaudit(context.audit);
|
|
2950
2951
|
rendercapabilities(context.capabilities);
|
|
@@ -3253,10 +3254,10 @@ function rendersessions(context) {
|
|
|
3253
3254
|
summary.textContent = `Latest session diff (${diff.changes.length} changes)`;
|
|
3254
3255
|
diffview.append(summary);
|
|
3255
3256
|
for (const change of diff.changes) {
|
|
3256
|
-
const
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
diffview.append(
|
|
3257
|
+
const line2 = document.createElement("p");
|
|
3258
|
+
line2.textContent = `${change.class} ${change.subject}: ${change.detail}`;
|
|
3259
|
+
line2.dataset.class = change.class;
|
|
3260
|
+
diffview.append(line2);
|
|
3260
3261
|
}
|
|
3261
3262
|
sessionsroot.append(diffview);
|
|
3262
3263
|
}
|
|
@@ -3305,19 +3306,19 @@ function renderrestorereview(record) {
|
|
|
3305
3306
|
title.textContent = `Restore review of ${record.name}: ${record.tabs.length} tabs, ${record.tabs.reduce((total, tab) => total + tab.forms.length, 0)} captured form fields, ${record.captures.length} linked captures.`;
|
|
3306
3307
|
review.append(title);
|
|
3307
3308
|
for (const tab of record.tabs) {
|
|
3308
|
-
const
|
|
3309
|
-
|
|
3310
|
-
review.append(
|
|
3309
|
+
const line2 = document.createElement("p");
|
|
3310
|
+
line2.textContent = `Tab ${tab.index}: ${tab.title || tab.url} \xB7 ${tab.forms.length} form fields \xB7 scroll ${tab.scrollx},${tab.scrolly}`;
|
|
3311
|
+
review.append(line2);
|
|
3311
3312
|
}
|
|
3312
3313
|
for (const entry of record.storage) {
|
|
3313
|
-
const
|
|
3314
|
-
|
|
3315
|
-
review.append(
|
|
3314
|
+
const line2 = document.createElement("p");
|
|
3315
|
+
line2.textContent = `Local storage of ${entry.origin}: ${entry.keys.length} keys captured.`;
|
|
3316
|
+
review.append(line2);
|
|
3316
3317
|
}
|
|
3317
3318
|
for (const entry of record.cookies) {
|
|
3318
|
-
const
|
|
3319
|
-
|
|
3320
|
-
review.append(
|
|
3319
|
+
const line2 = document.createElement("p");
|
|
3320
|
+
line2.textContent = `Cookies of ${entry.origin}: ${entry.names.length} names captured, values held back.`;
|
|
3321
|
+
review.append(line2);
|
|
3321
3322
|
}
|
|
3322
3323
|
review.append(button("Approve restore", async () => {
|
|
3323
3324
|
const result = await request({ kind: "approverestore", sessionid: record.id });
|
|
@@ -3350,11 +3351,11 @@ function rendercontroldecision(entry) {
|
|
|
3350
3351
|
summary.textContent = `control flow \xB7 ${control?.kind ?? "decision"} \xB7 ${entry.summary}`;
|
|
3351
3352
|
block.append(summary);
|
|
3352
3353
|
if (control?.branch !== void 0) {
|
|
3353
|
-
const
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
block.append(
|
|
3354
|
+
const line2 = document.createElement("p");
|
|
3355
|
+
line2.textContent = `Chose the path ${control.branch.path}: ${control.branch.reason}`;
|
|
3356
|
+
line2.dataset.class = "added";
|
|
3357
|
+
line2.dataset.branch = control.branch.path;
|
|
3358
|
+
block.append(line2);
|
|
3358
3359
|
}
|
|
3359
3360
|
if (control?.loops !== void 0 && control.loops.length > 0) {
|
|
3360
3361
|
const group = document.createElement("details");
|
|
@@ -3363,28 +3364,28 @@ function rendercontroldecision(entry) {
|
|
|
3363
3364
|
groupsummary.textContent = `Loop iterations (${control.loops.length})`;
|
|
3364
3365
|
group.append(groupsummary);
|
|
3365
3366
|
for (const counter of control.loops) {
|
|
3366
|
-
const
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
group.append(
|
|
3367
|
+
const line2 = document.createElement("p");
|
|
3368
|
+
line2.textContent = `${counter.path} \xB7 ${counter.ok ? "completed" : "failed"}`;
|
|
3369
|
+
line2.dataset.class = counter.ok ? "added" : "changed";
|
|
3370
|
+
group.append(line2);
|
|
3370
3371
|
}
|
|
3371
3372
|
block.append(group);
|
|
3372
3373
|
}
|
|
3373
3374
|
if (control?.retries !== void 0 && control.retries.length > 0) {
|
|
3374
3375
|
for (const attempt of control.retries) {
|
|
3375
|
-
const
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
block.append(
|
|
3376
|
+
const line2 = document.createElement("p");
|
|
3377
|
+
line2.textContent = `Retry attempt ${attempt.attempt} after a ${attempt.delay} ms backoff countdown for the ${attempt.errorclass} error class.`;
|
|
3378
|
+
line2.dataset.class = "changed";
|
|
3379
|
+
block.append(line2);
|
|
3379
3380
|
}
|
|
3380
3381
|
}
|
|
3381
3382
|
if (control?.timeouts !== void 0 && control.timeouts.length > 0) {
|
|
3382
3383
|
for (const abort of control.timeouts) {
|
|
3383
|
-
const
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
block.append(
|
|
3384
|
+
const line2 = document.createElement("p");
|
|
3385
|
+
line2.textContent = `Timeout abort: the ${abort.scope} exceeded its reviewed budget of ${abort.budget} milliseconds.`;
|
|
3386
|
+
line2.dataset.class = "changed";
|
|
3387
|
+
line2.dataset.timeout = "true";
|
|
3388
|
+
block.append(line2);
|
|
3388
3389
|
}
|
|
3389
3390
|
}
|
|
3390
3391
|
if (control?.branches !== void 0 && control.branches.length > 0) {
|
|
@@ -3402,16 +3403,16 @@ function rendercontroldecision(entry) {
|
|
|
3402
3403
|
block.append(lanes);
|
|
3403
3404
|
}
|
|
3404
3405
|
if (control?.join !== void 0) {
|
|
3405
|
-
const
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
block.append(
|
|
3406
|
+
const line2 = document.createElement("p");
|
|
3407
|
+
line2.textContent = `Join under the ${control.join.strategy} strategy merged ${control.join.merged.join(", ") || "no variable"}${control.join.conflicts.length > 0 ? ` with the conflicts ${control.join.conflicts.join(", ")}` : " with no conflict"}.`;
|
|
3408
|
+
line2.dataset.class = control.join.conflicts.length > 0 ? "changed" : "added";
|
|
3409
|
+
block.append(line2);
|
|
3409
3410
|
}
|
|
3410
3411
|
if (control?.catch !== void 0) {
|
|
3411
|
-
const
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
block.append(
|
|
3412
|
+
const line2 = document.createElement("p");
|
|
3413
|
+
line2.textContent = `The catch handler ran after the ${control.catch.errorclass} failure${control.catch.rerun ? " and reran the fragile body" : ""}.`;
|
|
3414
|
+
line2.dataset.class = "changed";
|
|
3415
|
+
block.append(line2);
|
|
3415
3416
|
}
|
|
3416
3417
|
return block;
|
|
3417
3418
|
}
|
|
@@ -3491,9 +3492,9 @@ function renderworkflows(context) {
|
|
|
3491
3492
|
review.append(headline);
|
|
3492
3493
|
const list = document.createElement("ol");
|
|
3493
3494
|
for (const step of workflowview.review.steps) {
|
|
3494
|
-
const
|
|
3495
|
-
|
|
3496
|
-
list.append(
|
|
3495
|
+
const line2 = document.createElement("li");
|
|
3496
|
+
line2.textContent = `${step.label} (${step.kind}${step.block !== void 0 ? ` \xB7 block ${step.block}` : ""}${step.target !== void 0 ? ` \xB7 ${step.target}` : ""}${step.expression !== void 0 ? ` \xB7 expression ${step.expression.operator} into ${step.expression.result}` : ""}${step.extract !== void 0 && step.extract.groups.length > 0 ? ` \xB7 extracts ${step.extract.groups.join(", ")}` : ""}${Array.isArray(step.bindings) && step.bindings.length > 0 ? ` \xB7 ${step.bindings.length} binding${step.bindings.length === 1 ? "" : "s"}` : ""}${controlreviewtext(step.control)}`;
|
|
3497
|
+
list.append(line2);
|
|
3497
3498
|
if (step.control !== void 0 && (step.control.kind === "loop" || step.control.kind === "repeatuntil")) {
|
|
3498
3499
|
const boundrow = document.createElement("div");
|
|
3499
3500
|
boundrow.className = "actions";
|
|
@@ -3554,12 +3555,12 @@ function renderworkflows(context) {
|
|
|
3554
3555
|
if (record) {
|
|
3555
3556
|
const steps = document.createElement("ol");
|
|
3556
3557
|
for (const [index, step] of record.steps.entries()) {
|
|
3557
|
-
const
|
|
3558
|
+
const line2 = document.createElement("li");
|
|
3558
3559
|
const entry = state?.log.find((candidate) => candidate.stepid === step.id);
|
|
3559
3560
|
const done = index < latest.cursor;
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
if (step.block !== void 0 && index === latest.cursor)
|
|
3561
|
+
line2.textContent = `${step.label} (${step.kind}${step.block !== void 0 ? ` \xB7 block ${step.block}` : ""})${done ? ` \xB7 done${entry?.checkpoint === true ? " \xB7 checkpointed" : ""}` : ""}${entry !== void 0 ? ` \xB7 ${entry.state}: ${entry.summary}` : ""}`;
|
|
3562
|
+
line2.dataset.class = entry?.state === "failed" || entry?.state === "refused" ? "changed" : done ? "added" : "unavailable";
|
|
3563
|
+
if (step.block !== void 0 && index === latest.cursor) line2.dataset.blockactive = "true";
|
|
3563
3564
|
const singlestep = document.createElement("div");
|
|
3564
3565
|
singlestep.className = "actions";
|
|
3565
3566
|
singlestep.append(button("Run single step", async () => {
|
|
@@ -3567,17 +3568,17 @@ function renderworkflows(context) {
|
|
|
3567
3568
|
status(outcome.steps[0] ? `Single step ${outcome.steps[0].state}: ${outcome.steps[0].summary}` : "The single step returned no outcome.");
|
|
3568
3569
|
await refresh();
|
|
3569
3570
|
}));
|
|
3570
|
-
|
|
3571
|
-
steps.append(
|
|
3571
|
+
line2.append(singlestep);
|
|
3572
|
+
steps.append(line2);
|
|
3572
3573
|
}
|
|
3573
3574
|
timeline.append(steps);
|
|
3574
3575
|
}
|
|
3575
3576
|
const runlog = document.createElement("div");
|
|
3576
3577
|
for (const entry of state?.log ?? []) {
|
|
3577
|
-
const
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
runlog.append(
|
|
3578
|
+
const line2 = document.createElement("p");
|
|
3579
|
+
line2.textContent = `${entry.state} \xB7 ${entry.label} \xB7 ${entry.duration} ms${entry.produced !== void 0 && entry.produced.length > 0 ? ` \xB7 produced ${entry.produced.join(", ")}` : ""}${entry.consumed !== void 0 && entry.consumed.length > 0 ? ` \xB7 consumed ${entry.consumed.join(", ")}` : ""} \xB7 ${entry.summary}`;
|
|
3580
|
+
line2.dataset.class = entry.state === "failed" || entry.state === "refused" ? "changed" : "added";
|
|
3581
|
+
runlog.append(line2);
|
|
3581
3582
|
if (entry.details !== void 0 && entry.details.control !== void 0) runlog.append(rendercontroldecision(entry));
|
|
3582
3583
|
}
|
|
3583
3584
|
timeline.append(runlog);
|
|
@@ -3590,9 +3591,9 @@ function renderworkflows(context) {
|
|
|
3590
3591
|
scopesummary.textContent = `Variables per scope (${scopes.reduce((total, scope) => total + scope.variables.length, 0)} values)`;
|
|
3591
3592
|
scopeview.append(scopesummary);
|
|
3592
3593
|
for (const scope of scopes) {
|
|
3593
|
-
const
|
|
3594
|
-
|
|
3595
|
-
scopeview.append(
|
|
3594
|
+
const line2 = document.createElement("p");
|
|
3595
|
+
line2.textContent = `Scope ${scope.name}${scope.parent !== void 0 ? ` (child of ${scope.parent})` : ""}: ${scope.variables.length === 0 ? "no variable" : scope.variables.map((variable) => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(", ")}]` : String(variable.value)} (${variable.kind})`).join(" \xB7 ")}`;
|
|
3596
|
+
scopeview.append(line2);
|
|
3596
3597
|
}
|
|
3597
3598
|
workflowsroot.append(scopeview);
|
|
3598
3599
|
}
|
|
@@ -3604,9 +3605,9 @@ function renderworkflows(context) {
|
|
|
3604
3605
|
provsummary.textContent = `Provenance (${provenance.length} entries)`;
|
|
3605
3606
|
provenanceview.append(provsummary);
|
|
3606
3607
|
for (const entry of provenance.slice(-12)) {
|
|
3607
|
-
const
|
|
3608
|
-
|
|
3609
|
-
provenanceview.append(
|
|
3608
|
+
const line2 = document.createElement("p");
|
|
3609
|
+
line2.textContent = `${entry.kind} \xB7 ${entry.name} = ${Array.isArray(entry.value) ? `[${entry.value.join(", ")}]` : String(entry.value)}`;
|
|
3610
|
+
provenanceview.append(line2);
|
|
3610
3611
|
}
|
|
3611
3612
|
workflowsroot.append(provenanceview);
|
|
3612
3613
|
}
|
|
@@ -3911,9 +3912,9 @@ function renderworkfloweditor(context) {
|
|
|
3911
3912
|
if (results.length > 0) {
|
|
3912
3913
|
const list = document.createElement("ul");
|
|
3913
3914
|
for (const result of results) {
|
|
3914
|
-
const
|
|
3915
|
-
|
|
3916
|
-
list.append(
|
|
3915
|
+
const line2 = document.createElement("li");
|
|
3916
|
+
line2.textContent = `${result.label} (${result.kind}) matched ${result.matched.join(", ")}`;
|
|
3917
|
+
list.append(line2);
|
|
3917
3918
|
}
|
|
3918
3919
|
canvascard.append(list);
|
|
3919
3920
|
}
|
|
@@ -3967,9 +3968,9 @@ function renderworkfloweditor(context) {
|
|
|
3967
3968
|
bindingssummary.textContent = `Bindings and nested params (${model.edges.filter((edge) => edge.to === inspectedstep.id || edge.from === inspectedstep.id).length} edges)`;
|
|
3968
3969
|
bindings.append(bindingssummary);
|
|
3969
3970
|
for (const edge of model.edges.filter((candidate) => candidate.to === inspectedstep?.id)) {
|
|
3970
|
-
const
|
|
3971
|
-
|
|
3972
|
-
|
|
3971
|
+
const line2 = document.createElement("p");
|
|
3972
|
+
line2.textContent = `${edge.variable} (${edge.kind}) from ${edge.from}${edge.path !== void 0 ? ` path ${edge.path}` : ""}`;
|
|
3973
|
+
line2.append(" ", button("Remove binding", async () => {
|
|
3973
3974
|
if (editorview.model === void 0) return;
|
|
3974
3975
|
try {
|
|
3975
3976
|
editorview.model = removeedge(editorview.model, edge.from, edge.to, edge.variable);
|
|
@@ -3979,7 +3980,7 @@ function renderworkfloweditor(context) {
|
|
|
3979
3980
|
}
|
|
3980
3981
|
await refresh();
|
|
3981
3982
|
}));
|
|
3982
|
-
bindings.append(
|
|
3983
|
+
bindings.append(line2);
|
|
3983
3984
|
}
|
|
3984
3985
|
const source = document.createElement("select");
|
|
3985
3986
|
for (const node of model.nodes) {
|
|
@@ -4147,9 +4148,9 @@ function renderworkfloweditor(context) {
|
|
|
4147
4148
|
palettebody.append(head);
|
|
4148
4149
|
const list = document.createElement("ul");
|
|
4149
4150
|
for (const entry of kinds) {
|
|
4150
|
-
const
|
|
4151
|
-
|
|
4152
|
-
list.append(
|
|
4151
|
+
const line2 = document.createElement("li");
|
|
4152
|
+
line2.textContent = `${entry.kind}${entry.optionschema.length > 0 ? ` \xB7 options: ${entry.optionschema.map((option) => `${option.name} ${option.kind}${option.required === true ? " (required)" : ""}`).join(", ")}` : ""}`;
|
|
4153
|
+
list.append(line2);
|
|
4153
4154
|
}
|
|
4154
4155
|
palettebody.append(list);
|
|
4155
4156
|
}
|
|
@@ -4165,10 +4166,10 @@ function renderworkfloweditor(context) {
|
|
|
4165
4166
|
versionsummary.textContent = `Version timeline (${editor.versions.filter((entry) => entry.workflowid === editorview.workflowid).length} versions of this workflow)`;
|
|
4166
4167
|
versioncard.append(versionsummary);
|
|
4167
4168
|
for (const version of editor.versions.filter((entry) => entry.workflowid === editorview.workflowid)) {
|
|
4168
|
-
const
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4169
|
+
const line2 = document.createElement("p");
|
|
4170
|
+
line2.className = "diffrow";
|
|
4171
|
+
line2.textContent = `v${version.version} \xB7 ${new Date(version.createdat).toISOString()} \xB7 ${version.steps} steps \xB7 ${version.risk ?? "ungraded"}${version.rollback === true ? " \xB7 rollback" : ""} \xB7 ${version.note}`;
|
|
4172
|
+
line2.append(" ", button("Roll back here", async () => {
|
|
4172
4173
|
try {
|
|
4173
4174
|
const rolled = await request({ kind: "rollbackversion", workflowid: editorview.workflowid, version: version.version });
|
|
4174
4175
|
status(`Rolled back to v${version.version}; stored as v${rolled.version} and ${rolled.reviewstate} until the rollback review approves it.`);
|
|
@@ -4177,7 +4178,7 @@ function renderworkfloweditor(context) {
|
|
|
4177
4178
|
}
|
|
4178
4179
|
await refresh();
|
|
4179
4180
|
}));
|
|
4180
|
-
versioncard.append(
|
|
4181
|
+
versioncard.append(line2);
|
|
4181
4182
|
}
|
|
4182
4183
|
const diffrow = document.createElement("div");
|
|
4183
4184
|
diffrow.className = "actions";
|
|
@@ -4208,25 +4209,25 @@ function renderworkfloweditor(context) {
|
|
|
4208
4209
|
headline.textContent = `Version diff v${diff.from} \u2192 v${diff.to}`;
|
|
4209
4210
|
card.append(headline);
|
|
4210
4211
|
for (const added of diff.added) {
|
|
4211
|
-
const
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
card.append(
|
|
4212
|
+
const line2 = document.createElement("p");
|
|
4213
|
+
line2.className = "diffrow";
|
|
4214
|
+
line2.dataset.class = "added";
|
|
4215
|
+
line2.textContent = `+ ${added.stepid} (${added.kind}) ${added.label}`;
|
|
4216
|
+
card.append(line2);
|
|
4216
4217
|
}
|
|
4217
4218
|
for (const removed of diff.removed) {
|
|
4218
|
-
const
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
card.append(
|
|
4219
|
+
const line2 = document.createElement("p");
|
|
4220
|
+
line2.className = "diffrow";
|
|
4221
|
+
line2.dataset.class = "removed";
|
|
4222
|
+
line2.textContent = `- ${removed.stepid} (${removed.kind}) ${removed.label}`;
|
|
4223
|
+
card.append(line2);
|
|
4223
4224
|
}
|
|
4224
4225
|
for (const changed of diff.changed) {
|
|
4225
|
-
const
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
card.append(
|
|
4226
|
+
const line2 = document.createElement("p");
|
|
4227
|
+
line2.className = "diffrow";
|
|
4228
|
+
line2.dataset.class = "changed";
|
|
4229
|
+
line2.textContent = `~ ${changed.stepid} (${changed.kind}) ${changed.label}: ${changed.changes.join(", ")}`;
|
|
4230
|
+
card.append(line2);
|
|
4230
4231
|
}
|
|
4231
4232
|
card.append(button("Close diff", async () => {
|
|
4232
4233
|
editorview.diff = void 0;
|
|
@@ -4258,10 +4259,10 @@ function renderworkfloweditor(context) {
|
|
|
4258
4259
|
logcard.append(logsummary);
|
|
4259
4260
|
const breakpoints = /* @__PURE__ */ new Set([...editor?.breakpoints ?? [], ...context.workflow.workflows.find((record) => record.id === editorview.workflowid)?.steps.flatMap((step) => step.breakpoint === true ? [step.id] : []) ?? []]);
|
|
4260
4261
|
for (const entry of context.workflow.log) {
|
|
4261
|
-
const
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
logcard.append(
|
|
4262
|
+
const line2 = document.createElement("p");
|
|
4263
|
+
line2.textContent = `${entry.state} \xB7 ${entry.label}${breakpoints.has(entry.stepid) ? " \xB7 breakpoint" : ""} \xB7 ${entry.duration} ms \xB7 ${entry.summary}`;
|
|
4264
|
+
line2.dataset.class = entry.state === "failed" || entry.state === "refused" ? "changed" : "added";
|
|
4265
|
+
logcard.append(line2);
|
|
4265
4266
|
}
|
|
4266
4267
|
if (context.workflow.log.length === 0) {
|
|
4267
4268
|
const empty = document.createElement("p");
|
|
@@ -4269,9 +4270,9 @@ function renderworkfloweditor(context) {
|
|
|
4269
4270
|
logcard.append(empty);
|
|
4270
4271
|
}
|
|
4271
4272
|
for (const scope of context.workflow.scopes) {
|
|
4272
|
-
const
|
|
4273
|
-
|
|
4274
|
-
logcard.append(
|
|
4273
|
+
const line2 = document.createElement("p");
|
|
4274
|
+
line2.textContent = `Scope ${scope.name}: ${scope.variables.length === 0 ? "no variable" : scope.variables.map((variable) => `${variable.name} = ${Array.isArray(variable.value) ? `[${variable.value.join(", ")}]` : String(variable.value)} (${variable.kind})`).join(" \xB7 ")}`;
|
|
4275
|
+
logcard.append(line2);
|
|
4275
4276
|
}
|
|
4276
4277
|
workfloweditorroot.append(logcard);
|
|
4277
4278
|
}
|
|
@@ -4318,13 +4319,13 @@ function renderworkfloweditor(context) {
|
|
|
4318
4319
|
historycard.append(historyfilters);
|
|
4319
4320
|
const historyentries = editorview.history ?? editor?.history ?? [];
|
|
4320
4321
|
for (const entry of historyentries.slice(0, 40)) {
|
|
4321
|
-
const
|
|
4322
|
-
|
|
4323
|
-
|
|
4322
|
+
const line2 = document.createElement("div");
|
|
4323
|
+
line2.className = "historyrow";
|
|
4324
|
+
line2.dataset.outcome = entry.outcome;
|
|
4324
4325
|
const detail = document.createElement("p");
|
|
4325
4326
|
detail.textContent = `${entry.outcome} \xB7 ${entry.steps}/${entry.total} steps \xB7 ${entry.duration} ms \xB7 ${entry.cause}${entry.dryrun === true ? " \xB7 dry run" : ""} \xB7 ${new Date(entry.startedat).toISOString()}`;
|
|
4326
|
-
|
|
4327
|
-
historycard.append(
|
|
4327
|
+
line2.append(detail);
|
|
4328
|
+
historycard.append(line2);
|
|
4328
4329
|
}
|
|
4329
4330
|
workfloweditorroot.append(historycard);
|
|
4330
4331
|
const filecard = document.createElement("details");
|
|
@@ -4371,9 +4372,9 @@ function renderworkfloweditor(context) {
|
|
|
4371
4372
|
review.append(headline);
|
|
4372
4373
|
const list = document.createElement("ol");
|
|
4373
4374
|
for (const step of editorview.importreview.steps) {
|
|
4374
|
-
const
|
|
4375
|
-
|
|
4376
|
-
list.append(
|
|
4375
|
+
const line2 = document.createElement("li");
|
|
4376
|
+
line2.textContent = `${step.label} (${step.kind}${step.block !== void 0 ? ` \xB7 block ${step.block}` : ""}${step.target !== void 0 ? ` \xB7 ${step.target}` : ""})`;
|
|
4377
|
+
list.append(line2);
|
|
4377
4378
|
}
|
|
4378
4379
|
review.append(list);
|
|
4379
4380
|
review.append(button("Approve import", async () => {
|
|
@@ -4398,9 +4399,9 @@ function renderworkfloweditor(context) {
|
|
|
4398
4399
|
filecard.append(review);
|
|
4399
4400
|
}
|
|
4400
4401
|
for (const pending of editor?.imports ?? []) {
|
|
4401
|
-
const
|
|
4402
|
-
|
|
4403
|
-
|
|
4402
|
+
const line2 = document.createElement("p");
|
|
4403
|
+
line2.textContent = `Pending import ${pending.name} v${pending.version} (${pending.steps} steps, ${pending.risk})${pending.filename !== void 0 ? ` from ${pending.filename}` : ""}`;
|
|
4404
|
+
line2.append(" ", button("Review steps", async () => {
|
|
4404
4405
|
try {
|
|
4405
4406
|
const steps = await request({ kind: "workflowreview", workflowid: pending.workflowid });
|
|
4406
4407
|
editorview.importreview = { importid: pending.id, workflowid: pending.workflowid, name: pending.name, version: pending.version, risk: pending.risk, steps: steps.steps };
|
|
@@ -4410,7 +4411,7 @@ function renderworkfloweditor(context) {
|
|
|
4410
4411
|
}
|
|
4411
4412
|
await refresh();
|
|
4412
4413
|
}));
|
|
4413
|
-
filecard.append(
|
|
4414
|
+
filecard.append(line2);
|
|
4414
4415
|
}
|
|
4415
4416
|
const exportrow = document.createElement("div");
|
|
4416
4417
|
exportrow.className = "actions";
|
|
@@ -4501,9 +4502,9 @@ function renderworkfloweditor(context) {
|
|
|
4501
4502
|
}));
|
|
4502
4503
|
watchdogcard.append(watchdogactions);
|
|
4503
4504
|
for (const event of (editor?.watchdog.events ?? []).slice(0, 15)) {
|
|
4504
|
-
const
|
|
4505
|
-
|
|
4506
|
-
watchdogcard.append(
|
|
4505
|
+
const line2 = document.createElement("p");
|
|
4506
|
+
line2.textContent = `${event.verdict} \xB7 ${event.action} \xB7 ${new Date(event.at).toISOString()} \xB7 ${event.outcome}`;
|
|
4507
|
+
watchdogcard.append(line2);
|
|
4507
4508
|
}
|
|
4508
4509
|
workfloweditorroot.append(watchdogcard);
|
|
4509
4510
|
const overridecard = document.createElement("details");
|
|
@@ -4548,9 +4549,9 @@ function renderworkfloweditor(context) {
|
|
|
4548
4549
|
await refresh();
|
|
4549
4550
|
}));
|
|
4550
4551
|
for (const override of editor?.overrides ?? []) {
|
|
4551
|
-
const
|
|
4552
|
-
|
|
4553
|
-
|
|
4552
|
+
const line2 = document.createElement("p");
|
|
4553
|
+
line2.textContent = `${override.pattern} of ${override.workflowid}: ${Object.entries(override.deltas).map(([knob, delta]) => `${knob} ${delta}`).join(", ") || "no delta"}`;
|
|
4554
|
+
line2.append(" ", button("Remove override", async () => {
|
|
4554
4555
|
try {
|
|
4555
4556
|
await request({ kind: "removesiteoverride", id: override.id });
|
|
4556
4557
|
status(`Removed the override ${override.pattern}.`);
|
|
@@ -4559,7 +4560,7 @@ function renderworkfloweditor(context) {
|
|
|
4559
4560
|
}
|
|
4560
4561
|
await refresh();
|
|
4561
4562
|
}));
|
|
4562
|
-
overridecard.append(
|
|
4563
|
+
overridecard.append(line2);
|
|
4563
4564
|
}
|
|
4564
4565
|
workfloweditorroot.append(overridecard);
|
|
4565
4566
|
}
|
|
@@ -4661,9 +4662,9 @@ function rendertriggers(context) {
|
|
|
4661
4662
|
summary.textContent = `Fire history (${triggerview.history.length} records)`;
|
|
4662
4663
|
history.append(summary);
|
|
4663
4664
|
for (const fire of triggerview.history.slice(0, 25)) {
|
|
4664
|
-
const
|
|
4665
|
-
|
|
4666
|
-
history.append(
|
|
4665
|
+
const line2 = document.createElement("p");
|
|
4666
|
+
line2.textContent = `${new Date(fire.at).toISOString()} \xB7 ${fire.cause}${fire.url !== void 0 ? ` \xB7 ${fire.url}` : ""}${fire.title !== void 0 ? ` \xB7 ${fire.title}` : ""}`;
|
|
4667
|
+
history.append(line2);
|
|
4667
4668
|
}
|
|
4668
4669
|
triggersroot.append(history);
|
|
4669
4670
|
}
|
|
@@ -4674,9 +4675,9 @@ function rendertriggers(context) {
|
|
|
4674
4675
|
headline.textContent = `Manual run step preview: ${triggerview.manual.preview.length} expanded step${triggerview.manual.preview.length === 1 ? "" : "s"}; approve or cancel before anything runs.`;
|
|
4675
4676
|
preview.append(headline);
|
|
4676
4677
|
for (const step of triggerview.manual.preview) {
|
|
4677
|
-
const
|
|
4678
|
-
|
|
4679
|
-
preview.append(
|
|
4678
|
+
const line2 = document.createElement("p");
|
|
4679
|
+
line2.textContent = `${step.stepid} \xB7 ${step.kind} \xB7 ${step.label}${step.block !== void 0 ? ` \xB7 block ${step.block}` : ""}${step.control !== void 0 ? ` \xB7 ${Object.entries(step.control).map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(", ") : String(value)}`).join(" \xB7 ")}` : ""}`;
|
|
4680
|
+
preview.append(line2);
|
|
4680
4681
|
}
|
|
4681
4682
|
const actions = document.createElement("div");
|
|
4682
4683
|
actions.className = "actions";
|
|
@@ -4869,15 +4870,15 @@ function renderagentprotocol(context) {
|
|
|
4869
4870
|
remoteline.textContent = `Endpoint ${mcp.remote.endpoint} \xB7 tls ${mcp.remote.tls.mode}${mcp.remote.tls.certificaterequired ? " (certificate required)" : ""}${mcp.remote.tls.verified ? " and verified" : " and unverified"} \xB7 ${mcp.remote.paired} of ${mcp.remote.clients} client${mcp.remote.clients === 1 ? "" : "s"} paired \xB7 ${mcp.remote.tokenslive} live token${mcp.remote.tokenslive === 1 ? "" : "s"}.`;
|
|
4870
4871
|
remotebox.append(remoteline);
|
|
4871
4872
|
for (const channel of mcp.channels.slice(0, 10)) {
|
|
4872
|
-
const
|
|
4873
|
+
const line2 = document.createElement("p");
|
|
4873
4874
|
const beatage = Math.max(0, Math.round((Date.now() - channel.lastbeatat) / 1e3));
|
|
4874
|
-
|
|
4875
|
-
remotebox.append(
|
|
4875
|
+
line2.textContent = `Stream channel ${channel.id.slice(0, 12)} of ${channel.clientid} \xB7 ${channel.closedat === void 0 ? `heartbeat ${beatage}s ago` : `closed at ${new Date(channel.closedat).toISOString()}`}.`;
|
|
4876
|
+
remotebox.append(line2);
|
|
4876
4877
|
}
|
|
4877
4878
|
for (const shake of mcp.handshakes.slice(0, 5)) {
|
|
4878
|
-
const
|
|
4879
|
-
|
|
4880
|
-
remotebox.append(
|
|
4879
|
+
const line2 = document.createElement("p");
|
|
4880
|
+
line2.textContent = `Auth handshake ${shake.method} of ${shake.clientid} \xB7 ${shake.outcome}${shake.outcome === "refused" ? " (consentrefused error, no pairing state leaked)" : ""} \xB7 ${new Date(shake.at).toISOString()}.`;
|
|
4881
|
+
remotebox.append(line2);
|
|
4881
4882
|
}
|
|
4882
4883
|
const pairingline = document.createElement("p");
|
|
4883
4884
|
pairingline.textContent = mcp.pairing.length > 0 ? `Pairing code ${mcp.pairing[0]?.code} for ${mcp.pairing[0]?.scopes.join(", ") || "no"} namespaces \xB7 expires at ${new Date(mcp.pairing[0]?.expiresat ?? Date.now()).toISOString()} \xB7 single use.` : "No pairing code pending; issue one while a session is live to pair a remote client.";
|
|
@@ -4931,9 +4932,9 @@ function renderagentprotocol(context) {
|
|
|
4931
4932
|
allowlistsummary.textContent = `Client allowlist (${mcp.allowlist.length} entr${mcp.allowlist.length === 1 ? "y" : "ies"})`;
|
|
4932
4933
|
allowlistbox.append(allowlistsummary);
|
|
4933
4934
|
for (const entry of mcp.allowlist) {
|
|
4934
|
-
const
|
|
4935
|
-
|
|
4936
|
-
allowlistbox.append(
|
|
4935
|
+
const line2 = document.createElement("p");
|
|
4936
|
+
line2.textContent = `${entry.displayname} \xB7 ${entry.fingerprint.slice(0, 12)} \xB7 namespaces ${entry.namespaces.join(", ") || "none"} \xB7 granted ${new Date(entry.grantedat).toISOString()} \xB7 ${entry.history.length} grant change${entry.history.length === 1 ? "" : "s"}.`;
|
|
4937
|
+
allowlistbox.append(line2);
|
|
4937
4938
|
const actions = document.createElement("div");
|
|
4938
4939
|
actions.className = "actions";
|
|
4939
4940
|
actions.append(button(`Rescope to browser+memory`, async () => {
|
|
@@ -4988,9 +4989,9 @@ function renderagentprotocol(context) {
|
|
|
4988
4989
|
domainsummary.textContent = `${namespace} (${tools.length} tools)`;
|
|
4989
4990
|
domain.append(domainsummary);
|
|
4990
4991
|
for (const tool of tools) {
|
|
4991
|
-
const
|
|
4992
|
-
|
|
4993
|
-
domain.append(
|
|
4992
|
+
const line2 = document.createElement("p");
|
|
4993
|
+
line2.textContent = `${tool.name} v${tool.version} \xB7 ${tool.risk} \xB7 ${tool.description.split(".")[0] ?? tool.description}${tool.consentmeta !== void 0 ? ` \xB7 ${tool.consentmeta.riskclass} \xB7 approval gate ${tool.consentmeta.approvalrequired ? "required" : "off"} \xB7 ${tool.consentmeta.originscope} scope \xB7 review: ${tool.consentmeta.review}` : ""}`;
|
|
4994
|
+
domain.append(line2);
|
|
4994
4995
|
}
|
|
4995
4996
|
catalogbox.append(domain);
|
|
4996
4997
|
}
|
|
@@ -5001,9 +5002,9 @@ function renderagentprotocol(context) {
|
|
|
5001
5002
|
runtimesummary.textContent = `Call runtime (${mcp.inflight?.length ?? 0} in flight, ${mcp.dryruntoggle === true ? "dry run armed" : "dry run off"}, ${mcp.mocks?.length ?? 0} mock${(mcp.mocks?.length ?? 0) === 1 ? "" : "s"})`;
|
|
5002
5003
|
runtimebox.append(runtimesummary);
|
|
5003
5004
|
for (const call of mcp.inflight ?? []) {
|
|
5004
|
-
const
|
|
5005
|
-
|
|
5006
|
-
runtimebox.append(
|
|
5005
|
+
const line2 = document.createElement("p");
|
|
5006
|
+
line2.textContent = `In flight ${call.tool} of ${call.clientid} \xB7 call ${call.callid.slice(0, 12)} \xB7 ${call.chunks} chunk${call.chunks === 1 ? "" : "s"} \xB7 open ${Math.max(0, Math.round((Date.now() - call.startedat) / 1e3))}s${call.dryrun === true ? " \xB7 dry run" : ""}.`;
|
|
5007
|
+
runtimebox.append(line2);
|
|
5007
5008
|
const actions = document.createElement("div");
|
|
5008
5009
|
actions.className = "actions";
|
|
5009
5010
|
actions.append(button("Cancel call", async () => {
|
|
@@ -5038,9 +5039,9 @@ function renderagentprotocol(context) {
|
|
|
5038
5039
|
}));
|
|
5039
5040
|
runtimebox.append(runtimeactions);
|
|
5040
5041
|
for (const mock of mcp.mocks ?? []) {
|
|
5041
|
-
const
|
|
5042
|
-
|
|
5043
|
-
runtimebox.append(
|
|
5042
|
+
const line2 = document.createElement("p");
|
|
5043
|
+
line2.textContent = `Tool mock ${mock.tool} \xB7 test context \xB7 created ${new Date(mock.createdat).toISOString()}.`;
|
|
5044
|
+
runtimebox.append(line2);
|
|
5044
5045
|
const actions = document.createElement("div");
|
|
5045
5046
|
actions.className = "actions";
|
|
5046
5047
|
actions.append(button("Remove mock", async () => {
|
|
@@ -5057,11 +5058,11 @@ function renderagentprotocol(context) {
|
|
|
5057
5058
|
limitssummary.textContent = `Rate limits (${mcp.limits?.length ?? 0} client${(mcp.limits?.length ?? 0) === 1 ? "" : "s"} limited)`;
|
|
5058
5059
|
limitsbox.append(limitssummary);
|
|
5059
5060
|
for (const limit of mcp.limits ?? []) {
|
|
5060
|
-
const
|
|
5061
|
+
const line2 = document.createElement("p");
|
|
5061
5062
|
const used = limit.budget !== void 0 ? Math.min(100, Math.round(limit.used / limit.budget * 100)) : 0;
|
|
5062
5063
|
const bar = limit.budget !== void 0 ? " " + "\u2588".repeat(Math.round(used / 10)) + "\xB7".repeat(10 - Math.round(used / 10)) : "";
|
|
5063
|
-
|
|
5064
|
-
limitsbox.append(
|
|
5064
|
+
line2.textContent = `${limit.clientid} \xB7 ${limit.used}${limit.budget !== void 0 ? ` of ${limit.budget}` : " of unbounded"} call${limit.used === 1 ? "" : "s"} in the ${limit.windowms}ms window${bar} \xB7 resets in ${Math.max(0, Math.round((limit.windowstartedat + limit.windowms - Date.now()) / 1e3))}s.`;
|
|
5065
|
+
limitsbox.append(line2);
|
|
5065
5066
|
const actions = document.createElement("div");
|
|
5066
5067
|
actions.className = "actions";
|
|
5067
5068
|
actions.append(button("Remove limit", async () => {
|
|
@@ -5101,14 +5102,14 @@ function renderagentprotocol(context) {
|
|
|
5101
5102
|
streamsummary.textContent = `Streaming and progress (${mcp.chunks?.length ?? 0} chunk${(mcp.chunks?.length ?? 0) === 1 ? "" : "s"}, ${mcp.progressnotices?.length ?? 0} notice${(mcp.progressnotices?.length ?? 0) === 1 ? "" : "s"})`;
|
|
5102
5103
|
streambox.append(streamsummary);
|
|
5103
5104
|
for (const notice of (mcp.progressnotices ?? []).slice(0, 5)) {
|
|
5104
|
-
const
|
|
5105
|
-
|
|
5106
|
-
streambox.append(
|
|
5105
|
+
const line2 = document.createElement("p");
|
|
5106
|
+
line2.textContent = `Progress ${notice.percent !== void 0 ? `${notice.percent}%` : ""} of the call ${notice.callid.slice(0, 12)} \xB7 ${notice.message}${notice.cancellable ? " \xB7 cancellable" : ""} \xB7 ${new Date(notice.at).toISOString()}.`;
|
|
5107
|
+
streambox.append(line2);
|
|
5107
5108
|
}
|
|
5108
5109
|
for (const chunk of (mcp.chunks ?? []).slice(0, 10)) {
|
|
5109
|
-
const
|
|
5110
|
-
|
|
5111
|
-
streambox.append(
|
|
5110
|
+
const line2 = document.createElement("p");
|
|
5111
|
+
line2.textContent = `Chunk ${chunk.seq}${chunk.done ? " (done)" : ""} of the call ${chunk.callid.slice(0, 12)} \xB7 ${chunk.content.slice(0, 60)}${chunk.content.length > 60 ? "\u2026" : ""}`;
|
|
5112
|
+
streambox.append(line2);
|
|
5112
5113
|
}
|
|
5113
5114
|
if ((mcp.chunks?.length ?? 0) === 0 && (mcp.progressnotices?.length ?? 0) === 0) {
|
|
5114
5115
|
const empty = document.createElement("p");
|
|
@@ -5122,9 +5123,9 @@ function renderagentprotocol(context) {
|
|
|
5122
5123
|
samplingsummary.textContent = `Sampling callbacks (${mcp.sampling?.length ?? 0})`;
|
|
5123
5124
|
samplingbox.append(samplingsummary);
|
|
5124
5125
|
for (const callback of mcp.sampling ?? []) {
|
|
5125
|
-
const
|
|
5126
|
-
|
|
5127
|
-
samplingbox.append(
|
|
5126
|
+
const line2 = document.createElement("p");
|
|
5127
|
+
line2.textContent = `${callback.state} \xB7 client ${callback.clientid} \xB7 requested ${new Date(callback.requestedat).toISOString()}${callback.answeredat !== void 0 ? ` \xB7 answered ${new Date(callback.answeredat).toISOString()}` : ""}${callback.pagecontent !== void 0 ? " \xB7 page content granted" : " \xB7 page content stripped"}.`;
|
|
5128
|
+
samplingbox.append(line2);
|
|
5128
5129
|
const payload = document.createElement("p");
|
|
5129
5130
|
payload.textContent = `Prompt: ${callback.prompt}${callback.system !== void 0 ? ` System: ${callback.system}` : ""}${callback.answer !== void 0 ? ` Answer: ${callback.answer}` : ""}`;
|
|
5130
5131
|
samplingbox.append(payload);
|
|
@@ -5171,9 +5172,9 @@ function renderagentprotocol(context) {
|
|
|
5171
5172
|
subssummary.textContent = `Subscriptions (${mcp.subscriptions?.length ?? 0} event, ${mcp.watches?.length ?? 0} resource)`;
|
|
5172
5173
|
subsbox.append(subssummary);
|
|
5173
5174
|
for (const subscription of mcp.subscriptions ?? []) {
|
|
5174
|
-
const
|
|
5175
|
-
|
|
5176
|
-
subsbox.append(
|
|
5175
|
+
const line2 = document.createElement("p");
|
|
5176
|
+
line2.textContent = `Client ${subscription.clientid} \xB7 kinds ${subscription.kinds.join(", ")}${subscription.origin !== void 0 ? ` \xB7 origin ${subscription.origin}` : ""}${subscription.tool !== void 0 ? ` \xB7 tool ${subscription.tool}` : ""} \xB7 subscribed ${new Date(subscription.createdat).toISOString()}${subscription.lastdeliveredat !== void 0 ? ` \xB7 last delivery ${new Date(subscription.lastdeliveredat).toISOString()}` : ""}.`;
|
|
5177
|
+
subsbox.append(line2);
|
|
5177
5178
|
const actions = document.createElement("div");
|
|
5178
5179
|
actions.className = "actions";
|
|
5179
5180
|
actions.append(button("Unsubscribe", async () => {
|
|
@@ -5184,9 +5185,9 @@ function renderagentprotocol(context) {
|
|
|
5184
5185
|
subsbox.append(actions);
|
|
5185
5186
|
}
|
|
5186
5187
|
for (const watch of mcp.watches ?? []) {
|
|
5187
|
-
const
|
|
5188
|
-
|
|
5189
|
-
subsbox.append(
|
|
5188
|
+
const line2 = document.createElement("p");
|
|
5189
|
+
line2.textContent = `Client ${watch.clientid} watches the ${watch.resource} resource \xB7 since ${new Date(watch.createdat).toISOString()}${watch.lastdeliveredat !== void 0 ? ` \xB7 last delta ${new Date(watch.lastdeliveredat).toISOString()}` : ""}.`;
|
|
5190
|
+
subsbox.append(line2);
|
|
5190
5191
|
const actions = document.createElement("div");
|
|
5191
5192
|
actions.className = "actions";
|
|
5192
5193
|
actions.append(button("Unwatch", async () => {
|
|
@@ -5208,10 +5209,10 @@ function renderagentprotocol(context) {
|
|
|
5208
5209
|
batchsummary.textContent = `Batch calls (${mcp.batches?.length ?? 0})`;
|
|
5209
5210
|
batchbox.append(batchsummary);
|
|
5210
5211
|
for (const batch of mcp.batches ?? []) {
|
|
5211
|
-
const
|
|
5212
|
+
const line2 = document.createElement("p");
|
|
5212
5213
|
const done = batch.outcomes.length;
|
|
5213
|
-
|
|
5214
|
-
batchbox.append(
|
|
5214
|
+
line2.textContent = `${batch.state} \xB7 client ${batch.clientid} \xB7 ${done} of ${batch.calls.length} member${batch.calls.length === 1 ? "" : "s"} done \xB7 stop on error ${batch.stoponerror ? "on" : "off"} \xB7 created ${new Date(batch.createdat).toISOString()}.`;
|
|
5215
|
+
batchbox.append(line2);
|
|
5215
5216
|
for (const outcome of batch.outcomes.slice(0, 10)) {
|
|
5216
5217
|
const item = document.createElement("p");
|
|
5217
5218
|
item.textContent = ` ${outcome.ok ? "ran" : "failed"} \xB7 ${outcome.tool} (${outcome.callid}).`;
|
|
@@ -5230,9 +5231,9 @@ function renderagentprotocol(context) {
|
|
|
5230
5231
|
callssummary.textContent = `Audited tool calls (${(mcp.calllog ?? mcp.calls).length} shown, every call logged)`;
|
|
5231
5232
|
callsbox.append(callssummary);
|
|
5232
5233
|
for (const call of (mcp.calllog ?? mcp.calls).slice(0, 25)) {
|
|
5233
|
-
const
|
|
5234
|
-
|
|
5235
|
-
callsbox.append(
|
|
5234
|
+
const line2 = document.createElement("p");
|
|
5235
|
+
line2.textContent = `${new Date(call.at).toISOString()} \xB7 ${call.clientid} \xB7 ${call.tool} \xB7 ${call.origin} \xB7 ${call.ok ? "ran behind the gates" : `refused${call.code !== void 0 ? ` (${call.code})` : ""}`}${call.dryrun === true ? " \xB7 dry run" : ""}${call.mocked === true ? " \xB7 mocked" : ""}${call.batchid !== void 0 ? " \xB7 batch member" : ""}${call.idempotencykey !== void 0 ? ` \xB7 key ${call.idempotencykey.slice(0, 10)}` : ""}${call.replayed === true ? " \xB7 idempotent replay" : ""}`;
|
|
5236
|
+
callsbox.append(line2);
|
|
5236
5237
|
}
|
|
5237
5238
|
if ((mcp.calllog ?? mcp.calls).length === 0) {
|
|
5238
5239
|
const empty = document.createElement("p");
|
|
@@ -5627,13 +5628,13 @@ function rendersecurity(context) {
|
|
|
5627
5628
|
allowbox.append(none);
|
|
5628
5629
|
}
|
|
5629
5630
|
for (const entry of view.allowlist) {
|
|
5630
|
-
const
|
|
5631
|
-
|
|
5632
|
-
|
|
5631
|
+
const line2 = document.createElement("p");
|
|
5632
|
+
line2.textContent = `${entry.origin} \xB7 profile workspace ${entry.profileid} \xB7 granted ${new Date(entry.grantedat).toLocaleString()}`;
|
|
5633
|
+
line2.append(" ", button("Remove", async () => {
|
|
5633
5634
|
await request({ kind: "security", allowlist: { remove: { origin: entry.origin } } });
|
|
5634
5635
|
await refresh();
|
|
5635
5636
|
}));
|
|
5636
|
-
allowbox.append(
|
|
5637
|
+
allowbox.append(line2);
|
|
5637
5638
|
}
|
|
5638
5639
|
const origininput = document.createElement("input");
|
|
5639
5640
|
origininput.placeholder = "https://exact.example";
|
|
@@ -5662,9 +5663,9 @@ function rendersecurity(context) {
|
|
|
5662
5663
|
profilebox.append(none);
|
|
5663
5664
|
}
|
|
5664
5665
|
for (const profile of view.profiles) {
|
|
5665
|
-
const
|
|
5666
|
-
|
|
5667
|
-
profilebox.append(
|
|
5666
|
+
const line2 = document.createElement("p");
|
|
5667
|
+
line2.textContent = `${profile.origin}: ${profile.grants.length} granted kind${profile.grants.length === 1 ? "" : "s"}${profile.denials.length > 0 ? `, ${profile.denials.length} denied kind${profile.denials.length === 1 ? "" : "s"}` : ""}.`;
|
|
5668
|
+
profilebox.append(line2);
|
|
5668
5669
|
}
|
|
5669
5670
|
if (context.session?.origin !== void 0) {
|
|
5670
5671
|
const kindinput = document.createElement("input");
|
|
@@ -5696,13 +5697,13 @@ function rendersecurity(context) {
|
|
|
5696
5697
|
}
|
|
5697
5698
|
for (const window2 of view.windows) {
|
|
5698
5699
|
const remaining = window2.state === "active" ? Math.max(0, window2.expiresat - now) : 0;
|
|
5699
|
-
const
|
|
5700
|
-
|
|
5700
|
+
const line2 = document.createElement("p");
|
|
5701
|
+
line2.textContent = `${window2.origin} \xB7 ${window2.state === "active" ? `active, ${Math.ceil(remaining / 1e3)}s of the ${window2.boundary} boundary left` : `closed at ${new Date(window2.closedat ?? window2.expiresat).toLocaleString()}`} \xB7 ${window2.kinds.length} kind${window2.kinds.length === 1 ? "" : "s"} covered.`;
|
|
5701
5702
|
if (window2.state === "active") {
|
|
5702
5703
|
const durationinput2 = document.createElement("input");
|
|
5703
5704
|
durationinput2.placeholder = "duration in ms";
|
|
5704
5705
|
durationinput2.setAttribute("aria-label", "Renewal duration in milliseconds");
|
|
5705
|
-
|
|
5706
|
+
line2.append(" ", durationinput2, " ", button("Renew", async () => {
|
|
5706
5707
|
const duration = Number(durationinput2.value.trim());
|
|
5707
5708
|
const offer = Number.isFinite(duration) && duration > 0 ? duration : view.promptduration;
|
|
5708
5709
|
if (offer === void 0) throw new Error("The renewal prompt needs its duration in milliseconds; no grant ever defaults to unlimited.");
|
|
@@ -5710,7 +5711,7 @@ function rendersecurity(context) {
|
|
|
5710
5711
|
await refresh();
|
|
5711
5712
|
}));
|
|
5712
5713
|
}
|
|
5713
|
-
windowbox.append(
|
|
5714
|
+
windowbox.append(line2);
|
|
5714
5715
|
}
|
|
5715
5716
|
const durationinput = document.createElement("input");
|
|
5716
5717
|
durationinput.placeholder = "duration in ms";
|
|
@@ -5741,9 +5742,9 @@ function rendersecurity(context) {
|
|
|
5741
5742
|
}
|
|
5742
5743
|
for (const pending of prompts) {
|
|
5743
5744
|
const classification = context.plan?.steps.find((step) => step.id === pending.stepid) !== void 0 ? sensitiveclassesof(context.plan.steps.find((step) => step.id === pending.stepid)) : { classes: [], bydefault: false };
|
|
5744
|
-
const
|
|
5745
|
-
|
|
5746
|
-
promptbox.append(
|
|
5745
|
+
const line2 = document.createElement("p");
|
|
5746
|
+
line2.textContent = `${pending.prompt}${classification.classes.length > 0 ? ` Class badge: ${classification.classes.join(", ")}.` : classification.bydefault ? " Class badge: sensitive by default." : ""}`;
|
|
5747
|
+
promptbox.append(line2);
|
|
5747
5748
|
}
|
|
5748
5749
|
if (context.session?.origin !== void 0 && prompts.length > 0) {
|
|
5749
5750
|
promptbox.append(button("Consent to every sensitive class", async () => {
|
|
@@ -5795,13 +5796,13 @@ function rendersecurity(context) {
|
|
|
5795
5796
|
maskbox.append(none);
|
|
5796
5797
|
}
|
|
5797
5798
|
for (const rule of view.maskrules) {
|
|
5798
|
-
const
|
|
5799
|
-
|
|
5800
|
-
|
|
5799
|
+
const line2 = document.createElement("p");
|
|
5800
|
+
line2.textContent = `${rule.shapes.join(", ")}${rule.origin !== void 0 ? ` scoped to ${rule.origin}` : " global"} \xB7 values show as [redacted] fields in step details.`;
|
|
5801
|
+
line2.append(" ", button("Remove", async () => {
|
|
5801
5802
|
await request({ kind: "security", mask: { remove: { id: rule.id } } });
|
|
5802
5803
|
await refresh();
|
|
5803
5804
|
}));
|
|
5804
|
-
maskbox.append(
|
|
5805
|
+
maskbox.append(line2);
|
|
5805
5806
|
}
|
|
5806
5807
|
securityroot.append(maskbox);
|
|
5807
5808
|
const gatebox = document.createElement("details");
|
|
@@ -5817,17 +5818,17 @@ function rendersecurity(context) {
|
|
|
5817
5818
|
gatebox.append(none);
|
|
5818
5819
|
}
|
|
5819
5820
|
for (const gate of gates) {
|
|
5820
|
-
const
|
|
5821
|
+
const line2 = document.createElement("p");
|
|
5821
5822
|
const payload = Object.entries(gate.payload).map(([key, value]) => `${key} ${value}`).join(", ");
|
|
5822
|
-
|
|
5823
|
-
if (gate.state === "open")
|
|
5823
|
+
line2.textContent = `${gate.kind} \xB7 step ${gate.stepid} on ${gate.origin} \xB7 ${payload} \xB7 ${gate.state}${gate.resolvedat !== void 0 ? ` at ${new Date(gate.resolvedat).toLocaleTimeString()} by ${gate.actor ?? "the user"}` : " \xB7 waiting for one distinct human action; no timeout resolves a gate"}.`;
|
|
5824
|
+
if (gate.state === "open") line2.append(" ", button("Approve", async () => {
|
|
5824
5825
|
await request({ kind: "security", gate: { resolve: { gateid: gate.gateid, decision: "resolved" } } });
|
|
5825
5826
|
await refresh();
|
|
5826
5827
|
}), " ", button("Refuse", async () => {
|
|
5827
5828
|
await request({ kind: "security", gate: { resolve: { gateid: gate.gateid, decision: "refused" } } });
|
|
5828
5829
|
await refresh();
|
|
5829
5830
|
}));
|
|
5830
|
-
gatebox.append(
|
|
5831
|
+
gatebox.append(line2);
|
|
5831
5832
|
}
|
|
5832
5833
|
securityroot.append(gatebox);
|
|
5833
5834
|
const deferbox = document.createElement("details");
|
|
@@ -5867,16 +5868,16 @@ function rendersecurity(context) {
|
|
|
5867
5868
|
chainbox.append(none);
|
|
5868
5869
|
}
|
|
5869
5870
|
for (const chain of view.chain) {
|
|
5870
|
-
const
|
|
5871
|
-
|
|
5872
|
-
|
|
5871
|
+
const line2 = document.createElement("p");
|
|
5872
|
+
line2.textContent = `${chain.runid}: ${chain.valid ? "chain verified" : `chain broken at entry ${chain.brokenat ?? "unknown"}`} \xB7 ${chain.entries} entries${chain.sealhash !== void 0 ? ` \xB7 seal hash ${chain.sealhash.slice(0, 12)}\u2026 at ${new Date(chain.sealedat ?? 0).toLocaleString()}` : " \xB7 unsealed"}.`;
|
|
5873
|
+
line2.append(" ", button("Read log", async () => {
|
|
5873
5874
|
const read = await request({ kind: "security", read: { runid: chain.runid } });
|
|
5874
5875
|
status(read.verification ?? `The log of ${chain.runid} read through the audit accessor.`);
|
|
5875
5876
|
}), " ", button("Export audit file", async () => {
|
|
5876
5877
|
const exported = await request({ kind: "security", export: { runid: chain.runid } });
|
|
5877
5878
|
status(`The verified run log of ${chain.runid} was exported as an audit file with ${exported.export?.entries ?? 0} entries.`);
|
|
5878
5879
|
}));
|
|
5879
|
-
chainbox.append(
|
|
5880
|
+
chainbox.append(line2);
|
|
5880
5881
|
}
|
|
5881
5882
|
const chainnote = document.createElement("p");
|
|
5882
5883
|
chainnote.className = "muted";
|
|
@@ -5953,9 +5954,9 @@ function renderenvironments(context) {
|
|
|
5953
5954
|
groupbox.append(none);
|
|
5954
5955
|
}
|
|
5955
5956
|
for (const [environment, stepids] of grouped) {
|
|
5956
|
-
const
|
|
5957
|
-
|
|
5958
|
-
groupbox.append(
|
|
5957
|
+
const line2 = document.createElement("p");
|
|
5958
|
+
line2.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(", ")}` : ""}`;
|
|
5959
|
+
groupbox.append(line2);
|
|
5959
5960
|
}
|
|
5960
5961
|
environmentsroot.append(groupbox);
|
|
5961
5962
|
const grantbox = document.createElement("div");
|
|
@@ -7054,4 +7055,477 @@ function renderagents(context) {
|
|
|
7054
7055
|
}
|
|
7055
7056
|
});
|
|
7056
7057
|
}
|
|
7058
|
+
var historystate = { hits: [], query: "" };
|
|
7059
|
+
function rendersessiongrid(view) {
|
|
7060
|
+
const root = document.querySelector("#sessiongrid");
|
|
7061
|
+
if (!root) return;
|
|
7062
|
+
root.replaceChildren();
|
|
7063
|
+
const empty = view.emptystates.find((state) => state.surface === "sessiongrid");
|
|
7064
|
+
if (view.grid.length === 0) {
|
|
7065
|
+
root.append(line(empty?.message ?? "No session exists yet; start the first run by describing an objective and reviewing the plan the agent proposes."));
|
|
7066
|
+
return;
|
|
7067
|
+
}
|
|
7068
|
+
for (const row of view.grid) {
|
|
7069
|
+
const item = document.createElement("div");
|
|
7070
|
+
item.className = "row";
|
|
7071
|
+
const summary = document.createElement("p");
|
|
7072
|
+
summary.textContent = `${row.state} run ${row.runid} \u2014 ${row.origins.join(", ")} \u2014 ${row.outcome} \u2014 ${row.completed}/${row.steps} steps \u2014 lock ${row.lock}${row.sealhash !== void 0 ? ` \u2014 sealed ${row.sealhash.slice(0, 12)}` : ""}`;
|
|
7073
|
+
item.append(summary);
|
|
7074
|
+
if (row.actions.includes("cancelrun")) item.append(button("Cancel run", async () => {
|
|
7075
|
+
await request({ kind: "sessions", cancel: { runid: row.runid, ...view.cancelrollback !== void 0 ? { rollback: view.cancelrollback } : {} } });
|
|
7076
|
+
status(`The run ${row.runid} cancelled with its queued rollback.`);
|
|
7077
|
+
await refresh();
|
|
7078
|
+
}));
|
|
7079
|
+
if (row.actions.includes("resume")) item.append(" ", button("Resume", async () => {
|
|
7080
|
+
await request({ kind: "sessions", grid: { resume: { runid: row.runid } } });
|
|
7081
|
+
status(`The session of the run ${row.runid} resumed.`);
|
|
7082
|
+
await refresh();
|
|
7083
|
+
}));
|
|
7084
|
+
if (row.actions.includes("reopen")) item.append(" ", button("Reopen sealed run", async () => {
|
|
7085
|
+
const result = await request({ kind: "sessions", grid: { reopen: { runid: row.runid } } });
|
|
7086
|
+
status(`The sealed run ${row.runid} reopened with ${result.entries} verified log entries.`);
|
|
7087
|
+
}));
|
|
7088
|
+
item.append(" ", button("Open in sidepanel", async () => {
|
|
7089
|
+
await request({ kind: "sessions", grid: { open: { runid: row.runid } } });
|
|
7090
|
+
}));
|
|
7091
|
+
root.append(item);
|
|
7092
|
+
}
|
|
7093
|
+
}
|
|
7094
|
+
function renderhistorysearch(view) {
|
|
7095
|
+
const root = document.querySelector("#historysearch");
|
|
7096
|
+
if (!root) return;
|
|
7097
|
+
root.replaceChildren();
|
|
7098
|
+
if (!view.historyindex) {
|
|
7099
|
+
root.append(line("The historysearch index building stays off in the options; turn it on to search sessions, notes and summaries."));
|
|
7100
|
+
return;
|
|
7101
|
+
}
|
|
7102
|
+
const input = document.createElement("input");
|
|
7103
|
+
input.placeholder = "Search sessions, notes and run summaries";
|
|
7104
|
+
input.value = historystate.query;
|
|
7105
|
+
input.addEventListener("keydown", (event) => {
|
|
7106
|
+
if (event.key !== "Enter") return;
|
|
7107
|
+
void (async () => {
|
|
7108
|
+
const answer = await request({ kind: "sessions", search: { query: { text: input.value } } });
|
|
7109
|
+
historystate.hits = answer.hits;
|
|
7110
|
+
historystate.query = input.value;
|
|
7111
|
+
renderhistorysearch(view);
|
|
7112
|
+
})();
|
|
7113
|
+
});
|
|
7114
|
+
root.append(input, " ", button("Search", async () => {
|
|
7115
|
+
const answer = await request({ kind: "sessions", search: { query: { text: input.value } } });
|
|
7116
|
+
historystate.hits = answer.hits;
|
|
7117
|
+
historystate.query = input.value;
|
|
7118
|
+
renderhistorysearch(view);
|
|
7119
|
+
}));
|
|
7120
|
+
if (historystate.hits.length === 0) {
|
|
7121
|
+
root.append(line(view.emptystates.find((state) => state.surface === "historysearch")?.message ?? "No history matches yet; start with a first query such as an origin, a note title or a kind the runs executed."));
|
|
7122
|
+
return;
|
|
7123
|
+
}
|
|
7124
|
+
for (const hit of historystate.hits) {
|
|
7125
|
+
const item = document.createElement("div");
|
|
7126
|
+
item.className = "row";
|
|
7127
|
+
const text = document.createElement("p");
|
|
7128
|
+
text.textContent = `${hit.source}: ${hit.title} \u2014 ${hit.excerpt}${hit.highlights.length > 0 ? ` [matched: ${hit.highlights.join(", ")}]` : ""}`;
|
|
7129
|
+
item.append(text);
|
|
7130
|
+
item.append(button("Open sealed run", async () => {
|
|
7131
|
+
await request({ kind: "sessions", grid: { open: { runid: hit.source === "summary" ? hit.id : hit.id } } });
|
|
7132
|
+
status(`The history hit ${hit.id} links to its sealed run view.`);
|
|
7133
|
+
}));
|
|
7134
|
+
root.append(item);
|
|
7135
|
+
}
|
|
7136
|
+
}
|
|
7137
|
+
function rendersitenotes(view) {
|
|
7138
|
+
const root = document.querySelector("#sitenotes");
|
|
7139
|
+
if (!root) return;
|
|
7140
|
+
root.replaceChildren();
|
|
7141
|
+
if (view.notes.length === 0) root.append(line(view.emptystates.find((state) => state.surface === "sitenotes")?.message ?? "No site note exists yet; write the first note with a title and a body and the note flow keeps it per origin with its author provenance."));
|
|
7142
|
+
for (const note of view.notes) {
|
|
7143
|
+
const item = document.createElement("div");
|
|
7144
|
+
item.className = "row";
|
|
7145
|
+
const text = document.createElement("p");
|
|
7146
|
+
text.textContent = `${note.origin}: ${note.title} \u2014 ${note.body}${note.sensitive ? " (sensitive: the body stays sealed at rest)" : ""} \u2014 by ${note.author} at ${new Date(note.updatedat).toLocaleString()}`;
|
|
7147
|
+
item.append(text);
|
|
7148
|
+
item.append(button("Edit note", async () => {
|
|
7149
|
+
const title2 = window.prompt("Note title", note.title);
|
|
7150
|
+
if (title2 === null) return;
|
|
7151
|
+
const body2 = window.prompt("Note body", note.body);
|
|
7152
|
+
if (body2 === null) return;
|
|
7153
|
+
await request({ kind: "sessions", note: { edit: { id: note.id, title: title2, body: body2 } } });
|
|
7154
|
+
status("The site note edit landed with its author provenance.");
|
|
7155
|
+
await refresh();
|
|
7156
|
+
}), " ", button("Remove note", async () => {
|
|
7157
|
+
await request({ kind: "sessions", note: { remove: { id: note.id } } });
|
|
7158
|
+
status("The site note removed.");
|
|
7159
|
+
await refresh();
|
|
7160
|
+
}));
|
|
7161
|
+
root.append(item);
|
|
7162
|
+
}
|
|
7163
|
+
const title = document.createElement("input");
|
|
7164
|
+
title.placeholder = "note title";
|
|
7165
|
+
const body = document.createElement("input");
|
|
7166
|
+
body.placeholder = "note body";
|
|
7167
|
+
const sensitive = document.createElement("input");
|
|
7168
|
+
sensitive.type = "checkbox";
|
|
7169
|
+
const senslabel = document.createElement("label");
|
|
7170
|
+
senslabel.append(sensitive, " sensitive (seals the body at rest)");
|
|
7171
|
+
root.append(document.createElement("hr"), title, " ", body, " ", senslabel, " ", button("Write note", async () => {
|
|
7172
|
+
await request({ kind: "sessions", note: { add: { title: title.value, body: body.value, consent: true, ...sensitive.checked ? { sensitive: true } : {} } } });
|
|
7173
|
+
status("The site note landed per origin behind the explicit consent of the write.");
|
|
7174
|
+
await refresh();
|
|
7175
|
+
}));
|
|
7176
|
+
}
|
|
7177
|
+
function renderscratchpad(view) {
|
|
7178
|
+
const root = document.querySelector("#scratchpad");
|
|
7179
|
+
if (!root) return;
|
|
7180
|
+
root.replaceChildren();
|
|
7181
|
+
if (view.scratchpad.length === 0) root.append(line(view.emptystates.find((state) => state.surface === "scratchpad")?.message ?? "The scratchpad holds no entry yet; the agent appends its per task notes here while the reviewed steps run, and every entry carries its step provenance."));
|
|
7182
|
+
for (const entry of view.scratchpad) {
|
|
7183
|
+
const item = document.createElement("p");
|
|
7184
|
+
item.textContent = `${new Date(entry.at).toLocaleTimeString()} ${entry.author}${entry.stepid !== void 0 ? ` beside ${entry.stepid}` : ""}: ${entry.text}`;
|
|
7185
|
+
root.append(item);
|
|
7186
|
+
}
|
|
7187
|
+
const text = document.createElement("input");
|
|
7188
|
+
text.placeholder = "append one scratchpad entry";
|
|
7189
|
+
root.append(document.createElement("hr"), text, " ", button("Append", async () => {
|
|
7190
|
+
await request({ kind: "sessions", scratch: { append: { text: text.value } } });
|
|
7191
|
+
status("The scratchpad entry appended; the pad stays append only.");
|
|
7192
|
+
await refresh();
|
|
7193
|
+
}));
|
|
7194
|
+
}
|
|
7195
|
+
function rendersessionmemory(view) {
|
|
7196
|
+
const root = document.querySelector("#sessionmemory");
|
|
7197
|
+
if (!root) return;
|
|
7198
|
+
root.replaceChildren();
|
|
7199
|
+
const summaryhead = document.createElement("h3");
|
|
7200
|
+
summaryhead.textContent = "Run summaries";
|
|
7201
|
+
root.append(summaryhead);
|
|
7202
|
+
if (view.summaries.length === 0) root.append(line("No run summary exists yet; the executor distills one at run completion as an offscreen worker task."));
|
|
7203
|
+
for (const summary of view.summaries) {
|
|
7204
|
+
root.append(line(`${summary.runid} \u2014 ${summary.origins.join(", ")} \u2014 ${summary.kinds.length} kind${summary.kinds.length === 1 ? "" : "s"} \u2014 ${summary.steps} step outcome${summary.steps === 1 ? "" : "s"} \u2014 distilled ${summary.provenance === "offscreenworker" ? "inside the offscreen worker pool" : "inline beside the page"} at ${new Date(summary.distilledat).toLocaleString()}`));
|
|
7205
|
+
}
|
|
7206
|
+
const recallhead = document.createElement("h3");
|
|
7207
|
+
recallhead.textContent = "Semantic recall";
|
|
7208
|
+
root.append(recallhead);
|
|
7209
|
+
if (view.recall.length === 0) root.append(line("No past extraction matches the current objective inside the run scope yet."));
|
|
7210
|
+
for (const match of view.recall) root.append(line(`${match.origin} run ${match.runid} step ${match.stepid} \u2014 score ${match.score.toFixed(3)} \u2014 ${match.reason}`));
|
|
7211
|
+
const recallquery = document.createElement("input");
|
|
7212
|
+
recallquery.placeholder = "recall past extractions while planning";
|
|
7213
|
+
root.append(recallquery, " ", button("Recall", async () => {
|
|
7214
|
+
const answer = await request({ kind: "sessions", recall: { query: { text: recallquery.value } } });
|
|
7215
|
+
status(answer.matches.length > 0 ? answer.matches.map((match) => `${match.entry.origin} ${match.entry.stepid} ${match.score.toFixed(3)}`).join(" \xB7 ") : "No past extraction matches the query inside the run scope.");
|
|
7216
|
+
}));
|
|
7217
|
+
const correctionshead = document.createElement("h3");
|
|
7218
|
+
correctionshead.textContent = "Correction memory";
|
|
7219
|
+
root.append(correctionshead);
|
|
7220
|
+
if (view.corrections.length === 0) root.append(line("No correction exists yet; plan review edits and rejections land here per origin and kind."));
|
|
7221
|
+
for (const correction of view.corrections) root.append(line(`${correction.source} ${correction.kind} step ${correction.stepid} of ${correction.origin}: ${correction.reason}`));
|
|
7222
|
+
const consenthead = document.createElement("h3");
|
|
7223
|
+
consenthead.textContent = "Consent memory";
|
|
7224
|
+
root.append(consenthead);
|
|
7225
|
+
if (view.consentmemory.length === 0) root.append(line("No consent decision exists yet; every grant, denial, expiry and revocation lands here per origin and stays advisory."));
|
|
7226
|
+
for (const entry of view.consentmemory) root.append(line(`${entry.origin} ${entry.decision} ${entry.kinds.join(", ")} \u2014 boundary ${entry.boundary} \u2014 ${new Date(entry.at).toLocaleString()}${entry.expiresat !== void 0 ? ` \u2014 expires ${new Date(entry.expiresat).toLocaleString()}` : ""}`));
|
|
7227
|
+
const errorshead = document.createElement("h3");
|
|
7228
|
+
errorshead.textContent = "Error surfaces";
|
|
7229
|
+
root.append(errorshead);
|
|
7230
|
+
if (view.errors.length === 0) root.append(line("No failed step recorded an error surface yet."));
|
|
7231
|
+
for (const surface of view.errors) {
|
|
7232
|
+
const item = document.createElement("div");
|
|
7233
|
+
item.className = "row";
|
|
7234
|
+
item.append(line(`${surface.cause} failure of step ${surface.stepid} of run ${surface.runid}: ${surface.message} \u2014 retry ${surface.retry.allowed ? "allowed" : "refused"}: ${surface.retry.reason}`));
|
|
7235
|
+
if (surface.retry.allowed) item.append(button("Retry reviewed step", async () => {
|
|
7236
|
+
const output = await request({ kind: "sessions", retry: { stepid: surface.stepid } });
|
|
7237
|
+
status(output.summary);
|
|
7238
|
+
await refresh();
|
|
7239
|
+
}));
|
|
7240
|
+
root.append(item);
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
function rendersessioninterface(context) {
|
|
7244
|
+
const view = context.sessionview;
|
|
7245
|
+
if (!view) return;
|
|
7246
|
+
rendersessiongrid(view);
|
|
7247
|
+
renderhistorysearch(view);
|
|
7248
|
+
rendersitenotes(view);
|
|
7249
|
+
renderscratchpad(view);
|
|
7250
|
+
rendersessionmemory(view);
|
|
7251
|
+
}
|
|
7252
|
+
var tasksubmitbutton = document.querySelector("#tasksubmit");
|
|
7253
|
+
var plancardsroot = document.querySelector("#plancards");
|
|
7254
|
+
var stepstimelineroot = document.querySelector("#stepstimeline");
|
|
7255
|
+
var logstreamroot = document.querySelector("#logstream");
|
|
7256
|
+
var logstreampaused = false;
|
|
7257
|
+
var logstreamfilter = {};
|
|
7258
|
+
function applyworkspacetabs(active) {
|
|
7259
|
+
const plantitles = ["Current plan", "Clickable map", "Detected shapes", "Derived selectors", "Structured diagnostics"];
|
|
7260
|
+
const reviewtitles = ["Plan cards", "Steps timeline", "Log stream", "Local audit", "Session grid", "History search", "Site notes", "Scratchpad", "Session memory", "Security", "Console diff", "Datasets", "Consent banners", "Accessibility tree", "Reader view", "Snapshot diffs", "Agent protocol", "Models"];
|
|
7261
|
+
for (const section of Array.from(document.querySelectorAll("main > section"))) {
|
|
7262
|
+
const title = section.querySelector("h2")?.textContent?.trim() ?? "";
|
|
7263
|
+
const tab = plantitles.includes(title) ? "plan" : reviewtitles.includes(title) ? "review" : "run";
|
|
7264
|
+
section.hidden = tab !== active;
|
|
7265
|
+
}
|
|
7266
|
+
for (const tab of ["plan", "run", "review"]) {
|
|
7267
|
+
const element = document.querySelector(`#tab${tab}`);
|
|
7268
|
+
if (element) element.className = tab === active ? "" : "secondary";
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7271
|
+
for (const tab of ["plan", "run", "review"]) {
|
|
7272
|
+
document.querySelector(`#tab${tab}`)?.addEventListener("click", () => applyworkspacetabs(tab));
|
|
7273
|
+
}
|
|
7274
|
+
applyworkspacetabs("plan");
|
|
7275
|
+
tasksubmitbutton?.addEventListener("click", () => {
|
|
7276
|
+
const text = objective?.value ?? "";
|
|
7277
|
+
if (text.trim() === "") {
|
|
7278
|
+
status("Describe the goal first; the proposal flow needs its natural language task.", true);
|
|
7279
|
+
return;
|
|
7280
|
+
}
|
|
7281
|
+
void (async () => {
|
|
7282
|
+
status("The taskinput goal routes through the proposal flow; the plan generates.");
|
|
7283
|
+
const result = await request({ kind: "surface", task: { submit: { text, surface: "sidepanel" } } });
|
|
7284
|
+
status(`The taskinput goal became the plan ${result.plan?.id ?? ""}; review its plancards below.`);
|
|
7285
|
+
await refresh();
|
|
7286
|
+
await rendersurfacereview();
|
|
7287
|
+
})().catch((error) => status(error instanceof Error ? error.message : String(error), true));
|
|
7288
|
+
});
|
|
7289
|
+
async function renderplancards() {
|
|
7290
|
+
if (!plancardsroot) return;
|
|
7291
|
+
try {
|
|
7292
|
+
const result = await request({ kind: "surface", review: { groups: true } });
|
|
7293
|
+
plancardsroot.replaceChildren();
|
|
7294
|
+
if (result.cards.length === 0) {
|
|
7295
|
+
plancardsroot.textContent = "No plan exists yet; submit a task goal and the proposed steps render their cards here.";
|
|
7296
|
+
return;
|
|
7297
|
+
}
|
|
7298
|
+
for (const group of result.groups) {
|
|
7299
|
+
const heading = document.createElement("h3");
|
|
7300
|
+
heading.textContent = `${group.risk} steps${group.expanded ? " (expanded)" : ""}`;
|
|
7301
|
+
plancardsroot.append(heading);
|
|
7302
|
+
for (const card of group.cards) {
|
|
7303
|
+
const item = document.createElement("div");
|
|
7304
|
+
item.className = "panel";
|
|
7305
|
+
const label = document.createElement("strong");
|
|
7306
|
+
label.textContent = `${card.stepid} \xB7 ${card.kind} \xB7 ${card.environment}`;
|
|
7307
|
+
const summary = document.createElement("p");
|
|
7308
|
+
summary.textContent = card.summary;
|
|
7309
|
+
const options2 = document.createElement("p");
|
|
7310
|
+
options2.className = "muted";
|
|
7311
|
+
options2.textContent = card.options === "" ? "No reviewed options." : `Options: ${card.options}`;
|
|
7312
|
+
item.append(label, summary, options2);
|
|
7313
|
+
for (const correction of card.corrections) item.append(Object.assign(document.createElement("p"), { className: "muted", textContent: `Correction memory (${correction.source}): ${correction.reason}` }));
|
|
7314
|
+
if (card.editable) {
|
|
7315
|
+
item.append(button("Approve step", () => resolveStep(card.stepid, "approve")));
|
|
7316
|
+
item.append(" ", button("Reject step", () => resolveStep(card.stepid, "reject")));
|
|
7317
|
+
item.append(" ", button("Edit step", () => editStep(card.stepid)));
|
|
7318
|
+
}
|
|
7319
|
+
if (card.risk === "sensitive") item.append(" ", button("Diff preview", () => diffPreview(card.stepid)));
|
|
7320
|
+
plancardsroot.append(item);
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7323
|
+
} catch (error) {
|
|
7324
|
+
plancardsroot.textContent = error instanceof Error ? error.message : String(error);
|
|
7325
|
+
}
|
|
7326
|
+
}
|
|
7327
|
+
async function resolveStep(stepid, resolution) {
|
|
7328
|
+
const result = await request({ kind: "surface", approve: { resolve: { stepid, resolution, surface: "sidepanel" } } });
|
|
7329
|
+
status(`The step ${result.resolution.stepid} resolved with a ${result.resolution.resolution}; the resolution landed in the immutable log.`);
|
|
7330
|
+
await refresh();
|
|
7331
|
+
await rendersurfacereview();
|
|
7332
|
+
}
|
|
7333
|
+
async function editStep(stepid) {
|
|
7334
|
+
if (!plancardsroot) return;
|
|
7335
|
+
const editor = document.createElement("div");
|
|
7336
|
+
editor.className = "panel";
|
|
7337
|
+
const input = document.createElement("textarea");
|
|
7338
|
+
input.rows = 4;
|
|
7339
|
+
input.value = '{ "kind": "click", "summary": "Describe the corrected step." }';
|
|
7340
|
+
const save = button("Save edit", async () => {
|
|
7341
|
+
const result = await request({ kind: "surface", approve: { resolve: { stepid, resolution: "edit", edited: input.value, surface: "sidepanel" } } });
|
|
7342
|
+
status(`The step ${result.resolution.stepid} carries the edited shape and the correction memory recorded the change.`);
|
|
7343
|
+
editor.remove();
|
|
7344
|
+
await refresh();
|
|
7345
|
+
await rendersurfacereview();
|
|
7346
|
+
});
|
|
7347
|
+
editor.append(input, save);
|
|
7348
|
+
plancardsroot.append(editor);
|
|
7349
|
+
}
|
|
7350
|
+
async function diffPreview(stepid) {
|
|
7351
|
+
const before = {};
|
|
7352
|
+
try {
|
|
7353
|
+
const preview = await request({ kind: "preview", stepid });
|
|
7354
|
+
if (preview.resolvedtarget?.selector !== void 0) before.selector = preview.resolvedtarget.selector;
|
|
7355
|
+
if (preview.resolvedtarget?.text !== void 0) before.text = preview.resolvedtarget.text;
|
|
7356
|
+
if (preview.resolvedtarget?.mode !== void 0) before.mode = preview.resolvedtarget.mode;
|
|
7357
|
+
} catch {
|
|
7358
|
+
}
|
|
7359
|
+
const result = await request({ kind: "surface", diff: { preview: { stepid, before } } });
|
|
7360
|
+
const detail = result.preview.changes.map((change) => `${change.kind} ${change.field}${change.before !== void 0 ? ` from ${change.before}` : ""}${change.after !== void 0 ? ` to ${change.after}` : ""}`).join("; ");
|
|
7361
|
+
const masked = Object.entries(result.preview.maskverdicts).map(([field, verdict]) => `${field}: ${verdict}`).join("; ");
|
|
7362
|
+
status(`Diff preview of ${stepid} (${result.preview.provenance}): ${detail === "" ? "no field changes" : detail}${masked === "" ? "" : ` \u2014 masked: ${masked}`}`);
|
|
7363
|
+
}
|
|
7364
|
+
async function renderstepstimeline() {
|
|
7365
|
+
if (!stepstimelineroot) return;
|
|
7366
|
+
try {
|
|
7367
|
+
const result = await request({ kind: "surface", timeline: { nodes: true } });
|
|
7368
|
+
stepstimelineroot.replaceChildren();
|
|
7369
|
+
if (result.nodes.length === 0) {
|
|
7370
|
+
stepstimelineroot.textContent = "No plan runs yet; the timeline derives its nodes from progress records with no new state.";
|
|
7371
|
+
return;
|
|
7372
|
+
}
|
|
7373
|
+
const list = document.createElement("ol");
|
|
7374
|
+
list.className = "audit";
|
|
7375
|
+
for (const node of result.nodes) {
|
|
7376
|
+
const item = document.createElement("li");
|
|
7377
|
+
item.id = node.anchor.slice(1);
|
|
7378
|
+
const badge = node.active ? " \u25B6" : "";
|
|
7379
|
+
const duration = node.durationms !== void 0 ? ` \xB7 ${node.durationms}ms` : "";
|
|
7380
|
+
const environment = node.environment !== void 0 ? ` \xB7 ${node.environment}` : "";
|
|
7381
|
+
item.textContent = `${node.stepid} ${node.kind} \u2014 ${node.status}${duration}${environment}${badge}${node.resultsummary !== void 0 ? ` \u2014 ${node.resultsummary}` : ""}`;
|
|
7382
|
+
if (node.status === "waiting") item.append(" ", button("Diff preview at the gate wait", () => diffPreview(node.stepid)));
|
|
7383
|
+
if (node.active) item.scrollIntoView({ block: "nearest" });
|
|
7384
|
+
list.append(item);
|
|
7385
|
+
}
|
|
7386
|
+
stepstimelineroot.append(list);
|
|
7387
|
+
} catch (error) {
|
|
7388
|
+
stepstimelineroot.textContent = error instanceof Error ? error.message : String(error);
|
|
7389
|
+
}
|
|
7390
|
+
}
|
|
7391
|
+
async function renderlogstream() {
|
|
7392
|
+
if (!logstreamroot) return;
|
|
7393
|
+
try {
|
|
7394
|
+
const result = await request({ kind: "surface", logstream: { read: { filters: logstreamfilter } } });
|
|
7395
|
+
logstreamroot.replaceChildren();
|
|
7396
|
+
const controls = document.createElement("div");
|
|
7397
|
+
controls.className = "actions";
|
|
7398
|
+
const pause = button(logstreampaused ? "Resume stream" : "Pause stream", async () => {
|
|
7399
|
+
logstreampaused = !logstreampaused;
|
|
7400
|
+
await renderlogstream();
|
|
7401
|
+
});
|
|
7402
|
+
const levelselect = document.createElement("select");
|
|
7403
|
+
for (const level of ["", "error", "warn", "info", "log", "debug", "trace"]) {
|
|
7404
|
+
const option = document.createElement("option");
|
|
7405
|
+
option.value = level;
|
|
7406
|
+
option.textContent = level === "" ? "all levels" : level;
|
|
7407
|
+
levelselect.append(option);
|
|
7408
|
+
}
|
|
7409
|
+
levelselect.value = logstreamfilter.level ?? "";
|
|
7410
|
+
levelselect.addEventListener("change", () => {
|
|
7411
|
+
const level = levelselect.value;
|
|
7412
|
+
logstreamfilter = { ...logstreamfilter, ...level !== "" ? { level } : {} };
|
|
7413
|
+
void renderlogstream();
|
|
7414
|
+
});
|
|
7415
|
+
const copy = button("Copy verified excerpt", async () => {
|
|
7416
|
+
const excerpt = await request({ kind: "surface", logstream: { excerpt: {} } });
|
|
7417
|
+
await navigator.clipboard?.writeText(excerpt.excerpt).catch(() => {
|
|
7418
|
+
});
|
|
7419
|
+
status(excerpt.reason);
|
|
7420
|
+
});
|
|
7421
|
+
const chain = document.createElement("span");
|
|
7422
|
+
chain.className = "muted";
|
|
7423
|
+
chain.textContent = result.chain.valid ? `chain verified \xB7 ${result.total} events` : `chain broken: ${result.chain.reason}`;
|
|
7424
|
+
controls.append(pause, levelselect, copy, chain);
|
|
7425
|
+
const list = document.createElement("ol");
|
|
7426
|
+
list.className = "audit";
|
|
7427
|
+
for (const event of logstreampaused ? [] : result.events) {
|
|
7428
|
+
const item = document.createElement("li");
|
|
7429
|
+
item.textContent = `[${new Date(event.at).toLocaleTimeString()}] ${event.level} ${event.source}${event.stepid !== void 0 ? ` step ${event.stepid}` : ""} ${event.origin} \u2014 ${event.summary}${event.masked ? ` (${event.maskverdict})` : ""}`;
|
|
7430
|
+
list.append(item);
|
|
7431
|
+
}
|
|
7432
|
+
if (logstreampaused) list.append(Object.assign(document.createElement("li"), { textContent: "The live stream pauses while the run continues; the full history stays in memory." }));
|
|
7433
|
+
logstreamroot.append(controls, list);
|
|
7434
|
+
} catch (error) {
|
|
7435
|
+
logstreamroot.textContent = error instanceof Error ? error.message : String(error);
|
|
7436
|
+
}
|
|
7437
|
+
}
|
|
7438
|
+
async function rendersurfacereview() {
|
|
7439
|
+
await renderplancards();
|
|
7440
|
+
await renderstepstimeline();
|
|
7441
|
+
await renderlogstream();
|
|
7442
|
+
}
|
|
7443
|
+
void rendersurfacereview().catch(() => {
|
|
7444
|
+
});
|
|
7445
|
+
var surfacechannel = typeof BroadcastChannel === "function" ? new BroadcastChannel("devthinksurfaces") : void 0;
|
|
7446
|
+
surfacechannel?.addEventListener("message", (event) => {
|
|
7447
|
+
const frame = event.data;
|
|
7448
|
+
if (frame?.channel === "logstream") {
|
|
7449
|
+
if (!logstreampaused) void renderlogstream().catch(() => {
|
|
7450
|
+
});
|
|
7451
|
+
return;
|
|
7452
|
+
}
|
|
7453
|
+
void refresh().catch(() => {
|
|
7454
|
+
});
|
|
7455
|
+
void rendersurfacereview().catch(() => {
|
|
7456
|
+
});
|
|
7457
|
+
});
|
|
7458
|
+
var paletteinputnode = document.querySelector("#paletteinput");
|
|
7459
|
+
var palettematchespanel = document.querySelector("#palettematches");
|
|
7460
|
+
async function renderworkspacepalette() {
|
|
7461
|
+
if (!palettematchespanel) return;
|
|
7462
|
+
try {
|
|
7463
|
+
const result = await request({ kind: "surface", palette: { query: { text: paletteinputnode?.value ?? "" } } });
|
|
7464
|
+
palettematchespanel.replaceChildren();
|
|
7465
|
+
for (const match of result.matches.slice(0, 6)) {
|
|
7466
|
+
const item = document.createElement("button");
|
|
7467
|
+
item.type = "button";
|
|
7468
|
+
item.className = "secondary";
|
|
7469
|
+
item.textContent = `${match.entry.label} (${match.entry.action.surface})`;
|
|
7470
|
+
item.title = match.reason;
|
|
7471
|
+
item.addEventListener("click", () => {
|
|
7472
|
+
void runworkspacepalette(match.entry.action.command).catch((error) => status(error instanceof Error ? error.message : String(error), true));
|
|
7473
|
+
});
|
|
7474
|
+
palettematchespanel.append(item, " ");
|
|
7475
|
+
}
|
|
7476
|
+
if (result.matches.length === 0) palettematchespanel.textContent = "No command matches; the palette lists only the actions the current capability set allows.";
|
|
7477
|
+
} catch (error) {
|
|
7478
|
+
palettematchespanel.textContent = error instanceof Error ? error.message : String(error);
|
|
7479
|
+
}
|
|
7480
|
+
}
|
|
7481
|
+
async function runworkspacepalette(command) {
|
|
7482
|
+
await request({ kind: "surface", palette: { used: { command } } });
|
|
7483
|
+
if (command === "opendashboardpage" || command === "historysearch") {
|
|
7484
|
+
await chrome.tabs.create({ url: chrome.runtime.getURL("dashboardpage.html") });
|
|
7485
|
+
status("The dashboardpage opened in a new tab.");
|
|
7486
|
+
return;
|
|
7487
|
+
}
|
|
7488
|
+
if (command === "openoptionspage") {
|
|
7489
|
+
await chrome.tabs.create({ url: chrome.runtime.getURL("optionspage.html") });
|
|
7490
|
+
status("The optionspage opened in a new tab.");
|
|
7491
|
+
return;
|
|
7492
|
+
}
|
|
7493
|
+
if (command === "opentransparencypage") {
|
|
7494
|
+
await chrome.tabs.create({ url: chrome.runtime.getURL("transparencypage.html") });
|
|
7495
|
+
status("The transparencypage opened in a new tab.");
|
|
7496
|
+
return;
|
|
7497
|
+
}
|
|
7498
|
+
if (command === "replayonboarding") {
|
|
7499
|
+
await request({ kind: "surface", onboarding: { replay: true } });
|
|
7500
|
+
status("The onboarding walkthrough replays on the next popup open.");
|
|
7501
|
+
return;
|
|
7502
|
+
}
|
|
7503
|
+
if (command === "copyauditexcerpt") {
|
|
7504
|
+
const result = await request({ kind: "surface", logstream: { excerpt: {} } });
|
|
7505
|
+
await navigator.clipboard?.writeText(result.excerpt).catch(() => {
|
|
7506
|
+
});
|
|
7507
|
+
status("The verified range copied as an audit excerpt.");
|
|
7508
|
+
return;
|
|
7509
|
+
}
|
|
7510
|
+
const route = await request({ kind: "surface", bus: { action: { surface: "sidepanel", command } } });
|
|
7511
|
+
status(route.route.reason);
|
|
7512
|
+
await refresh();
|
|
7513
|
+
await rendersurfacereview();
|
|
7514
|
+
}
|
|
7515
|
+
paletteinputnode?.addEventListener("input", () => {
|
|
7516
|
+
void renderworkspacepalette();
|
|
7517
|
+
});
|
|
7518
|
+
document.querySelector("#paletteopen")?.addEventListener("click", () => {
|
|
7519
|
+
paletteinputnode?.focus();
|
|
7520
|
+
void renderworkspacepalette();
|
|
7521
|
+
});
|
|
7522
|
+
document.addEventListener("keydown", (event) => {
|
|
7523
|
+
if (event.ctrlKey && event.key === ".") {
|
|
7524
|
+
event.preventDefault();
|
|
7525
|
+
paletteinputnode?.focus();
|
|
7526
|
+
void renderworkspacepalette();
|
|
7527
|
+
}
|
|
7528
|
+
});
|
|
7529
|
+
void renderworkspacepalette().catch(() => {
|
|
7530
|
+
});
|
|
7057
7531
|
//# sourceMappingURL=sidepanel.js.map
|