@cesarus777/opencode-cgp 0.4.0 → 0.4.2
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/CHANGELOG.md +37 -0
- package/README.md +19 -11
- package/dist/cli.js +906 -237
- package/dist/core.js +88 -59
- package/dist/index.js +710 -166
- package/dist/tui.js +1416 -702
- package/dist/types/archive.d.ts +40 -0
- package/dist/types/core.d.ts +1 -1
- package/dist/types/dashboard/controller.d.ts +2 -0
- package/dist/types/dashboard/inventory.d.ts +1 -1
- package/dist/types/dashboard/terminal.d.ts +8 -0
- package/dist/types/dashboard/terminalview.d.ts +9 -2
- package/dist/types/dashboard/view.d.ts +4 -1
- package/dist/types/history.d.ts +39 -2
- package/dist/types/historyclient.d.ts +15 -0
- package/dist/types/historyserver.d.ts +2 -1
- package/dist/types/modelanalytics.d.ts +11 -0
- package/dist/types/modelanalyticsserver.d.ts +2 -1
- package/dist/types/tui/charts.d.ts +2 -3
- package/dist/types/tui/compactformat.d.ts +12 -3
- package/dist/types/tui/historystate.d.ts +49 -0
- package/dist/types/tui/inventory.d.ts +12 -0
- package/dist/types/tui/panelcontrols.d.ts +8 -0
- package/dist/types/tui/panelformat.d.ts +12 -0
- package/dist/types/tui/panelview.d.ts +22 -0
- package/dist/types/tui/quantity.d.ts +1 -0
- package/dist/types/tui/sidebar.d.ts +0 -5
- package/dist/types/tui/state.d.ts +3 -1
- package/dist/types/tui/statusformat.d.ts +19 -0
- package/package.json +2 -1
package/dist/tui.js
CHANGED
|
@@ -461,6 +461,51 @@ var init_rpc = __esm(() => {
|
|
|
461
461
|
});
|
|
462
462
|
});
|
|
463
463
|
|
|
464
|
+
// src/historyclient.ts
|
|
465
|
+
function historyFailure(error, signal) {
|
|
466
|
+
if (signal?.aborted && signal.reason instanceof DOMException && signal.reason.name === "TimeoutError" || error instanceof DOMException && error.name === "TimeoutError")
|
|
467
|
+
return new HistoryFailure("timeout");
|
|
468
|
+
if (error instanceof HistoryFailure)
|
|
469
|
+
return error;
|
|
470
|
+
const code = typeof error === "object" && error !== null && "type" in error ? error.type : undefined;
|
|
471
|
+
return new HistoryFailure(code === "rpc.unavailable" || code === "rpc.method_not_found" ? "unsupported" : code === "rpc.invalid_output" ? "incompatible" : code === "rpc.invalid_input" ? "rejected" : "unavailable");
|
|
472
|
+
}
|
|
473
|
+
function checkedHistory(value, sessionId) {
|
|
474
|
+
if (!isHistoryResult(value) || value.data.series.some((series) => series.sessionId !== sessionId))
|
|
475
|
+
throw new HistoryFailure("incompatible");
|
|
476
|
+
return value;
|
|
477
|
+
}
|
|
478
|
+
function historyStatusLines(input) {
|
|
479
|
+
const messages = {
|
|
480
|
+
unsupported: "History service is unavailable in this server location. Check that the owning server has a plugin version with chart history. Press r to check again.",
|
|
481
|
+
timeout: "History request timed out. Press r to retry.",
|
|
482
|
+
incompatible: "History response is incompatible. Check client/server plugin versions. Press r to retry.",
|
|
483
|
+
rejected: "History request was rejected. Check client/server plugin versions. Press r to retry.",
|
|
484
|
+
unavailable: "History could not be loaded. Press r to retry."
|
|
485
|
+
};
|
|
486
|
+
return [
|
|
487
|
+
...input.status === "loading" ? [
|
|
488
|
+
input.loadedAt === undefined ? "Loading retained history\u2026" : "Updating history \xB7 showing previous results"
|
|
489
|
+
] : input.status === "disabled" ? [
|
|
490
|
+
"History recording is disabled in this server location. Press r to check again after configuration changes."
|
|
491
|
+
] : input.status === "unavailable" ? [messages[input.reason ?? "unavailable"]] : [],
|
|
492
|
+
...input.stale && input.loadedAt !== undefined ? [
|
|
493
|
+
`Showing previous results \xB7 last loaded ${new Date(input.loadedAt).toISOString()}`
|
|
494
|
+
] : []
|
|
495
|
+
];
|
|
496
|
+
}
|
|
497
|
+
var HistoryFailure;
|
|
498
|
+
var init_historyclient = __esm(() => {
|
|
499
|
+
init_rpc();
|
|
500
|
+
HistoryFailure = class HistoryFailure extends Error {
|
|
501
|
+
reason;
|
|
502
|
+
constructor(reason) {
|
|
503
|
+
super(`History ${reason}`);
|
|
504
|
+
this.reason = reason;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
});
|
|
508
|
+
|
|
464
509
|
// src/family.ts
|
|
465
510
|
function metric(snapshot, now, staleMs) {
|
|
466
511
|
const m = snapshot?.measurement;
|
|
@@ -839,6 +884,209 @@ var init_transport = __esm(() => {
|
|
|
839
884
|
init_rpc();
|
|
840
885
|
});
|
|
841
886
|
|
|
887
|
+
// src/tui/quantity.ts
|
|
888
|
+
function tokens(value) {
|
|
889
|
+
if (value === undefined || !Number.isFinite(value))
|
|
890
|
+
return "?";
|
|
891
|
+
const magnitude = Math.abs(value);
|
|
892
|
+
if (magnitude >= 1e6)
|
|
893
|
+
return `${+(value / 1e6).toFixed(1)}M`;
|
|
894
|
+
if (magnitude >= 1000)
|
|
895
|
+
return `${+(value / 1000).toFixed(1)}K`;
|
|
896
|
+
return String(value);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/tui/statusformat.ts
|
|
900
|
+
function freshnessLabel(row2) {
|
|
901
|
+
switch (row2?.freshness) {
|
|
902
|
+
case "fresh":
|
|
903
|
+
return;
|
|
904
|
+
case "stale":
|
|
905
|
+
return "Measurement out of date";
|
|
906
|
+
case "invalid":
|
|
907
|
+
return "Usage unavailable";
|
|
908
|
+
default:
|
|
909
|
+
return "Usage unknown";
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function measurementLabel(row2, ageMs) {
|
|
913
|
+
const m = row2?.snapshot?.measurement;
|
|
914
|
+
if (!m || row2?.freshness === "missing")
|
|
915
|
+
return "Usage unknown";
|
|
916
|
+
if (row2?.freshness === "invalid")
|
|
917
|
+
return "Usage unavailable";
|
|
918
|
+
const age = ageMs === undefined ? "" : ` \xB7 measured ${Math.floor(Math.max(0, ageMs) / 1000)}s ago`;
|
|
919
|
+
return `${m.confidence === "reported" ? "Provider reported" : "Estimated"}${age}${row2?.freshness === "stale" ? " \xB7 out of date" : ""}`;
|
|
920
|
+
}
|
|
921
|
+
function measurementExplanation(row2) {
|
|
922
|
+
const m = row2.snapshot?.measurement;
|
|
923
|
+
if (!m || row2.freshness === "missing")
|
|
924
|
+
return ["No measurement available."];
|
|
925
|
+
if (row2.freshness === "invalid")
|
|
926
|
+
return ["Measurement cannot be used for this session."];
|
|
927
|
+
return [
|
|
928
|
+
m.scope === "completed-request" ? "Usage from the last completed request; not the next request's size." : "Usage for the prepared request; not a completed request.",
|
|
929
|
+
m.provenance === "serialized-estimate" ? "Estimate from serialized request content." : "Provider usage includes input and cache tokens."
|
|
930
|
+
];
|
|
931
|
+
}
|
|
932
|
+
function compactionLabel(row2, compact = false) {
|
|
933
|
+
const phase = row2?.snapshot?.compaction.phase;
|
|
934
|
+
if (!phase || phase === "idle")
|
|
935
|
+
return;
|
|
936
|
+
if (compact)
|
|
937
|
+
return {
|
|
938
|
+
requesting: "Requesting",
|
|
939
|
+
accepted: "Waiting",
|
|
940
|
+
running: "Compacting",
|
|
941
|
+
"awaiting-measurement": "Checking",
|
|
942
|
+
blocked: "Retry held",
|
|
943
|
+
uncertain: "Unconfirmed"
|
|
944
|
+
}[phase];
|
|
945
|
+
return {
|
|
946
|
+
requesting: "Requesting compaction",
|
|
947
|
+
accepted: "Compaction request accepted \xB7 waiting to start",
|
|
948
|
+
running: "Compaction running",
|
|
949
|
+
"awaiting-measurement": "Compaction ended \xB7 checking context reduction",
|
|
950
|
+
blocked: "Automatic compaction retry suppressed",
|
|
951
|
+
uncertain: "Completion unconfirmed \xB7 automatic retry suppressed"
|
|
952
|
+
}[phase];
|
|
953
|
+
}
|
|
954
|
+
function reasonExplanation(reason) {
|
|
955
|
+
switch (reason) {
|
|
956
|
+
case "below-threshold":
|
|
957
|
+
return "Context is below the policy threshold.";
|
|
958
|
+
case "threshold-crossed":
|
|
959
|
+
return "Context reached the policy threshold; this does not guarantee compaction.";
|
|
960
|
+
case "missing-usage":
|
|
961
|
+
return "No measurement available for the policy decision.";
|
|
962
|
+
case "model-changed":
|
|
963
|
+
return "The measurement belongs to a different model.";
|
|
964
|
+
case "invalid-usage":
|
|
965
|
+
return "The measurement cannot be used for the policy decision.";
|
|
966
|
+
case "stale-usage":
|
|
967
|
+
return "The policy measurement is out of date.";
|
|
968
|
+
case "missing-model-budget":
|
|
969
|
+
return "Model capacity is unavailable for this threshold.";
|
|
970
|
+
case "incompatible-model-budget":
|
|
971
|
+
return "The threshold is incompatible with model capacity.";
|
|
972
|
+
case "compaction-failed":
|
|
973
|
+
return "Compaction failed; automatic retries are limited after repeated failures.";
|
|
974
|
+
case "reclaim-unverifiable":
|
|
975
|
+
return "Context reduction could not be verified with comparable provider readings.";
|
|
976
|
+
case "insufficient-reclaim":
|
|
977
|
+
return "Measured context reduction was below the required minimum.";
|
|
978
|
+
case "admission-outcome-unknown":
|
|
979
|
+
return "Whether the compaction request was accepted is unconfirmed.";
|
|
980
|
+
case "completion-event-timeout":
|
|
981
|
+
return "No confirming completion event arrived within the waiting period.";
|
|
982
|
+
case "restart-needs-lifecycle-evidence":
|
|
983
|
+
return "The previous request needs confirming lifecycle evidence after restart.";
|
|
984
|
+
case "event-stream-gap":
|
|
985
|
+
return "Automatic requests are suspended after an event gap; reload required.";
|
|
986
|
+
case "persistence-unavailable":
|
|
987
|
+
return "Safety storage is unavailable; repair storage and reload.";
|
|
988
|
+
case "capacity-exceeded":
|
|
989
|
+
return "Monitoring limit reached; some sessions are unavailable.";
|
|
990
|
+
case "model-metadata-unavailable":
|
|
991
|
+
return "Some model limits are unavailable.";
|
|
992
|
+
default:
|
|
993
|
+
return "See diagnostic codes.";
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function pressureLabel(row2) {
|
|
997
|
+
if (row2?.freshness !== "fresh")
|
|
998
|
+
return "Threshold pressure unknown";
|
|
999
|
+
switch (row2.pressure) {
|
|
1000
|
+
case "crossed":
|
|
1001
|
+
return "Threshold reached";
|
|
1002
|
+
case "near":
|
|
1003
|
+
return "Near threshold";
|
|
1004
|
+
case "normal":
|
|
1005
|
+
return "Below threshold";
|
|
1006
|
+
default:
|
|
1007
|
+
return "Threshold pressure unknown";
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
function thresholdDistance(row2, compact = false) {
|
|
1011
|
+
const delta = row2?.triggerDeltaTokens;
|
|
1012
|
+
if (row2?.freshness !== "fresh" || row2.pressure === "unknown" || delta === undefined || !Number.isFinite(delta))
|
|
1013
|
+
return "pressure unknown";
|
|
1014
|
+
if (delta === 0)
|
|
1015
|
+
return row2.pressure === "crossed" ? "Threshold reached" : "At threshold \xB7 requires more";
|
|
1016
|
+
if (compact)
|
|
1017
|
+
return `${tokens(Math.abs(delta))} ${delta < 0 ? "over" : "below"}${row2.pressure === "near" ? " \xB7 Near threshold" : delta < 0 ? " \xB7 Threshold reached" : ""}`;
|
|
1018
|
+
return `${tokens(Math.abs(delta))} ${Math.abs(delta) === 1 ? "token" : "tokens"} ${delta < 0 ? "over" : "below"} threshold`;
|
|
1019
|
+
}
|
|
1020
|
+
function guardStatusLines(health, compact = false) {
|
|
1021
|
+
switch (health?.enforcement) {
|
|
1022
|
+
case "observing":
|
|
1023
|
+
return compact ? ["Observing", "No Guard compact"] : ["Observing \xB7 Guard won't request compaction"];
|
|
1024
|
+
case "available":
|
|
1025
|
+
return compact ? ["Guard requests", "enabled"] : ["Guard automatic requests enabled"];
|
|
1026
|
+
case "disabled":
|
|
1027
|
+
return ["Guard disabled"];
|
|
1028
|
+
case "suspended": {
|
|
1029
|
+
const gap = health.reasons.includes("event-stream-gap");
|
|
1030
|
+
const storage = health.reasons.includes("persistence-unavailable");
|
|
1031
|
+
return compact ? [
|
|
1032
|
+
"Guard suspended",
|
|
1033
|
+
...storage ? ["Storage: repair"] : [],
|
|
1034
|
+
...gap ? ["Reload required"] : storage ? ["Then reload"] : ["See Details"]
|
|
1035
|
+
] : [
|
|
1036
|
+
"Guard suspended" + (storage ? " \xB7 safety storage unavailable; repair storage and reload" : "") + (gap ? " \xB7 reload required" : storage ? "" : " \xB7 see Details")
|
|
1037
|
+
];
|
|
1038
|
+
}
|
|
1039
|
+
default:
|
|
1040
|
+
return ["Guard status unknown"];
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function panelStatus(health) {
|
|
1044
|
+
return guardStatusLines(health).join(" \xB7 ");
|
|
1045
|
+
}
|
|
1046
|
+
function connectionLabel(connection, compact = false) {
|
|
1047
|
+
switch (connection) {
|
|
1048
|
+
case "loading":
|
|
1049
|
+
return "Connecting";
|
|
1050
|
+
case "live":
|
|
1051
|
+
return "Live";
|
|
1052
|
+
case "reconnecting":
|
|
1053
|
+
return "Reconnecting";
|
|
1054
|
+
case "unavailable":
|
|
1055
|
+
return compact ? "Unavailable" : "Connection unavailable";
|
|
1056
|
+
case "incompatible":
|
|
1057
|
+
return compact ? "Unsupported" : "Monitoring unsupported";
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
function connectionNotice(connection, retainedMeasurements, compact = false) {
|
|
1061
|
+
if (connection === "live")
|
|
1062
|
+
return;
|
|
1063
|
+
return retainedMeasurements ? compact ? "Last data shown" : "Showing last received measurements" : compact ? "No measurements" : "No measurements available";
|
|
1064
|
+
}
|
|
1065
|
+
function monitorStatusLines(connection, health, retainedMeasurements, compact = false) {
|
|
1066
|
+
const notice = connectionNotice(connection, retainedMeasurements, compact);
|
|
1067
|
+
const reasons = health?.reasons ?? [];
|
|
1068
|
+
const limited = reasons.includes("capacity-exceeded");
|
|
1069
|
+
const model = reasons.includes("model-metadata-unavailable");
|
|
1070
|
+
const attention = health?.enforcement !== "suspended" && reasons.length > 0;
|
|
1071
|
+
return [
|
|
1072
|
+
...health && connection !== "live" ? [compact ? "Last known:" : "Last known Guard:"] : [],
|
|
1073
|
+
...guardStatusLines(health, compact),
|
|
1074
|
+
...attention ? compact ? [limited ? "Monitor limit" : model ? "Limits unknown" : "See Details"] : [
|
|
1075
|
+
...limited ? ["Monitoring limit reached \xB7 some sessions unavailable"] : [],
|
|
1076
|
+
...model ? ["Some model limits unavailable \xB7 context may be unknown"] : [],
|
|
1077
|
+
...!limited && !model ? ["Guard needs attention \xB7 see Details"] : []
|
|
1078
|
+
] : [],
|
|
1079
|
+
...notice ? [notice] : []
|
|
1080
|
+
];
|
|
1081
|
+
}
|
|
1082
|
+
var contextHistoryLegend;
|
|
1083
|
+
var init_statusformat = __esm(() => {
|
|
1084
|
+
contextHistoryLegend = [
|
|
1085
|
+
"Recent samples \u2192 now \xB7 \u2504 threshold",
|
|
1086
|
+
"Dim = last known context"
|
|
1087
|
+
];
|
|
1088
|
+
});
|
|
1089
|
+
|
|
842
1090
|
// src/tui/format.ts
|
|
843
1091
|
function quantity(n) {
|
|
844
1092
|
return n === undefined || !Number.isFinite(n) ? "?" : Math.abs(n) >= 1e6 ? `${(n / 1e6).toFixed(1)}m` : Math.abs(n) >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);
|
|
@@ -866,22 +1114,6 @@ function clip(value, width) {
|
|
|
866
1114
|
}
|
|
867
1115
|
return width < 3 ? ".".repeat(Math.max(0, width)) : result + "...";
|
|
868
1116
|
}
|
|
869
|
-
function rowLines(row2, width) {
|
|
870
|
-
const s = row2.snapshot, m = s?.measurement;
|
|
871
|
-
const prefix = row2.current ? "* " : row2.depth > 5 ? ".../" : " ".repeat(Math.min(row2.depth, 5)) + "|-";
|
|
872
|
-
const percent = row2.utilizationPercent === undefined ? "?" : `${row2.utilizationPercent.toFixed(1)}%`;
|
|
873
|
-
const warning = row2.freshness === "stale" ? " STALE" : row2.pressure === "crossed" ? " !! crossed" : row2.pressure === "near" ? " ! near" : "";
|
|
874
|
-
const suffix = ` ${statuses[row2.node.status]} ${m?.confidence === "approximate" ? "~" : ""}${percent}${warning}`;
|
|
875
|
-
const label = clip(`${prefix}${row2.node.agent ?? row2.node.sessionId}`, Math.max(1, width - cells(suffix)));
|
|
876
|
-
return [
|
|
877
|
-
clip(`${label}${suffix}`, width),
|
|
878
|
-
...performanceLines(row2, width),
|
|
879
|
-
...wrap(`${quantity(m?.tokens)}/${quantity(s?.capacityTokens)} input; to ${quantity(row2.triggerDeltaTokens)}`, width),
|
|
880
|
-
...s && s.compaction.phase !== "idle" ? wrap(`compact: ${s.compaction.phase}`, width) : [],
|
|
881
|
-
...row2.node.interrupted ? [clip("interrupted", width)] : [],
|
|
882
|
-
...row2.hidden ? wrap(`+ ${row2.hidden} completed descendants`, width) : []
|
|
883
|
-
];
|
|
884
|
-
}
|
|
885
1117
|
function detailLines(row2, width, expanded = false, ageMs = 0) {
|
|
886
1118
|
const s = row2?.snapshot, m = s?.measurement;
|
|
887
1119
|
if (!row2)
|
|
@@ -892,22 +1124,29 @@ function detailLines(row2, width, expanded = false, ageMs = 0) {
|
|
|
892
1124
|
...wrap("Guard: not monitored / unavailable", width)
|
|
893
1125
|
];
|
|
894
1126
|
const threshold = s.policy.configured;
|
|
895
|
-
const
|
|
1127
|
+
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
896
1128
|
const lines = [
|
|
897
1129
|
`${s.agent ?? "?"} / ${s.model ?? "?"}`,
|
|
1130
|
+
`${row2.freshness === "stale" ? "Last measured" : "Context"} ${valid2 && m?.confidence === "approximate" ? "~" : ""}${quantity(valid2 ? m?.tokens : undefined)} / ${quantity(s.capacityTokens)} input`,
|
|
1131
|
+
`${valid2 ? row2.utilizationPercent?.toFixed(1) ?? "?" : "?"}% capacity \xB7 ${pressureLabel(row2)}`,
|
|
1132
|
+
`Threshold ${quantity(s.policy.triggerTokens)} \xB7 ${thresholdDistance(row2)}`,
|
|
1133
|
+
measurementLabel(row2, ageMs),
|
|
1134
|
+
...measurementExplanation(row2),
|
|
1135
|
+
compactionLabel(row2) ?? "No compaction request in progress.",
|
|
1136
|
+
...s.compaction.blockedReason ? [reasonExplanation(s.compaction.blockedReason)] : [],
|
|
1137
|
+
`Recorded policy decision: ${reasonExplanation(s.policy.reason)}`,
|
|
898
1138
|
...performanceLines(row2, width),
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
m ? `${Math.floor(Math.max(0, ageMs) / 1000)}s ago; ${row2.freshness}` : ""
|
|
1139
|
+
...s.performance ? [
|
|
1140
|
+
"TPS: tokens per second. TTFT: time to first output (text or reasoning); approximate.",
|
|
1141
|
+
"Live TPS is estimated; completed rates use provider output including reasoning and matched timing.",
|
|
1142
|
+
"Model average uses matched request durations; session average includes idle and tool time.",
|
|
1143
|
+
...s.performance.partial ? [
|
|
1144
|
+
"Incomplete timing coverage for model averages; only matched observed durations are included."
|
|
1145
|
+
] : []
|
|
1146
|
+
] : []
|
|
908
1147
|
];
|
|
909
1148
|
if (expanded)
|
|
910
|
-
lines.push(`Policy ${s.policy.id}: ${s.policy.reason}`, `Limits in/context/out ${quantity(s.limits?.input)}/${quantity(s.limits?.context)}/${quantity(s.limits?.output)}`, `Output reserve ${quantity(s.outputReserveTokens)}`, `Provenance ${m?.provenance ?? "?"}`, `Cooldown until ${s.compaction.cooldownUntil ?? "?"}`, `Cumulative (${s.cumulativeScope})`, `Input ${quantity(s.cumulative?.input)} output ${quantity(s.cumulative?.output)}`, `Reasoning ${quantity(s.cumulative?.reasoning)}`, `Cache read ${quantity(s.cumulative?.cache.read)} write ${quantity(s.cumulative?.cache.write)}`);
|
|
1149
|
+
lines.push("Diagnostic codes and accounting:", `Compaction phase: ${s.compaction.phase}`, `Armed: ${s.compaction.armed} (one eligibility condition, not permission to compact)`, `Blocked reason: ${s.compaction.blockedReason ?? "?"}`, `Measurement confidence: ${m?.confidence ?? "?"}`, `Measurement scope: ${m?.scope ?? "?"}`, `Measurement freshness: ${row2.freshness}`, `Trigger ${threshold.type === "ratio" ? `${threshold.value * 100}%` : `${threshold.value} ${threshold.type}`} (${s.policy.comparison})`, `Resolved trigger ${s.policy.triggerTokens ?? "?"}`, `Policy ${s.policy.id}: ${s.policy.reason}`, `Pressure code: ${row2.pressure}`, `Recorded tokens: ${quantity(m?.tokens)}`, `Limits in/context/out ${quantity(s.limits?.input)}/${quantity(s.limits?.context)}/${quantity(s.limits?.output)}`, `Output reserve ${quantity(s.outputReserveTokens)}`, `Provenance ${m?.provenance ?? "?"}`, `Cooldown until ${s.compaction.cooldownUntil ?? "?"}`, `Cumulative (${s.cumulativeScope})`, `Input ${quantity(s.cumulative?.input)} output ${quantity(s.cumulative?.output)}`, `Reasoning ${quantity(s.cumulative?.reasoning)}`, `Cache read ${quantity(s.cumulative?.cache.read)} write ${quantity(s.cumulative?.cache.write)}`);
|
|
911
1150
|
return lines.filter(Boolean).flatMap((line) => wrap(line, width));
|
|
912
1151
|
}
|
|
913
1152
|
function sanitize(value) {
|
|
@@ -944,15 +1183,86 @@ function performanceLines(row2, width) {
|
|
|
944
1183
|
...wrap(`TTFT ${p.ttftMs === undefined ? "?" : `~${(p.ttftMs / 1000).toFixed(2)}s`}${p.latestRequestTps === undefined ? "" : ` \xB7 Last ${value(p.latestRequestTps)} t/s`}`, width)
|
|
945
1184
|
];
|
|
946
1185
|
}
|
|
947
|
-
var segmenter
|
|
1186
|
+
var segmenter;
|
|
948
1187
|
var init_format = __esm(() => {
|
|
1188
|
+
init_statusformat();
|
|
949
1189
|
segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
950
|
-
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
// src/tui/panelformat.ts
|
|
1193
|
+
function panelSummary(row2, width, age, compact = false) {
|
|
1194
|
+
if (!row2)
|
|
1195
|
+
return [clip("No sessions available \xB7 r refresh", width)];
|
|
1196
|
+
const snapshot = row2.snapshot;
|
|
1197
|
+
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
1198
|
+
const prefix = row2.freshness === "stale" ? "Last measured" : "Context";
|
|
1199
|
+
const percent = `${row2.utilizationPercent === undefined ? "?" : Math.round(row2.utilizationPercent)}%`;
|
|
1200
|
+
const estimate = valid2 && snapshot?.measurement?.confidence === "approximate" ? "~" : "";
|
|
1201
|
+
const identity = `${width < 28 ? ">" : "Selected:"} ${row2.node.agent ?? row2.node.sessionId}${row2.current ? width < 28 ? " *" : " (current)" : ""}`;
|
|
1202
|
+
const threshold = `Threshold ${tokens(snapshot?.policy.triggerTokens)} \xB7 ${thresholdDistance(row2)}`;
|
|
1203
|
+
const occupancy = compact ? `${prefix} ${estimate}${percent}` : `${prefix} ${estimate}${tokens(valid2 ? snapshot?.measurement?.tokens : undefined)}/${tokens(snapshot?.capacityTokens)} \xB7 ${percent}`;
|
|
1204
|
+
return [
|
|
1205
|
+
clip(identity, width),
|
|
1206
|
+
clip(occupancy, width),
|
|
1207
|
+
...!compact ? [
|
|
1208
|
+
clip(cells(threshold) <= width ? threshold : thresholdDistance(row2), width),
|
|
1209
|
+
clip(`${row2.node.model ?? snapshot?.model ?? "Model unknown"} \xB7 ${panelStatuses[row2.node.status]}`, width),
|
|
1210
|
+
...wrap(measurementLabel(row2, age), width)
|
|
1211
|
+
] : []
|
|
1212
|
+
];
|
|
1213
|
+
}
|
|
1214
|
+
function tableLine(identity, status, context, threshold, width) {
|
|
1215
|
+
const pad = (value, size) => {
|
|
1216
|
+
const text2 = clip(value, size);
|
|
1217
|
+
return text2 + " ".repeat(Math.max(0, size - cells(text2)));
|
|
1218
|
+
};
|
|
1219
|
+
return `${pad(identity, width - 47)} ${pad(status, 8)} ${pad(context, 7)} ${pad(threshold, 29)}`;
|
|
1220
|
+
}
|
|
1221
|
+
function panelRowHeading(label, width) {
|
|
1222
|
+
return width >= 72 ? tableLine(label, "State", "Context", "Threshold", width) : clip(label, width);
|
|
1223
|
+
}
|
|
1224
|
+
function panelRowLines(row2, width, selected) {
|
|
1225
|
+
const marker = `${selected ? ">" : " "}${row2.current ? "*" : " "}`;
|
|
1226
|
+
const indent = " ".repeat(Math.min(row2.depth, Math.floor(width / 24))) + (row2.depth ? "\u2514 " : "");
|
|
1227
|
+
const identity = `${marker} ${indent}${row2.node.agent ?? row2.node.sessionId}`;
|
|
1228
|
+
const percent = `${(row2.freshness === "fresh" || row2.freshness === "stale") && row2.snapshot?.measurement?.confidence === "approximate" ? "~" : ""}${row2.utilizationPercent === undefined ? "?" : Math.round(row2.utilizationPercent)}%`;
|
|
1229
|
+
const status = width < 28 ? {
|
|
951
1230
|
running: "RUN",
|
|
952
1231
|
idle: "IDLE",
|
|
953
1232
|
completed: "DONE",
|
|
954
1233
|
failed: "FAIL",
|
|
955
1234
|
unknown: "?"
|
|
1235
|
+
}[row2.node.status] : panelStatuses[row2.node.status];
|
|
1236
|
+
const distance = thresholdDistance(row2, true);
|
|
1237
|
+
const pad = (value, size) => {
|
|
1238
|
+
const text2 = clip(value, size);
|
|
1239
|
+
return text2 + " ".repeat(Math.max(0, size - cells(text2)));
|
|
1240
|
+
};
|
|
1241
|
+
const lines = width >= 72 ? [tableLine(identity, status, percent, distance, width)] : [
|
|
1242
|
+
`${pad(identity, Math.max(1, width - status.length - 1))} ${status}`,
|
|
1243
|
+
clip(`${percent} context \xB7 ${distance}`, width)
|
|
1244
|
+
];
|
|
1245
|
+
const exception = [
|
|
1246
|
+
freshnessLabel(row2),
|
|
1247
|
+
compactionLabel(row2),
|
|
1248
|
+
row2.node.interrupted ? "interrupted" : "",
|
|
1249
|
+
row2.hidden ? `+${row2.hidden} hidden \xB7 Space expands` : ""
|
|
1250
|
+
].filter(Boolean).join(" \xB7 ");
|
|
1251
|
+
if (exception)
|
|
1252
|
+
lines.push(...wrap(exception, width));
|
|
1253
|
+
return lines.map((line) => clip(line, width));
|
|
1254
|
+
}
|
|
1255
|
+
var panelStatuses;
|
|
1256
|
+
var init_panelformat = __esm(() => {
|
|
1257
|
+
init_format();
|
|
1258
|
+
init_statusformat();
|
|
1259
|
+
init_statusformat();
|
|
1260
|
+
panelStatuses = {
|
|
1261
|
+
running: "RUNNING",
|
|
1262
|
+
idle: "IDLE",
|
|
1263
|
+
completed: "DONE",
|
|
1264
|
+
failed: "FAILED",
|
|
1265
|
+
unknown: "UNKNOWN"
|
|
956
1266
|
};
|
|
957
1267
|
});
|
|
958
1268
|
|
|
@@ -1067,15 +1377,15 @@ var init_chartformat = __esm(() => {
|
|
|
1067
1377
|
|
|
1068
1378
|
// src/tui.tsx
|
|
1069
1379
|
import { effect as _$effect5 } from "@opentui/solid";
|
|
1070
|
-
import {
|
|
1071
|
-
import { insertNode as _$insertNode5 } from "@opentui/solid";
|
|
1380
|
+
import { insert as _$insert5 } from "@opentui/solid";
|
|
1072
1381
|
import { setProp as _$setProp5 } from "@opentui/solid";
|
|
1073
1382
|
import { createElement as _$createElement5 } from "@opentui/solid";
|
|
1074
|
-
import { createComponent as _$
|
|
1383
|
+
import { createComponent as _$createComponent6 } from "@opentui/solid";
|
|
1075
1384
|
import { Plugin } from "@opencode/plugin/tui";
|
|
1076
1385
|
import { Show as Show4 } from "solid-js";
|
|
1077
1386
|
|
|
1078
1387
|
// src/tui/state.ts
|
|
1388
|
+
init_historyclient();
|
|
1079
1389
|
init_rpc();
|
|
1080
1390
|
import { createSignal } from "solid-js";
|
|
1081
1391
|
|
|
@@ -1214,6 +1524,21 @@ function contextChart(samples, capacity, trigger, width, now) {
|
|
|
1214
1524
|
init_transport();
|
|
1215
1525
|
|
|
1216
1526
|
// src/tui/inventory.ts
|
|
1527
|
+
function inventoryStatus(inventory, limit, scanning, failed) {
|
|
1528
|
+
const discovered = inventory?.sessions.size ?? 0;
|
|
1529
|
+
const pending = inventory?.pending.length ?? 0;
|
|
1530
|
+
return {
|
|
1531
|
+
discovered,
|
|
1532
|
+
limit,
|
|
1533
|
+
scanning,
|
|
1534
|
+
failed,
|
|
1535
|
+
damaged: inventory?.damaged ?? false,
|
|
1536
|
+
pending,
|
|
1537
|
+
pages: inventory?.pages ?? 0,
|
|
1538
|
+
complete: !failed && (inventory?.complete ?? false),
|
|
1539
|
+
canLoadMore: !scanning && pending > 0 && discovered < 2048
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1217
1542
|
async function discoverFamily(client, currentId, signal, cached, maxNodes = 1024, previous) {
|
|
1218
1543
|
const sessions = new Map(previous?.sessions);
|
|
1219
1544
|
let damaged = previous?.damaged ?? false, pages = 0, rootId = previous?.rootId ?? currentId;
|
|
@@ -1367,7 +1692,7 @@ function createGuardState(context) {
|
|
|
1367
1692
|
inventory = undefined;
|
|
1368
1693
|
evidence.clear();
|
|
1369
1694
|
maxNodes = 1024;
|
|
1370
|
-
|
|
1695
|
+
scanFailed = false;
|
|
1371
1696
|
notify();
|
|
1372
1697
|
scan();
|
|
1373
1698
|
}
|
|
@@ -1382,6 +1707,7 @@ function createGuardState(context) {
|
|
|
1382
1707
|
controller.signal,
|
|
1383
1708
|
AbortSignal.timeout(15000)
|
|
1384
1709
|
]);
|
|
1710
|
+
notify();
|
|
1385
1711
|
try {
|
|
1386
1712
|
const next = await discoverFamily(context.client, currentId, signal, (id) => context.data.session.get(id), maxNodes, more ? inventory : undefined);
|
|
1387
1713
|
if (signal.aborted || generation !== scanGeneration)
|
|
@@ -1442,8 +1768,10 @@ function createGuardState(context) {
|
|
|
1442
1768
|
notify();
|
|
1443
1769
|
}
|
|
1444
1770
|
} finally {
|
|
1445
|
-
if (generation === scanGeneration)
|
|
1771
|
+
if (generation === scanGeneration) {
|
|
1446
1772
|
scanning = false;
|
|
1773
|
+
notify();
|
|
1774
|
+
}
|
|
1447
1775
|
}
|
|
1448
1776
|
}
|
|
1449
1777
|
function acquire(id) {
|
|
@@ -1555,14 +1883,20 @@ function createGuardState(context) {
|
|
|
1555
1883
|
return {
|
|
1556
1884
|
version,
|
|
1557
1885
|
acquire,
|
|
1558
|
-
|
|
1886
|
+
historyLocation(id) {
|
|
1887
|
+
version();
|
|
1559
1888
|
const info = inventory?.sessions.get(id);
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1889
|
+
return info ? locationKey(info.location) : "unknown";
|
|
1890
|
+
},
|
|
1891
|
+
async history(id, from, to, signal) {
|
|
1892
|
+
try {
|
|
1893
|
+
const info = inventory?.sessions.get(id);
|
|
1894
|
+
if (!info)
|
|
1895
|
+
throw new Error("Session location unavailable");
|
|
1896
|
+
return checkedHistory(await context.client.rpc(historyRpc).read({ schemaVersion: 1, sessionId: id, from, to, maxPoints: 240 }, { location: info.location, signal }), id);
|
|
1897
|
+
} catch (error) {
|
|
1898
|
+
throw historyFailure(error, signal);
|
|
1899
|
+
}
|
|
1566
1900
|
},
|
|
1567
1901
|
rows,
|
|
1568
1902
|
contextTrace: (row2) => contextTraces.update(row2),
|
|
@@ -1586,7 +1920,11 @@ function createGuardState(context) {
|
|
|
1586
1920
|
},
|
|
1587
1921
|
complete() {
|
|
1588
1922
|
version();
|
|
1589
|
-
return inventory?.complete ?? false;
|
|
1923
|
+
return !scanFailed && (inventory?.complete ?? false);
|
|
1924
|
+
},
|
|
1925
|
+
inventoryStatus() {
|
|
1926
|
+
version();
|
|
1927
|
+
return inventoryStatus(inventory, maxNodes, scanning, scanFailed);
|
|
1590
1928
|
},
|
|
1591
1929
|
refresh() {
|
|
1592
1930
|
scan();
|
|
@@ -1594,6 +1932,8 @@ function createGuardState(context) {
|
|
|
1594
1932
|
c.refresh();
|
|
1595
1933
|
},
|
|
1596
1934
|
loadMore() {
|
|
1935
|
+
if (!inventoryStatus(inventory, maxNodes, scanning, scanFailed).canLoadMore)
|
|
1936
|
+
return;
|
|
1597
1937
|
maxNodes = Math.min(2048, maxNodes + 1024);
|
|
1598
1938
|
scan(true);
|
|
1599
1939
|
},
|
|
@@ -1620,19 +1960,12 @@ function sameLocation(a, b) {
|
|
|
1620
1960
|
}
|
|
1621
1961
|
|
|
1622
1962
|
// src/tui/sidebar.tsx
|
|
1623
|
-
init_format();
|
|
1624
|
-
import { effect as _$effect2 } from "@opentui/solid";
|
|
1625
1963
|
import { createComponent as _$createComponent2 } from "@opentui/solid";
|
|
1626
|
-
import {
|
|
1627
|
-
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
1628
|
-
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
1629
|
-
import { memo as _$memo2 } from "@opentui/solid";
|
|
1630
|
-
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
1631
|
-
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
1632
|
-
import { For as For2, createEffect as createEffect2, createMemo as createMemo2, onCleanup, Show as Show2 } from "solid-js";
|
|
1964
|
+
import { createEffect as createEffect2, createMemo as createMemo2, onCleanup } from "solid-js";
|
|
1633
1965
|
|
|
1634
1966
|
// src/tui/compact.tsx
|
|
1635
1967
|
init_format();
|
|
1968
|
+
init_statusformat();
|
|
1636
1969
|
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
1637
1970
|
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
1638
1971
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
@@ -1645,16 +1978,8 @@ import { For, Index, Show, createEffect, createMemo, createSignal as createSigna
|
|
|
1645
1978
|
|
|
1646
1979
|
// src/tui/compactformat.ts
|
|
1647
1980
|
init_format();
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
return "?";
|
|
1651
|
-
const magnitude = Math.abs(value);
|
|
1652
|
-
if (magnitude >= 1e6)
|
|
1653
|
-
return `${+(value / 1e6).toFixed(1)}M`;
|
|
1654
|
-
if (magnitude >= 1000)
|
|
1655
|
-
return `${+(value / 1000).toFixed(1)}K`;
|
|
1656
|
-
return String(value);
|
|
1657
|
-
}
|
|
1981
|
+
init_panelformat();
|
|
1982
|
+
init_statusformat();
|
|
1658
1983
|
function columns(left, right, width) {
|
|
1659
1984
|
if (cells(left) + cells(right) + 1 > width)
|
|
1660
1985
|
return [...wrap(left, width), ...wrap(right, width)];
|
|
@@ -1667,73 +1992,64 @@ function progress(ratio, width) {
|
|
|
1667
1992
|
const filled = valid2 ? Math.round(Math.min(1, ratio) * size) : 0;
|
|
1668
1993
|
return clip("\u2588".repeat(filled) + "\u2591".repeat(size - filled) + " " + label, width);
|
|
1669
1994
|
}
|
|
1670
|
-
function mainSections(row2, width, age
|
|
1995
|
+
function mainSections(row2, width, age) {
|
|
1671
1996
|
if (!row2)
|
|
1672
1997
|
return [{ tone: "base", lines: wrap("Loading session family...", width) }];
|
|
1673
1998
|
const s = row2.snapshot, m = s?.measurement;
|
|
1674
1999
|
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
1675
2000
|
const measured = valid2 ? m?.tokens : undefined;
|
|
1676
|
-
const ratio =
|
|
1677
|
-
const
|
|
2001
|
+
const ratio = measured !== undefined && s?.capacityTokens !== undefined && s.capacityTokens > 0 ? measured / s.capacityTokens : undefined;
|
|
2002
|
+
const lifecycle = compactionLabel(row2);
|
|
1678
2003
|
return [
|
|
1679
|
-
...row2.snapshot?.performance ? [{ tone: "base", lines: performanceLines(row2, width) }] : [],
|
|
1680
2004
|
{
|
|
1681
2005
|
tone: "execution",
|
|
1682
2006
|
lines: columns(`${row2.node.agent ?? s?.agent ?? "Main"} \xB7 ${row2.node.model ?? s?.model ?? "?"}`, row2.node.status.toUpperCase(), width)
|
|
1683
2007
|
},
|
|
1684
2008
|
{
|
|
1685
2009
|
tone: "base",
|
|
1686
|
-
lines:
|
|
1687
|
-
"",
|
|
1688
|
-
...columns("Context", `${tokens(measured)} / ${tokens(s?.capacityTokens)}`, width)
|
|
1689
|
-
]
|
|
1690
|
-
},
|
|
1691
|
-
...contextChart(samples ?? (m && valid2 ? [{ at: m.at, tokens: m.tokens }] : []), s?.capacityTokens ?? chartCapacity, s?.policy.triggerTokens, width, m ? m.at + age : s?.observedAt === undefined ? undefined : s.observedAt + age).map(({ line, threshold, segments }) => ({
|
|
1692
|
-
tone: threshold ? "threshold" : "pressure",
|
|
1693
|
-
lines: [line],
|
|
1694
|
-
...segments ? { segments } : {}
|
|
1695
|
-
})),
|
|
1696
|
-
...samples?.some((sample) => sample.held) || m && age > 2500 ? [
|
|
1697
|
-
{
|
|
1698
|
-
tone: "measurement",
|
|
1699
|
-
lines: wrap("muted held \xB7 last known context", width)
|
|
1700
|
-
}
|
|
1701
|
-
] : [],
|
|
1702
|
-
{
|
|
1703
|
-
tone: "base",
|
|
1704
|
-
lines: wrap(`${ratio(s?.capacityTokens) === undefined ? "?" : Math.round((ratio(s?.capacityTokens) ?? 0) * 100)}% used \xB7 recent samples \u2192 now`, width)
|
|
1705
|
-
},
|
|
1706
|
-
{
|
|
1707
|
-
tone: "base",
|
|
1708
|
-
lines: [
|
|
1709
|
-
"",
|
|
1710
|
-
...columns("Compact threshold", `${tokens(measured)} / ${tokens(s?.policy.triggerTokens)}`, width)
|
|
1711
|
-
]
|
|
2010
|
+
lines: columns(row2.freshness === "stale" ? "Last measured" : "Context", `${m?.confidence === "approximate" && valid2 ? "~" : ""}${tokens(measured)} / ${tokens(s?.capacityTokens)}`, width)
|
|
1712
2011
|
},
|
|
2012
|
+
{ tone: "measurement", lines: [progress(ratio, width)] },
|
|
1713
2013
|
{
|
|
1714
2014
|
tone: "pressure",
|
|
1715
2015
|
lines: [
|
|
1716
|
-
...wrap(
|
|
1717
|
-
...
|
|
1718
|
-
...
|
|
2016
|
+
...wrap(thresholdDistance(row2), width),
|
|
2017
|
+
...["near", "crossed"].includes(row2.pressure) && row2.freshness === "fresh" ? wrap(pressureLabel(row2), width) : [],
|
|
2018
|
+
...s?.capacityTokens !== undefined && s.policy.triggerTokens !== undefined && s.policy.triggerTokens > s.capacityTokens ? wrap("Threshold above capacity", width) : []
|
|
1719
2019
|
]
|
|
1720
2020
|
},
|
|
1721
2021
|
{
|
|
1722
2022
|
tone: "measurement",
|
|
1723
|
-
lines:
|
|
1724
|
-
"",
|
|
1725
|
-
...wrap(`Measurement: ${m?.confidence ?? "unknown"}${m ? ` \xB7 ${Math.floor(Math.max(0, age) / 1000)}s ago` : ""}${row2.freshness !== "fresh" ? ` \xB7 ${row2.freshness.toUpperCase()}` : ""}`, width)
|
|
1726
|
-
]
|
|
2023
|
+
lines: wrap(measurementLabel(row2, age), width)
|
|
1727
2024
|
},
|
|
1728
2025
|
{
|
|
1729
2026
|
tone: "base",
|
|
1730
2027
|
lines: [
|
|
1731
|
-
...
|
|
2028
|
+
...lifecycle ? wrap(lifecycle, width) : [],
|
|
2029
|
+
...row2.node.interrupted ? wrap("Interrupted", width) : [],
|
|
1732
2030
|
...!s ? wrap("Guard: not monitored / unavailable", width) : []
|
|
1733
2031
|
]
|
|
1734
2032
|
}
|
|
1735
2033
|
];
|
|
1736
2034
|
}
|
|
2035
|
+
function historySections(row2, width, age, samples, chartCapacity) {
|
|
2036
|
+
const s = row2?.snapshot, m = s?.measurement;
|
|
2037
|
+
return [
|
|
2038
|
+
...contextChart(samples, s?.capacityTokens ?? chartCapacity, s?.policy.triggerTokens, width, m ? m.at + age : s ? s.observedAt + age : undefined).map(({ line, threshold, segments }) => ({
|
|
2039
|
+
tone: threshold ? "threshold" : "measurement",
|
|
2040
|
+
lines: [line],
|
|
2041
|
+
...segments ? { segments } : {}
|
|
2042
|
+
})),
|
|
2043
|
+
{
|
|
2044
|
+
tone: "measurement",
|
|
2045
|
+
lines: contextHistoryLegend.flatMap((line) => wrap(line, width))
|
|
2046
|
+
},
|
|
2047
|
+
{
|
|
2048
|
+
tone: "pressure",
|
|
2049
|
+
lines: wrap(`Policy threshold ${tokens(s?.policy.triggerTokens)} \xB7 ${row2?.freshness === "fresh" && row2.pressureRatio !== undefined ? Math.round(row2.pressureRatio * 100) : "?"}% of threshold`, width)
|
|
2050
|
+
}
|
|
2051
|
+
];
|
|
2052
|
+
}
|
|
1737
2053
|
var statusSymbol = {
|
|
1738
2054
|
running: "\u25CF",
|
|
1739
2055
|
idle: "\u25CC",
|
|
@@ -1742,27 +2058,32 @@ var statusSymbol = {
|
|
|
1742
2058
|
failed: "\u2715"
|
|
1743
2059
|
};
|
|
1744
2060
|
function agentHeading(row2, width) {
|
|
1745
|
-
|
|
1746
|
-
const percent = row2.utilizationPercent === undefined ? "?%" : `${Math.round(row2.utilizationPercent)}%`;
|
|
1747
|
-
return cells(name) + cells(percent) + 1 <= width ? columns(name, percent, width)[0] ?? "" : clip(name, width);
|
|
2061
|
+
return clip(`${statusSymbol[row2.node.status]} ${row2.node.agent ?? row2.node.sessionId}`, width);
|
|
1748
2062
|
}
|
|
1749
2063
|
function agentLines(row2, width) {
|
|
1750
2064
|
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
1751
|
-
const
|
|
1752
|
-
const
|
|
1753
|
-
const
|
|
2065
|
+
const percent = valid2 && row2.utilizationPercent !== undefined ? `${Math.round(row2.utilizationPercent)}%` : "?%";
|
|
2066
|
+
const estimate = valid2 && row2.snapshot?.measurement?.confidence === "approximate" ? "~" : "";
|
|
2067
|
+
const context = `${row2.freshness === "stale" ? "Last measured" : "Context"} ${estimate}${percent}`;
|
|
2068
|
+
const pressure = pressureLabel(row2);
|
|
2069
|
+
const full = `${context} \xB7 ${pressure}`;
|
|
2070
|
+
const short = `${row2.freshness === "stale" ? "Last measured" : "Ctx"} ${estimate}${percent} \xB7 ${pressure === "Below threshold" ? "Threshold below" : pressure}`;
|
|
2071
|
+
const lifecycle = compactionLabel(row2);
|
|
1754
2072
|
return [
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
...
|
|
1758
|
-
...
|
|
1759
|
-
...row2.
|
|
2073
|
+
progress(valid2 && row2.utilizationPercent !== undefined ? row2.utilizationPercent / 100 : undefined, width),
|
|
2074
|
+
...wrap(cells(full) <= width ? full : short, width),
|
|
2075
|
+
...row2.node.status === "failed" || row2.node.status === "unknown" ? wrap(row2.node.status.toUpperCase(), width) : [],
|
|
2076
|
+
...row2.freshness !== "fresh" ? wrap(freshnessLabel(row2) ?? "", width) : [],
|
|
2077
|
+
...row2.node.interrupted ? wrap("Interrupted", width) : [],
|
|
2078
|
+
...lifecycle ? wrap(lifecycle, width) : []
|
|
1760
2079
|
];
|
|
1761
2080
|
}
|
|
1762
|
-
function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure) {
|
|
2081
|
+
function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure, trustworthy = true) {
|
|
1763
2082
|
const children = new Map;
|
|
1764
|
-
|
|
1765
|
-
|
|
2083
|
+
const unique = new Map(rows.map((row2) => [row2.node.sessionId, row2]));
|
|
2084
|
+
let complete = unique.size <= 2048;
|
|
2085
|
+
for (const row2 of [...unique.values()].slice(0, 2048)) {
|
|
2086
|
+
if (!row2.node.parentId)
|
|
1766
2087
|
continue;
|
|
1767
2088
|
const list = children.get(row2.node.parentId) ?? [];
|
|
1768
2089
|
list.push(row2);
|
|
@@ -1771,41 +2092,79 @@ function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure) {
|
|
|
1771
2092
|
const seen = new Set([sessionID]);
|
|
1772
2093
|
const all = [];
|
|
1773
2094
|
const build = (id, depth) => {
|
|
1774
|
-
if (depth > 64)
|
|
1775
|
-
|
|
2095
|
+
if (depth > 64) {
|
|
2096
|
+
const safe2 = !children.get(id)?.length;
|
|
2097
|
+
if (!safe2)
|
|
2098
|
+
complete = false;
|
|
2099
|
+
return { branches: [], safe: safe2 };
|
|
2100
|
+
}
|
|
2101
|
+
let safe = true;
|
|
1776
2102
|
const branches2 = [];
|
|
1777
2103
|
for (const row2 of children.get(id) ?? []) {
|
|
1778
|
-
if (seen.has(row2.node.sessionId))
|
|
2104
|
+
if (seen.has(row2.node.sessionId)) {
|
|
2105
|
+
safe = false;
|
|
2106
|
+
complete = false;
|
|
1779
2107
|
continue;
|
|
2108
|
+
}
|
|
1780
2109
|
seen.add(row2.node.sessionId);
|
|
1781
2110
|
all.push(row2);
|
|
1782
2111
|
const nested = build(row2.node.sessionId, depth + 1);
|
|
1783
|
-
|
|
1784
|
-
|
|
2112
|
+
const branchSafe = nested.safe && row2.hidden === 0;
|
|
2113
|
+
safe &&= branchSafe;
|
|
2114
|
+
complete &&= branchSafe;
|
|
2115
|
+
const eligible = trustworthy && unique.size <= 2048 && branchSafe && row2.node.status === "completed" && row2.freshness === "fresh" && row2.pressure === "normal" && row2.snapshot?.compaction.phase === "idle" && !row2.node.interrupted && nested.branches.every((b) => b.eligible);
|
|
1785
2116
|
branches2.push({
|
|
1786
2117
|
row: row2,
|
|
1787
|
-
children: nested,
|
|
1788
|
-
|
|
1789
|
-
|
|
2118
|
+
children: nested.branches,
|
|
2119
|
+
eligible,
|
|
2120
|
+
active: row2.node.status === "running" || nested.branches.some((b) => b.active),
|
|
2121
|
+
pressure: Math.max(row2.pressureRatio ?? -1, ...nested.branches.map((b) => b.pressure)),
|
|
2122
|
+
size: 1 + nested.branches.reduce((sum, b) => sum + b.size, 0),
|
|
2123
|
+
attention: !eligible || nested.branches.some((b) => b.attention)
|
|
1790
2124
|
});
|
|
1791
2125
|
}
|
|
1792
|
-
return
|
|
2126
|
+
return {
|
|
2127
|
+
safe,
|
|
2128
|
+
branches: branches2.sort((a, b) => Number(b.active) - Number(a.active) || (byPressure ? b.pressure - a.pressure : 0))
|
|
2129
|
+
};
|
|
1793
2130
|
};
|
|
1794
|
-
const branches = build(sessionID, 0);
|
|
2131
|
+
const { branches } = build(sessionID, 0);
|
|
1795
2132
|
const visible = [];
|
|
2133
|
+
let grouped = 0;
|
|
2134
|
+
const count2 = (items) => {
|
|
2135
|
+
for (const item of items) {
|
|
2136
|
+
if (item.eligible)
|
|
2137
|
+
grouped++;
|
|
2138
|
+
count2(item.children);
|
|
2139
|
+
}
|
|
2140
|
+
};
|
|
2141
|
+
count2(branches);
|
|
1796
2142
|
const visit = (items, depth) => {
|
|
1797
2143
|
for (const item of items) {
|
|
2144
|
+
if (hideCompleted && item.eligible)
|
|
2145
|
+
continue;
|
|
2146
|
+
const folded = collapsed.has(item.row.node.sessionId);
|
|
1798
2147
|
visible.push({
|
|
1799
2148
|
row: item.row,
|
|
1800
2149
|
depth,
|
|
1801
|
-
hasChildren: !!item.children.length
|
|
2150
|
+
hasChildren: !!item.children.length,
|
|
2151
|
+
hidden: folded ? item.size - 1 : 0,
|
|
2152
|
+
attention: folded && item.children.some((b) => b.attention)
|
|
1802
2153
|
});
|
|
1803
|
-
if (!
|
|
2154
|
+
if (!folded)
|
|
1804
2155
|
visit(item.children, depth + 1);
|
|
1805
2156
|
}
|
|
1806
2157
|
};
|
|
1807
2158
|
visit(branches, 0);
|
|
1808
|
-
return { all, visible };
|
|
2159
|
+
return { all, visible, grouped, complete };
|
|
2160
|
+
}
|
|
2161
|
+
function routeFamily(rows, sessionID) {
|
|
2162
|
+
const tree = subagentTree(rows, sessionID, new Set, false, false, false);
|
|
2163
|
+
const root = rows.find((row2) => row2.node.sessionId === sessionID);
|
|
2164
|
+
return {
|
|
2165
|
+
rows: [...root ? [root] : [], ...tree.all],
|
|
2166
|
+
complete: !!root && root.hidden === 0 && tree.complete
|
|
2167
|
+
};
|
|
1809
2168
|
}
|
|
1810
2169
|
function statistics(rows, sessionID, complete, width) {
|
|
1811
2170
|
const sum = (value) => {
|
|
@@ -1825,15 +2184,19 @@ function CompactSidebar(props) {
|
|
|
1825
2184
|
const [measuredWidth, setMeasuredWidth] = createSignal2(props.width);
|
|
1826
2185
|
const width = () => Math.max(1, Math.min(props.width, measuredWidth()) - 4);
|
|
1827
2186
|
const [collapsed, setCollapsed] = createSignal2(new Set);
|
|
1828
|
-
const [hideCompleted, setHideCompleted] = createSignal2(
|
|
2187
|
+
const [hideCompleted, setHideCompleted] = createSignal2(true);
|
|
2188
|
+
const [showHistory, setShowHistory] = createSignal2(true);
|
|
1829
2189
|
const [byPressure, setByPressure] = createSignal2(true);
|
|
1830
2190
|
createEffect(() => {
|
|
1831
2191
|
props.sessionID;
|
|
1832
2192
|
setCollapsed(new Set);
|
|
2193
|
+
setShowHistory(true);
|
|
1833
2194
|
});
|
|
1834
2195
|
const current = createMemo(() => props.rows.find((r) => r.node.sessionId === props.sessionID));
|
|
1835
2196
|
const trace = createMemo(() => props.state.contextTrace(current()));
|
|
1836
|
-
const
|
|
2197
|
+
const inventory = createMemo(() => props.state.inventoryStatus());
|
|
2198
|
+
const trustworthy = () => inventory().complete && !inventory().scanning && !inventory().failed && !inventory().damaged;
|
|
2199
|
+
const tree = createMemo(() => subagentTree(props.rows, props.sessionID, collapsed(), hideCompleted(), byPressure(), trustworthy()));
|
|
1837
2200
|
const entries = createMemo(() => new Map(tree().visible.map((entry) => [entry.row.node.sessionId, entry])));
|
|
1838
2201
|
const toggle = (id) => setCollapsed((previous) => {
|
|
1839
2202
|
const next = new Set(previous);
|
|
@@ -1844,13 +2207,21 @@ function CompactSidebar(props) {
|
|
|
1844
2207
|
return next;
|
|
1845
2208
|
});
|
|
1846
2209
|
const toggleCompleted = () => setHideCompleted((value) => !value);
|
|
2210
|
+
const toggleHistory = () => setShowHistory((value) => !value);
|
|
1847
2211
|
const toggleSort = () => setByPressure((value) => !value);
|
|
1848
2212
|
const toggleGroups = () => setCollapsed((previous) => previous.size ? new Set : new Set(tree().all.map((r) => r.node.sessionId)));
|
|
1849
2213
|
props.context.keymap.layer(() => ({
|
|
1850
2214
|
mode: "global",
|
|
1851
2215
|
commands: [{
|
|
2216
|
+
id: "context-guard.history",
|
|
2217
|
+
title: "Show or hide sidebar context history",
|
|
2218
|
+
group: "Context Guard",
|
|
2219
|
+
palette: true,
|
|
2220
|
+
bind: false,
|
|
2221
|
+
run: toggleHistory
|
|
2222
|
+
}, {
|
|
1852
2223
|
id: "context-guard.completed",
|
|
1853
|
-
title: "
|
|
2224
|
+
title: "Show or hide completed subagent group",
|
|
1854
2225
|
group: "Context Guard",
|
|
1855
2226
|
palette: true,
|
|
1856
2227
|
bind: false,
|
|
@@ -1894,45 +2265,21 @@ function CompactSidebar(props) {
|
|
|
1894
2265
|
})()
|
|
1895
2266
|
});
|
|
1896
2267
|
}
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
return
|
|
1900
|
-
};
|
|
1901
|
-
const notices = createMemo(() => [...!["2.0.29", "2.1.2"].includes(props.context.app.version) ? wrap(`Runtime ${props.context.app.version}: unverified`, width()) : [], ...props.state.connection() !== "live" ? wrap(`Connection: ${props.state.connection()}`, width()) : [], ...props.state.health()?.mode === "observe" ? ["Observe mode"] : [], ...props.state.health()?.enforcement === "disabled" || props.state.health()?.enforcement === "suspended" ? wrap(`Guard: ${props.state.health()?.enforcement}`, width()) : [], ...(props.state.health()?.reasons ?? []).flatMap((reason) => wrap(reason, width()))]);
|
|
1902
|
-
return (() => {
|
|
1903
|
-
var _el$2 = _$createElement("box"), _el$3 = _$createElement("text"), _el$5 = _$createElement("text"), _el$6 = _$createElement("text"), _el$8 = _$createElement("text"), _el$9 = _$createElement("text"), _el$0 = _$createElement("text"), _el$1 = _$createElement("text"), _el$11 = _$createElement("text"), _el$12 = _$createElement("text");
|
|
1904
|
-
_$insertNode(_el$2, _el$3);
|
|
1905
|
-
_$insertNode(_el$2, _el$5);
|
|
1906
|
-
_$insertNode(_el$2, _el$6);
|
|
1907
|
-
_$insertNode(_el$2, _el$8);
|
|
1908
|
-
_$insertNode(_el$2, _el$9);
|
|
1909
|
-
_$insertNode(_el$2, _el$0);
|
|
1910
|
-
_$insertNode(_el$2, _el$1);
|
|
1911
|
-
_$insertNode(_el$2, _el$11);
|
|
1912
|
-
_$insertNode(_el$2, _el$12);
|
|
1913
|
-
_$setProp(_el$2, "width", "100%");
|
|
1914
|
-
_$setProp(_el$2, "flexShrink", 0);
|
|
1915
|
-
_$setProp(_el$2, "border", true);
|
|
1916
|
-
_$setProp(_el$2, "borderStyle", "rounded");
|
|
1917
|
-
_$setProp(_el$2, "title", " CONTEXT GUARD ");
|
|
1918
|
-
_$setProp(_el$2, "paddingX", 1);
|
|
1919
|
-
_$setProp(_el$2, "flexDirection", "column");
|
|
1920
|
-
_$setProp(_el$2, "onSizeChange", function() {
|
|
1921
|
-
setMeasuredWidth(this.width);
|
|
1922
|
-
});
|
|
1923
|
-
_$insert(_el$2, _$createComponent(Index, {
|
|
2268
|
+
const notices = createMemo(() => [...!["2.0.29", "2.1.2"].includes(props.context.app.version) ? wrap(`Runtime ${props.context.app.version}: unverified`, width()) : [], ...[connectionLabel(props.state.connection(), width() < 28), ...monitorStatusLines(props.state.connection(), props.state.health(), props.rows.some((row2) => row2.snapshot?.measurement !== undefined), width() < 28)].flatMap((line) => wrap(line, width()))]);
|
|
2269
|
+
function Sections(input) {
|
|
2270
|
+
return _$createComponent(Index, {
|
|
1924
2271
|
get each() {
|
|
1925
|
-
return
|
|
2272
|
+
return input.sections;
|
|
1926
2273
|
},
|
|
1927
|
-
children: (
|
|
2274
|
+
children: (section) => _$createComponent(Index, {
|
|
1928
2275
|
get each() {
|
|
1929
|
-
return
|
|
2276
|
+
return section().lines;
|
|
1930
2277
|
},
|
|
1931
2278
|
children: (line) => (() => {
|
|
1932
|
-
var _el$
|
|
1933
|
-
_$insert(_el$
|
|
2279
|
+
var _el$2 = _$createElement("text");
|
|
2280
|
+
_$insert(_el$2, _$createComponent(Show, {
|
|
1934
2281
|
get when() {
|
|
1935
|
-
return
|
|
2282
|
+
return section().segments;
|
|
1936
2283
|
},
|
|
1937
2284
|
get fallback() {
|
|
1938
2285
|
return line() || " ";
|
|
@@ -1940,51 +2287,86 @@ function CompactSidebar(props) {
|
|
|
1940
2287
|
get children() {
|
|
1941
2288
|
return _$createComponent(For, {
|
|
1942
2289
|
get each() {
|
|
1943
|
-
return
|
|
2290
|
+
return section().segments;
|
|
1944
2291
|
},
|
|
1945
2292
|
children: (part) => (() => {
|
|
1946
|
-
var _el$
|
|
1947
|
-
_$insert(_el$
|
|
1948
|
-
_$effect((_$p) => _$setProp(_el$
|
|
2293
|
+
var _el$3 = _$createElement("span");
|
|
2294
|
+
_$insert(_el$3, () => part.text);
|
|
2295
|
+
_$effect((_$p) => _$setProp(_el$3, "style", {
|
|
1949
2296
|
fg: part.tone === "axis" || part.tone === "held" ? colors().muted : part.tone === "threshold" ? colors().feedback.warning.base : current()?.freshness === "fresh" ? colors().base : colors().muted
|
|
1950
2297
|
}, _$p));
|
|
1951
|
-
return _el$
|
|
2298
|
+
return _el$3;
|
|
1952
2299
|
})()
|
|
1953
2300
|
});
|
|
1954
2301
|
}
|
|
1955
2302
|
}));
|
|
1956
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1957
|
-
return _el$
|
|
2303
|
+
_$effect((_$p) => _$setProp(_el$2, "fg", section().tone === "execution" ? executionColor(current()) : section().tone === "threshold" ? colors().feedback.warning.base : section().tone === "pressure" ? pressureColor(current()) : section().tone === "measurement" ? current()?.freshness === "fresh" ? colors().muted : colors().feedback.warning.base : colors().base, _$p));
|
|
2304
|
+
return _el$2;
|
|
1958
2305
|
})()
|
|
1959
2306
|
})
|
|
1960
|
-
})
|
|
1961
|
-
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2309
|
+
return (() => {
|
|
2310
|
+
var _el$4 = _$createElement("box"), _el$5 = _$createElement("text"), _el$6 = _$createElement("text"), _el$8 = _$createElement("text"), _el$9 = _$createElement("text");
|
|
2311
|
+
_$insertNode(_el$4, _el$5);
|
|
2312
|
+
_$insertNode(_el$4, _el$6);
|
|
2313
|
+
_$insertNode(_el$4, _el$8);
|
|
2314
|
+
_$insertNode(_el$4, _el$9);
|
|
2315
|
+
_$setProp(_el$4, "width", "100%");
|
|
2316
|
+
_$setProp(_el$4, "flexShrink", 0);
|
|
2317
|
+
_$setProp(_el$4, "border", true);
|
|
2318
|
+
_$setProp(_el$4, "borderStyle", "rounded");
|
|
2319
|
+
_$setProp(_el$4, "title", " CONTEXT GUARD ");
|
|
2320
|
+
_$setProp(_el$4, "paddingX", 1);
|
|
2321
|
+
_$setProp(_el$4, "flexDirection", "column");
|
|
2322
|
+
_$setProp(_el$4, "onSizeChange", function() {
|
|
2323
|
+
setMeasuredWidth(this.width);
|
|
2324
|
+
});
|
|
2325
|
+
_$insert(_el$4, _$createComponent(Sections, {
|
|
2326
|
+
get sections() {
|
|
2327
|
+
return mainSections(current(), width(), props.state.age(props.sessionID));
|
|
2328
|
+
}
|
|
2329
|
+
}), _el$5);
|
|
2330
|
+
_$insert(_el$4, _$createComponent(Index, {
|
|
1962
2331
|
get each() {
|
|
1963
2332
|
return notices();
|
|
1964
2333
|
},
|
|
1965
2334
|
children: (line) => (() => {
|
|
1966
|
-
var _el$
|
|
1967
|
-
_$insert(_el$
|
|
1968
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1969
|
-
return _el$
|
|
2335
|
+
var _el$0 = _$createElement("text");
|
|
2336
|
+
_$insert(_el$0, line);
|
|
2337
|
+
_$effect((_$p) => _$setProp(_el$0, "fg", colors().feedback.warning.base, _$p));
|
|
2338
|
+
return _el$0;
|
|
1970
2339
|
})()
|
|
1971
|
-
}), _el$
|
|
1972
|
-
_$
|
|
1973
|
-
_$insert(_el$5, () =>
|
|
1974
|
-
_$
|
|
2340
|
+
}), _el$5);
|
|
2341
|
+
_$setProp(_el$5, "onMouseDown", () => props.context.ui.panel.open("context-guard.monitor"));
|
|
2342
|
+
_$insert(_el$5, () => clip("Open: /context-guard", width()));
|
|
2343
|
+
_$setProp(_el$6, "onMouseDown", toggleHistory);
|
|
2344
|
+
_$insert(_el$6, () => clip(showHistory() ? "History: hide" : "History: show", width()));
|
|
2345
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
2346
|
+
get when() {
|
|
2347
|
+
return showHistory();
|
|
2348
|
+
},
|
|
2349
|
+
get children() {
|
|
2350
|
+
return _$createComponent(Sections, {
|
|
2351
|
+
get sections() {
|
|
2352
|
+
return historySections(current(), width(), props.state.age(props.sessionID), trace().samples, trace().capacity);
|
|
2353
|
+
}
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
}), _el$8);
|
|
2357
|
+
_$insert(_el$4, _$createComponent(Lines, {
|
|
1975
2358
|
get lines() {
|
|
1976
|
-
return wrap(
|
|
2359
|
+
return wrap(`SUBAGENTS (${tree().all.length}) \xB7 ${tree().all.filter((r) => r.node.status === "running").length} running${trustworthy() && tree().complete ? "" : " \xB7 partial"}`, width());
|
|
1977
2360
|
}
|
|
1978
|
-
}), _el$
|
|
1979
|
-
_$
|
|
1980
|
-
_$insert(_el$2, _$createComponent(For, {
|
|
2361
|
+
}), _el$8);
|
|
2362
|
+
_$insert(_el$4, _$createComponent(For, {
|
|
1981
2363
|
get each() {
|
|
1982
2364
|
return tree().visible.map((entry) => entry.row.node.sessionId);
|
|
1983
2365
|
},
|
|
1984
2366
|
children: (id) => {
|
|
1985
2367
|
const entry = () => entries().get(id);
|
|
1986
2368
|
const row2 = () => entry()?.row;
|
|
1987
|
-
const indent = () => " ".repeat(Math.min(entry()?.depth ?? 0, Math.
|
|
2369
|
+
const indent = () => " ".repeat(Math.min((entry()?.depth ?? 0) * 2, Math.max(0, width() - 16)));
|
|
1988
2370
|
const prefix = () => `${indent()}${entry()?.depth ? "\u2514\u2500 " : ""}${entry()?.hasChildren ? collapsed().has(id) ? "\u25B8 " : "\u25BE " : ""}`;
|
|
1989
2371
|
const nameWidth = () => Math.max(1, width() - cells(prefix()));
|
|
1990
2372
|
return _$createComponent(Show, {
|
|
@@ -1992,90 +2374,99 @@ function CompactSidebar(props) {
|
|
|
1992
2374
|
return row2();
|
|
1993
2375
|
},
|
|
1994
2376
|
children: (item) => (() => {
|
|
1995
|
-
var _el$
|
|
1996
|
-
_$insertNode(_el$
|
|
1997
|
-
_$
|
|
1998
|
-
_$setProp(_el$
|
|
1999
|
-
_$
|
|
2000
|
-
_$
|
|
2001
|
-
_$setProp(_el$
|
|
2002
|
-
_$
|
|
2003
|
-
_$insert(_el$17, _$createComponent(Show, {
|
|
2377
|
+
var _el$1 = _$createElement("box"), _el$10 = _$createElement("box"), _el$12 = _$createElement("text"), _el$13 = _$createElement("span"), _el$14 = _$createElement("span");
|
|
2378
|
+
_$insertNode(_el$1, _el$10);
|
|
2379
|
+
_$setProp(_el$1, "flexDirection", "column");
|
|
2380
|
+
_$setProp(_el$1, "flexShrink", 0);
|
|
2381
|
+
_$insertNode(_el$10, _el$12);
|
|
2382
|
+
_$setProp(_el$10, "flexDirection", "row");
|
|
2383
|
+
_$setProp(_el$10, "flexShrink", 0);
|
|
2384
|
+
_$insert(_el$10, _$createComponent(Show, {
|
|
2004
2385
|
get when() {
|
|
2005
2386
|
return prefix();
|
|
2006
2387
|
},
|
|
2007
2388
|
get children() {
|
|
2008
|
-
var _el$
|
|
2009
|
-
_$setProp(_el$
|
|
2010
|
-
_$insert(_el$
|
|
2011
|
-
_$effect((_$p) => _$setProp(_el$
|
|
2012
|
-
return _el$
|
|
2389
|
+
var _el$11 = _$createElement("text");
|
|
2390
|
+
_$setProp(_el$11, "onMouseDown", () => toggle(id));
|
|
2391
|
+
_$insert(_el$11, prefix);
|
|
2392
|
+
_$effect((_$p) => _$setProp(_el$11, "fg", colors().muted, _$p));
|
|
2393
|
+
return _el$11;
|
|
2013
2394
|
}
|
|
2014
|
-
}), _el$
|
|
2015
|
-
_$insertNode(_el$
|
|
2016
|
-
_$insertNode(_el$
|
|
2017
|
-
_$setProp(_el$
|
|
2395
|
+
}), _el$12);
|
|
2396
|
+
_$insertNode(_el$12, _el$13);
|
|
2397
|
+
_$insertNode(_el$12, _el$14);
|
|
2398
|
+
_$setProp(_el$12, "onMouseDown", () => props.context.ui.router.navigate({
|
|
2018
2399
|
type: "session",
|
|
2019
2400
|
sessionID: id
|
|
2020
2401
|
}));
|
|
2021
|
-
_$insert(_el$
|
|
2022
|
-
_$insert(_el$
|
|
2023
|
-
_$insert(_el$
|
|
2402
|
+
_$insert(_el$13, () => agentHeading(item(), nameWidth()).slice(0, 1));
|
|
2403
|
+
_$insert(_el$14, () => agentHeading(item(), nameWidth()).slice(1));
|
|
2404
|
+
_$insert(_el$1, _$createComponent(Index, {
|
|
2024
2405
|
get each() {
|
|
2025
2406
|
return agentLines(item(), Math.max(1, width() - cells(indent()) - 2));
|
|
2026
2407
|
},
|
|
2027
2408
|
children: (line) => (() => {
|
|
2028
|
-
var _el$
|
|
2029
|
-
_$insertNode(_el$
|
|
2030
|
-
_$insert(_el$
|
|
2031
|
-
_$insert(_el$
|
|
2032
|
-
_$effect((_$p) => _$setProp(_el$
|
|
2033
|
-
return _el$
|
|
2409
|
+
var _el$15 = _$createElement("text"), _el$16 = _$createTextNode(` `);
|
|
2410
|
+
_$insertNode(_el$15, _el$16);
|
|
2411
|
+
_$insert(_el$15, indent, _el$16);
|
|
2412
|
+
_$insert(_el$15, line, null);
|
|
2413
|
+
_$effect((_$p) => _$setProp(_el$15, "fg", rowColor(item()), _$p));
|
|
2414
|
+
return _el$15;
|
|
2034
2415
|
})()
|
|
2035
|
-
}),
|
|
2036
|
-
_$
|
|
2416
|
+
}), null);
|
|
2417
|
+
_$insert(_el$1, _$createComponent(Show, {
|
|
2418
|
+
get when() {
|
|
2419
|
+
return entry()?.hidden;
|
|
2420
|
+
},
|
|
2421
|
+
get children() {
|
|
2422
|
+
return _$createComponent(Lines, {
|
|
2423
|
+
get lines() {
|
|
2424
|
+
return wrap(`${entry()?.hidden} hidden${entry()?.attention ? " \xB7 needs attention" : ""}`, width());
|
|
2425
|
+
}
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
}), null);
|
|
2037
2429
|
_$effect((_p$) => {
|
|
2038
|
-
var _v$
|
|
2430
|
+
var _v$8 = rowColor(item()), _v$9 = {
|
|
2039
2431
|
fg: executionColor(item())
|
|
2040
2432
|
};
|
|
2041
|
-
_v$
|
|
2042
|
-
_v$
|
|
2433
|
+
_v$8 !== _p$.e && (_p$.e = _$setProp(_el$12, "fg", _v$8, _p$.e));
|
|
2434
|
+
_v$9 !== _p$.t && (_p$.t = _$setProp(_el$13, "style", _v$9, _p$.t));
|
|
2043
2435
|
return _p$;
|
|
2044
2436
|
}, {
|
|
2045
2437
|
e: undefined,
|
|
2046
2438
|
t: undefined
|
|
2047
2439
|
});
|
|
2048
|
-
return _el$
|
|
2440
|
+
return _el$1;
|
|
2049
2441
|
})()
|
|
2050
2442
|
});
|
|
2051
2443
|
}
|
|
2052
2444
|
}), _el$8);
|
|
2053
|
-
_$
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
return statistics(props.rows.filter((r) => r.node.sessionId === props.sessionID).concat(tree().all), props.sessionID, props.state.complete(), width());
|
|
2445
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
2446
|
+
get when() {
|
|
2447
|
+
return tree().grouped > 0;
|
|
2448
|
+
},
|
|
2449
|
+
get children() {
|
|
2450
|
+
var _el$7 = _$createElement("text");
|
|
2451
|
+
_$setProp(_el$7, "onMouseDown", toggleCompleted);
|
|
2452
|
+
_$insert(_el$7, () => clip(`Completed (${tree().grouped}): ${hideCompleted() ? "show" : "hide"}`, width()));
|
|
2453
|
+
_$effect((_$p) => _$setProp(_el$7, "fg", colors().muted, _$p));
|
|
2454
|
+
return _el$7;
|
|
2064
2455
|
}
|
|
2065
|
-
}), _el$
|
|
2066
|
-
_$setProp(_el$
|
|
2067
|
-
_$insert(_el$
|
|
2456
|
+
}), _el$8);
|
|
2457
|
+
_$setProp(_el$8, "onMouseDown", toggleSort);
|
|
2458
|
+
_$insert(_el$8, () => clip(byPressure() ? "Sort: pressure" : "Sort: activity", width()));
|
|
2459
|
+
_$setProp(_el$9, "onMouseDown", toggleGroups);
|
|
2460
|
+
_$insert(_el$9, () => clip(collapsed().size ? "Expand groups" : "Collapse groups", width()));
|
|
2068
2461
|
_$effect((_p$) => {
|
|
2069
|
-
var _v$ = props.width, _v$2 = colors().muted, _v$3 = colors().base, _v$4 = colors().muted, _v$5 = colors().muted, _v$6 = colors().muted, _v$7 = colors().muted
|
|
2070
|
-
_v$ !== _p$.e && (_p$.e = _$setProp(_el$
|
|
2071
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
2072
|
-
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
2462
|
+
var _v$ = props.width, _v$2 = colors().muted, _v$3 = colors().base, _v$4 = colors().muted, _v$5 = colors().muted, _v$6 = colors().muted, _v$7 = colors().muted;
|
|
2463
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$4, "maxWidth", _v$, _p$.e));
|
|
2464
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$4, "borderColor", _v$2, _p$.t));
|
|
2465
|
+
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$4, "titleColor", _v$3, _p$.a));
|
|
2073
2466
|
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$5, "fg", _v$4, _p$.o));
|
|
2074
|
-
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$
|
|
2075
|
-
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$
|
|
2076
|
-
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$
|
|
2077
|
-
_v$8 !== _p$.h && (_p$.h = _$setProp(_el$11, "fg", _v$8, _p$.h));
|
|
2078
|
-
_v$9 !== _p$.r && (_p$.r = _$setProp(_el$12, "fg", _v$9, _p$.r));
|
|
2467
|
+
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$6, "fg", _v$5, _p$.i));
|
|
2468
|
+
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$8, "fg", _v$6, _p$.n));
|
|
2469
|
+
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$9, "fg", _v$7, _p$.s));
|
|
2079
2470
|
return _p$;
|
|
2080
2471
|
}, {
|
|
2081
2472
|
e: undefined,
|
|
@@ -2084,11 +2475,9 @@ function CompactSidebar(props) {
|
|
|
2084
2475
|
o: undefined,
|
|
2085
2476
|
i: undefined,
|
|
2086
2477
|
n: undefined,
|
|
2087
|
-
s: undefined
|
|
2088
|
-
h: undefined,
|
|
2089
|
-
r: undefined
|
|
2478
|
+
s: undefined
|
|
2090
2479
|
});
|
|
2091
|
-
return _el$
|
|
2480
|
+
return _el$4;
|
|
2092
2481
|
})();
|
|
2093
2482
|
}
|
|
2094
2483
|
|
|
@@ -2097,573 +2486,892 @@ function GuardView(props) {
|
|
|
2097
2486
|
const consumer = props.state.acquire(props.sessionID);
|
|
2098
2487
|
createEffect2(() => consumer.update(props.sessionID));
|
|
2099
2488
|
onCleanup(() => consumer.release());
|
|
2100
|
-
const rows = createMemo2(() => props.
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
const detail = createMemo2(() => {
|
|
2105
|
-
const lines = detailLines(current(), props.width, props.expanded, props.state.age(props.sessionID));
|
|
2106
|
-
if (props.expanded) {
|
|
2107
|
-
const byId = new Map(rows().map((row2) => [row2.node.sessionId, row2.node]));
|
|
2108
|
-
const ancestry = [], seen = new Set;
|
|
2109
|
-
let node = byId.get(props.sessionID);
|
|
2110
|
-
while (node && !seen.has(node.sessionId)) {
|
|
2111
|
-
seen.add(node.sessionId);
|
|
2112
|
-
ancestry.unshift(node.agent ?? node.sessionId);
|
|
2113
|
-
node = node.parentId ? byId.get(node.parentId) : undefined;
|
|
2114
|
-
}
|
|
2115
|
-
lines.push(...wrap(`Ancestry: ${ancestry.join(" / ")}`, props.width));
|
|
2116
|
-
}
|
|
2117
|
-
if (props.inspectId && props.inspectId !== props.sessionID) {
|
|
2118
|
-
const inspected = rows().find((row2) => row2.node.sessionId === props.inspectId);
|
|
2119
|
-
lines.push(...wrap(`Inspect: ${props.inspectId}`, props.width), ...detailLines(inspected, props.width, true, props.state.age(props.inspectId)));
|
|
2120
|
-
}
|
|
2121
|
-
return lines;
|
|
2122
|
-
});
|
|
2123
|
-
const visible = createMemo2(() => {
|
|
2124
|
-
if (!props.expanded)
|
|
2125
|
-
return rows().slice(0, 7);
|
|
2126
|
-
const index = Math.max(0, rows().findIndex((row2) => row2.node.sessionId === props.selectedId));
|
|
2127
|
-
return rows().slice(Math.max(0, index - 10), Math.max(0, index - 10) + 25);
|
|
2128
|
-
});
|
|
2129
|
-
return _$createComponent2(Show2, {
|
|
2130
|
-
get when() {
|
|
2131
|
-
return props.expanded;
|
|
2489
|
+
const rows = createMemo2(() => props.state.rows([], true));
|
|
2490
|
+
return _$createComponent2(CompactSidebar, {
|
|
2491
|
+
get sessionID() {
|
|
2492
|
+
return props.sessionID;
|
|
2132
2493
|
},
|
|
2133
|
-
get
|
|
2134
|
-
return
|
|
2135
|
-
get sessionID() {
|
|
2136
|
-
return props.sessionID;
|
|
2137
|
-
},
|
|
2138
|
-
get state() {
|
|
2139
|
-
return props.state;
|
|
2140
|
-
},
|
|
2141
|
-
get context() {
|
|
2142
|
-
return props.context;
|
|
2143
|
-
},
|
|
2144
|
-
get rows() {
|
|
2145
|
-
return rows();
|
|
2146
|
-
},
|
|
2147
|
-
get width() {
|
|
2148
|
-
return props.width;
|
|
2149
|
-
}
|
|
2150
|
-
});
|
|
2494
|
+
get state() {
|
|
2495
|
+
return props.state;
|
|
2151
2496
|
},
|
|
2152
|
-
get
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
_$setProp2(_el$, "flexDirection", "column");
|
|
2161
|
-
_$setProp2(_el$, "gap", 0);
|
|
2162
|
-
_$insertNode2(_el$2, _el$3);
|
|
2163
|
-
_$insert2(_el$2, () => props.state.health()?.mode ?? "?", null);
|
|
2164
|
-
_$insert2(_el$4, (() => {
|
|
2165
|
-
var _c$ = _$memo2(() => !!["2.0.29", "2.1.2"].includes(props.context.app.version));
|
|
2166
|
-
return () => _c$() ? "" : clip(`Runtime ${props.context.app.version}: unverified (tested: 2.0.29, 2.1.2)`, props.width);
|
|
2167
|
-
})());
|
|
2168
|
-
_$insert2(_el$5, () => clip(`${props.state.connection()} / ${props.state.health()?.enforcement ?? "?"}`, props.width));
|
|
2169
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2170
|
-
get each() {
|
|
2171
|
-
return chart();
|
|
2172
|
-
},
|
|
2173
|
-
children: (item) => (() => {
|
|
2174
|
-
var _el$1 = _$createElement2("text");
|
|
2175
|
-
_$insert2(_el$1, _$createComponent2(Show2, {
|
|
2176
|
-
get when() {
|
|
2177
|
-
return item.segments;
|
|
2178
|
-
},
|
|
2179
|
-
get fallback() {
|
|
2180
|
-
return item.line;
|
|
2181
|
-
},
|
|
2182
|
-
get children() {
|
|
2183
|
-
return _$createComponent2(For2, {
|
|
2184
|
-
get each() {
|
|
2185
|
-
return item.segments;
|
|
2186
|
-
},
|
|
2187
|
-
children: (part) => (() => {
|
|
2188
|
-
var _el$10 = _$createElement2("span");
|
|
2189
|
-
_$insert2(_el$10, () => part.text);
|
|
2190
|
-
_$effect2((_$p) => _$setProp2(_el$10, "style", {
|
|
2191
|
-
fg: part.tone === "axis" || part.tone === "held" ? props.context.theme.text.muted : part.tone === "threshold" ? props.context.theme.text.feedback.warning.base : current()?.freshness === "fresh" ? props.context.theme.text.base : props.context.theme.text.muted
|
|
2192
|
-
}, _$p));
|
|
2193
|
-
return _el$10;
|
|
2194
|
-
})()
|
|
2195
|
-
});
|
|
2196
|
-
}
|
|
2197
|
-
}));
|
|
2198
|
-
_$effect2((_$p) => _$setProp2(_el$1, "fg", item.threshold ? props.context.theme.text.feedback.warning.base : props.context.theme.text.muted, _$p));
|
|
2199
|
-
return _el$1;
|
|
2200
|
-
})()
|
|
2201
|
-
}), _el$6);
|
|
2202
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2203
|
-
get each() {
|
|
2204
|
-
return wrap("Recent context samples \u2192 now \xB7 \u2504 trigger \xB7 muted held", props.width);
|
|
2205
|
-
},
|
|
2206
|
-
children: (line) => (() => {
|
|
2207
|
-
var _el$11 = _$createElement2("text");
|
|
2208
|
-
_$insert2(_el$11, line);
|
|
2209
|
-
_$effect2((_$p) => _$setProp2(_el$11, "fg", props.context.theme.text.muted, _$p));
|
|
2210
|
-
return _el$11;
|
|
2211
|
-
})()
|
|
2212
|
-
}), _el$6);
|
|
2213
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2214
|
-
get each() {
|
|
2215
|
-
return detail();
|
|
2216
|
-
},
|
|
2217
|
-
children: (line) => (() => {
|
|
2218
|
-
var _el$12 = _$createElement2("text");
|
|
2219
|
-
_$insert2(_el$12, line);
|
|
2220
|
-
_$effect2((_$p) => _$setProp2(_el$12, "fg", props.context.theme.text.base, _$p));
|
|
2221
|
-
return _el$12;
|
|
2222
|
-
})()
|
|
2223
|
-
}), _el$6);
|
|
2224
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2225
|
-
get each() {
|
|
2226
|
-
return props.state.health()?.reasons ?? [];
|
|
2227
|
-
},
|
|
2228
|
-
children: (reason) => (() => {
|
|
2229
|
-
var _el$13 = _$createElement2("text");
|
|
2230
|
-
_$insert2(_el$13, () => clip(reason, props.width));
|
|
2231
|
-
_$effect2((_$p) => _$setProp2(_el$13, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
2232
|
-
return _el$13;
|
|
2233
|
-
})()
|
|
2234
|
-
}), _el$6);
|
|
2235
|
-
_$insert2(_el$6, (() => {
|
|
2236
|
-
var _c$2 = _$memo2(() => props.state.health()?.mode === "observe");
|
|
2237
|
-
return () => _c$2() ? current()?.pressure === "crossed" ? "Observe: would compact" : "Observe: no admission" : "";
|
|
2238
|
-
})());
|
|
2239
|
-
_$insertNode2(_el$7, _el$8);
|
|
2240
|
-
_$insertNode2(_el$7, _el$9);
|
|
2241
|
-
_$insert2(_el$7, () => rows().length, _el$9);
|
|
2242
|
-
_$insert2(_el$7, () => props.state.complete() ? "" : " partial", null);
|
|
2243
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2244
|
-
get each() {
|
|
2245
|
-
return visible();
|
|
2246
|
-
},
|
|
2247
|
-
children: (row2) => (() => {
|
|
2248
|
-
var _el$14 = _$createElement2("box");
|
|
2249
|
-
_$setProp2(_el$14, "flexDirection", "column");
|
|
2250
|
-
_$setProp2(_el$14, "onMouseDown", () => {
|
|
2251
|
-
if (row2.hidden)
|
|
2252
|
-
props.state.expand(row2.node.sessionId);
|
|
2253
|
-
else {
|
|
2254
|
-
if (props.expanded)
|
|
2255
|
-
props.context.ui.panel.close();
|
|
2256
|
-
props.context.ui.router.navigate({
|
|
2257
|
-
type: "session",
|
|
2258
|
-
sessionID: row2.node.sessionId
|
|
2259
|
-
});
|
|
2260
|
-
}
|
|
2261
|
-
});
|
|
2262
|
-
_$insert2(_el$14, _$createComponent2(For2, {
|
|
2263
|
-
get each() {
|
|
2264
|
-
return rowLines(row2, Math.max(1, props.width - (props.expanded ? 2 : 0))).map((line) => props.expanded ? `${row2.node.sessionId === props.selectedId ? ">" : " "} ${line}` : line);
|
|
2265
|
-
},
|
|
2266
|
-
children: (line) => (() => {
|
|
2267
|
-
var _el$15 = _$createElement2("text");
|
|
2268
|
-
_$insert2(_el$15, line);
|
|
2269
|
-
_$effect2((_$p) => _$setProp2(_el$15, "fg", row2.pressure === "crossed" ? props.context.theme.text.feedback.error.base : row2.pressure === "near" ? props.context.theme.text.feedback.warning.base : props.context.theme.text.base, _$p));
|
|
2270
|
-
return _el$15;
|
|
2271
|
-
})()
|
|
2272
|
-
}));
|
|
2273
|
-
_$effect2((_$p) => _$setProp2(_el$14, "id", `context-guard.row.${row2.node.sessionId}`, _$p));
|
|
2274
|
-
return _el$14;
|
|
2275
|
-
})()
|
|
2276
|
-
}), _el$0);
|
|
2277
|
-
_$setProp2(_el$0, "onMouseDown", () => props.context.ui.panel.open("context-guard.monitor"));
|
|
2278
|
-
_$insert2(_el$0, (() => {
|
|
2279
|
-
var _c$3 = _$memo2(() => rows().length > visible().length);
|
|
2280
|
-
return () => _c$3() ? `+ ${rows().length - visible().length} rows; open panel` : "Open: /context-guard";
|
|
2281
|
-
})());
|
|
2282
|
-
_$effect2((_p$) => {
|
|
2283
|
-
var _v$ = props.context.theme.text.base, _v$2 = props.context.theme.text.muted, _v$3 = props.context.theme.text.muted, _v$4 = props.context.theme.text.muted, _v$5 = props.context.theme.text.base, _v$6 = props.context.theme.text.muted;
|
|
2284
|
-
_v$ !== _p$.e && (_p$.e = _$setProp2(_el$2, "fg", _v$, _p$.e));
|
|
2285
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp2(_el$4, "fg", _v$2, _p$.t));
|
|
2286
|
-
_v$3 !== _p$.a && (_p$.a = _$setProp2(_el$5, "fg", _v$3, _p$.a));
|
|
2287
|
-
_v$4 !== _p$.o && (_p$.o = _$setProp2(_el$6, "fg", _v$4, _p$.o));
|
|
2288
|
-
_v$5 !== _p$.i && (_p$.i = _$setProp2(_el$7, "fg", _v$5, _p$.i));
|
|
2289
|
-
_v$6 !== _p$.n && (_p$.n = _$setProp2(_el$0, "fg", _v$6, _p$.n));
|
|
2290
|
-
return _p$;
|
|
2291
|
-
}, {
|
|
2292
|
-
e: undefined,
|
|
2293
|
-
t: undefined,
|
|
2294
|
-
a: undefined,
|
|
2295
|
-
o: undefined,
|
|
2296
|
-
i: undefined,
|
|
2297
|
-
n: undefined
|
|
2298
|
-
});
|
|
2299
|
-
return _el$;
|
|
2497
|
+
get context() {
|
|
2498
|
+
return props.context;
|
|
2499
|
+
},
|
|
2500
|
+
get rows() {
|
|
2501
|
+
return rows();
|
|
2502
|
+
},
|
|
2503
|
+
get width() {
|
|
2504
|
+
return props.width;
|
|
2300
2505
|
}
|
|
2301
2506
|
});
|
|
2302
2507
|
}
|
|
2303
2508
|
|
|
2304
2509
|
// src/tui/panel.tsx
|
|
2305
|
-
import {
|
|
2306
|
-
import { memo as _$memo3 } from "@opentui/solid";
|
|
2510
|
+
import { use as _$use } from "@opentui/solid";
|
|
2307
2511
|
import { insertNode as _$insertNode4 } from "@opentui/solid";
|
|
2512
|
+
import { memo as _$memo2 } from "@opentui/solid";
|
|
2513
|
+
import { effect as _$effect4 } from "@opentui/solid";
|
|
2514
|
+
import { createComponent as _$createComponent5 } from "@opentui/solid";
|
|
2308
2515
|
import { insert as _$insert4 } from "@opentui/solid";
|
|
2309
|
-
import { createComponent as _$createComponent4 } from "@opentui/solid";
|
|
2310
|
-
import { use as _$use } from "@opentui/solid";
|
|
2311
2516
|
import { setProp as _$setProp4 } from "@opentui/solid";
|
|
2312
2517
|
import { createElement as _$createElement4 } from "@opentui/solid";
|
|
2313
|
-
import { createSignal as
|
|
2518
|
+
import { createSignal as createSignal3, createMemo as createMemo4, createEffect as createEffect3, on, onCleanup as onCleanup2, Show as Show3, For as For4 } from "solid-js";
|
|
2314
2519
|
|
|
2315
2520
|
// src/tui/charts.tsx
|
|
2316
2521
|
init_chartformat();
|
|
2522
|
+
init_historyclient();
|
|
2317
2523
|
init_format();
|
|
2318
|
-
import { effect as _$
|
|
2319
|
-
import { insertNode as _$
|
|
2320
|
-
import { insert as _$
|
|
2524
|
+
import { effect as _$effect2 } from "@opentui/solid";
|
|
2525
|
+
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
2526
|
+
import { insert as _$insert2 } from "@opentui/solid";
|
|
2321
2527
|
import { createComponent as _$createComponent3 } from "@opentui/solid";
|
|
2322
|
-
import { setProp as _$
|
|
2323
|
-
import { createElement as _$
|
|
2324
|
-
import {
|
|
2528
|
+
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
2529
|
+
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
2530
|
+
import { For as For2 } from "solid-js";
|
|
2325
2531
|
function HistoryCharts(props) {
|
|
2326
|
-
const [result, setResult] = createSignal3();
|
|
2327
|
-
const [status, setStatus] = createSignal3("Loading retained history...");
|
|
2328
|
-
const [range, setRange] = createSignal3({
|
|
2329
|
-
from: 0,
|
|
2330
|
-
to: 0
|
|
2331
|
-
});
|
|
2332
|
-
createEffect3(() => {
|
|
2333
|
-
const { sessionId: id, windowMs } = props;
|
|
2334
|
-
props.refresh;
|
|
2335
|
-
let pending = false, disposed = false;
|
|
2336
|
-
let controller;
|
|
2337
|
-
setResult(undefined);
|
|
2338
|
-
async function read() {
|
|
2339
|
-
if (pending || disposed)
|
|
2340
|
-
return;
|
|
2341
|
-
pending = true;
|
|
2342
|
-
controller = new AbortController;
|
|
2343
|
-
const to = Date.now(), from = Math.max(0, to - windowMs);
|
|
2344
|
-
try {
|
|
2345
|
-
const next = await props.state.history(id, from, to, AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]));
|
|
2346
|
-
if (!disposed) {
|
|
2347
|
-
setResult(next);
|
|
2348
|
-
setRange({
|
|
2349
|
-
from,
|
|
2350
|
-
to
|
|
2351
|
-
});
|
|
2352
|
-
setStatus("");
|
|
2353
|
-
}
|
|
2354
|
-
} catch {
|
|
2355
|
-
if (!disposed)
|
|
2356
|
-
setStatus("History unavailable. The owning server must support chart history RPC. Press r to retry.");
|
|
2357
|
-
} finally {
|
|
2358
|
-
pending = false;
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
read();
|
|
2362
|
-
const timer = setInterval(() => {
|
|
2363
|
-
read();
|
|
2364
|
-
}, 5000);
|
|
2365
|
-
onCleanup2(() => {
|
|
2366
|
-
disposed = true;
|
|
2367
|
-
controller?.abort();
|
|
2368
|
-
clearInterval(timer);
|
|
2369
|
-
});
|
|
2370
|
-
});
|
|
2371
2532
|
const lines = () => {
|
|
2372
|
-
const current = result
|
|
2373
|
-
return current ? historyChartLines(current, Math.max(4, props.width),
|
|
2533
|
+
const current = props.view.result;
|
|
2534
|
+
return current ? historyChartLines(current, Math.max(4, props.width), props.view.from ?? 0, props.view.to ?? 0, props.metricIndex) : [];
|
|
2374
2535
|
};
|
|
2375
2536
|
return (() => {
|
|
2376
|
-
var _el$ = _$
|
|
2377
|
-
_$
|
|
2378
|
-
_$
|
|
2379
|
-
_$
|
|
2537
|
+
var _el$ = _$createElement2("box"), _el$2 = _$createElement2("box");
|
|
2538
|
+
_$insertNode2(_el$, _el$2);
|
|
2539
|
+
_$setProp2(_el$, "flexDirection", "column");
|
|
2540
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2380
2541
|
get each() {
|
|
2381
2542
|
return wrap(`Performance charts \xB7 ${props.sessionId}`, props.width);
|
|
2382
2543
|
},
|
|
2383
2544
|
children: (line) => (() => {
|
|
2384
|
-
var _el$3 = _$
|
|
2385
|
-
_$
|
|
2386
|
-
_$
|
|
2545
|
+
var _el$3 = _$createElement2("text");
|
|
2546
|
+
_$insert2(_el$3, line);
|
|
2547
|
+
_$effect2((_$p) => _$setProp2(_el$3, "fg", props.context.theme.text.base, _$p));
|
|
2387
2548
|
return _el$3;
|
|
2388
2549
|
})()
|
|
2389
2550
|
}), _el$2);
|
|
2390
|
-
_$
|
|
2551
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2391
2552
|
get each() {
|
|
2392
|
-
return wrap(
|
|
2553
|
+
return wrap(`Window: ${new Map([[300000, "5 minutes"], [3600000, "1 hour"], [86400000, "24 hours"], [604800000, "7 days"]]).get(props.windowMs) ?? `${props.windowMs / 60000} minutes`} \xB7 [ / ] changes`, props.width);
|
|
2393
2554
|
},
|
|
2394
2555
|
children: (line) => (() => {
|
|
2395
|
-
var _el$4 = _$
|
|
2396
|
-
_$
|
|
2397
|
-
_$
|
|
2556
|
+
var _el$4 = _$createElement2("text");
|
|
2557
|
+
_$insert2(_el$4, line);
|
|
2558
|
+
_$effect2((_$p) => _$setProp2(_el$4, "fg", props.context.theme.text.muted, _$p));
|
|
2398
2559
|
return _el$4;
|
|
2399
2560
|
})()
|
|
2400
2561
|
}), _el$2);
|
|
2401
|
-
_$
|
|
2402
|
-
_$setProp3(_el$2, "paddingTop", 1);
|
|
2403
|
-
_$insert3(_el$2, _$createComponent3(For3, {
|
|
2562
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2404
2563
|
get each() {
|
|
2405
|
-
return
|
|
2564
|
+
return historyStatusLines(props.view).flatMap((line) => wrap(line, props.width));
|
|
2406
2565
|
},
|
|
2407
2566
|
children: (line) => (() => {
|
|
2408
|
-
var _el$5 = _$
|
|
2409
|
-
_$
|
|
2410
|
-
_$
|
|
2567
|
+
var _el$5 = _$createElement2("text");
|
|
2568
|
+
_$insert2(_el$5, line);
|
|
2569
|
+
_$effect2((_$p) => _$setProp2(_el$5, "fg", props.context.theme.text.muted, _$p));
|
|
2411
2570
|
return _el$5;
|
|
2412
2571
|
})()
|
|
2572
|
+
}), _el$2);
|
|
2573
|
+
_$setProp2(_el$2, "flexDirection", "column");
|
|
2574
|
+
_$setProp2(_el$2, "paddingTop", 1);
|
|
2575
|
+
_$insert2(_el$2, _$createComponent3(For2, {
|
|
2576
|
+
get each() {
|
|
2577
|
+
return lines();
|
|
2578
|
+
},
|
|
2579
|
+
children: (line) => (() => {
|
|
2580
|
+
var _el$6 = _$createElement2("text");
|
|
2581
|
+
_$insert2(_el$6, line || " ");
|
|
2582
|
+
_$effect2((_$p) => _$setProp2(_el$6, "fg", props.context.theme.text.base, _$p));
|
|
2583
|
+
return _el$6;
|
|
2584
|
+
})()
|
|
2413
2585
|
}));
|
|
2414
2586
|
return _el$;
|
|
2415
2587
|
})();
|
|
2416
2588
|
}
|
|
2417
2589
|
|
|
2590
|
+
// src/tui/historystate.ts
|
|
2591
|
+
init_historyclient();
|
|
2592
|
+
|
|
2593
|
+
class HistoryState {
|
|
2594
|
+
options;
|
|
2595
|
+
query;
|
|
2596
|
+
generation = 0;
|
|
2597
|
+
active;
|
|
2598
|
+
pending = false;
|
|
2599
|
+
stopped = false;
|
|
2600
|
+
paused = false;
|
|
2601
|
+
timer;
|
|
2602
|
+
view = { status: "idle", stale: false };
|
|
2603
|
+
now;
|
|
2604
|
+
schedule;
|
|
2605
|
+
cancel;
|
|
2606
|
+
constructor(options) {
|
|
2607
|
+
this.options = options;
|
|
2608
|
+
this.now = options.now ?? Date.now;
|
|
2609
|
+
this.schedule = options.schedule ?? ((callback, ms) => setTimeout(callback, ms));
|
|
2610
|
+
this.cancel = options.cancel ?? clearTimeout;
|
|
2611
|
+
}
|
|
2612
|
+
setQuery(query) {
|
|
2613
|
+
if (this.stopped || query.location === this.query?.location && query.sessionId === this.query.sessionId && query.windowMs === this.query.windowMs)
|
|
2614
|
+
return;
|
|
2615
|
+
this.generation++;
|
|
2616
|
+
this.active?.abort();
|
|
2617
|
+
this.query = { ...query };
|
|
2618
|
+
this.view = { status: "loading", stale: false };
|
|
2619
|
+
if (this.paused)
|
|
2620
|
+
this.publish(this.view);
|
|
2621
|
+
else
|
|
2622
|
+
this.refresh();
|
|
2623
|
+
}
|
|
2624
|
+
pause() {
|
|
2625
|
+
if (this.stopped || this.paused)
|
|
2626
|
+
return;
|
|
2627
|
+
this.paused = true;
|
|
2628
|
+
this.generation++;
|
|
2629
|
+
this.pending = false;
|
|
2630
|
+
this.clearTimer();
|
|
2631
|
+
this.active?.abort();
|
|
2632
|
+
if (this.view.status === "loading" && this.view.result)
|
|
2633
|
+
this.publish({
|
|
2634
|
+
...this.view,
|
|
2635
|
+
status: "ready",
|
|
2636
|
+
reason: undefined,
|
|
2637
|
+
stale: true
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
resume() {
|
|
2641
|
+
if (this.stopped || !this.paused)
|
|
2642
|
+
return;
|
|
2643
|
+
this.paused = false;
|
|
2644
|
+
if (this.query && this.view.status === "loading")
|
|
2645
|
+
this.refresh();
|
|
2646
|
+
else if (this.query && (this.view.status === "ready" || this.view.reason === "timeout" || this.view.reason === "unavailable"))
|
|
2647
|
+
this.timer = this.schedule(() => {
|
|
2648
|
+
this.timer = undefined;
|
|
2649
|
+
this.refresh();
|
|
2650
|
+
}, 5000);
|
|
2651
|
+
}
|
|
2652
|
+
refresh() {
|
|
2653
|
+
if (this.stopped || this.paused || !this.query)
|
|
2654
|
+
return;
|
|
2655
|
+
this.clearTimer();
|
|
2656
|
+
this.pending = true;
|
|
2657
|
+
this.publish({
|
|
2658
|
+
...this.view,
|
|
2659
|
+
status: "loading",
|
|
2660
|
+
reason: undefined,
|
|
2661
|
+
stale: this.view.result !== undefined
|
|
2662
|
+
});
|
|
2663
|
+
this.pump();
|
|
2664
|
+
}
|
|
2665
|
+
dispose() {
|
|
2666
|
+
this.stopped = true;
|
|
2667
|
+
this.generation++;
|
|
2668
|
+
this.pending = false;
|
|
2669
|
+
this.clearTimer();
|
|
2670
|
+
this.active?.abort();
|
|
2671
|
+
}
|
|
2672
|
+
clearTimer() {
|
|
2673
|
+
if (this.timer !== undefined)
|
|
2674
|
+
this.cancel(this.timer);
|
|
2675
|
+
this.timer = undefined;
|
|
2676
|
+
}
|
|
2677
|
+
publish(view) {
|
|
2678
|
+
const { reason, ...rest } = view;
|
|
2679
|
+
this.view = { ...rest, ...reason === undefined ? {} : { reason } };
|
|
2680
|
+
this.options.changed(this.view);
|
|
2681
|
+
}
|
|
2682
|
+
async pump() {
|
|
2683
|
+
if (this.stopped || this.paused || this.active || !this.pending || !this.query)
|
|
2684
|
+
return;
|
|
2685
|
+
this.pending = false;
|
|
2686
|
+
const query = this.query, generation = this.generation;
|
|
2687
|
+
const controller = new AbortController;
|
|
2688
|
+
this.active = controller;
|
|
2689
|
+
const signal = AbortSignal.any([
|
|
2690
|
+
controller.signal,
|
|
2691
|
+
this.options.deadline?.() ?? AbortSignal.timeout(5000)
|
|
2692
|
+
]);
|
|
2693
|
+
const to = Math.max(0, Math.floor(this.now())), from = Math.max(0, to - query.windowMs);
|
|
2694
|
+
const current = () => !this.stopped && generation === this.generation;
|
|
2695
|
+
try {
|
|
2696
|
+
const result = checkedHistory(await this.options.read(query.sessionId, from, to, signal), query.sessionId);
|
|
2697
|
+
if (!current())
|
|
2698
|
+
return;
|
|
2699
|
+
if (signal.aborted)
|
|
2700
|
+
throw historyFailure(undefined, signal);
|
|
2701
|
+
this.publish({
|
|
2702
|
+
status: result.enabled ? "ready" : "disabled",
|
|
2703
|
+
result,
|
|
2704
|
+
from,
|
|
2705
|
+
to,
|
|
2706
|
+
loadedAt: this.now(),
|
|
2707
|
+
stale: false
|
|
2708
|
+
});
|
|
2709
|
+
} catch (error) {
|
|
2710
|
+
if (current())
|
|
2711
|
+
this.publish({
|
|
2712
|
+
...this.view,
|
|
2713
|
+
status: "unavailable",
|
|
2714
|
+
reason: historyFailure(error, signal).reason,
|
|
2715
|
+
stale: this.view.result !== undefined
|
|
2716
|
+
});
|
|
2717
|
+
} finally {
|
|
2718
|
+
this.active = undefined;
|
|
2719
|
+
if (this.pending && !this.paused) {
|
|
2720
|
+
this.publish({
|
|
2721
|
+
...this.view,
|
|
2722
|
+
status: "loading",
|
|
2723
|
+
reason: undefined,
|
|
2724
|
+
stale: this.view.result !== undefined
|
|
2725
|
+
});
|
|
2726
|
+
this.pump();
|
|
2727
|
+
} else if (current() && !this.paused && (this.view.status === "ready" || this.view.reason === "timeout" || this.view.reason === "unavailable")) {
|
|
2728
|
+
this.timer = this.schedule(() => {
|
|
2729
|
+
this.timer = undefined;
|
|
2730
|
+
this.refresh();
|
|
2731
|
+
}, 5000);
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
// src/tui/panelview.tsx
|
|
2738
|
+
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
2739
|
+
import { insertNode as _$insertNode3 } from "@opentui/solid";
|
|
2740
|
+
import { effect as _$effect3 } from "@opentui/solid";
|
|
2741
|
+
import { insert as _$insert3 } from "@opentui/solid";
|
|
2742
|
+
import { setProp as _$setProp3 } from "@opentui/solid";
|
|
2743
|
+
import { createElement as _$createElement3 } from "@opentui/solid";
|
|
2744
|
+
import { createComponent as _$createComponent4 } from "@opentui/solid";
|
|
2745
|
+
import { For as For3, Index as Index2, Show as Show2, createMemo as createMemo3 } from "solid-js";
|
|
2746
|
+
init_format();
|
|
2747
|
+
init_statusformat();
|
|
2748
|
+
init_panelformat();
|
|
2749
|
+
function PanelOverview(props) {
|
|
2750
|
+
const visible = createMemo3(() => {
|
|
2751
|
+
const index = Math.max(0, props.rows.findIndex((row2) => row2.node.sessionId === props.selectedId));
|
|
2752
|
+
const start = Math.max(0, index - 10);
|
|
2753
|
+
return props.rows.slice(start, start + 25);
|
|
2754
|
+
});
|
|
2755
|
+
return _$createComponent4(Index2, {
|
|
2756
|
+
get each() {
|
|
2757
|
+
return visible();
|
|
2758
|
+
},
|
|
2759
|
+
children: (row2) => (() => {
|
|
2760
|
+
var _el$ = _$createElement3("box");
|
|
2761
|
+
_$setProp3(_el$, "flexDirection", "column");
|
|
2762
|
+
_$setProp3(_el$, "flexShrink", 0);
|
|
2763
|
+
_$setProp3(_el$, "onMouseDown", () => props.open(row2()));
|
|
2764
|
+
_$insert3(_el$, _$createComponent4(Index2, {
|
|
2765
|
+
get each() {
|
|
2766
|
+
return panelRowLines(row2(), props.width, row2().node.sessionId === props.selectedId);
|
|
2767
|
+
},
|
|
2768
|
+
children: (line) => (() => {
|
|
2769
|
+
var _el$2 = _$createElement3("text");
|
|
2770
|
+
_$insert3(_el$2, line);
|
|
2771
|
+
_$effect3((_$p) => _$setProp3(_el$2, "fg", row2().pressure === "crossed" || row2().node.status === "failed" ? props.context.theme.text.feedback.error.base : row2().pressure === "near" ? props.context.theme.text.feedback.warning.base : props.context.theme.text.base, _$p));
|
|
2772
|
+
return _el$2;
|
|
2773
|
+
})()
|
|
2774
|
+
}));
|
|
2775
|
+
_$effect3((_$p) => _$setProp3(_el$, "id", `context-guard.row.${row2().node.sessionId}`, _$p));
|
|
2776
|
+
return _el$;
|
|
2777
|
+
})()
|
|
2778
|
+
});
|
|
2779
|
+
}
|
|
2780
|
+
function PanelDetails(props) {
|
|
2781
|
+
const chart = createMemo3(() => contextChart(props.trace.samples, props.row?.snapshot?.capacityTokens ?? props.trace.capacity, props.row?.snapshot?.policy.triggerTokens, props.width, props.row?.snapshot?.measurement ? props.row.snapshot.measurement.at + props.age : undefined));
|
|
2782
|
+
const detail = createMemo3(() => {
|
|
2783
|
+
const row2 = props.row;
|
|
2784
|
+
if (!row2)
|
|
2785
|
+
return ["No selected session; return to Overview."];
|
|
2786
|
+
const byId = new Map(props.rows.map((r) => [r.node.sessionId, r.node]));
|
|
2787
|
+
const ancestry = [], seen = new Set;
|
|
2788
|
+
let node = row2.node;
|
|
2789
|
+
while (!seen.has(node.sessionId)) {
|
|
2790
|
+
seen.add(node.sessionId);
|
|
2791
|
+
ancestry.unshift(node.agent ?? node.sessionId);
|
|
2792
|
+
const parent = node.parentId ? byId.get(node.parentId) : undefined;
|
|
2793
|
+
if (!parent)
|
|
2794
|
+
break;
|
|
2795
|
+
node = parent;
|
|
2796
|
+
}
|
|
2797
|
+
return [`Session: ${row2.node.sessionId}${row2.current ? " (current)" : ""}`, ...detailLines(row2, props.width, true, props.age), `Ancestry: ${ancestry.join(" / ")}`, ...props.reasons.flatMap((reason) => [reasonExplanation(reason), `Health reason code: ${reason}`]), `Route family statistics: ${props.routeID}${props.familyComplete ? "" : " \xB7 partial"}`, ...statistics(props.familyRows, props.routeID, props.familyComplete, props.width), "Guard input = prompt + caches. Native Context uses different totals."].flatMap((line) => wrap(line, props.width));
|
|
2798
|
+
});
|
|
2799
|
+
return (() => {
|
|
2800
|
+
var _el$3 = _$createElement3("box"), _el$4 = _$createElement3("text");
|
|
2801
|
+
_$insertNode3(_el$3, _el$4);
|
|
2802
|
+
_$setProp3(_el$3, "flexDirection", "column");
|
|
2803
|
+
_$setProp3(_el$3, "flexShrink", 0);
|
|
2804
|
+
_$insertNode3(_el$4, _$createTextNode2(`Context history`));
|
|
2805
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2806
|
+
get each() {
|
|
2807
|
+
return chart();
|
|
2808
|
+
},
|
|
2809
|
+
children: (item) => (() => {
|
|
2810
|
+
var _el$6 = _$createElement3("text");
|
|
2811
|
+
_$insert3(_el$6, _$createComponent4(Show2, {
|
|
2812
|
+
get when() {
|
|
2813
|
+
return item.segments;
|
|
2814
|
+
},
|
|
2815
|
+
get fallback() {
|
|
2816
|
+
return item.line;
|
|
2817
|
+
},
|
|
2818
|
+
get children() {
|
|
2819
|
+
return _$createComponent4(For3, {
|
|
2820
|
+
get each() {
|
|
2821
|
+
return item.segments;
|
|
2822
|
+
},
|
|
2823
|
+
children: (part) => (() => {
|
|
2824
|
+
var _el$7 = _$createElement3("span");
|
|
2825
|
+
_$insert3(_el$7, () => part.text);
|
|
2826
|
+
_$effect3((_$p) => _$setProp3(_el$7, "style", {
|
|
2827
|
+
fg: part.tone === "threshold" ? props.context.theme.text.feedback.warning.base : part.tone === "axis" || part.tone === "held" || props.row?.freshness !== "fresh" ? props.context.theme.text.muted : props.context.theme.text.base
|
|
2828
|
+
}, _$p));
|
|
2829
|
+
return _el$7;
|
|
2830
|
+
})()
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
}));
|
|
2834
|
+
_$effect3((_$p) => _$setProp3(_el$6, "fg", item.threshold ? props.context.theme.text.feedback.warning.base : props.context.theme.text.muted, _$p));
|
|
2835
|
+
return _el$6;
|
|
2836
|
+
})()
|
|
2837
|
+
}), null);
|
|
2838
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2839
|
+
get each() {
|
|
2840
|
+
return contextHistoryLegend.flatMap((line) => wrap(line, props.width));
|
|
2841
|
+
},
|
|
2842
|
+
children: (line) => (() => {
|
|
2843
|
+
var _el$8 = _$createElement3("text");
|
|
2844
|
+
_$insert3(_el$8, line);
|
|
2845
|
+
_$effect3((_$p) => _$setProp3(_el$8, "fg", props.context.theme.text.muted, _$p));
|
|
2846
|
+
return _el$8;
|
|
2847
|
+
})()
|
|
2848
|
+
}), null);
|
|
2849
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2850
|
+
get each() {
|
|
2851
|
+
return detail();
|
|
2852
|
+
},
|
|
2853
|
+
children: (line) => (() => {
|
|
2854
|
+
var _el$9 = _$createElement3("text");
|
|
2855
|
+
_$insert3(_el$9, line);
|
|
2856
|
+
_$effect3((_$p) => _$setProp3(_el$9, "fg", props.context.theme.text.base, _$p));
|
|
2857
|
+
return _el$9;
|
|
2858
|
+
})()
|
|
2859
|
+
}), null);
|
|
2860
|
+
_$effect3((_$p) => _$setProp3(_el$4, "fg", props.context.theme.text.base, _$p));
|
|
2861
|
+
return _el$3;
|
|
2862
|
+
})();
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2418
2865
|
// src/tui/panel.tsx
|
|
2866
|
+
init_panelformat();
|
|
2419
2867
|
init_chartformat();
|
|
2420
2868
|
init_format();
|
|
2869
|
+
init_statusformat();
|
|
2870
|
+
|
|
2871
|
+
// src/tui/panelcontrols.ts
|
|
2872
|
+
init_format();
|
|
2873
|
+
function inventoryMessages(status) {
|
|
2874
|
+
if (status.scanning)
|
|
2875
|
+
return [`Discovering agents \xB7 ${status.discovered} found`];
|
|
2876
|
+
const lines = [];
|
|
2877
|
+
if (status.failed || status.damaged)
|
|
2878
|
+
lines.push("Family discovery incomplete \xB7 refresh to rescan");
|
|
2879
|
+
if (status.pending && status.discovered >= 2048)
|
|
2880
|
+
lines.push("Partial family \xB7 2048-node limit reached");
|
|
2881
|
+
else if (status.canLoadMore)
|
|
2882
|
+
lines.push(status.discovered >= status.limit ? `Partial family \xB7 ${status.limit}-node limit \xB7 load more allows 2048` : "Partial family \xB7 load more available");
|
|
2883
|
+
else if (!status.complete && !lines.length)
|
|
2884
|
+
lines.push("Family discovery incomplete \xB7 refresh to rescan");
|
|
2885
|
+
return lines;
|
|
2886
|
+
}
|
|
2887
|
+
function footerActions(essential, optional, width) {
|
|
2888
|
+
const result = [];
|
|
2889
|
+
let used = 0;
|
|
2890
|
+
for (const action of [...essential, ...optional]) {
|
|
2891
|
+
const size = cells(action.label) + (result.length ? 1 : 0);
|
|
2892
|
+
if (used + size > width)
|
|
2893
|
+
continue;
|
|
2894
|
+
result.push(action);
|
|
2895
|
+
used += size;
|
|
2896
|
+
}
|
|
2897
|
+
return result;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
// src/tui/panel.tsx
|
|
2421
2901
|
function GuardPanel(props) {
|
|
2422
|
-
const
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
const
|
|
2902
|
+
const consumer = props.state.acquire(props.input.sessionID);
|
|
2903
|
+
createEffect3(on(() => props.input.sessionID, (id) => consumer.update(id)));
|
|
2904
|
+
onCleanup2(() => consumer.release());
|
|
2905
|
+
const [help, setHelp] = createSignal3(false);
|
|
2906
|
+
let sourceScroll = 0;
|
|
2907
|
+
const [view, setView] = createSignal3("overview");
|
|
2908
|
+
const [metricIndex, setMetricIndex] = createSignal3(0);
|
|
2909
|
+
const [viewportWidth, setViewportWidth] = createSignal3();
|
|
2910
|
+
const [height, setHeight] = createSignal3(24);
|
|
2911
|
+
const width = () => Math.max(1, Math.min(props.input.width - 4, viewportWidth() ?? Infinity));
|
|
2912
|
+
const compact = () => height() < 18;
|
|
2426
2913
|
const windows = [300000, 3600000, 86400000, 7 * 86400000];
|
|
2427
|
-
const [windowIndex, setWindowIndex] =
|
|
2428
|
-
const [chartRefresh, setChartRefresh] =
|
|
2429
|
-
const [
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2914
|
+
const [windowIndex, setWindowIndex] = createSignal3(1);
|
|
2915
|
+
const [chartRefresh, setChartRefresh] = createSignal3(0);
|
|
2916
|
+
const [chartView, setChartView] = createSignal3({
|
|
2917
|
+
status: "idle",
|
|
2918
|
+
stale: false
|
|
2919
|
+
});
|
|
2920
|
+
const history = new HistoryState({
|
|
2921
|
+
read: (id, from, to, signal) => props.state.history(id, from, to, signal),
|
|
2922
|
+
changed: setChartView
|
|
2923
|
+
});
|
|
2924
|
+
history.pause();
|
|
2925
|
+
onCleanup2(() => history.dispose());
|
|
2926
|
+
const [selected, setSelected] = createSignal3(props.input.sessionID);
|
|
2927
|
+
const [order, setOrder] = createSignal3([]);
|
|
2928
|
+
const rows = createMemo4(() => props.state.rows(order()));
|
|
2929
|
+
const family = createMemo4(() => routeFamily(props.state.rows([], true), props.input.sessionID));
|
|
2930
|
+
const selectedRow = createMemo4(() => rows().find((row2) => row2.node.sessionId === selected()));
|
|
2931
|
+
createEffect3(on(() => {
|
|
2932
|
+
const id = selected();
|
|
2933
|
+
return id ? [id, windows[windowIndex()] ?? 3600000, props.state.historyLocation(id)] : undefined;
|
|
2934
|
+
}, (query) => {
|
|
2935
|
+
if (query)
|
|
2936
|
+
history.setQuery({
|
|
2937
|
+
sessionId: query[0],
|
|
2938
|
+
windowMs: query[1],
|
|
2939
|
+
location: query[2]
|
|
2940
|
+
});
|
|
2941
|
+
}));
|
|
2942
|
+
createEffect3(on(chartRefresh, () => history.refresh(), {
|
|
2943
|
+
defer: true
|
|
2944
|
+
}));
|
|
2433
2945
|
const offset = () => Math.max(0, rows().findIndex((row2) => row2.node.sessionId === selected()));
|
|
2434
|
-
|
|
2946
|
+
const trace = createMemo4(() => props.state.contextTrace(selectedRow()));
|
|
2947
|
+
createEffect3(() => {
|
|
2948
|
+
const current = rows().find((row2) => row2.node.sessionId === props.input.sessionID);
|
|
2949
|
+
if (current && current.node.sessionId !== selected())
|
|
2950
|
+
props.state.contextTrace(current);
|
|
2951
|
+
});
|
|
2952
|
+
createEffect3(() => {
|
|
2435
2953
|
if (!props.input.focused)
|
|
2436
2954
|
setOrder([]);
|
|
2437
2955
|
});
|
|
2438
|
-
|
|
2439
|
-
|
|
2956
|
+
createEffect3(on(() => props.input.sessionID, (id) => {
|
|
2957
|
+
history.pause();
|
|
2958
|
+
setSelected(id);
|
|
2440
2959
|
setOrder([]);
|
|
2960
|
+
setHelp(false);
|
|
2961
|
+
sourceScroll = 0;
|
|
2962
|
+
setView("overview");
|
|
2963
|
+
}));
|
|
2964
|
+
createEffect3(() => {
|
|
2965
|
+
const family2 = rows();
|
|
2966
|
+
if (!family2.some((row2) => row2.node.sessionId === selected()))
|
|
2967
|
+
setSelected(family2.find((row2) => row2.node.sessionId === props.input.sessionID)?.node.sessionId ?? family2[0]?.node.sessionId);
|
|
2441
2968
|
});
|
|
2442
2969
|
let scroll;
|
|
2443
2970
|
let follow;
|
|
2444
|
-
function
|
|
2971
|
+
function cancelFollow() {
|
|
2445
2972
|
if (follow)
|
|
2446
2973
|
props.context.renderer.removeFrameCallback(follow);
|
|
2974
|
+
follow = undefined;
|
|
2975
|
+
}
|
|
2976
|
+
function afterLayout(action) {
|
|
2977
|
+
if (!props.context.renderer)
|
|
2978
|
+
return;
|
|
2979
|
+
cancelFollow();
|
|
2447
2980
|
let frames = 0;
|
|
2448
2981
|
follow = async () => {
|
|
2449
|
-
|
|
2450
|
-
if (++frames >= 2
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
} else
|
|
2982
|
+
action();
|
|
2983
|
+
if (++frames >= 2)
|
|
2984
|
+
cancelFollow();
|
|
2985
|
+
else
|
|
2454
2986
|
props.context.renderer.requestRender();
|
|
2455
2987
|
};
|
|
2456
2988
|
props.context.renderer.setFrameCallback(follow);
|
|
2457
2989
|
props.context.renderer.requestRender();
|
|
2458
2990
|
}
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2991
|
+
function revealSelection() {
|
|
2992
|
+
afterLayout(() => scroll?.scrollChildIntoView(`context-guard.row.${selected()}`));
|
|
2993
|
+
}
|
|
2994
|
+
function toggleHelp() {
|
|
2995
|
+
cancelFollow();
|
|
2996
|
+
if (!help()) {
|
|
2997
|
+
if (view() === "charts")
|
|
2998
|
+
history.pause();
|
|
2999
|
+
sourceScroll = scroll?.scrollTop ?? 0;
|
|
3000
|
+
setHelp(true);
|
|
3001
|
+
afterLayout(() => scroll?.scrollTo(0));
|
|
3002
|
+
} else {
|
|
3003
|
+
setHelp(false);
|
|
3004
|
+
if (view() === "charts")
|
|
3005
|
+
history.resume();
|
|
3006
|
+
afterLayout(() => scroll?.scrollTo(sourceScroll));
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
onCleanup2(cancelFollow);
|
|
3010
|
+
createEffect3(() => {
|
|
3011
|
+
view();
|
|
3012
|
+
selected();
|
|
3013
|
+
rows();
|
|
3014
|
+
width();
|
|
3015
|
+
height();
|
|
3016
|
+
if (!help() && view() === "overview")
|
|
3017
|
+
revealSelection();
|
|
2462
3018
|
});
|
|
3019
|
+
function changeView(next) {
|
|
3020
|
+
if (next !== "overview" && !selectedRow())
|
|
3021
|
+
return;
|
|
3022
|
+
cancelFollow();
|
|
3023
|
+
if (view() === "charts" && next !== "charts")
|
|
3024
|
+
history.pause();
|
|
3025
|
+
setView(next);
|
|
3026
|
+
if (next === "charts")
|
|
3027
|
+
history.resume();
|
|
3028
|
+
scroll?.scrollTo(0);
|
|
3029
|
+
if (next === "overview")
|
|
3030
|
+
revealSelection();
|
|
3031
|
+
}
|
|
2463
3032
|
function move(delta) {
|
|
2464
3033
|
setOrder(rows().map((row3) => row3.node.sessionId));
|
|
2465
3034
|
const row2 = rows()[Math.max(0, Math.min(rows().length - 1, offset() + delta))];
|
|
2466
|
-
if (row2)
|
|
3035
|
+
if (row2)
|
|
2467
3036
|
setSelected(row2.node.sessionId);
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
}
|
|
3037
|
+
if (view() === "charts")
|
|
3038
|
+
scroll?.scrollTo(0);
|
|
2471
3039
|
}
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
run: () => {
|
|
2505
|
-
if (showCharts())
|
|
2506
|
-
setWindowIndex((i) => Math.max(0, i - 1));
|
|
2507
|
-
}
|
|
2508
|
-
}, {
|
|
2509
|
-
id: "context-guard.chart-longer",
|
|
2510
|
-
title: "Longer chart window",
|
|
2511
|
-
bind: "]",
|
|
2512
|
-
run: () => {
|
|
2513
|
-
if (showCharts())
|
|
2514
|
-
setWindowIndex((i) => Math.min(windows.length - 1, i + 1));
|
|
2515
|
-
}
|
|
2516
|
-
}, {
|
|
2517
|
-
id: "context-guard.inspect",
|
|
2518
|
-
title: "Inspect selected session",
|
|
2519
|
-
bind: "i",
|
|
2520
|
-
run: () => setInspectId(inspectId() === selected() ? undefined : selected())
|
|
2521
|
-
}, {
|
|
2522
|
-
id: "context-guard.refresh",
|
|
2523
|
-
title: "Refresh Context Guard",
|
|
2524
|
-
bind: "r",
|
|
2525
|
-
run: () => {
|
|
2526
|
-
setOrder([]);
|
|
2527
|
-
props.state.refresh();
|
|
2528
|
-
setChartRefresh((n) => n + 1);
|
|
2529
|
-
}
|
|
2530
|
-
}, {
|
|
2531
|
-
id: "context-guard.load-more",
|
|
2532
|
-
title: "Load more family",
|
|
2533
|
-
bind: "l",
|
|
2534
|
-
run: () => props.state.loadMore()
|
|
2535
|
-
}, {
|
|
2536
|
-
id: "context-guard.next",
|
|
2537
|
-
bind: "down",
|
|
2538
|
-
run: () => move(1)
|
|
2539
|
-
}, {
|
|
2540
|
-
id: "context-guard.previous",
|
|
2541
|
-
bind: "up",
|
|
2542
|
-
run: () => move(-1)
|
|
2543
|
-
}, {
|
|
2544
|
-
id: "context-guard.expand",
|
|
2545
|
-
bind: "space",
|
|
3040
|
+
function open(row2) {
|
|
3041
|
+
if (!row2)
|
|
3042
|
+
return;
|
|
3043
|
+
props.input.close();
|
|
3044
|
+
props.context.ui.router.navigate({
|
|
3045
|
+
type: "session",
|
|
3046
|
+
sessionID: row2.node.sessionId
|
|
3047
|
+
});
|
|
3048
|
+
}
|
|
3049
|
+
function page(delta) {
|
|
3050
|
+
if (!help() && view() === "overview")
|
|
3051
|
+
move(delta * Math.max(1, Math.floor((scroll?.viewport.height ?? 1) / (width() >= 72 ? 1 : 3))));
|
|
3052
|
+
else
|
|
3053
|
+
scroll?.scrollBy(delta * Math.max(1, (scroll.viewport.height ?? 1) - 1));
|
|
3054
|
+
}
|
|
3055
|
+
function edge(last) {
|
|
3056
|
+
if (!help() && view() === "overview")
|
|
3057
|
+
move(last ? rows().length : -rows().length);
|
|
3058
|
+
else
|
|
3059
|
+
scroll?.scrollTo(last ? scroll.scrollHeight : 0);
|
|
3060
|
+
}
|
|
3061
|
+
const inventory = () => props.state.inventoryStatus();
|
|
3062
|
+
const expandable = () => {
|
|
3063
|
+
const row2 = selectedRow();
|
|
3064
|
+
return !!row2 && (row2.hidden > 0 || row2.node.status === "completed" && rows().some((r) => r.node.parentId === row2.node.sessionId));
|
|
3065
|
+
};
|
|
3066
|
+
function command(name, title, bind, run, enabled = () => !help()) {
|
|
3067
|
+
return {
|
|
3068
|
+
id: `context-guard.${name}`,
|
|
3069
|
+
title,
|
|
3070
|
+
bind,
|
|
3071
|
+
enabled,
|
|
2546
3072
|
run: () => {
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
props.state.expand(row2.node.sessionId);
|
|
3073
|
+
if (props.input.focused && enabled())
|
|
3074
|
+
run();
|
|
2550
3075
|
}
|
|
2551
|
-
}
|
|
2552
|
-
|
|
2553
|
-
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
const commands = () => [command("close", "Close Context Guard", "q", () => props.input.close(), () => true), command("help", "Toggle native panel help", "?", toggleHelp, () => true), command("help-back", "Return from help", "escape", toggleHelp, help), command("chart-previous", "Previous chart metric", "left", () => setMetricIndex((i) => (i + chartMetrics.length - 1) % chartMetrics.length), () => !help() && view() === "charts"), command("chart-next", "Next chart metric", "right", () => setMetricIndex((i) => (i + 1) % chartMetrics.length), () => !help() && view() === "charts"), command("charts", "Toggle performance charts", "c", () => changeView(view() === "charts" ? "overview" : "charts"), () => !help() && !!selectedRow()), command("chart-shorter", "Shorter chart window", "[", () => setWindowIndex((i) => Math.max(0, i - 1)), () => !help() && view() === "charts"), command("chart-longer", "Longer chart window", "]", () => setWindowIndex((i) => Math.min(windows.length - 1, i + 1)), () => !help() && view() === "charts"), command("inspect", "Toggle selected session details", "i", () => changeView(view() === "details" ? "overview" : "details"), () => !help() && !!selectedRow()), command("refresh", "Refresh inventory, measurements and active charts", "r", () => {
|
|
3079
|
+
setOrder([]);
|
|
3080
|
+
props.state.refresh();
|
|
3081
|
+
setChartRefresh((n) => n + 1);
|
|
3082
|
+
}), command("load-more", "Load more family", "l", () => props.state.loadMore(), () => !help() && view() === "overview" && inventory().canLoadMore), command("next", "Next session or scroll down", "down", () => help() || view() === "details" ? scroll?.scrollBy(1) : move(1), () => true), command("previous", "Previous session or scroll up", "up", () => help() || view() === "details" ? scroll?.scrollBy(-1) : move(-1), () => true), command("page-next", "Next page", "pagedown", () => page(1), () => true), command("page-previous", "Previous page", "pageup", () => page(-1), () => true), command("first", "First row or top", "home", () => edge(false), () => true), command("last", "Last row or bottom", "end", () => edge(true), () => true), command("expand", "Toggle selected branch", "space", () => {
|
|
3083
|
+
const row2 = selectedRow();
|
|
3084
|
+
if (row2)
|
|
3085
|
+
props.state.expand(row2.node.sessionId);
|
|
3086
|
+
}, () => !help() && view() === "overview" && expandable()), command("open", "Open selected session", "return", () => open(selectedRow()), () => !help() && !!selectedRow())];
|
|
3087
|
+
props.context.keymap.layer(() => ({
|
|
3088
|
+
enabled: () => props.input.focused,
|
|
3089
|
+
commands: commands()
|
|
3090
|
+
}));
|
|
3091
|
+
const shortcut = (name) => props.context.keymap.shortcuts(`context-guard.${name}`).join("/");
|
|
3092
|
+
const helpLines = () => ["Native OpenCode panel \u2014 keyboard help", `Return to ${view()}; selected session: ${selectedRow()?.node.agent ?? selected() ?? "none"}`, "> marks selection; * marks the current OpenCode route. Open selected session navigates there and closes the panel.", "Overview: arrows select agents. Details: arrows scroll. Charts: arrows select sessions; Left/Right changes metric and brackets change window.", "PageUp/PageDown moves selection in Overview and scrolls Details/Charts/help. Home/End reaches the first/last row or top/bottom.", "Space toggles a branch in Overview. Load more resumes pending family discovery when available.", ...inventoryMessages(inventory()), `Discovered ${inventory().discovered} \xB7 node limit ${inventory().limit} \xB7 pages ${inventory().pages} \xB7 pending branches ${inventory().pending}`, "Refresh rescans inventory and measurements; it cannot resume suspended enforcement. Reload/repair instructions remain in Guard status.", "Configured native bindings (unbound actions have no shortcut):", ...commands().map((c) => `${props.context.keymap.shortcuts(c.id ?? "").join(" / ") || "Unbound"}: ${c.title}`), "Default bindings differ: native l loads more; standalone l edits location. Native brackets change windows; standalone brackets inspect observations and w changes windows.", "Open Context Guard is also available in the root prompt slash menu and command palette. Set the client plugin option openShortcut for keyboard entry from a child composer.", "End of native panel help"].flatMap((line) => wrap(line, width()));
|
|
3093
|
+
const statusLines = () => monitorStatusLines(props.state.connection(), props.state.health(), rows().some((row2) => row2.snapshot?.measurement !== undefined), width() < 28).flatMap((line) => wrap(line, width()));
|
|
3094
|
+
const notice = () => compactionLabel(selectedRow());
|
|
3095
|
+
const actions = () => {
|
|
3096
|
+
const action = (name, label) => ({
|
|
3097
|
+
id: name,
|
|
3098
|
+
label: ["help", "close"].includes(name) && cells(`${shortcut(name)} ${label}`) > Math.floor((width() - 1) / 2) ? label : `${shortcut(name) ? shortcut(name) + " " : ""}${label}`,
|
|
2554
3099
|
run: () => {
|
|
2555
|
-
|
|
2556
|
-
if (row2) {
|
|
2557
|
-
props.input.close();
|
|
2558
|
-
props.context.ui.router.navigate({
|
|
2559
|
-
type: "session",
|
|
2560
|
-
sessionID: row2.node.sessionId
|
|
2561
|
-
});
|
|
2562
|
-
}
|
|
3100
|
+
commands().find((c) => c.id === `context-guard.${name}`)?.run();
|
|
2563
3101
|
}
|
|
2564
|
-
}
|
|
2565
|
-
|
|
2566
|
-
|
|
3102
|
+
});
|
|
3103
|
+
const optional = help() ? [action("help-back", "back")] : [...view() === "overview" && inventory().canLoadMore ? [action("load-more", "more")] : [], ...view() === "charts" ? [action("charts", "back")] : [], ...selectedRow() ? [action("inspect", view() === "details" ? "back" : "details")] : [], ...view() !== "charts" && selectedRow() ? [action("charts", "charts")] : [], ...view() === "overview" && expandable() ? [action("expand", "branch")] : []];
|
|
3104
|
+
return footerActions([action("help", help() ? "back" : "help"), action("close", "close")], optional, width());
|
|
3105
|
+
};
|
|
3106
|
+
const hint = () => {
|
|
3107
|
+
if (help())
|
|
3108
|
+
return `${shortcut("previous")}/${shortcut("next")} scroll`;
|
|
3109
|
+
if (view() === "charts")
|
|
3110
|
+
return `${shortcut("refresh")} refresh \xB7 ${shortcut("chart-previous")}/${shortcut("chart-next")} metric ${shortcut("previous")}/${shortcut("next")} session ${shortcut("chart-shorter")}/${shortcut("chart-longer")} window`;
|
|
3111
|
+
if (view() === "details")
|
|
3112
|
+
return `${shortcut("previous")}/${shortcut("next")} scroll \xB7 ${shortcut("page-previous")}/${shortcut("page-next")} page`;
|
|
3113
|
+
return `${shortcut("previous")}/${shortcut("next")} select \xB7 ${shortcut("open")} open \xB7 ${inventory().canLoadMore ? shortcut("load-more") + " more" : shortcut("refresh") + " refresh"}`;
|
|
3114
|
+
};
|
|
2567
3115
|
return (() => {
|
|
2568
|
-
var _el$ = _$createElement4("box"), _el$2 = _$createElement4("
|
|
3116
|
+
var _el$ = _$createElement4("box"), _el$2 = _$createElement4("box"), _el$3 = _$createElement4("text"), _el$6 = _$createElement4("scrollbox"), _el$7 = _$createElement4("box"), _el$8 = _$createElement4("box"), _el$9 = _$createElement4("text");
|
|
2569
3117
|
_$insertNode4(_el$, _el$2);
|
|
2570
|
-
_$insertNode4(_el$, _el$
|
|
3118
|
+
_$insertNode4(_el$, _el$6);
|
|
3119
|
+
_$insertNode4(_el$, _el$7);
|
|
2571
3120
|
_$setProp4(_el$, "flexDirection", "column");
|
|
2572
3121
|
_$setProp4(_el$, "flexGrow", 1);
|
|
3122
|
+
_$setProp4(_el$, "minHeight", 0);
|
|
2573
3123
|
_$setProp4(_el$, "paddingLeft", 2);
|
|
2574
3124
|
_$setProp4(_el$, "paddingRight", 2);
|
|
2575
|
-
_$setProp4(_el$, "
|
|
2576
|
-
|
|
3125
|
+
_$setProp4(_el$, "onSizeChange", function() {
|
|
3126
|
+
setHeight(this.height);
|
|
3127
|
+
});
|
|
2577
3128
|
_$insertNode4(_el$2, _el$3);
|
|
3129
|
+
_$setProp4(_el$2, "flexDirection", "column");
|
|
3130
|
+
_$setProp4(_el$2, "flexShrink", 0);
|
|
3131
|
+
_$insert4(_el$3, () => clip(width() < 28 ? `${connectionLabel(props.state.connection(), true)} \xB7 Guard` : `${connectionLabel(props.state.connection())} \xB7 Context Guard \xB7 ${help() ? "help" : view()}`, width()));
|
|
3132
|
+
_$insert4(_el$2, _$createComponent5(For4, {
|
|
3133
|
+
get each() {
|
|
3134
|
+
return statusLines();
|
|
3135
|
+
},
|
|
3136
|
+
children: (line) => (() => {
|
|
3137
|
+
var _el$0 = _$createElement4("text");
|
|
3138
|
+
_$insert4(_el$0, line);
|
|
3139
|
+
_$effect4((_$p) => _$setProp4(_el$0, "fg", props.state.health()?.enforcement === "suspended" || props.state.health()?.enforcement === "disabled" ? props.context.theme.text.feedback.warning.base : props.context.theme.text.muted, _$p));
|
|
3140
|
+
return _el$0;
|
|
3141
|
+
})()
|
|
3142
|
+
}), null);
|
|
3143
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3144
|
+
get when() {
|
|
3145
|
+
return !["2.0.29", "2.1.2"].includes(props.context.app.version);
|
|
3146
|
+
},
|
|
3147
|
+
get children() {
|
|
3148
|
+
var _el$4 = _$createElement4("text");
|
|
3149
|
+
_$insert4(_el$4, () => clip(`Runtime ${props.context.app.version}: unverified`, width()));
|
|
3150
|
+
_$effect4((_$p) => _$setProp4(_el$4, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
3151
|
+
return _el$4;
|
|
3152
|
+
}
|
|
3153
|
+
}), null);
|
|
3154
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3155
|
+
get when() {
|
|
3156
|
+
return notice();
|
|
3157
|
+
},
|
|
3158
|
+
children: (message) => (() => {
|
|
3159
|
+
var _el$1 = _$createElement4("text");
|
|
3160
|
+
_$insert4(_el$1, () => clip(message(), width()));
|
|
3161
|
+
_$effect4((_$p) => _$setProp4(_el$1, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
3162
|
+
return _el$1;
|
|
3163
|
+
})()
|
|
3164
|
+
}), null);
|
|
3165
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3166
|
+
get when() {
|
|
3167
|
+
return _$memo2(() => !!(help() || view() !== "overview"))() && selectedRow();
|
|
3168
|
+
},
|
|
3169
|
+
children: (row2) => (() => {
|
|
3170
|
+
var _el$10 = _$createElement4("text");
|
|
3171
|
+
_$insert4(_el$10, () => clip(`Selected: ${row2().node.agent ?? row2().node.sessionId}`, width()));
|
|
3172
|
+
_$effect4((_$p) => _$setProp4(_el$10, "fg", props.context.theme.text.base, _$p));
|
|
3173
|
+
return _el$10;
|
|
3174
|
+
})()
|
|
3175
|
+
}), null);
|
|
3176
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3177
|
+
get when() {
|
|
3178
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
3179
|
+
},
|
|
3180
|
+
get children() {
|
|
3181
|
+
return [_$createComponent5(For4, {
|
|
3182
|
+
get each() {
|
|
3183
|
+
return panelSummary(selectedRow(), width(), props.state.age(selected() ?? ""), compact());
|
|
3184
|
+
},
|
|
3185
|
+
children: (line) => (() => {
|
|
3186
|
+
var _el$11 = _$createElement4("text");
|
|
3187
|
+
_$insert4(_el$11, line);
|
|
3188
|
+
_$effect4((_$p) => _$setProp4(_el$11, "fg", props.context.theme.text.base, _$p));
|
|
3189
|
+
return _el$11;
|
|
3190
|
+
})()
|
|
3191
|
+
}), (() => {
|
|
3192
|
+
var _el$5 = _$createElement4("text");
|
|
3193
|
+
_$insert4(_el$5, () => panelRowHeading(`Family ${rows().length ? offset() + 1 : 0}/${rows().length}${props.state.complete() ? "" : " \xB7 partial"} \xB7 * current`, width()));
|
|
3194
|
+
_$effect4((_$p) => _$setProp4(_el$5, "fg", props.context.theme.text.muted, _$p));
|
|
3195
|
+
return _el$5;
|
|
3196
|
+
})()];
|
|
3197
|
+
}
|
|
3198
|
+
}), null);
|
|
3199
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3200
|
+
get when() {
|
|
3201
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
3202
|
+
},
|
|
3203
|
+
get children() {
|
|
3204
|
+
return _$createComponent5(For4, {
|
|
3205
|
+
get each() {
|
|
3206
|
+
return inventoryMessages(inventory());
|
|
3207
|
+
},
|
|
3208
|
+
children: (line) => (() => {
|
|
3209
|
+
var _el$12 = _$createElement4("text");
|
|
3210
|
+
_$insert4(_el$12, () => clip(line, width()));
|
|
3211
|
+
_$effect4((_$p) => _$setProp4(_el$12, "fg", props.context.theme.text.muted, _$p));
|
|
3212
|
+
return _el$12;
|
|
3213
|
+
})()
|
|
3214
|
+
});
|
|
3215
|
+
}
|
|
3216
|
+
}), null);
|
|
2578
3217
|
_$use((value) => {
|
|
2579
3218
|
scroll = value;
|
|
2580
|
-
}, _el$
|
|
2581
|
-
_$setProp4(_el$
|
|
3219
|
+
}, _el$6);
|
|
3220
|
+
_$setProp4(_el$6, "viewportOptions", {
|
|
2582
3221
|
onSizeChange: function() {
|
|
2583
3222
|
setViewportWidth(this.width);
|
|
2584
3223
|
}
|
|
2585
3224
|
});
|
|
2586
|
-
_$setProp4(_el$
|
|
2587
|
-
_$setProp4(_el$
|
|
2588
|
-
_$
|
|
2589
|
-
_$
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
return props.input.sessionID;
|
|
2593
|
-
},
|
|
2594
|
-
get state() {
|
|
2595
|
-
return props.state;
|
|
2596
|
-
},
|
|
2597
|
-
get context() {
|
|
2598
|
-
return props.context;
|
|
2599
|
-
},
|
|
2600
|
-
get width() {
|
|
2601
|
-
return width();
|
|
2602
|
-
},
|
|
2603
|
-
expanded: true,
|
|
2604
|
-
get family() {
|
|
2605
|
-
return rows();
|
|
2606
|
-
},
|
|
2607
|
-
get selectedId() {
|
|
2608
|
-
return selected();
|
|
3225
|
+
_$setProp4(_el$6, "flexGrow", 1);
|
|
3226
|
+
_$setProp4(_el$6, "minHeight", 0);
|
|
3227
|
+
_$setProp4(_el$6, "scrollX", false);
|
|
3228
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3229
|
+
get when() {
|
|
3230
|
+
return help();
|
|
2609
3231
|
},
|
|
2610
|
-
get
|
|
2611
|
-
return
|
|
3232
|
+
get children() {
|
|
3233
|
+
return _$createComponent5(For4, {
|
|
3234
|
+
get each() {
|
|
3235
|
+
return helpLines();
|
|
3236
|
+
},
|
|
3237
|
+
children: (line) => (() => {
|
|
3238
|
+
var _el$13 = _$createElement4("text");
|
|
3239
|
+
_$insert4(_el$13, line);
|
|
3240
|
+
_$effect4((_$p) => _$setProp4(_el$13, "fg", props.context.theme.text.base, _$p));
|
|
3241
|
+
return _el$13;
|
|
3242
|
+
})()
|
|
3243
|
+
});
|
|
2612
3244
|
}
|
|
2613
|
-
}),
|
|
2614
|
-
_$insert4(_el$
|
|
2615
|
-
_$insert4(_el$2, _$createComponent4(Show3, {
|
|
3245
|
+
}), null);
|
|
3246
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
2616
3247
|
get when() {
|
|
2617
|
-
return
|
|
3248
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
2618
3249
|
},
|
|
2619
3250
|
get children() {
|
|
2620
|
-
return _$
|
|
2621
|
-
get
|
|
3251
|
+
return _$createComponent5(PanelOverview, {
|
|
3252
|
+
get rows() {
|
|
3253
|
+
return rows();
|
|
3254
|
+
},
|
|
3255
|
+
get selectedId() {
|
|
2622
3256
|
return selected();
|
|
2623
3257
|
},
|
|
2624
|
-
get
|
|
2625
|
-
return
|
|
3258
|
+
get width() {
|
|
3259
|
+
return width();
|
|
3260
|
+
},
|
|
3261
|
+
get context() {
|
|
3262
|
+
return props.context;
|
|
3263
|
+
},
|
|
3264
|
+
open: (row2) => {
|
|
3265
|
+
if (row2.hidden)
|
|
3266
|
+
props.state.expand(row2.node.sessionId);
|
|
3267
|
+
else
|
|
3268
|
+
open(row2);
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3272
|
+
}), null);
|
|
3273
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3274
|
+
get when() {
|
|
3275
|
+
return _$memo2(() => !!!help())() && view() === "details";
|
|
3276
|
+
},
|
|
3277
|
+
get children() {
|
|
3278
|
+
return _$createComponent5(PanelDetails, {
|
|
3279
|
+
get row() {
|
|
3280
|
+
return selectedRow();
|
|
3281
|
+
},
|
|
3282
|
+
get rows() {
|
|
3283
|
+
return rows();
|
|
3284
|
+
},
|
|
3285
|
+
get routeID() {
|
|
3286
|
+
return props.input.sessionID;
|
|
2626
3287
|
},
|
|
2627
|
-
get
|
|
2628
|
-
return
|
|
3288
|
+
get familyRows() {
|
|
3289
|
+
return family().rows;
|
|
2629
3290
|
},
|
|
2630
|
-
get
|
|
2631
|
-
return
|
|
3291
|
+
get familyComplete() {
|
|
3292
|
+
return _$memo2(() => !!family().complete)() && props.state.complete();
|
|
3293
|
+
},
|
|
3294
|
+
get trace() {
|
|
3295
|
+
return trace();
|
|
2632
3296
|
},
|
|
2633
3297
|
get width() {
|
|
2634
3298
|
return width();
|
|
2635
3299
|
},
|
|
2636
|
-
get
|
|
2637
|
-
return props.state;
|
|
3300
|
+
get age() {
|
|
3301
|
+
return props.state.age(selected() ?? "");
|
|
2638
3302
|
},
|
|
2639
3303
|
get context() {
|
|
2640
3304
|
return props.context;
|
|
3305
|
+
},
|
|
3306
|
+
get reasons() {
|
|
3307
|
+
return props.state.health()?.reasons ?? [];
|
|
2641
3308
|
}
|
|
2642
3309
|
});
|
|
2643
3310
|
}
|
|
2644
3311
|
}), null);
|
|
2645
|
-
_$
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
3312
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3313
|
+
get when() {
|
|
3314
|
+
return _$memo2(() => !!(!help() && view() === "charts"))() && selected();
|
|
3315
|
+
},
|
|
3316
|
+
children: (id) => _$createComponent5(HistoryCharts, {
|
|
3317
|
+
get sessionId() {
|
|
3318
|
+
return id();
|
|
3319
|
+
},
|
|
3320
|
+
get windowMs() {
|
|
3321
|
+
return windows[windowIndex()] ?? 3600000;
|
|
3322
|
+
},
|
|
3323
|
+
get metricIndex() {
|
|
3324
|
+
return metricIndex();
|
|
3325
|
+
},
|
|
3326
|
+
get width() {
|
|
3327
|
+
return width();
|
|
3328
|
+
},
|
|
3329
|
+
get view() {
|
|
3330
|
+
return chartView();
|
|
3331
|
+
},
|
|
3332
|
+
get context() {
|
|
3333
|
+
return props.context;
|
|
3334
|
+
}
|
|
3335
|
+
})
|
|
3336
|
+
}), null);
|
|
3337
|
+
_$insertNode4(_el$7, _el$8);
|
|
3338
|
+
_$insertNode4(_el$7, _el$9);
|
|
3339
|
+
_$setProp4(_el$7, "flexDirection", "column");
|
|
3340
|
+
_$setProp4(_el$7, "flexShrink", 0);
|
|
3341
|
+
_$setProp4(_el$8, "flexDirection", "row");
|
|
3342
|
+
_$setProp4(_el$8, "flexShrink", 0);
|
|
3343
|
+
_$insert4(_el$8, _$createComponent5(For4, {
|
|
2649
3344
|
get each() {
|
|
2650
|
-
return
|
|
3345
|
+
return actions();
|
|
2651
3346
|
},
|
|
2652
|
-
children: (
|
|
2653
|
-
var _el$
|
|
2654
|
-
_$insert4(_el$
|
|
2655
|
-
_$effect4((
|
|
2656
|
-
|
|
3347
|
+
children: (action, index) => (() => {
|
|
3348
|
+
var _el$14 = _$createElement4("text");
|
|
3349
|
+
_$insert4(_el$14, () => `${index() ? " " : ""}${action.label}`);
|
|
3350
|
+
_$effect4((_p$) => {
|
|
3351
|
+
var _v$5 = props.context.theme.text.muted, _v$6 = action.run;
|
|
3352
|
+
_v$5 !== _p$.e && (_p$.e = _$setProp4(_el$14, "fg", _v$5, _p$.e));
|
|
3353
|
+
_v$6 !== _p$.t && (_p$.t = _$setProp4(_el$14, "onMouseDown", _v$6, _p$.t));
|
|
3354
|
+
return _p$;
|
|
3355
|
+
}, {
|
|
3356
|
+
e: undefined,
|
|
3357
|
+
t: undefined
|
|
3358
|
+
});
|
|
3359
|
+
return _el$14;
|
|
2657
3360
|
})()
|
|
2658
3361
|
}));
|
|
3362
|
+
_$insert4(_el$9, () => clip(hint(), width()));
|
|
2659
3363
|
_$effect4((_p$) => {
|
|
2660
|
-
var _v$ =
|
|
2661
|
-
_v$ !== _p$.e && (_p$.e = _$setProp4(_el
|
|
2662
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp4(_el
|
|
3364
|
+
var _v$ = compact() ? 0 : 1, _v$2 = compact() ? 0 : 1, _v$3 = props.context.theme.text.base, _v$4 = props.context.theme.text.muted;
|
|
3365
|
+
_v$ !== _p$.e && (_p$.e = _$setProp4(_el$, "paddingTop", _v$, _p$.e));
|
|
3366
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp4(_el$, "paddingBottom", _v$2, _p$.t));
|
|
3367
|
+
_v$3 !== _p$.a && (_p$.a = _$setProp4(_el$3, "fg", _v$3, _p$.a));
|
|
3368
|
+
_v$4 !== _p$.o && (_p$.o = _$setProp4(_el$9, "fg", _v$4, _p$.o));
|
|
2663
3369
|
return _p$;
|
|
2664
3370
|
}, {
|
|
2665
3371
|
e: undefined,
|
|
2666
|
-
t: undefined
|
|
3372
|
+
t: undefined,
|
|
3373
|
+
a: undefined,
|
|
3374
|
+
o: undefined
|
|
2667
3375
|
});
|
|
2668
3376
|
return _el$;
|
|
2669
3377
|
})();
|
|
@@ -2673,14 +3381,18 @@ function GuardPanel(props) {
|
|
|
2673
3381
|
var tui_default = Plugin.define({
|
|
2674
3382
|
id: "context-guard",
|
|
2675
3383
|
setup(context) {
|
|
2676
|
-
|
|
3384
|
+
const openShortcut = context.options.openShortcut;
|
|
3385
|
+
if (openShortcut !== undefined && (typeof openShortcut !== "string" || !openShortcut.trim() || openShortcut.length > 128 || /[\x00-\x1f\x7f-\x9f]/.test(openShortcut))) {
|
|
3386
|
+
throw new Error("Context Guard openShortcut must be a nonempty key sequence of at most 128 characters.");
|
|
3387
|
+
}
|
|
3388
|
+
if (typeof context.client?.rpc !== "function" || typeof context.ui?.slot !== "function" || typeof context.ui?.panel?.open !== "function" || typeof context.keymap?.layer !== "function" || typeof context.keymap?.shortcuts !== "function") {
|
|
2677
3389
|
throw new Error("Context Guard TUI requires OpenCode 2.0.29 public RPC and panel APIs; use the Guard inspect CLI on unsupported hosts.");
|
|
2678
3390
|
}
|
|
2679
3391
|
const state = createGuardState(context), unregister = [];
|
|
2680
3392
|
try {
|
|
2681
3393
|
unregister.push(context.ui.slot({
|
|
2682
3394
|
append: "sidebar.content",
|
|
2683
|
-
render: (input) => _$
|
|
3395
|
+
render: (input) => _$createComponent6(GuardView, {
|
|
2684
3396
|
get sessionID() {
|
|
2685
3397
|
return input.sessionID;
|
|
2686
3398
|
},
|
|
@@ -2691,12 +3403,12 @@ var tui_default = Plugin.define({
|
|
|
2691
3403
|
}));
|
|
2692
3404
|
unregister.push(context.ui.slot({
|
|
2693
3405
|
append: "session.panel",
|
|
2694
|
-
render: (input) => _$
|
|
3406
|
+
render: (input) => _$createComponent6(Show4, {
|
|
2695
3407
|
get when() {
|
|
2696
3408
|
return input.name === "context-guard.monitor";
|
|
2697
3409
|
},
|
|
2698
3410
|
get children() {
|
|
2699
|
-
return _$
|
|
3411
|
+
return _$createComponent6(GuardPanel, {
|
|
2700
3412
|
input,
|
|
2701
3413
|
state,
|
|
2702
3414
|
context
|
|
@@ -2706,14 +3418,14 @@ var tui_default = Plugin.define({
|
|
|
2706
3418
|
}));
|
|
2707
3419
|
unregister.push(context.ui.slot({
|
|
2708
3420
|
append: "session.composer.top",
|
|
2709
|
-
render: (input) => _$
|
|
3421
|
+
render: (input) => _$createComponent6(Show4, {
|
|
2710
3422
|
get when() {
|
|
2711
3423
|
return context.data.session.get(input.sessionID)?.parentID;
|
|
2712
3424
|
},
|
|
2713
3425
|
get children() {
|
|
2714
3426
|
var _el$ = _$createElement5("text");
|
|
2715
|
-
_$insertNode5(_el$, _$createTextNode3(`Context Guard: open panel`));
|
|
2716
3427
|
_$setProp5(_el$, "onMouseDown", () => context.ui.panel.open("context-guard.monitor"));
|
|
3428
|
+
_$insert5(_el$, () => `Context Guard: open panel${context.keymap.shortcuts("context-guard.show").length ? ` (${context.keymap.shortcuts("context-guard.show").join(" / ")})` : ""}`);
|
|
2717
3429
|
_$effect5((_$p) => _$setProp5(_el$, "fg", context.theme.text.muted, _$p));
|
|
2718
3430
|
return _el$;
|
|
2719
3431
|
}
|
|
@@ -2726,7 +3438,9 @@ var tui_default = Plugin.define({
|
|
|
2726
3438
|
title: "Open Context Guard",
|
|
2727
3439
|
group: "Context Guard",
|
|
2728
3440
|
palette: true,
|
|
2729
|
-
|
|
3441
|
+
...typeof openShortcut === "string" ? {
|
|
3442
|
+
bind: openShortcut
|
|
3443
|
+
} : {},
|
|
2730
3444
|
slash: {
|
|
2731
3445
|
name: "context-guard"
|
|
2732
3446
|
},
|