@cesarus777/opencode-cgp 0.3.1 → 0.4.1
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 +38 -0
- package/README.md +23 -9
- package/dist/cli.js +1179 -92
- package/dist/core.js +49 -4
- package/dist/index.js +570 -9
- package/dist/rpc.js +129 -2
- package/dist/tui.js +1543 -707
- package/dist/types/adapter.d.ts +2 -0
- package/dist/types/core.d.ts +1 -0
- package/dist/types/dashboard/command.d.ts +1 -1
- package/dist/types/dashboard/connection.d.ts +2 -0
- package/dist/types/dashboard/controller.d.ts +4 -0
- package/dist/types/dashboard/models.d.ts +42 -0
- package/dist/types/dashboard/modelview.d.ts +30 -0
- package/dist/types/dashboard/port.d.ts +6 -0
- package/dist/types/dashboard/terminal.d.ts +7 -0
- package/dist/types/dashboard/terminalview.d.ts +7 -2
- package/dist/types/dashboard/view.d.ts +6 -1
- package/dist/types/history.d.ts +1 -0
- package/dist/types/historyclient.d.ts +15 -0
- package/dist/types/modelanalytics.d.ts +8 -0
- package/dist/types/modelanalyticsserver.d.ts +16 -0
- package/dist/types/modelseries.d.ts +43 -0
- package/dist/types/rpc.d.ts +28 -0
- package/dist/types/tui/chartformat.d.ts +1 -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 +1 -1
package/dist/tui.js
CHANGED
|
@@ -43,6 +43,12 @@ function isHistoryRead(value) {
|
|
|
43
43
|
function isHistoryResult(value) {
|
|
44
44
|
return valid(value, historyResultSchema);
|
|
45
45
|
}
|
|
46
|
+
function isAnalyticsRead(value) {
|
|
47
|
+
return valid(value, analyticsReadSchema) && record(value) && typeof value.from === "number" && typeof value.to === "number" && value.from < value.to && value.to - value.from <= 604800000 && !(value.model !== undefined && value.unknownModel === true) && (!(value.modelCursor || value.requestCursor) || typeof value.snapshotId === "string");
|
|
48
|
+
}
|
|
49
|
+
function isAnalyticsResult(value) {
|
|
50
|
+
return valid(value, analyticsResultSchema);
|
|
51
|
+
}
|
|
46
52
|
function record(x) {
|
|
47
53
|
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
48
54
|
}
|
|
@@ -100,7 +106,7 @@ var count, text, enumeration = (...values) => ({ type: "string", enum: values })
|
|
|
100
106
|
type: "array",
|
|
101
107
|
items,
|
|
102
108
|
maxItems
|
|
103
|
-
}), measurement, row, batchFields, readSchema, batchSchema, resultSchema, monitorRpc, nonnegative, performanceSchema, performanceRow, performanceBatchSchema, performanceResultSchema, performanceRpc, chartPointSchema, chartRequestSchema, historyReadSchema, historyResultSchema, historyRpc;
|
|
109
|
+
}), measurement, row, batchFields, readSchema, batchSchema, resultSchema, monitorRpc, nonnegative, performanceSchema, performanceRow, performanceBatchSchema, performanceResultSchema, performanceRpc, chartPointSchema, chartRequestSchema, historyReadSchema, historyResultSchema, historyRpc, modelSummarySchema, analyticsReadSchema, analyticsResultSchema, analyticsRpc;
|
|
104
110
|
var init_rpc = __esm(() => {
|
|
105
111
|
count = {
|
|
106
112
|
type: "integer",
|
|
@@ -336,6 +342,168 @@ var init_rpc = __esm(() => {
|
|
|
336
342
|
methods: { read: { input: historyReadSchema, output: historyResultSchema } },
|
|
337
343
|
events: {}
|
|
338
344
|
});
|
|
345
|
+
modelSummarySchema = object({
|
|
346
|
+
model: text,
|
|
347
|
+
sessions: count,
|
|
348
|
+
completedRequests: count,
|
|
349
|
+
partialRequests: count,
|
|
350
|
+
legacyAttributionRequests: count,
|
|
351
|
+
tpsRequests: count,
|
|
352
|
+
ttftRequests: count,
|
|
353
|
+
excludedTpsRequests: count,
|
|
354
|
+
excludedTtftRequests: count,
|
|
355
|
+
outputTokens: nonnegative,
|
|
356
|
+
durationMs: nonnegative,
|
|
357
|
+
averageTps: nonnegative,
|
|
358
|
+
meanTtftMs: nonnegative,
|
|
359
|
+
medianTtftMs: nonnegative,
|
|
360
|
+
p95TtftMs: nonnegative
|
|
361
|
+
}, [
|
|
362
|
+
"sessions",
|
|
363
|
+
"completedRequests",
|
|
364
|
+
"partialRequests",
|
|
365
|
+
"legacyAttributionRequests",
|
|
366
|
+
"tpsRequests",
|
|
367
|
+
"ttftRequests",
|
|
368
|
+
"excludedTpsRequests",
|
|
369
|
+
"excludedTtftRequests",
|
|
370
|
+
"outputTokens",
|
|
371
|
+
"durationMs"
|
|
372
|
+
]);
|
|
373
|
+
analyticsReadSchema = object({
|
|
374
|
+
schemaVersion: { const: 1 },
|
|
375
|
+
from: count,
|
|
376
|
+
to: count,
|
|
377
|
+
buckets: { type: "integer", minimum: 1, maximum: 240 },
|
|
378
|
+
agent: text,
|
|
379
|
+
model: text,
|
|
380
|
+
unknownModel: { type: "boolean" },
|
|
381
|
+
sort: enumeration("requests", "tps", "ttft", "identity"),
|
|
382
|
+
snapshotId: text,
|
|
383
|
+
modelCursor: text,
|
|
384
|
+
requestCursor: text
|
|
385
|
+
}, ["schemaVersion", "from", "to", "buckets"]);
|
|
386
|
+
analyticsResultSchema = object({
|
|
387
|
+
schemaVersion: { const: 1 },
|
|
388
|
+
generatedAt: count,
|
|
389
|
+
expiresAt: count,
|
|
390
|
+
snapshotId: text,
|
|
391
|
+
enabled: { type: "boolean" },
|
|
392
|
+
from: count,
|
|
393
|
+
to: count,
|
|
394
|
+
agent: text,
|
|
395
|
+
models: array(modelSummarySchema, 50),
|
|
396
|
+
totalModels: count,
|
|
397
|
+
nextModelsCursor: text,
|
|
398
|
+
selected: modelSummarySchema,
|
|
399
|
+
buckets: array(object({ from: nonnegative, to: nonnegative, summary: modelSummarySchema }, ["from", "to"]), 240),
|
|
400
|
+
requests: array(object({
|
|
401
|
+
location: text,
|
|
402
|
+
sessionId: text,
|
|
403
|
+
requestId: text,
|
|
404
|
+
startedAt: count,
|
|
405
|
+
completedAt: count,
|
|
406
|
+
model: text,
|
|
407
|
+
agent: text,
|
|
408
|
+
attribution: enumeration("request", "legacy-record", "unknown"),
|
|
409
|
+
partial: { type: "boolean" },
|
|
410
|
+
outputTokens: nonnegative,
|
|
411
|
+
ttftMs: nonnegative
|
|
412
|
+
}, [
|
|
413
|
+
"location",
|
|
414
|
+
"sessionId",
|
|
415
|
+
"requestId",
|
|
416
|
+
"startedAt",
|
|
417
|
+
"completedAt",
|
|
418
|
+
"attribution",
|
|
419
|
+
"partial"
|
|
420
|
+
]), 50),
|
|
421
|
+
nextRequestsCursor: text,
|
|
422
|
+
coverage: object({
|
|
423
|
+
source: enumeration("retained-request-records"),
|
|
424
|
+
scannedRecords: count,
|
|
425
|
+
unscannedRecords: count,
|
|
426
|
+
duplicateRecords: count,
|
|
427
|
+
conflictingRequests: count,
|
|
428
|
+
missingIdentityRecords: count,
|
|
429
|
+
incompleteRequests: count,
|
|
430
|
+
invalidTimingRequests: count,
|
|
431
|
+
gapRecords: count,
|
|
432
|
+
maxRequests: count,
|
|
433
|
+
partial: { type: "boolean" }
|
|
434
|
+
}),
|
|
435
|
+
metadata: historyResultSchema.properties.metadata ?? {},
|
|
436
|
+
gaps: array(count, 128),
|
|
437
|
+
omittedGaps: count
|
|
438
|
+
}, [
|
|
439
|
+
"schemaVersion",
|
|
440
|
+
"generatedAt",
|
|
441
|
+
"expiresAt",
|
|
442
|
+
"snapshotId",
|
|
443
|
+
"enabled",
|
|
444
|
+
"from",
|
|
445
|
+
"to",
|
|
446
|
+
"models",
|
|
447
|
+
"totalModels",
|
|
448
|
+
"buckets",
|
|
449
|
+
"requests",
|
|
450
|
+
"coverage",
|
|
451
|
+
"metadata",
|
|
452
|
+
"gaps",
|
|
453
|
+
"omittedGaps"
|
|
454
|
+
]);
|
|
455
|
+
analyticsRpc = Rpc.define({
|
|
456
|
+
id: "context-guard.analytics.v1",
|
|
457
|
+
methods: {
|
|
458
|
+
read: { input: analyticsReadSchema, output: analyticsResultSchema }
|
|
459
|
+
},
|
|
460
|
+
events: {}
|
|
461
|
+
});
|
|
462
|
+
});
|
|
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
|
+
};
|
|
339
507
|
});
|
|
340
508
|
|
|
341
509
|
// src/family.ts
|
|
@@ -716,6 +884,209 @@ var init_transport = __esm(() => {
|
|
|
716
884
|
init_rpc();
|
|
717
885
|
});
|
|
718
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
|
+
|
|
719
1090
|
// src/tui/format.ts
|
|
720
1091
|
function quantity(n) {
|
|
721
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);
|
|
@@ -743,22 +1114,6 @@ function clip(value, width) {
|
|
|
743
1114
|
}
|
|
744
1115
|
return width < 3 ? ".".repeat(Math.max(0, width)) : result + "...";
|
|
745
1116
|
}
|
|
746
|
-
function rowLines(row2, width) {
|
|
747
|
-
const s = row2.snapshot, m = s?.measurement;
|
|
748
|
-
const prefix = row2.current ? "* " : row2.depth > 5 ? ".../" : " ".repeat(Math.min(row2.depth, 5)) + "|-";
|
|
749
|
-
const percent = row2.utilizationPercent === undefined ? "?" : `${row2.utilizationPercent.toFixed(1)}%`;
|
|
750
|
-
const warning = row2.freshness === "stale" ? " STALE" : row2.pressure === "crossed" ? " !! crossed" : row2.pressure === "near" ? " ! near" : "";
|
|
751
|
-
const suffix = ` ${statuses[row2.node.status]} ${m?.confidence === "approximate" ? "~" : ""}${percent}${warning}`;
|
|
752
|
-
const label = clip(`${prefix}${row2.node.agent ?? row2.node.sessionId}`, Math.max(1, width - cells(suffix)));
|
|
753
|
-
return [
|
|
754
|
-
clip(`${label}${suffix}`, width),
|
|
755
|
-
...performanceLines(row2, width),
|
|
756
|
-
...wrap(`${quantity(m?.tokens)}/${quantity(s?.capacityTokens)} input; to ${quantity(row2.triggerDeltaTokens)}`, width),
|
|
757
|
-
...s && s.compaction.phase !== "idle" ? wrap(`compact: ${s.compaction.phase}`, width) : [],
|
|
758
|
-
...row2.node.interrupted ? [clip("interrupted", width)] : [],
|
|
759
|
-
...row2.hidden ? wrap(`+ ${row2.hidden} completed descendants`, width) : []
|
|
760
|
-
];
|
|
761
|
-
}
|
|
762
1117
|
function detailLines(row2, width, expanded = false, ageMs = 0) {
|
|
763
1118
|
const s = row2?.snapshot, m = s?.measurement;
|
|
764
1119
|
if (!row2)
|
|
@@ -769,22 +1124,29 @@ function detailLines(row2, width, expanded = false, ageMs = 0) {
|
|
|
769
1124
|
...wrap("Guard: not monitored / unavailable", width)
|
|
770
1125
|
];
|
|
771
1126
|
const threshold = s.policy.configured;
|
|
772
|
-
const
|
|
1127
|
+
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
773
1128
|
const lines = [
|
|
774
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)}`,
|
|
775
1138
|
...performanceLines(row2, width),
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
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
|
+
] : []
|
|
785
1147
|
];
|
|
786
1148
|
if (expanded)
|
|
787
|
-
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)}`);
|
|
788
1150
|
return lines.filter(Boolean).flatMap((line) => wrap(line, width));
|
|
789
1151
|
}
|
|
790
1152
|
function sanitize(value) {
|
|
@@ -821,22 +1183,93 @@ function performanceLines(row2, width) {
|
|
|
821
1183
|
...wrap(`TTFT ${p.ttftMs === undefined ? "?" : `~${(p.ttftMs / 1000).toFixed(2)}s`}${p.latestRequestTps === undefined ? "" : ` \xB7 Last ${value(p.latestRequestTps)} t/s`}`, width)
|
|
822
1184
|
];
|
|
823
1185
|
}
|
|
824
|
-
var segmenter
|
|
1186
|
+
var segmenter;
|
|
825
1187
|
var init_format = __esm(() => {
|
|
1188
|
+
init_statusformat();
|
|
826
1189
|
segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
827
|
-
|
|
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 ? {
|
|
828
1230
|
running: "RUN",
|
|
829
1231
|
idle: "IDLE",
|
|
830
1232
|
completed: "DONE",
|
|
831
1233
|
failed: "FAIL",
|
|
832
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"
|
|
833
1266
|
};
|
|
834
1267
|
});
|
|
835
1268
|
|
|
836
1269
|
// src/tui/chartformat.ts
|
|
837
|
-
function columns2(points, from, to, width, gaps = []) {
|
|
1270
|
+
function columns2(points, from, to, width, gaps = [], halfOpen = false) {
|
|
838
1271
|
const size = Math.max(1, Math.min(120, Math.floor(width))), values = Array.from({ length: size });
|
|
839
|
-
const column = (time) => Math.max(0, Math.min(size - 1, Math.floor((time - from) / Math.max(1, to - from) * (size - 1))));
|
|
1272
|
+
const column = (time) => Math.max(0, Math.min(size - 1, Math.floor((time - from) / Math.max(1, to - from) * (halfOpen ? size : size - 1))));
|
|
840
1273
|
let min = Infinity, max = -Infinity;
|
|
841
1274
|
for (const point of points) {
|
|
842
1275
|
if (point.time < from || point.time > to || point.value === undefined || !Number.isFinite(point.value) || point.value < 0)
|
|
@@ -860,12 +1293,12 @@ function sparkline(points, from, to, width, gaps = []) {
|
|
|
860
1293
|
chars[column(time)] = "\u2506";
|
|
861
1294
|
return { line: chars.join(""), ...min === Infinity ? {} : { min, max } };
|
|
862
1295
|
}
|
|
863
|
-
function metricPlot(points, from, to, width, gaps = []) {
|
|
1296
|
+
function metricPlot(points, from, to, width, gaps = [], halfOpen = false) {
|
|
864
1297
|
const label = (value) => value >= 1e6 ? `${(value / 1e6).toFixed(1)}M` : value >= 1000 ? `${(value / 1000).toFixed(1)}k` : value.toFixed(1);
|
|
865
1298
|
const peak = Math.max(0, ...points.filter((p) => p.time >= from && p.time <= to && Number.isFinite(p.value)).map((p) => p.value ?? 0));
|
|
866
1299
|
const scale = Math.max(1, peak);
|
|
867
1300
|
const gutter = width >= 20 ? Math.max(label(scale).length, 3) : 0;
|
|
868
|
-
const { values, column } = columns2(points, from, to, Math.max(1, width - gutter - 2), gaps);
|
|
1301
|
+
const { values, column } = columns2(points, from, to, Math.max(1, halfOpen ? Math.min(points.length, width - gutter - 2) : width - gutter - 2), gaps, halfOpen);
|
|
869
1302
|
const gapColumns = new Set(gaps.filter((time) => time >= from && time <= to).map(column));
|
|
870
1303
|
const height = 6;
|
|
871
1304
|
const blocks = " \u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
|
|
@@ -944,15 +1377,15 @@ var init_chartformat = __esm(() => {
|
|
|
944
1377
|
|
|
945
1378
|
// src/tui.tsx
|
|
946
1379
|
import { effect as _$effect5 } from "@opentui/solid";
|
|
947
|
-
import {
|
|
948
|
-
import { insertNode as _$insertNode5 } from "@opentui/solid";
|
|
1380
|
+
import { insert as _$insert5 } from "@opentui/solid";
|
|
949
1381
|
import { setProp as _$setProp5 } from "@opentui/solid";
|
|
950
1382
|
import { createElement as _$createElement5 } from "@opentui/solid";
|
|
951
|
-
import { createComponent as _$
|
|
1383
|
+
import { createComponent as _$createComponent6 } from "@opentui/solid";
|
|
952
1384
|
import { Plugin } from "@opencode/plugin/tui";
|
|
953
1385
|
import { Show as Show4 } from "solid-js";
|
|
954
1386
|
|
|
955
1387
|
// src/tui/state.ts
|
|
1388
|
+
init_historyclient();
|
|
956
1389
|
init_rpc();
|
|
957
1390
|
import { createSignal } from "solid-js";
|
|
958
1391
|
|
|
@@ -1091,6 +1524,21 @@ function contextChart(samples, capacity, trigger, width, now) {
|
|
|
1091
1524
|
init_transport();
|
|
1092
1525
|
|
|
1093
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
|
+
}
|
|
1094
1542
|
async function discoverFamily(client, currentId, signal, cached, maxNodes = 1024, previous) {
|
|
1095
1543
|
const sessions = new Map(previous?.sessions);
|
|
1096
1544
|
let damaged = previous?.damaged ?? false, pages = 0, rootId = previous?.rootId ?? currentId;
|
|
@@ -1244,7 +1692,7 @@ function createGuardState(context) {
|
|
|
1244
1692
|
inventory = undefined;
|
|
1245
1693
|
evidence.clear();
|
|
1246
1694
|
maxNodes = 1024;
|
|
1247
|
-
|
|
1695
|
+
scanFailed = false;
|
|
1248
1696
|
notify();
|
|
1249
1697
|
scan();
|
|
1250
1698
|
}
|
|
@@ -1259,6 +1707,7 @@ function createGuardState(context) {
|
|
|
1259
1707
|
controller.signal,
|
|
1260
1708
|
AbortSignal.timeout(15000)
|
|
1261
1709
|
]);
|
|
1710
|
+
notify();
|
|
1262
1711
|
try {
|
|
1263
1712
|
const next = await discoverFamily(context.client, currentId, signal, (id) => context.data.session.get(id), maxNodes, more ? inventory : undefined);
|
|
1264
1713
|
if (signal.aborted || generation !== scanGeneration)
|
|
@@ -1319,8 +1768,10 @@ function createGuardState(context) {
|
|
|
1319
1768
|
notify();
|
|
1320
1769
|
}
|
|
1321
1770
|
} finally {
|
|
1322
|
-
if (generation === scanGeneration)
|
|
1771
|
+
if (generation === scanGeneration) {
|
|
1323
1772
|
scanning = false;
|
|
1773
|
+
notify();
|
|
1774
|
+
}
|
|
1324
1775
|
}
|
|
1325
1776
|
}
|
|
1326
1777
|
function acquire(id) {
|
|
@@ -1432,14 +1883,20 @@ function createGuardState(context) {
|
|
|
1432
1883
|
return {
|
|
1433
1884
|
version,
|
|
1434
1885
|
acquire,
|
|
1435
|
-
|
|
1886
|
+
historyLocation(id) {
|
|
1887
|
+
version();
|
|
1436
1888
|
const info = inventory?.sessions.get(id);
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
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
|
+
}
|
|
1443
1900
|
},
|
|
1444
1901
|
rows,
|
|
1445
1902
|
contextTrace: (row2) => contextTraces.update(row2),
|
|
@@ -1463,7 +1920,11 @@ function createGuardState(context) {
|
|
|
1463
1920
|
},
|
|
1464
1921
|
complete() {
|
|
1465
1922
|
version();
|
|
1466
|
-
return inventory?.complete ?? false;
|
|
1923
|
+
return !scanFailed && (inventory?.complete ?? false);
|
|
1924
|
+
},
|
|
1925
|
+
inventoryStatus() {
|
|
1926
|
+
version();
|
|
1927
|
+
return inventoryStatus(inventory, maxNodes, scanning, scanFailed);
|
|
1467
1928
|
},
|
|
1468
1929
|
refresh() {
|
|
1469
1930
|
scan();
|
|
@@ -1471,6 +1932,8 @@ function createGuardState(context) {
|
|
|
1471
1932
|
c.refresh();
|
|
1472
1933
|
},
|
|
1473
1934
|
loadMore() {
|
|
1935
|
+
if (!inventoryStatus(inventory, maxNodes, scanning, scanFailed).canLoadMore)
|
|
1936
|
+
return;
|
|
1474
1937
|
maxNodes = Math.min(2048, maxNodes + 1024);
|
|
1475
1938
|
scan(true);
|
|
1476
1939
|
},
|
|
@@ -1497,19 +1960,12 @@ function sameLocation(a, b) {
|
|
|
1497
1960
|
}
|
|
1498
1961
|
|
|
1499
1962
|
// src/tui/sidebar.tsx
|
|
1500
|
-
init_format();
|
|
1501
|
-
import { effect as _$effect2 } from "@opentui/solid";
|
|
1502
1963
|
import { createComponent as _$createComponent2 } from "@opentui/solid";
|
|
1503
|
-
import {
|
|
1504
|
-
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
1505
|
-
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
1506
|
-
import { memo as _$memo2 } from "@opentui/solid";
|
|
1507
|
-
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
1508
|
-
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
1509
|
-
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";
|
|
1510
1965
|
|
|
1511
1966
|
// src/tui/compact.tsx
|
|
1512
1967
|
init_format();
|
|
1968
|
+
init_statusformat();
|
|
1513
1969
|
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
1514
1970
|
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
1515
1971
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
@@ -1522,16 +1978,8 @@ import { For, Index, Show, createEffect, createMemo, createSignal as createSigna
|
|
|
1522
1978
|
|
|
1523
1979
|
// src/tui/compactformat.ts
|
|
1524
1980
|
init_format();
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
return "?";
|
|
1528
|
-
const magnitude = Math.abs(value);
|
|
1529
|
-
if (magnitude >= 1e6)
|
|
1530
|
-
return `${+(value / 1e6).toFixed(1)}M`;
|
|
1531
|
-
if (magnitude >= 1000)
|
|
1532
|
-
return `${+(value / 1000).toFixed(1)}K`;
|
|
1533
|
-
return String(value);
|
|
1534
|
-
}
|
|
1981
|
+
init_panelformat();
|
|
1982
|
+
init_statusformat();
|
|
1535
1983
|
function columns(left, right, width) {
|
|
1536
1984
|
if (cells(left) + cells(right) + 1 > width)
|
|
1537
1985
|
return [...wrap(left, width), ...wrap(right, width)];
|
|
@@ -1544,73 +1992,64 @@ function progress(ratio, width) {
|
|
|
1544
1992
|
const filled = valid2 ? Math.round(Math.min(1, ratio) * size) : 0;
|
|
1545
1993
|
return clip("\u2588".repeat(filled) + "\u2591".repeat(size - filled) + " " + label, width);
|
|
1546
1994
|
}
|
|
1547
|
-
function mainSections(row2, width, age
|
|
1995
|
+
function mainSections(row2, width, age) {
|
|
1548
1996
|
if (!row2)
|
|
1549
1997
|
return [{ tone: "base", lines: wrap("Loading session family...", width) }];
|
|
1550
1998
|
const s = row2.snapshot, m = s?.measurement;
|
|
1551
1999
|
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
1552
2000
|
const measured = valid2 ? m?.tokens : undefined;
|
|
1553
|
-
const ratio =
|
|
1554
|
-
const
|
|
2001
|
+
const ratio = measured !== undefined && s?.capacityTokens !== undefined && s.capacityTokens > 0 ? measured / s.capacityTokens : undefined;
|
|
2002
|
+
const lifecycle = compactionLabel(row2);
|
|
1555
2003
|
return [
|
|
1556
|
-
...row2.snapshot?.performance ? [{ tone: "base", lines: performanceLines(row2, width) }] : [],
|
|
1557
2004
|
{
|
|
1558
2005
|
tone: "execution",
|
|
1559
2006
|
lines: columns(`${row2.node.agent ?? s?.agent ?? "Main"} \xB7 ${row2.node.model ?? s?.model ?? "?"}`, row2.node.status.toUpperCase(), width)
|
|
1560
2007
|
},
|
|
1561
2008
|
{
|
|
1562
2009
|
tone: "base",
|
|
1563
|
-
lines:
|
|
1564
|
-
"",
|
|
1565
|
-
...columns("Context", `${tokens(measured)} / ${tokens(s?.capacityTokens)}`, width)
|
|
1566
|
-
]
|
|
1567
|
-
},
|
|
1568
|
-
...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 }) => ({
|
|
1569
|
-
tone: threshold ? "threshold" : "pressure",
|
|
1570
|
-
lines: [line],
|
|
1571
|
-
...segments ? { segments } : {}
|
|
1572
|
-
})),
|
|
1573
|
-
...samples?.some((sample) => sample.held) || m && age > 2500 ? [
|
|
1574
|
-
{
|
|
1575
|
-
tone: "measurement",
|
|
1576
|
-
lines: wrap("muted held \xB7 last known context", width)
|
|
1577
|
-
}
|
|
1578
|
-
] : [],
|
|
1579
|
-
{
|
|
1580
|
-
tone: "base",
|
|
1581
|
-
lines: wrap(`${ratio(s?.capacityTokens) === undefined ? "?" : Math.round((ratio(s?.capacityTokens) ?? 0) * 100)}% used \xB7 recent samples \u2192 now`, width)
|
|
1582
|
-
},
|
|
1583
|
-
{
|
|
1584
|
-
tone: "base",
|
|
1585
|
-
lines: [
|
|
1586
|
-
"",
|
|
1587
|
-
...columns("Compact threshold", `${tokens(measured)} / ${tokens(s?.policy.triggerTokens)}`, width)
|
|
1588
|
-
]
|
|
2010
|
+
lines: columns(row2.freshness === "stale" ? "Last measured" : "Context", `${m?.confidence === "approximate" && valid2 ? "~" : ""}${tokens(measured)} / ${tokens(s?.capacityTokens)}`, width)
|
|
1589
2011
|
},
|
|
2012
|
+
{ tone: "measurement", lines: [progress(ratio, width)] },
|
|
1590
2013
|
{
|
|
1591
2014
|
tone: "pressure",
|
|
1592
2015
|
lines: [
|
|
1593
|
-
...wrap(
|
|
1594
|
-
...
|
|
1595
|
-
...
|
|
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) : []
|
|
1596
2019
|
]
|
|
1597
2020
|
},
|
|
1598
2021
|
{
|
|
1599
2022
|
tone: "measurement",
|
|
1600
|
-
lines:
|
|
1601
|
-
"",
|
|
1602
|
-
...wrap(`Measurement: ${m?.confidence ?? "unknown"}${m ? ` \xB7 ${Math.floor(Math.max(0, age) / 1000)}s ago` : ""}${row2.freshness !== "fresh" ? ` \xB7 ${row2.freshness.toUpperCase()}` : ""}`, width)
|
|
1603
|
-
]
|
|
2023
|
+
lines: wrap(measurementLabel(row2, age), width)
|
|
1604
2024
|
},
|
|
1605
2025
|
{
|
|
1606
2026
|
tone: "base",
|
|
1607
2027
|
lines: [
|
|
1608
|
-
...
|
|
2028
|
+
...lifecycle ? wrap(lifecycle, width) : [],
|
|
2029
|
+
...row2.node.interrupted ? wrap("Interrupted", width) : [],
|
|
1609
2030
|
...!s ? wrap("Guard: not monitored / unavailable", width) : []
|
|
1610
2031
|
]
|
|
1611
2032
|
}
|
|
1612
2033
|
];
|
|
1613
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
|
+
}
|
|
1614
2053
|
var statusSymbol = {
|
|
1615
2054
|
running: "\u25CF",
|
|
1616
2055
|
idle: "\u25CC",
|
|
@@ -1619,27 +2058,31 @@ var statusSymbol = {
|
|
|
1619
2058
|
failed: "\u2715"
|
|
1620
2059
|
};
|
|
1621
2060
|
function agentHeading(row2, width) {
|
|
1622
|
-
|
|
1623
|
-
const percent = row2.utilizationPercent === undefined ? "?%" : `${Math.round(row2.utilizationPercent)}%`;
|
|
1624
|
-
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);
|
|
1625
2062
|
}
|
|
1626
2063
|
function agentLines(row2, width) {
|
|
1627
2064
|
const valid2 = row2.freshness === "fresh" || row2.freshness === "stale";
|
|
1628
|
-
const
|
|
1629
|
-
const
|
|
1630
|
-
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);
|
|
1631
2072
|
return [
|
|
1632
|
-
...
|
|
1633
|
-
|
|
1634
|
-
...
|
|
1635
|
-
...
|
|
1636
|
-
...
|
|
2073
|
+
...wrap(cells(full) <= width ? full : short, width),
|
|
2074
|
+
...row2.node.status === "failed" || row2.node.status === "unknown" ? wrap(row2.node.status.toUpperCase(), width) : [],
|
|
2075
|
+
...row2.freshness !== "fresh" ? wrap(freshnessLabel(row2) ?? "", width) : [],
|
|
2076
|
+
...row2.node.interrupted ? wrap("Interrupted", width) : [],
|
|
2077
|
+
...lifecycle ? wrap(lifecycle, width) : []
|
|
1637
2078
|
];
|
|
1638
2079
|
}
|
|
1639
|
-
function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure) {
|
|
2080
|
+
function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure, trustworthy = true) {
|
|
1640
2081
|
const children = new Map;
|
|
1641
|
-
|
|
1642
|
-
|
|
2082
|
+
const unique = new Map(rows.map((row2) => [row2.node.sessionId, row2]));
|
|
2083
|
+
let complete = unique.size <= 2048;
|
|
2084
|
+
for (const row2 of [...unique.values()].slice(0, 2048)) {
|
|
2085
|
+
if (!row2.node.parentId)
|
|
1643
2086
|
continue;
|
|
1644
2087
|
const list = children.get(row2.node.parentId) ?? [];
|
|
1645
2088
|
list.push(row2);
|
|
@@ -1648,41 +2091,79 @@ function subagentTree(rows, sessionID, collapsed, hideCompleted, byPressure) {
|
|
|
1648
2091
|
const seen = new Set([sessionID]);
|
|
1649
2092
|
const all = [];
|
|
1650
2093
|
const build = (id, depth) => {
|
|
1651
|
-
if (depth > 64)
|
|
1652
|
-
|
|
2094
|
+
if (depth > 64) {
|
|
2095
|
+
const safe2 = !children.get(id)?.length;
|
|
2096
|
+
if (!safe2)
|
|
2097
|
+
complete = false;
|
|
2098
|
+
return { branches: [], safe: safe2 };
|
|
2099
|
+
}
|
|
2100
|
+
let safe = true;
|
|
1653
2101
|
const branches2 = [];
|
|
1654
2102
|
for (const row2 of children.get(id) ?? []) {
|
|
1655
|
-
if (seen.has(row2.node.sessionId))
|
|
2103
|
+
if (seen.has(row2.node.sessionId)) {
|
|
2104
|
+
safe = false;
|
|
2105
|
+
complete = false;
|
|
1656
2106
|
continue;
|
|
2107
|
+
}
|
|
1657
2108
|
seen.add(row2.node.sessionId);
|
|
1658
2109
|
all.push(row2);
|
|
1659
2110
|
const nested = build(row2.node.sessionId, depth + 1);
|
|
1660
|
-
|
|
1661
|
-
|
|
2111
|
+
const branchSafe = nested.safe && row2.hidden === 0;
|
|
2112
|
+
safe &&= branchSafe;
|
|
2113
|
+
complete &&= branchSafe;
|
|
2114
|
+
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);
|
|
1662
2115
|
branches2.push({
|
|
1663
2116
|
row: row2,
|
|
1664
|
-
children: nested,
|
|
1665
|
-
|
|
1666
|
-
|
|
2117
|
+
children: nested.branches,
|
|
2118
|
+
eligible,
|
|
2119
|
+
active: row2.node.status === "running" || nested.branches.some((b) => b.active),
|
|
2120
|
+
pressure: Math.max(row2.pressureRatio ?? -1, ...nested.branches.map((b) => b.pressure)),
|
|
2121
|
+
size: 1 + nested.branches.reduce((sum, b) => sum + b.size, 0),
|
|
2122
|
+
attention: !eligible || nested.branches.some((b) => b.attention)
|
|
1667
2123
|
});
|
|
1668
2124
|
}
|
|
1669
|
-
return
|
|
2125
|
+
return {
|
|
2126
|
+
safe,
|
|
2127
|
+
branches: branches2.sort((a, b) => Number(b.active) - Number(a.active) || (byPressure ? b.pressure - a.pressure : 0))
|
|
2128
|
+
};
|
|
1670
2129
|
};
|
|
1671
|
-
const branches = build(sessionID, 0);
|
|
2130
|
+
const { branches } = build(sessionID, 0);
|
|
1672
2131
|
const visible = [];
|
|
2132
|
+
let grouped = 0;
|
|
2133
|
+
const count2 = (items) => {
|
|
2134
|
+
for (const item of items) {
|
|
2135
|
+
if (item.eligible)
|
|
2136
|
+
grouped++;
|
|
2137
|
+
count2(item.children);
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
count2(branches);
|
|
1673
2141
|
const visit = (items, depth) => {
|
|
1674
2142
|
for (const item of items) {
|
|
2143
|
+
if (hideCompleted && item.eligible)
|
|
2144
|
+
continue;
|
|
2145
|
+
const folded = collapsed.has(item.row.node.sessionId);
|
|
1675
2146
|
visible.push({
|
|
1676
2147
|
row: item.row,
|
|
1677
2148
|
depth,
|
|
1678
|
-
hasChildren: !!item.children.length
|
|
2149
|
+
hasChildren: !!item.children.length,
|
|
2150
|
+
hidden: folded ? item.size - 1 : 0,
|
|
2151
|
+
attention: folded && item.children.some((b) => b.attention)
|
|
1679
2152
|
});
|
|
1680
|
-
if (!
|
|
2153
|
+
if (!folded)
|
|
1681
2154
|
visit(item.children, depth + 1);
|
|
1682
2155
|
}
|
|
1683
2156
|
};
|
|
1684
2157
|
visit(branches, 0);
|
|
1685
|
-
return { all, visible };
|
|
2158
|
+
return { all, visible, grouped, complete };
|
|
2159
|
+
}
|
|
2160
|
+
function routeFamily(rows, sessionID) {
|
|
2161
|
+
const tree = subagentTree(rows, sessionID, new Set, false, false, false);
|
|
2162
|
+
const root = rows.find((row2) => row2.node.sessionId === sessionID);
|
|
2163
|
+
return {
|
|
2164
|
+
rows: [...root ? [root] : [], ...tree.all],
|
|
2165
|
+
complete: !!root && root.hidden === 0 && tree.complete
|
|
2166
|
+
};
|
|
1686
2167
|
}
|
|
1687
2168
|
function statistics(rows, sessionID, complete, width) {
|
|
1688
2169
|
const sum = (value) => {
|
|
@@ -1702,15 +2183,19 @@ function CompactSidebar(props) {
|
|
|
1702
2183
|
const [measuredWidth, setMeasuredWidth] = createSignal2(props.width);
|
|
1703
2184
|
const width = () => Math.max(1, Math.min(props.width, measuredWidth()) - 4);
|
|
1704
2185
|
const [collapsed, setCollapsed] = createSignal2(new Set);
|
|
1705
|
-
const [hideCompleted, setHideCompleted] = createSignal2(
|
|
2186
|
+
const [hideCompleted, setHideCompleted] = createSignal2(true);
|
|
2187
|
+
const [showHistory, setShowHistory] = createSignal2(false);
|
|
1706
2188
|
const [byPressure, setByPressure] = createSignal2(true);
|
|
1707
2189
|
createEffect(() => {
|
|
1708
2190
|
props.sessionID;
|
|
1709
2191
|
setCollapsed(new Set);
|
|
2192
|
+
setShowHistory(false);
|
|
1710
2193
|
});
|
|
1711
2194
|
const current = createMemo(() => props.rows.find((r) => r.node.sessionId === props.sessionID));
|
|
1712
2195
|
const trace = createMemo(() => props.state.contextTrace(current()));
|
|
1713
|
-
const
|
|
2196
|
+
const inventory = createMemo(() => props.state.inventoryStatus());
|
|
2197
|
+
const trustworthy = () => inventory().complete && !inventory().scanning && !inventory().failed && !inventory().damaged;
|
|
2198
|
+
const tree = createMemo(() => subagentTree(props.rows, props.sessionID, collapsed(), hideCompleted(), byPressure(), trustworthy()));
|
|
1714
2199
|
const entries = createMemo(() => new Map(tree().visible.map((entry) => [entry.row.node.sessionId, entry])));
|
|
1715
2200
|
const toggle = (id) => setCollapsed((previous) => {
|
|
1716
2201
|
const next = new Set(previous);
|
|
@@ -1721,13 +2206,21 @@ function CompactSidebar(props) {
|
|
|
1721
2206
|
return next;
|
|
1722
2207
|
});
|
|
1723
2208
|
const toggleCompleted = () => setHideCompleted((value) => !value);
|
|
2209
|
+
const toggleHistory = () => setShowHistory((value) => !value);
|
|
1724
2210
|
const toggleSort = () => setByPressure((value) => !value);
|
|
1725
2211
|
const toggleGroups = () => setCollapsed((previous) => previous.size ? new Set : new Set(tree().all.map((r) => r.node.sessionId)));
|
|
1726
2212
|
props.context.keymap.layer(() => ({
|
|
1727
2213
|
mode: "global",
|
|
1728
2214
|
commands: [{
|
|
2215
|
+
id: "context-guard.history",
|
|
2216
|
+
title: "Show or hide sidebar context history",
|
|
2217
|
+
group: "Context Guard",
|
|
2218
|
+
palette: true,
|
|
2219
|
+
bind: false,
|
|
2220
|
+
run: toggleHistory
|
|
2221
|
+
}, {
|
|
1729
2222
|
id: "context-guard.completed",
|
|
1730
|
-
title: "
|
|
2223
|
+
title: "Show or hide completed subagent group",
|
|
1731
2224
|
group: "Context Guard",
|
|
1732
2225
|
palette: true,
|
|
1733
2226
|
bind: false,
|
|
@@ -1771,45 +2264,21 @@ function CompactSidebar(props) {
|
|
|
1771
2264
|
})()
|
|
1772
2265
|
});
|
|
1773
2266
|
}
|
|
1774
|
-
const
|
|
1775
|
-
|
|
1776
|
-
return
|
|
1777
|
-
};
|
|
1778
|
-
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()))]);
|
|
1779
|
-
return (() => {
|
|
1780
|
-
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");
|
|
1781
|
-
_$insertNode(_el$2, _el$3);
|
|
1782
|
-
_$insertNode(_el$2, _el$5);
|
|
1783
|
-
_$insertNode(_el$2, _el$6);
|
|
1784
|
-
_$insertNode(_el$2, _el$8);
|
|
1785
|
-
_$insertNode(_el$2, _el$9);
|
|
1786
|
-
_$insertNode(_el$2, _el$0);
|
|
1787
|
-
_$insertNode(_el$2, _el$1);
|
|
1788
|
-
_$insertNode(_el$2, _el$11);
|
|
1789
|
-
_$insertNode(_el$2, _el$12);
|
|
1790
|
-
_$setProp(_el$2, "width", "100%");
|
|
1791
|
-
_$setProp(_el$2, "flexShrink", 0);
|
|
1792
|
-
_$setProp(_el$2, "border", true);
|
|
1793
|
-
_$setProp(_el$2, "borderStyle", "rounded");
|
|
1794
|
-
_$setProp(_el$2, "title", " CONTEXT GUARD ");
|
|
1795
|
-
_$setProp(_el$2, "paddingX", 1);
|
|
1796
|
-
_$setProp(_el$2, "flexDirection", "column");
|
|
1797
|
-
_$setProp(_el$2, "onSizeChange", function() {
|
|
1798
|
-
setMeasuredWidth(this.width);
|
|
1799
|
-
});
|
|
1800
|
-
_$insert(_el$2, _$createComponent(Index, {
|
|
2267
|
+
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()))]);
|
|
2268
|
+
function Sections(input) {
|
|
2269
|
+
return _$createComponent(Index, {
|
|
1801
2270
|
get each() {
|
|
1802
|
-
return
|
|
2271
|
+
return input.sections;
|
|
1803
2272
|
},
|
|
1804
|
-
children: (
|
|
2273
|
+
children: (section) => _$createComponent(Index, {
|
|
1805
2274
|
get each() {
|
|
1806
|
-
return
|
|
2275
|
+
return section().lines;
|
|
1807
2276
|
},
|
|
1808
2277
|
children: (line) => (() => {
|
|
1809
|
-
var _el$
|
|
1810
|
-
_$insert(_el$
|
|
2278
|
+
var _el$2 = _$createElement("text");
|
|
2279
|
+
_$insert(_el$2, _$createComponent(Show, {
|
|
1811
2280
|
get when() {
|
|
1812
|
-
return
|
|
2281
|
+
return section().segments;
|
|
1813
2282
|
},
|
|
1814
2283
|
get fallback() {
|
|
1815
2284
|
return line() || " ";
|
|
@@ -1817,51 +2286,86 @@ function CompactSidebar(props) {
|
|
|
1817
2286
|
get children() {
|
|
1818
2287
|
return _$createComponent(For, {
|
|
1819
2288
|
get each() {
|
|
1820
|
-
return
|
|
2289
|
+
return section().segments;
|
|
1821
2290
|
},
|
|
1822
2291
|
children: (part) => (() => {
|
|
1823
|
-
var _el$
|
|
1824
|
-
_$insert(_el$
|
|
1825
|
-
_$effect((_$p) => _$setProp(_el$
|
|
2292
|
+
var _el$3 = _$createElement("span");
|
|
2293
|
+
_$insert(_el$3, () => part.text);
|
|
2294
|
+
_$effect((_$p) => _$setProp(_el$3, "style", {
|
|
1826
2295
|
fg: part.tone === "axis" || part.tone === "held" ? colors().muted : part.tone === "threshold" ? colors().feedback.warning.base : current()?.freshness === "fresh" ? colors().base : colors().muted
|
|
1827
2296
|
}, _$p));
|
|
1828
|
-
return _el$
|
|
2297
|
+
return _el$3;
|
|
1829
2298
|
})()
|
|
1830
2299
|
});
|
|
1831
2300
|
}
|
|
1832
2301
|
}));
|
|
1833
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1834
|
-
return _el$
|
|
2302
|
+
_$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));
|
|
2303
|
+
return _el$2;
|
|
1835
2304
|
})()
|
|
1836
2305
|
})
|
|
1837
|
-
})
|
|
1838
|
-
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
return (() => {
|
|
2309
|
+
var _el$4 = _$createElement("box"), _el$5 = _$createElement("text"), _el$6 = _$createElement("text"), _el$8 = _$createElement("text"), _el$9 = _$createElement("text");
|
|
2310
|
+
_$insertNode(_el$4, _el$5);
|
|
2311
|
+
_$insertNode(_el$4, _el$6);
|
|
2312
|
+
_$insertNode(_el$4, _el$8);
|
|
2313
|
+
_$insertNode(_el$4, _el$9);
|
|
2314
|
+
_$setProp(_el$4, "width", "100%");
|
|
2315
|
+
_$setProp(_el$4, "flexShrink", 0);
|
|
2316
|
+
_$setProp(_el$4, "border", true);
|
|
2317
|
+
_$setProp(_el$4, "borderStyle", "rounded");
|
|
2318
|
+
_$setProp(_el$4, "title", " CONTEXT GUARD ");
|
|
2319
|
+
_$setProp(_el$4, "paddingX", 1);
|
|
2320
|
+
_$setProp(_el$4, "flexDirection", "column");
|
|
2321
|
+
_$setProp(_el$4, "onSizeChange", function() {
|
|
2322
|
+
setMeasuredWidth(this.width);
|
|
2323
|
+
});
|
|
2324
|
+
_$insert(_el$4, _$createComponent(Sections, {
|
|
2325
|
+
get sections() {
|
|
2326
|
+
return mainSections(current(), width(), props.state.age(props.sessionID));
|
|
2327
|
+
}
|
|
2328
|
+
}), _el$5);
|
|
2329
|
+
_$insert(_el$4, _$createComponent(Index, {
|
|
1839
2330
|
get each() {
|
|
1840
2331
|
return notices();
|
|
1841
2332
|
},
|
|
1842
2333
|
children: (line) => (() => {
|
|
1843
|
-
var _el$
|
|
1844
|
-
_$insert(_el$
|
|
1845
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1846
|
-
return _el$
|
|
2334
|
+
var _el$0 = _$createElement("text");
|
|
2335
|
+
_$insert(_el$0, line);
|
|
2336
|
+
_$effect((_$p) => _$setProp(_el$0, "fg", colors().feedback.warning.base, _$p));
|
|
2337
|
+
return _el$0;
|
|
1847
2338
|
})()
|
|
1848
|
-
}), _el$
|
|
1849
|
-
_$
|
|
1850
|
-
_$insert(_el$5, () =>
|
|
1851
|
-
_$
|
|
2339
|
+
}), _el$5);
|
|
2340
|
+
_$setProp(_el$5, "onMouseDown", () => props.context.ui.panel.open("context-guard.monitor"));
|
|
2341
|
+
_$insert(_el$5, () => clip("Open: /context-guard", width()));
|
|
2342
|
+
_$setProp(_el$6, "onMouseDown", toggleHistory);
|
|
2343
|
+
_$insert(_el$6, () => clip(showHistory() ? "History: hide" : "History: show", width()));
|
|
2344
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
2345
|
+
get when() {
|
|
2346
|
+
return showHistory();
|
|
2347
|
+
},
|
|
2348
|
+
get children() {
|
|
2349
|
+
return _$createComponent(Sections, {
|
|
2350
|
+
get sections() {
|
|
2351
|
+
return historySections(current(), width(), props.state.age(props.sessionID), trace().samples, trace().capacity);
|
|
2352
|
+
}
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}), _el$8);
|
|
2356
|
+
_$insert(_el$4, _$createComponent(Lines, {
|
|
1852
2357
|
get lines() {
|
|
1853
|
-
return wrap(
|
|
2358
|
+
return wrap(`SUBAGENTS (${tree().all.length}) \xB7 ${tree().all.filter((r) => r.node.status === "running").length} running${trustworthy() && tree().complete ? "" : " \xB7 partial"}`, width());
|
|
1854
2359
|
}
|
|
1855
|
-
}), _el$
|
|
1856
|
-
_$
|
|
1857
|
-
_$insert(_el$2, _$createComponent(For, {
|
|
2360
|
+
}), _el$8);
|
|
2361
|
+
_$insert(_el$4, _$createComponent(For, {
|
|
1858
2362
|
get each() {
|
|
1859
2363
|
return tree().visible.map((entry) => entry.row.node.sessionId);
|
|
1860
2364
|
},
|
|
1861
2365
|
children: (id) => {
|
|
1862
2366
|
const entry = () => entries().get(id);
|
|
1863
2367
|
const row2 = () => entry()?.row;
|
|
1864
|
-
const indent = () => " ".repeat(Math.min(entry()?.depth ?? 0, Math.
|
|
2368
|
+
const indent = () => " ".repeat(Math.min((entry()?.depth ?? 0) * 2, Math.max(0, width() - 16)));
|
|
1865
2369
|
const prefix = () => `${indent()}${entry()?.depth ? "\u2514\u2500 " : ""}${entry()?.hasChildren ? collapsed().has(id) ? "\u25B8 " : "\u25BE " : ""}`;
|
|
1866
2370
|
const nameWidth = () => Math.max(1, width() - cells(prefix()));
|
|
1867
2371
|
return _$createComponent(Show, {
|
|
@@ -1869,90 +2373,99 @@ function CompactSidebar(props) {
|
|
|
1869
2373
|
return row2();
|
|
1870
2374
|
},
|
|
1871
2375
|
children: (item) => (() => {
|
|
1872
|
-
var _el$
|
|
1873
|
-
_$insertNode(_el$
|
|
1874
|
-
_$
|
|
1875
|
-
_$setProp(_el$
|
|
1876
|
-
_$
|
|
1877
|
-
_$
|
|
1878
|
-
_$setProp(_el$
|
|
1879
|
-
_$
|
|
1880
|
-
_$insert(_el$17, _$createComponent(Show, {
|
|
2376
|
+
var _el$1 = _$createElement("box"), _el$10 = _$createElement("box"), _el$12 = _$createElement("text"), _el$13 = _$createElement("span"), _el$14 = _$createElement("span");
|
|
2377
|
+
_$insertNode(_el$1, _el$10);
|
|
2378
|
+
_$setProp(_el$1, "flexDirection", "column");
|
|
2379
|
+
_$setProp(_el$1, "flexShrink", 0);
|
|
2380
|
+
_$insertNode(_el$10, _el$12);
|
|
2381
|
+
_$setProp(_el$10, "flexDirection", "row");
|
|
2382
|
+
_$setProp(_el$10, "flexShrink", 0);
|
|
2383
|
+
_$insert(_el$10, _$createComponent(Show, {
|
|
1881
2384
|
get when() {
|
|
1882
2385
|
return prefix();
|
|
1883
2386
|
},
|
|
1884
2387
|
get children() {
|
|
1885
|
-
var _el$
|
|
1886
|
-
_$setProp(_el$
|
|
1887
|
-
_$insert(_el$
|
|
1888
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1889
|
-
return _el$
|
|
2388
|
+
var _el$11 = _$createElement("text");
|
|
2389
|
+
_$setProp(_el$11, "onMouseDown", () => toggle(id));
|
|
2390
|
+
_$insert(_el$11, prefix);
|
|
2391
|
+
_$effect((_$p) => _$setProp(_el$11, "fg", colors().muted, _$p));
|
|
2392
|
+
return _el$11;
|
|
1890
2393
|
}
|
|
1891
|
-
}), _el$
|
|
1892
|
-
_$insertNode(_el$
|
|
1893
|
-
_$insertNode(_el$
|
|
1894
|
-
_$setProp(_el$
|
|
2394
|
+
}), _el$12);
|
|
2395
|
+
_$insertNode(_el$12, _el$13);
|
|
2396
|
+
_$insertNode(_el$12, _el$14);
|
|
2397
|
+
_$setProp(_el$12, "onMouseDown", () => props.context.ui.router.navigate({
|
|
1895
2398
|
type: "session",
|
|
1896
2399
|
sessionID: id
|
|
1897
2400
|
}));
|
|
1898
|
-
_$insert(_el$
|
|
1899
|
-
_$insert(_el$
|
|
1900
|
-
_$insert(_el$
|
|
2401
|
+
_$insert(_el$13, () => agentHeading(item(), nameWidth()).slice(0, 1));
|
|
2402
|
+
_$insert(_el$14, () => agentHeading(item(), nameWidth()).slice(1));
|
|
2403
|
+
_$insert(_el$1, _$createComponent(Index, {
|
|
1901
2404
|
get each() {
|
|
1902
2405
|
return agentLines(item(), Math.max(1, width() - cells(indent()) - 2));
|
|
1903
2406
|
},
|
|
1904
2407
|
children: (line) => (() => {
|
|
1905
|
-
var _el$
|
|
1906
|
-
_$insertNode(_el$
|
|
1907
|
-
_$insert(_el$
|
|
1908
|
-
_$insert(_el$
|
|
1909
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1910
|
-
return _el$
|
|
2408
|
+
var _el$15 = _$createElement("text"), _el$16 = _$createTextNode(` `);
|
|
2409
|
+
_$insertNode(_el$15, _el$16);
|
|
2410
|
+
_$insert(_el$15, indent, _el$16);
|
|
2411
|
+
_$insert(_el$15, line, null);
|
|
2412
|
+
_$effect((_$p) => _$setProp(_el$15, "fg", rowColor(item()), _$p));
|
|
2413
|
+
return _el$15;
|
|
1911
2414
|
})()
|
|
1912
|
-
}),
|
|
1913
|
-
_$
|
|
2415
|
+
}), null);
|
|
2416
|
+
_$insert(_el$1, _$createComponent(Show, {
|
|
2417
|
+
get when() {
|
|
2418
|
+
return entry()?.hidden;
|
|
2419
|
+
},
|
|
2420
|
+
get children() {
|
|
2421
|
+
return _$createComponent(Lines, {
|
|
2422
|
+
get lines() {
|
|
2423
|
+
return wrap(`${entry()?.hidden} hidden${entry()?.attention ? " \xB7 needs attention" : ""}`, width());
|
|
2424
|
+
}
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
}), null);
|
|
1914
2428
|
_$effect((_p$) => {
|
|
1915
|
-
var _v$
|
|
2429
|
+
var _v$8 = rowColor(item()), _v$9 = {
|
|
1916
2430
|
fg: executionColor(item())
|
|
1917
2431
|
};
|
|
1918
|
-
_v$
|
|
1919
|
-
_v$
|
|
2432
|
+
_v$8 !== _p$.e && (_p$.e = _$setProp(_el$12, "fg", _v$8, _p$.e));
|
|
2433
|
+
_v$9 !== _p$.t && (_p$.t = _$setProp(_el$13, "style", _v$9, _p$.t));
|
|
1920
2434
|
return _p$;
|
|
1921
2435
|
}, {
|
|
1922
2436
|
e: undefined,
|
|
1923
2437
|
t: undefined
|
|
1924
2438
|
});
|
|
1925
|
-
return _el$
|
|
2439
|
+
return _el$1;
|
|
1926
2440
|
})()
|
|
1927
2441
|
});
|
|
1928
2442
|
}
|
|
1929
2443
|
}), _el$8);
|
|
1930
|
-
_$
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
return statistics(props.rows.filter((r) => r.node.sessionId === props.sessionID).concat(tree().all), props.sessionID, props.state.complete(), width());
|
|
2444
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
2445
|
+
get when() {
|
|
2446
|
+
return tree().grouped > 0;
|
|
2447
|
+
},
|
|
2448
|
+
get children() {
|
|
2449
|
+
var _el$7 = _$createElement("text");
|
|
2450
|
+
_$setProp(_el$7, "onMouseDown", toggleCompleted);
|
|
2451
|
+
_$insert(_el$7, () => clip(`Completed (${tree().grouped}): ${hideCompleted() ? "show" : "hide"}`, width()));
|
|
2452
|
+
_$effect((_$p) => _$setProp(_el$7, "fg", colors().muted, _$p));
|
|
2453
|
+
return _el$7;
|
|
1941
2454
|
}
|
|
1942
|
-
}), _el$
|
|
1943
|
-
_$setProp(_el$
|
|
1944
|
-
_$insert(_el$
|
|
2455
|
+
}), _el$8);
|
|
2456
|
+
_$setProp(_el$8, "onMouseDown", toggleSort);
|
|
2457
|
+
_$insert(_el$8, () => clip(byPressure() ? "Sort: pressure" : "Sort: activity", width()));
|
|
2458
|
+
_$setProp(_el$9, "onMouseDown", toggleGroups);
|
|
2459
|
+
_$insert(_el$9, () => clip(collapsed().size ? "Expand groups" : "Collapse groups", width()));
|
|
1945
2460
|
_$effect((_p$) => {
|
|
1946
|
-
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
|
|
1947
|
-
_v$ !== _p$.e && (_p$.e = _$setProp(_el$
|
|
1948
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1949
|
-
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
2461
|
+
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;
|
|
2462
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$4, "maxWidth", _v$, _p$.e));
|
|
2463
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$4, "borderColor", _v$2, _p$.t));
|
|
2464
|
+
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$4, "titleColor", _v$3, _p$.a));
|
|
1950
2465
|
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$5, "fg", _v$4, _p$.o));
|
|
1951
|
-
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$
|
|
1952
|
-
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$
|
|
1953
|
-
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$
|
|
1954
|
-
_v$8 !== _p$.h && (_p$.h = _$setProp(_el$11, "fg", _v$8, _p$.h));
|
|
1955
|
-
_v$9 !== _p$.r && (_p$.r = _$setProp(_el$12, "fg", _v$9, _p$.r));
|
|
2466
|
+
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$6, "fg", _v$5, _p$.i));
|
|
2467
|
+
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$8, "fg", _v$6, _p$.n));
|
|
2468
|
+
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$9, "fg", _v$7, _p$.s));
|
|
1956
2469
|
return _p$;
|
|
1957
2470
|
}, {
|
|
1958
2471
|
e: undefined,
|
|
@@ -1961,11 +2474,9 @@ function CompactSidebar(props) {
|
|
|
1961
2474
|
o: undefined,
|
|
1962
2475
|
i: undefined,
|
|
1963
2476
|
n: undefined,
|
|
1964
|
-
s: undefined
|
|
1965
|
-
h: undefined,
|
|
1966
|
-
r: undefined
|
|
2477
|
+
s: undefined
|
|
1967
2478
|
});
|
|
1968
|
-
return _el$
|
|
2479
|
+
return _el$4;
|
|
1969
2480
|
})();
|
|
1970
2481
|
}
|
|
1971
2482
|
|
|
@@ -1974,573 +2485,892 @@ function GuardView(props) {
|
|
|
1974
2485
|
const consumer = props.state.acquire(props.sessionID);
|
|
1975
2486
|
createEffect2(() => consumer.update(props.sessionID));
|
|
1976
2487
|
onCleanup(() => consumer.release());
|
|
1977
|
-
const rows = createMemo2(() => props.
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
const detail = createMemo2(() => {
|
|
1982
|
-
const lines = detailLines(current(), props.width, props.expanded, props.state.age(props.sessionID));
|
|
1983
|
-
if (props.expanded) {
|
|
1984
|
-
const byId = new Map(rows().map((row2) => [row2.node.sessionId, row2.node]));
|
|
1985
|
-
const ancestry = [], seen = new Set;
|
|
1986
|
-
let node = byId.get(props.sessionID);
|
|
1987
|
-
while (node && !seen.has(node.sessionId)) {
|
|
1988
|
-
seen.add(node.sessionId);
|
|
1989
|
-
ancestry.unshift(node.agent ?? node.sessionId);
|
|
1990
|
-
node = node.parentId ? byId.get(node.parentId) : undefined;
|
|
1991
|
-
}
|
|
1992
|
-
lines.push(...wrap(`Ancestry: ${ancestry.join(" / ")}`, props.width));
|
|
1993
|
-
}
|
|
1994
|
-
if (props.inspectId && props.inspectId !== props.sessionID) {
|
|
1995
|
-
const inspected = rows().find((row2) => row2.node.sessionId === props.inspectId);
|
|
1996
|
-
lines.push(...wrap(`Inspect: ${props.inspectId}`, props.width), ...detailLines(inspected, props.width, true, props.state.age(props.inspectId)));
|
|
1997
|
-
}
|
|
1998
|
-
return lines;
|
|
1999
|
-
});
|
|
2000
|
-
const visible = createMemo2(() => {
|
|
2001
|
-
if (!props.expanded)
|
|
2002
|
-
return rows().slice(0, 7);
|
|
2003
|
-
const index = Math.max(0, rows().findIndex((row2) => row2.node.sessionId === props.selectedId));
|
|
2004
|
-
return rows().slice(Math.max(0, index - 10), Math.max(0, index - 10) + 25);
|
|
2005
|
-
});
|
|
2006
|
-
return _$createComponent2(Show2, {
|
|
2007
|
-
get when() {
|
|
2008
|
-
return props.expanded;
|
|
2488
|
+
const rows = createMemo2(() => props.state.rows([], true));
|
|
2489
|
+
return _$createComponent2(CompactSidebar, {
|
|
2490
|
+
get sessionID() {
|
|
2491
|
+
return props.sessionID;
|
|
2009
2492
|
},
|
|
2010
|
-
get
|
|
2011
|
-
return
|
|
2012
|
-
get sessionID() {
|
|
2013
|
-
return props.sessionID;
|
|
2014
|
-
},
|
|
2015
|
-
get state() {
|
|
2016
|
-
return props.state;
|
|
2017
|
-
},
|
|
2018
|
-
get context() {
|
|
2019
|
-
return props.context;
|
|
2020
|
-
},
|
|
2021
|
-
get rows() {
|
|
2022
|
-
return rows();
|
|
2023
|
-
},
|
|
2024
|
-
get width() {
|
|
2025
|
-
return props.width;
|
|
2026
|
-
}
|
|
2027
|
-
});
|
|
2493
|
+
get state() {
|
|
2494
|
+
return props.state;
|
|
2028
2495
|
},
|
|
2029
|
-
get
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
_$setProp2(_el$, "flexDirection", "column");
|
|
2038
|
-
_$setProp2(_el$, "gap", 0);
|
|
2039
|
-
_$insertNode2(_el$2, _el$3);
|
|
2040
|
-
_$insert2(_el$2, () => props.state.health()?.mode ?? "?", null);
|
|
2041
|
-
_$insert2(_el$4, (() => {
|
|
2042
|
-
var _c$ = _$memo2(() => !!["2.0.29", "2.1.2"].includes(props.context.app.version));
|
|
2043
|
-
return () => _c$() ? "" : clip(`Runtime ${props.context.app.version}: unverified (tested: 2.0.29, 2.1.2)`, props.width);
|
|
2044
|
-
})());
|
|
2045
|
-
_$insert2(_el$5, () => clip(`${props.state.connection()} / ${props.state.health()?.enforcement ?? "?"}`, props.width));
|
|
2046
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2047
|
-
get each() {
|
|
2048
|
-
return chart();
|
|
2049
|
-
},
|
|
2050
|
-
children: (item) => (() => {
|
|
2051
|
-
var _el$1 = _$createElement2("text");
|
|
2052
|
-
_$insert2(_el$1, _$createComponent2(Show2, {
|
|
2053
|
-
get when() {
|
|
2054
|
-
return item.segments;
|
|
2055
|
-
},
|
|
2056
|
-
get fallback() {
|
|
2057
|
-
return item.line;
|
|
2058
|
-
},
|
|
2059
|
-
get children() {
|
|
2060
|
-
return _$createComponent2(For2, {
|
|
2061
|
-
get each() {
|
|
2062
|
-
return item.segments;
|
|
2063
|
-
},
|
|
2064
|
-
children: (part) => (() => {
|
|
2065
|
-
var _el$10 = _$createElement2("span");
|
|
2066
|
-
_$insert2(_el$10, () => part.text);
|
|
2067
|
-
_$effect2((_$p) => _$setProp2(_el$10, "style", {
|
|
2068
|
-
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
|
|
2069
|
-
}, _$p));
|
|
2070
|
-
return _el$10;
|
|
2071
|
-
})()
|
|
2072
|
-
});
|
|
2073
|
-
}
|
|
2074
|
-
}));
|
|
2075
|
-
_$effect2((_$p) => _$setProp2(_el$1, "fg", item.threshold ? props.context.theme.text.feedback.warning.base : props.context.theme.text.muted, _$p));
|
|
2076
|
-
return _el$1;
|
|
2077
|
-
})()
|
|
2078
|
-
}), _el$6);
|
|
2079
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2080
|
-
get each() {
|
|
2081
|
-
return wrap("Recent context samples \u2192 now \xB7 \u2504 trigger \xB7 muted held", props.width);
|
|
2082
|
-
},
|
|
2083
|
-
children: (line) => (() => {
|
|
2084
|
-
var _el$11 = _$createElement2("text");
|
|
2085
|
-
_$insert2(_el$11, line);
|
|
2086
|
-
_$effect2((_$p) => _$setProp2(_el$11, "fg", props.context.theme.text.muted, _$p));
|
|
2087
|
-
return _el$11;
|
|
2088
|
-
})()
|
|
2089
|
-
}), _el$6);
|
|
2090
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2091
|
-
get each() {
|
|
2092
|
-
return detail();
|
|
2093
|
-
},
|
|
2094
|
-
children: (line) => (() => {
|
|
2095
|
-
var _el$12 = _$createElement2("text");
|
|
2096
|
-
_$insert2(_el$12, line);
|
|
2097
|
-
_$effect2((_$p) => _$setProp2(_el$12, "fg", props.context.theme.text.base, _$p));
|
|
2098
|
-
return _el$12;
|
|
2099
|
-
})()
|
|
2100
|
-
}), _el$6);
|
|
2101
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2102
|
-
get each() {
|
|
2103
|
-
return props.state.health()?.reasons ?? [];
|
|
2104
|
-
},
|
|
2105
|
-
children: (reason) => (() => {
|
|
2106
|
-
var _el$13 = _$createElement2("text");
|
|
2107
|
-
_$insert2(_el$13, () => clip(reason, props.width));
|
|
2108
|
-
_$effect2((_$p) => _$setProp2(_el$13, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
2109
|
-
return _el$13;
|
|
2110
|
-
})()
|
|
2111
|
-
}), _el$6);
|
|
2112
|
-
_$insert2(_el$6, (() => {
|
|
2113
|
-
var _c$2 = _$memo2(() => props.state.health()?.mode === "observe");
|
|
2114
|
-
return () => _c$2() ? current()?.pressure === "crossed" ? "Observe: would compact" : "Observe: no admission" : "";
|
|
2115
|
-
})());
|
|
2116
|
-
_$insertNode2(_el$7, _el$8);
|
|
2117
|
-
_$insertNode2(_el$7, _el$9);
|
|
2118
|
-
_$insert2(_el$7, () => rows().length, _el$9);
|
|
2119
|
-
_$insert2(_el$7, () => props.state.complete() ? "" : " partial", null);
|
|
2120
|
-
_$insert2(_el$, _$createComponent2(For2, {
|
|
2121
|
-
get each() {
|
|
2122
|
-
return visible();
|
|
2123
|
-
},
|
|
2124
|
-
children: (row2) => (() => {
|
|
2125
|
-
var _el$14 = _$createElement2("box");
|
|
2126
|
-
_$setProp2(_el$14, "flexDirection", "column");
|
|
2127
|
-
_$setProp2(_el$14, "onMouseDown", () => {
|
|
2128
|
-
if (row2.hidden)
|
|
2129
|
-
props.state.expand(row2.node.sessionId);
|
|
2130
|
-
else {
|
|
2131
|
-
if (props.expanded)
|
|
2132
|
-
props.context.ui.panel.close();
|
|
2133
|
-
props.context.ui.router.navigate({
|
|
2134
|
-
type: "session",
|
|
2135
|
-
sessionID: row2.node.sessionId
|
|
2136
|
-
});
|
|
2137
|
-
}
|
|
2138
|
-
});
|
|
2139
|
-
_$insert2(_el$14, _$createComponent2(For2, {
|
|
2140
|
-
get each() {
|
|
2141
|
-
return rowLines(row2, Math.max(1, props.width - (props.expanded ? 2 : 0))).map((line) => props.expanded ? `${row2.node.sessionId === props.selectedId ? ">" : " "} ${line}` : line);
|
|
2142
|
-
},
|
|
2143
|
-
children: (line) => (() => {
|
|
2144
|
-
var _el$15 = _$createElement2("text");
|
|
2145
|
-
_$insert2(_el$15, line);
|
|
2146
|
-
_$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));
|
|
2147
|
-
return _el$15;
|
|
2148
|
-
})()
|
|
2149
|
-
}));
|
|
2150
|
-
_$effect2((_$p) => _$setProp2(_el$14, "id", `context-guard.row.${row2.node.sessionId}`, _$p));
|
|
2151
|
-
return _el$14;
|
|
2152
|
-
})()
|
|
2153
|
-
}), _el$0);
|
|
2154
|
-
_$setProp2(_el$0, "onMouseDown", () => props.context.ui.panel.open("context-guard.monitor"));
|
|
2155
|
-
_$insert2(_el$0, (() => {
|
|
2156
|
-
var _c$3 = _$memo2(() => rows().length > visible().length);
|
|
2157
|
-
return () => _c$3() ? `+ ${rows().length - visible().length} rows; open panel` : "Open: /context-guard";
|
|
2158
|
-
})());
|
|
2159
|
-
_$effect2((_p$) => {
|
|
2160
|
-
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;
|
|
2161
|
-
_v$ !== _p$.e && (_p$.e = _$setProp2(_el$2, "fg", _v$, _p$.e));
|
|
2162
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp2(_el$4, "fg", _v$2, _p$.t));
|
|
2163
|
-
_v$3 !== _p$.a && (_p$.a = _$setProp2(_el$5, "fg", _v$3, _p$.a));
|
|
2164
|
-
_v$4 !== _p$.o && (_p$.o = _$setProp2(_el$6, "fg", _v$4, _p$.o));
|
|
2165
|
-
_v$5 !== _p$.i && (_p$.i = _$setProp2(_el$7, "fg", _v$5, _p$.i));
|
|
2166
|
-
_v$6 !== _p$.n && (_p$.n = _$setProp2(_el$0, "fg", _v$6, _p$.n));
|
|
2167
|
-
return _p$;
|
|
2168
|
-
}, {
|
|
2169
|
-
e: undefined,
|
|
2170
|
-
t: undefined,
|
|
2171
|
-
a: undefined,
|
|
2172
|
-
o: undefined,
|
|
2173
|
-
i: undefined,
|
|
2174
|
-
n: undefined
|
|
2175
|
-
});
|
|
2176
|
-
return _el$;
|
|
2496
|
+
get context() {
|
|
2497
|
+
return props.context;
|
|
2498
|
+
},
|
|
2499
|
+
get rows() {
|
|
2500
|
+
return rows();
|
|
2501
|
+
},
|
|
2502
|
+
get width() {
|
|
2503
|
+
return props.width;
|
|
2177
2504
|
}
|
|
2178
2505
|
});
|
|
2179
2506
|
}
|
|
2180
2507
|
|
|
2181
2508
|
// src/tui/panel.tsx
|
|
2182
|
-
import {
|
|
2183
|
-
import { memo as _$memo3 } from "@opentui/solid";
|
|
2509
|
+
import { use as _$use } from "@opentui/solid";
|
|
2184
2510
|
import { insertNode as _$insertNode4 } from "@opentui/solid";
|
|
2511
|
+
import { memo as _$memo2 } from "@opentui/solid";
|
|
2512
|
+
import { effect as _$effect4 } from "@opentui/solid";
|
|
2513
|
+
import { createComponent as _$createComponent5 } from "@opentui/solid";
|
|
2185
2514
|
import { insert as _$insert4 } from "@opentui/solid";
|
|
2186
|
-
import { createComponent as _$createComponent4 } from "@opentui/solid";
|
|
2187
|
-
import { use as _$use } from "@opentui/solid";
|
|
2188
2515
|
import { setProp as _$setProp4 } from "@opentui/solid";
|
|
2189
2516
|
import { createElement as _$createElement4 } from "@opentui/solid";
|
|
2190
|
-
import { createSignal as
|
|
2517
|
+
import { createSignal as createSignal3, createMemo as createMemo4, createEffect as createEffect3, on, onCleanup as onCleanup2, Show as Show3, For as For4 } from "solid-js";
|
|
2191
2518
|
|
|
2192
2519
|
// src/tui/charts.tsx
|
|
2193
2520
|
init_chartformat();
|
|
2521
|
+
init_historyclient();
|
|
2194
2522
|
init_format();
|
|
2195
|
-
import { effect as _$
|
|
2196
|
-
import { insertNode as _$
|
|
2197
|
-
import { insert as _$
|
|
2523
|
+
import { effect as _$effect2 } from "@opentui/solid";
|
|
2524
|
+
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
2525
|
+
import { insert as _$insert2 } from "@opentui/solid";
|
|
2198
2526
|
import { createComponent as _$createComponent3 } from "@opentui/solid";
|
|
2199
|
-
import { setProp as _$
|
|
2200
|
-
import { createElement as _$
|
|
2201
|
-
import {
|
|
2527
|
+
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
2528
|
+
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
2529
|
+
import { For as For2 } from "solid-js";
|
|
2202
2530
|
function HistoryCharts(props) {
|
|
2203
|
-
const [result, setResult] = createSignal3();
|
|
2204
|
-
const [status, setStatus] = createSignal3("Loading retained history...");
|
|
2205
|
-
const [range, setRange] = createSignal3({
|
|
2206
|
-
from: 0,
|
|
2207
|
-
to: 0
|
|
2208
|
-
});
|
|
2209
|
-
createEffect3(() => {
|
|
2210
|
-
const { sessionId: id, windowMs } = props;
|
|
2211
|
-
props.refresh;
|
|
2212
|
-
let pending = false, disposed = false;
|
|
2213
|
-
let controller;
|
|
2214
|
-
setResult(undefined);
|
|
2215
|
-
async function read() {
|
|
2216
|
-
if (pending || disposed)
|
|
2217
|
-
return;
|
|
2218
|
-
pending = true;
|
|
2219
|
-
controller = new AbortController;
|
|
2220
|
-
const to = Date.now(), from = Math.max(0, to - windowMs);
|
|
2221
|
-
try {
|
|
2222
|
-
const next = await props.state.history(id, from, to, AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]));
|
|
2223
|
-
if (!disposed) {
|
|
2224
|
-
setResult(next);
|
|
2225
|
-
setRange({
|
|
2226
|
-
from,
|
|
2227
|
-
to
|
|
2228
|
-
});
|
|
2229
|
-
setStatus("");
|
|
2230
|
-
}
|
|
2231
|
-
} catch {
|
|
2232
|
-
if (!disposed)
|
|
2233
|
-
setStatus("History unavailable. The owning server must support chart history RPC. Press r to retry.");
|
|
2234
|
-
} finally {
|
|
2235
|
-
pending = false;
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
read();
|
|
2239
|
-
const timer = setInterval(() => {
|
|
2240
|
-
read();
|
|
2241
|
-
}, 5000);
|
|
2242
|
-
onCleanup2(() => {
|
|
2243
|
-
disposed = true;
|
|
2244
|
-
controller?.abort();
|
|
2245
|
-
clearInterval(timer);
|
|
2246
|
-
});
|
|
2247
|
-
});
|
|
2248
2531
|
const lines = () => {
|
|
2249
|
-
const current = result
|
|
2250
|
-
return current ? historyChartLines(current, Math.max(4, props.width),
|
|
2532
|
+
const current = props.view.result;
|
|
2533
|
+
return current ? historyChartLines(current, Math.max(4, props.width), props.view.from ?? 0, props.view.to ?? 0, props.metricIndex) : [];
|
|
2251
2534
|
};
|
|
2252
2535
|
return (() => {
|
|
2253
|
-
var _el$ = _$
|
|
2254
|
-
_$
|
|
2255
|
-
_$
|
|
2256
|
-
_$
|
|
2536
|
+
var _el$ = _$createElement2("box"), _el$2 = _$createElement2("box");
|
|
2537
|
+
_$insertNode2(_el$, _el$2);
|
|
2538
|
+
_$setProp2(_el$, "flexDirection", "column");
|
|
2539
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2257
2540
|
get each() {
|
|
2258
2541
|
return wrap(`Performance charts \xB7 ${props.sessionId}`, props.width);
|
|
2259
2542
|
},
|
|
2260
2543
|
children: (line) => (() => {
|
|
2261
|
-
var _el$3 = _$
|
|
2262
|
-
_$
|
|
2263
|
-
_$
|
|
2544
|
+
var _el$3 = _$createElement2("text");
|
|
2545
|
+
_$insert2(_el$3, line);
|
|
2546
|
+
_$effect2((_$p) => _$setProp2(_el$3, "fg", props.context.theme.text.base, _$p));
|
|
2264
2547
|
return _el$3;
|
|
2265
2548
|
})()
|
|
2266
2549
|
}), _el$2);
|
|
2267
|
-
_$
|
|
2550
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2268
2551
|
get each() {
|
|
2269
|
-
return wrap(
|
|
2552
|
+
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);
|
|
2270
2553
|
},
|
|
2271
2554
|
children: (line) => (() => {
|
|
2272
|
-
var _el$4 = _$
|
|
2273
|
-
_$
|
|
2274
|
-
_$
|
|
2555
|
+
var _el$4 = _$createElement2("text");
|
|
2556
|
+
_$insert2(_el$4, line);
|
|
2557
|
+
_$effect2((_$p) => _$setProp2(_el$4, "fg", props.context.theme.text.muted, _$p));
|
|
2275
2558
|
return _el$4;
|
|
2276
2559
|
})()
|
|
2277
2560
|
}), _el$2);
|
|
2278
|
-
_$
|
|
2279
|
-
_$setProp3(_el$2, "paddingTop", 1);
|
|
2280
|
-
_$insert3(_el$2, _$createComponent3(For3, {
|
|
2561
|
+
_$insert2(_el$, _$createComponent3(For2, {
|
|
2281
2562
|
get each() {
|
|
2282
|
-
return
|
|
2563
|
+
return historyStatusLines(props.view).flatMap((line) => wrap(line, props.width));
|
|
2283
2564
|
},
|
|
2284
2565
|
children: (line) => (() => {
|
|
2285
|
-
var _el$5 = _$
|
|
2286
|
-
_$
|
|
2287
|
-
_$
|
|
2566
|
+
var _el$5 = _$createElement2("text");
|
|
2567
|
+
_$insert2(_el$5, line);
|
|
2568
|
+
_$effect2((_$p) => _$setProp2(_el$5, "fg", props.context.theme.text.muted, _$p));
|
|
2288
2569
|
return _el$5;
|
|
2289
2570
|
})()
|
|
2571
|
+
}), _el$2);
|
|
2572
|
+
_$setProp2(_el$2, "flexDirection", "column");
|
|
2573
|
+
_$setProp2(_el$2, "paddingTop", 1);
|
|
2574
|
+
_$insert2(_el$2, _$createComponent3(For2, {
|
|
2575
|
+
get each() {
|
|
2576
|
+
return lines();
|
|
2577
|
+
},
|
|
2578
|
+
children: (line) => (() => {
|
|
2579
|
+
var _el$6 = _$createElement2("text");
|
|
2580
|
+
_$insert2(_el$6, line || " ");
|
|
2581
|
+
_$effect2((_$p) => _$setProp2(_el$6, "fg", props.context.theme.text.base, _$p));
|
|
2582
|
+
return _el$6;
|
|
2583
|
+
})()
|
|
2290
2584
|
}));
|
|
2291
2585
|
return _el$;
|
|
2292
2586
|
})();
|
|
2293
2587
|
}
|
|
2294
2588
|
|
|
2589
|
+
// src/tui/historystate.ts
|
|
2590
|
+
init_historyclient();
|
|
2591
|
+
|
|
2592
|
+
class HistoryState {
|
|
2593
|
+
options;
|
|
2594
|
+
query;
|
|
2595
|
+
generation = 0;
|
|
2596
|
+
active;
|
|
2597
|
+
pending = false;
|
|
2598
|
+
stopped = false;
|
|
2599
|
+
paused = false;
|
|
2600
|
+
timer;
|
|
2601
|
+
view = { status: "idle", stale: false };
|
|
2602
|
+
now;
|
|
2603
|
+
schedule;
|
|
2604
|
+
cancel;
|
|
2605
|
+
constructor(options) {
|
|
2606
|
+
this.options = options;
|
|
2607
|
+
this.now = options.now ?? Date.now;
|
|
2608
|
+
this.schedule = options.schedule ?? ((callback, ms) => setTimeout(callback, ms));
|
|
2609
|
+
this.cancel = options.cancel ?? clearTimeout;
|
|
2610
|
+
}
|
|
2611
|
+
setQuery(query) {
|
|
2612
|
+
if (this.stopped || query.location === this.query?.location && query.sessionId === this.query.sessionId && query.windowMs === this.query.windowMs)
|
|
2613
|
+
return;
|
|
2614
|
+
this.generation++;
|
|
2615
|
+
this.active?.abort();
|
|
2616
|
+
this.query = { ...query };
|
|
2617
|
+
this.view = { status: "loading", stale: false };
|
|
2618
|
+
if (this.paused)
|
|
2619
|
+
this.publish(this.view);
|
|
2620
|
+
else
|
|
2621
|
+
this.refresh();
|
|
2622
|
+
}
|
|
2623
|
+
pause() {
|
|
2624
|
+
if (this.stopped || this.paused)
|
|
2625
|
+
return;
|
|
2626
|
+
this.paused = true;
|
|
2627
|
+
this.generation++;
|
|
2628
|
+
this.pending = false;
|
|
2629
|
+
this.clearTimer();
|
|
2630
|
+
this.active?.abort();
|
|
2631
|
+
if (this.view.status === "loading" && this.view.result)
|
|
2632
|
+
this.publish({
|
|
2633
|
+
...this.view,
|
|
2634
|
+
status: "ready",
|
|
2635
|
+
reason: undefined,
|
|
2636
|
+
stale: true
|
|
2637
|
+
});
|
|
2638
|
+
}
|
|
2639
|
+
resume() {
|
|
2640
|
+
if (this.stopped || !this.paused)
|
|
2641
|
+
return;
|
|
2642
|
+
this.paused = false;
|
|
2643
|
+
if (this.query && this.view.status === "loading")
|
|
2644
|
+
this.refresh();
|
|
2645
|
+
else if (this.query && (this.view.status === "ready" || this.view.reason === "timeout" || this.view.reason === "unavailable"))
|
|
2646
|
+
this.timer = this.schedule(() => {
|
|
2647
|
+
this.timer = undefined;
|
|
2648
|
+
this.refresh();
|
|
2649
|
+
}, 5000);
|
|
2650
|
+
}
|
|
2651
|
+
refresh() {
|
|
2652
|
+
if (this.stopped || this.paused || !this.query)
|
|
2653
|
+
return;
|
|
2654
|
+
this.clearTimer();
|
|
2655
|
+
this.pending = true;
|
|
2656
|
+
this.publish({
|
|
2657
|
+
...this.view,
|
|
2658
|
+
status: "loading",
|
|
2659
|
+
reason: undefined,
|
|
2660
|
+
stale: this.view.result !== undefined
|
|
2661
|
+
});
|
|
2662
|
+
this.pump();
|
|
2663
|
+
}
|
|
2664
|
+
dispose() {
|
|
2665
|
+
this.stopped = true;
|
|
2666
|
+
this.generation++;
|
|
2667
|
+
this.pending = false;
|
|
2668
|
+
this.clearTimer();
|
|
2669
|
+
this.active?.abort();
|
|
2670
|
+
}
|
|
2671
|
+
clearTimer() {
|
|
2672
|
+
if (this.timer !== undefined)
|
|
2673
|
+
this.cancel(this.timer);
|
|
2674
|
+
this.timer = undefined;
|
|
2675
|
+
}
|
|
2676
|
+
publish(view) {
|
|
2677
|
+
const { reason, ...rest } = view;
|
|
2678
|
+
this.view = { ...rest, ...reason === undefined ? {} : { reason } };
|
|
2679
|
+
this.options.changed(this.view);
|
|
2680
|
+
}
|
|
2681
|
+
async pump() {
|
|
2682
|
+
if (this.stopped || this.paused || this.active || !this.pending || !this.query)
|
|
2683
|
+
return;
|
|
2684
|
+
this.pending = false;
|
|
2685
|
+
const query = this.query, generation = this.generation;
|
|
2686
|
+
const controller = new AbortController;
|
|
2687
|
+
this.active = controller;
|
|
2688
|
+
const signal = AbortSignal.any([
|
|
2689
|
+
controller.signal,
|
|
2690
|
+
this.options.deadline?.() ?? AbortSignal.timeout(5000)
|
|
2691
|
+
]);
|
|
2692
|
+
const to = Math.max(0, Math.floor(this.now())), from = Math.max(0, to - query.windowMs);
|
|
2693
|
+
const current = () => !this.stopped && generation === this.generation;
|
|
2694
|
+
try {
|
|
2695
|
+
const result = checkedHistory(await this.options.read(query.sessionId, from, to, signal), query.sessionId);
|
|
2696
|
+
if (!current())
|
|
2697
|
+
return;
|
|
2698
|
+
if (signal.aborted)
|
|
2699
|
+
throw historyFailure(undefined, signal);
|
|
2700
|
+
this.publish({
|
|
2701
|
+
status: result.enabled ? "ready" : "disabled",
|
|
2702
|
+
result,
|
|
2703
|
+
from,
|
|
2704
|
+
to,
|
|
2705
|
+
loadedAt: this.now(),
|
|
2706
|
+
stale: false
|
|
2707
|
+
});
|
|
2708
|
+
} catch (error) {
|
|
2709
|
+
if (current())
|
|
2710
|
+
this.publish({
|
|
2711
|
+
...this.view,
|
|
2712
|
+
status: "unavailable",
|
|
2713
|
+
reason: historyFailure(error, signal).reason,
|
|
2714
|
+
stale: this.view.result !== undefined
|
|
2715
|
+
});
|
|
2716
|
+
} finally {
|
|
2717
|
+
this.active = undefined;
|
|
2718
|
+
if (this.pending && !this.paused) {
|
|
2719
|
+
this.publish({
|
|
2720
|
+
...this.view,
|
|
2721
|
+
status: "loading",
|
|
2722
|
+
reason: undefined,
|
|
2723
|
+
stale: this.view.result !== undefined
|
|
2724
|
+
});
|
|
2725
|
+
this.pump();
|
|
2726
|
+
} else if (current() && !this.paused && (this.view.status === "ready" || this.view.reason === "timeout" || this.view.reason === "unavailable")) {
|
|
2727
|
+
this.timer = this.schedule(() => {
|
|
2728
|
+
this.timer = undefined;
|
|
2729
|
+
this.refresh();
|
|
2730
|
+
}, 5000);
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
// src/tui/panelview.tsx
|
|
2737
|
+
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
2738
|
+
import { insertNode as _$insertNode3 } from "@opentui/solid";
|
|
2739
|
+
import { effect as _$effect3 } from "@opentui/solid";
|
|
2740
|
+
import { insert as _$insert3 } from "@opentui/solid";
|
|
2741
|
+
import { setProp as _$setProp3 } from "@opentui/solid";
|
|
2742
|
+
import { createElement as _$createElement3 } from "@opentui/solid";
|
|
2743
|
+
import { createComponent as _$createComponent4 } from "@opentui/solid";
|
|
2744
|
+
import { For as For3, Index as Index2, Show as Show2, createMemo as createMemo3 } from "solid-js";
|
|
2745
|
+
init_format();
|
|
2746
|
+
init_statusformat();
|
|
2747
|
+
init_panelformat();
|
|
2748
|
+
function PanelOverview(props) {
|
|
2749
|
+
const visible = createMemo3(() => {
|
|
2750
|
+
const index = Math.max(0, props.rows.findIndex((row2) => row2.node.sessionId === props.selectedId));
|
|
2751
|
+
const start = Math.max(0, index - 10);
|
|
2752
|
+
return props.rows.slice(start, start + 25);
|
|
2753
|
+
});
|
|
2754
|
+
return _$createComponent4(Index2, {
|
|
2755
|
+
get each() {
|
|
2756
|
+
return visible();
|
|
2757
|
+
},
|
|
2758
|
+
children: (row2) => (() => {
|
|
2759
|
+
var _el$ = _$createElement3("box");
|
|
2760
|
+
_$setProp3(_el$, "flexDirection", "column");
|
|
2761
|
+
_$setProp3(_el$, "flexShrink", 0);
|
|
2762
|
+
_$setProp3(_el$, "onMouseDown", () => props.open(row2()));
|
|
2763
|
+
_$insert3(_el$, _$createComponent4(Index2, {
|
|
2764
|
+
get each() {
|
|
2765
|
+
return panelRowLines(row2(), props.width, row2().node.sessionId === props.selectedId);
|
|
2766
|
+
},
|
|
2767
|
+
children: (line) => (() => {
|
|
2768
|
+
var _el$2 = _$createElement3("text");
|
|
2769
|
+
_$insert3(_el$2, line);
|
|
2770
|
+
_$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));
|
|
2771
|
+
return _el$2;
|
|
2772
|
+
})()
|
|
2773
|
+
}));
|
|
2774
|
+
_$effect3((_$p) => _$setProp3(_el$, "id", `context-guard.row.${row2().node.sessionId}`, _$p));
|
|
2775
|
+
return _el$;
|
|
2776
|
+
})()
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
function PanelDetails(props) {
|
|
2780
|
+
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));
|
|
2781
|
+
const detail = createMemo3(() => {
|
|
2782
|
+
const row2 = props.row;
|
|
2783
|
+
if (!row2)
|
|
2784
|
+
return ["No selected session; return to Overview."];
|
|
2785
|
+
const byId = new Map(props.rows.map((r) => [r.node.sessionId, r.node]));
|
|
2786
|
+
const ancestry = [], seen = new Set;
|
|
2787
|
+
let node = row2.node;
|
|
2788
|
+
while (!seen.has(node.sessionId)) {
|
|
2789
|
+
seen.add(node.sessionId);
|
|
2790
|
+
ancestry.unshift(node.agent ?? node.sessionId);
|
|
2791
|
+
const parent = node.parentId ? byId.get(node.parentId) : undefined;
|
|
2792
|
+
if (!parent)
|
|
2793
|
+
break;
|
|
2794
|
+
node = parent;
|
|
2795
|
+
}
|
|
2796
|
+
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));
|
|
2797
|
+
});
|
|
2798
|
+
return (() => {
|
|
2799
|
+
var _el$3 = _$createElement3("box"), _el$4 = _$createElement3("text");
|
|
2800
|
+
_$insertNode3(_el$3, _el$4);
|
|
2801
|
+
_$setProp3(_el$3, "flexDirection", "column");
|
|
2802
|
+
_$setProp3(_el$3, "flexShrink", 0);
|
|
2803
|
+
_$insertNode3(_el$4, _$createTextNode2(`Context history`));
|
|
2804
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2805
|
+
get each() {
|
|
2806
|
+
return chart();
|
|
2807
|
+
},
|
|
2808
|
+
children: (item) => (() => {
|
|
2809
|
+
var _el$6 = _$createElement3("text");
|
|
2810
|
+
_$insert3(_el$6, _$createComponent4(Show2, {
|
|
2811
|
+
get when() {
|
|
2812
|
+
return item.segments;
|
|
2813
|
+
},
|
|
2814
|
+
get fallback() {
|
|
2815
|
+
return item.line;
|
|
2816
|
+
},
|
|
2817
|
+
get children() {
|
|
2818
|
+
return _$createComponent4(For3, {
|
|
2819
|
+
get each() {
|
|
2820
|
+
return item.segments;
|
|
2821
|
+
},
|
|
2822
|
+
children: (part) => (() => {
|
|
2823
|
+
var _el$7 = _$createElement3("span");
|
|
2824
|
+
_$insert3(_el$7, () => part.text);
|
|
2825
|
+
_$effect3((_$p) => _$setProp3(_el$7, "style", {
|
|
2826
|
+
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
|
|
2827
|
+
}, _$p));
|
|
2828
|
+
return _el$7;
|
|
2829
|
+
})()
|
|
2830
|
+
});
|
|
2831
|
+
}
|
|
2832
|
+
}));
|
|
2833
|
+
_$effect3((_$p) => _$setProp3(_el$6, "fg", item.threshold ? props.context.theme.text.feedback.warning.base : props.context.theme.text.muted, _$p));
|
|
2834
|
+
return _el$6;
|
|
2835
|
+
})()
|
|
2836
|
+
}), null);
|
|
2837
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2838
|
+
get each() {
|
|
2839
|
+
return contextHistoryLegend.flatMap((line) => wrap(line, props.width));
|
|
2840
|
+
},
|
|
2841
|
+
children: (line) => (() => {
|
|
2842
|
+
var _el$8 = _$createElement3("text");
|
|
2843
|
+
_$insert3(_el$8, line);
|
|
2844
|
+
_$effect3((_$p) => _$setProp3(_el$8, "fg", props.context.theme.text.muted, _$p));
|
|
2845
|
+
return _el$8;
|
|
2846
|
+
})()
|
|
2847
|
+
}), null);
|
|
2848
|
+
_$insert3(_el$3, _$createComponent4(For3, {
|
|
2849
|
+
get each() {
|
|
2850
|
+
return detail();
|
|
2851
|
+
},
|
|
2852
|
+
children: (line) => (() => {
|
|
2853
|
+
var _el$9 = _$createElement3("text");
|
|
2854
|
+
_$insert3(_el$9, line);
|
|
2855
|
+
_$effect3((_$p) => _$setProp3(_el$9, "fg", props.context.theme.text.base, _$p));
|
|
2856
|
+
return _el$9;
|
|
2857
|
+
})()
|
|
2858
|
+
}), null);
|
|
2859
|
+
_$effect3((_$p) => _$setProp3(_el$4, "fg", props.context.theme.text.base, _$p));
|
|
2860
|
+
return _el$3;
|
|
2861
|
+
})();
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2295
2864
|
// src/tui/panel.tsx
|
|
2865
|
+
init_panelformat();
|
|
2296
2866
|
init_chartformat();
|
|
2297
2867
|
init_format();
|
|
2868
|
+
init_statusformat();
|
|
2869
|
+
|
|
2870
|
+
// src/tui/panelcontrols.ts
|
|
2871
|
+
init_format();
|
|
2872
|
+
function inventoryMessages(status) {
|
|
2873
|
+
if (status.scanning)
|
|
2874
|
+
return [`Discovering agents \xB7 ${status.discovered} found`];
|
|
2875
|
+
const lines = [];
|
|
2876
|
+
if (status.failed || status.damaged)
|
|
2877
|
+
lines.push("Family discovery incomplete \xB7 refresh to rescan");
|
|
2878
|
+
if (status.pending && status.discovered >= 2048)
|
|
2879
|
+
lines.push("Partial family \xB7 2048-node limit reached");
|
|
2880
|
+
else if (status.canLoadMore)
|
|
2881
|
+
lines.push(status.discovered >= status.limit ? `Partial family \xB7 ${status.limit}-node limit \xB7 load more allows 2048` : "Partial family \xB7 load more available");
|
|
2882
|
+
else if (!status.complete && !lines.length)
|
|
2883
|
+
lines.push("Family discovery incomplete \xB7 refresh to rescan");
|
|
2884
|
+
return lines;
|
|
2885
|
+
}
|
|
2886
|
+
function footerActions(essential, optional, width) {
|
|
2887
|
+
const result = [];
|
|
2888
|
+
let used = 0;
|
|
2889
|
+
for (const action of [...essential, ...optional]) {
|
|
2890
|
+
const size = cells(action.label) + (result.length ? 1 : 0);
|
|
2891
|
+
if (used + size > width)
|
|
2892
|
+
continue;
|
|
2893
|
+
result.push(action);
|
|
2894
|
+
used += size;
|
|
2895
|
+
}
|
|
2896
|
+
return result;
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// src/tui/panel.tsx
|
|
2298
2900
|
function GuardPanel(props) {
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
const
|
|
2901
|
+
const consumer = props.state.acquire(props.input.sessionID);
|
|
2902
|
+
createEffect3(on(() => props.input.sessionID, (id) => consumer.update(id)));
|
|
2903
|
+
onCleanup2(() => consumer.release());
|
|
2904
|
+
const [help, setHelp] = createSignal3(false);
|
|
2905
|
+
let sourceScroll = 0;
|
|
2906
|
+
const [view, setView] = createSignal3("overview");
|
|
2907
|
+
const [metricIndex, setMetricIndex] = createSignal3(0);
|
|
2908
|
+
const [viewportWidth, setViewportWidth] = createSignal3();
|
|
2909
|
+
const [height, setHeight] = createSignal3(24);
|
|
2910
|
+
const width = () => Math.max(1, Math.min(props.input.width - 4, viewportWidth() ?? Infinity));
|
|
2911
|
+
const compact = () => height() < 18;
|
|
2303
2912
|
const windows = [300000, 3600000, 86400000, 7 * 86400000];
|
|
2304
|
-
const [windowIndex, setWindowIndex] =
|
|
2305
|
-
const [chartRefresh, setChartRefresh] =
|
|
2306
|
-
const [
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2913
|
+
const [windowIndex, setWindowIndex] = createSignal3(1);
|
|
2914
|
+
const [chartRefresh, setChartRefresh] = createSignal3(0);
|
|
2915
|
+
const [chartView, setChartView] = createSignal3({
|
|
2916
|
+
status: "idle",
|
|
2917
|
+
stale: false
|
|
2918
|
+
});
|
|
2919
|
+
const history = new HistoryState({
|
|
2920
|
+
read: (id, from, to, signal) => props.state.history(id, from, to, signal),
|
|
2921
|
+
changed: setChartView
|
|
2922
|
+
});
|
|
2923
|
+
history.pause();
|
|
2924
|
+
onCleanup2(() => history.dispose());
|
|
2925
|
+
const [selected, setSelected] = createSignal3(props.input.sessionID);
|
|
2926
|
+
const [order, setOrder] = createSignal3([]);
|
|
2927
|
+
const rows = createMemo4(() => props.state.rows(order()));
|
|
2928
|
+
const family = createMemo4(() => routeFamily(props.state.rows([], true), props.input.sessionID));
|
|
2929
|
+
const selectedRow = createMemo4(() => rows().find((row2) => row2.node.sessionId === selected()));
|
|
2930
|
+
createEffect3(on(() => {
|
|
2931
|
+
const id = selected();
|
|
2932
|
+
return id ? [id, windows[windowIndex()] ?? 3600000, props.state.historyLocation(id)] : undefined;
|
|
2933
|
+
}, (query) => {
|
|
2934
|
+
if (query)
|
|
2935
|
+
history.setQuery({
|
|
2936
|
+
sessionId: query[0],
|
|
2937
|
+
windowMs: query[1],
|
|
2938
|
+
location: query[2]
|
|
2939
|
+
});
|
|
2940
|
+
}));
|
|
2941
|
+
createEffect3(on(chartRefresh, () => history.refresh(), {
|
|
2942
|
+
defer: true
|
|
2943
|
+
}));
|
|
2310
2944
|
const offset = () => Math.max(0, rows().findIndex((row2) => row2.node.sessionId === selected()));
|
|
2311
|
-
|
|
2945
|
+
const trace = createMemo4(() => props.state.contextTrace(selectedRow()));
|
|
2946
|
+
createEffect3(() => {
|
|
2947
|
+
const current = rows().find((row2) => row2.node.sessionId === props.input.sessionID);
|
|
2948
|
+
if (current && current.node.sessionId !== selected())
|
|
2949
|
+
props.state.contextTrace(current);
|
|
2950
|
+
});
|
|
2951
|
+
createEffect3(() => {
|
|
2312
2952
|
if (!props.input.focused)
|
|
2313
2953
|
setOrder([]);
|
|
2314
2954
|
});
|
|
2315
|
-
|
|
2316
|
-
|
|
2955
|
+
createEffect3(on(() => props.input.sessionID, (id) => {
|
|
2956
|
+
history.pause();
|
|
2957
|
+
setSelected(id);
|
|
2317
2958
|
setOrder([]);
|
|
2959
|
+
setHelp(false);
|
|
2960
|
+
sourceScroll = 0;
|
|
2961
|
+
setView("overview");
|
|
2962
|
+
}));
|
|
2963
|
+
createEffect3(() => {
|
|
2964
|
+
const family2 = rows();
|
|
2965
|
+
if (!family2.some((row2) => row2.node.sessionId === selected()))
|
|
2966
|
+
setSelected(family2.find((row2) => row2.node.sessionId === props.input.sessionID)?.node.sessionId ?? family2[0]?.node.sessionId);
|
|
2318
2967
|
});
|
|
2319
2968
|
let scroll;
|
|
2320
2969
|
let follow;
|
|
2321
|
-
function
|
|
2970
|
+
function cancelFollow() {
|
|
2322
2971
|
if (follow)
|
|
2323
2972
|
props.context.renderer.removeFrameCallback(follow);
|
|
2973
|
+
follow = undefined;
|
|
2974
|
+
}
|
|
2975
|
+
function afterLayout(action) {
|
|
2976
|
+
if (!props.context.renderer)
|
|
2977
|
+
return;
|
|
2978
|
+
cancelFollow();
|
|
2324
2979
|
let frames = 0;
|
|
2325
2980
|
follow = async () => {
|
|
2326
|
-
|
|
2327
|
-
if (++frames >= 2
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
} else
|
|
2981
|
+
action();
|
|
2982
|
+
if (++frames >= 2)
|
|
2983
|
+
cancelFollow();
|
|
2984
|
+
else
|
|
2331
2985
|
props.context.renderer.requestRender();
|
|
2332
2986
|
};
|
|
2333
2987
|
props.context.renderer.setFrameCallback(follow);
|
|
2334
2988
|
props.context.renderer.requestRender();
|
|
2335
2989
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2990
|
+
function revealSelection() {
|
|
2991
|
+
afterLayout(() => scroll?.scrollChildIntoView(`context-guard.row.${selected()}`));
|
|
2992
|
+
}
|
|
2993
|
+
function toggleHelp() {
|
|
2994
|
+
cancelFollow();
|
|
2995
|
+
if (!help()) {
|
|
2996
|
+
if (view() === "charts")
|
|
2997
|
+
history.pause();
|
|
2998
|
+
sourceScroll = scroll?.scrollTop ?? 0;
|
|
2999
|
+
setHelp(true);
|
|
3000
|
+
afterLayout(() => scroll?.scrollTo(0));
|
|
3001
|
+
} else {
|
|
3002
|
+
setHelp(false);
|
|
3003
|
+
if (view() === "charts")
|
|
3004
|
+
history.resume();
|
|
3005
|
+
afterLayout(() => scroll?.scrollTo(sourceScroll));
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
onCleanup2(cancelFollow);
|
|
3009
|
+
createEffect3(() => {
|
|
3010
|
+
view();
|
|
3011
|
+
selected();
|
|
3012
|
+
rows();
|
|
3013
|
+
width();
|
|
3014
|
+
height();
|
|
3015
|
+
if (!help() && view() === "overview")
|
|
3016
|
+
revealSelection();
|
|
2339
3017
|
});
|
|
3018
|
+
function changeView(next) {
|
|
3019
|
+
if (next !== "overview" && !selectedRow())
|
|
3020
|
+
return;
|
|
3021
|
+
cancelFollow();
|
|
3022
|
+
if (view() === "charts" && next !== "charts")
|
|
3023
|
+
history.pause();
|
|
3024
|
+
setView(next);
|
|
3025
|
+
if (next === "charts")
|
|
3026
|
+
history.resume();
|
|
3027
|
+
scroll?.scrollTo(0);
|
|
3028
|
+
if (next === "overview")
|
|
3029
|
+
revealSelection();
|
|
3030
|
+
}
|
|
2340
3031
|
function move(delta) {
|
|
2341
3032
|
setOrder(rows().map((row3) => row3.node.sessionId));
|
|
2342
3033
|
const row2 = rows()[Math.max(0, Math.min(rows().length - 1, offset() + delta))];
|
|
2343
|
-
if (row2)
|
|
3034
|
+
if (row2)
|
|
2344
3035
|
setSelected(row2.node.sessionId);
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
}
|
|
3036
|
+
if (view() === "charts")
|
|
3037
|
+
scroll?.scrollTo(0);
|
|
2348
3038
|
}
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
run: () => {
|
|
2382
|
-
if (showCharts())
|
|
2383
|
-
setWindowIndex((i) => Math.max(0, i - 1));
|
|
2384
|
-
}
|
|
2385
|
-
}, {
|
|
2386
|
-
id: "context-guard.chart-longer",
|
|
2387
|
-
title: "Longer chart window",
|
|
2388
|
-
bind: "]",
|
|
2389
|
-
run: () => {
|
|
2390
|
-
if (showCharts())
|
|
2391
|
-
setWindowIndex((i) => Math.min(windows.length - 1, i + 1));
|
|
2392
|
-
}
|
|
2393
|
-
}, {
|
|
2394
|
-
id: "context-guard.inspect",
|
|
2395
|
-
title: "Inspect selected session",
|
|
2396
|
-
bind: "i",
|
|
2397
|
-
run: () => setInspectId(inspectId() === selected() ? undefined : selected())
|
|
2398
|
-
}, {
|
|
2399
|
-
id: "context-guard.refresh",
|
|
2400
|
-
title: "Refresh Context Guard",
|
|
2401
|
-
bind: "r",
|
|
2402
|
-
run: () => {
|
|
2403
|
-
setOrder([]);
|
|
2404
|
-
props.state.refresh();
|
|
2405
|
-
setChartRefresh((n) => n + 1);
|
|
2406
|
-
}
|
|
2407
|
-
}, {
|
|
2408
|
-
id: "context-guard.load-more",
|
|
2409
|
-
title: "Load more family",
|
|
2410
|
-
bind: "l",
|
|
2411
|
-
run: () => props.state.loadMore()
|
|
2412
|
-
}, {
|
|
2413
|
-
id: "context-guard.next",
|
|
2414
|
-
bind: "down",
|
|
2415
|
-
run: () => move(1)
|
|
2416
|
-
}, {
|
|
2417
|
-
id: "context-guard.previous",
|
|
2418
|
-
bind: "up",
|
|
2419
|
-
run: () => move(-1)
|
|
2420
|
-
}, {
|
|
2421
|
-
id: "context-guard.expand",
|
|
2422
|
-
bind: "space",
|
|
3039
|
+
function open(row2) {
|
|
3040
|
+
if (!row2)
|
|
3041
|
+
return;
|
|
3042
|
+
props.input.close();
|
|
3043
|
+
props.context.ui.router.navigate({
|
|
3044
|
+
type: "session",
|
|
3045
|
+
sessionID: row2.node.sessionId
|
|
3046
|
+
});
|
|
3047
|
+
}
|
|
3048
|
+
function page(delta) {
|
|
3049
|
+
if (!help() && view() === "overview")
|
|
3050
|
+
move(delta * Math.max(1, Math.floor((scroll?.viewport.height ?? 1) / (width() >= 72 ? 1 : 3))));
|
|
3051
|
+
else
|
|
3052
|
+
scroll?.scrollBy(delta * Math.max(1, (scroll.viewport.height ?? 1) - 1));
|
|
3053
|
+
}
|
|
3054
|
+
function edge(last) {
|
|
3055
|
+
if (!help() && view() === "overview")
|
|
3056
|
+
move(last ? rows().length : -rows().length);
|
|
3057
|
+
else
|
|
3058
|
+
scroll?.scrollTo(last ? scroll.scrollHeight : 0);
|
|
3059
|
+
}
|
|
3060
|
+
const inventory = () => props.state.inventoryStatus();
|
|
3061
|
+
const expandable = () => {
|
|
3062
|
+
const row2 = selectedRow();
|
|
3063
|
+
return !!row2 && (row2.hidden > 0 || row2.node.status === "completed" && rows().some((r) => r.node.parentId === row2.node.sessionId));
|
|
3064
|
+
};
|
|
3065
|
+
function command(name, title, bind, run, enabled = () => !help()) {
|
|
3066
|
+
return {
|
|
3067
|
+
id: `context-guard.${name}`,
|
|
3068
|
+
title,
|
|
3069
|
+
bind,
|
|
3070
|
+
enabled,
|
|
2423
3071
|
run: () => {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
props.state.expand(row2.node.sessionId);
|
|
3072
|
+
if (props.input.focused && enabled())
|
|
3073
|
+
run();
|
|
2427
3074
|
}
|
|
2428
|
-
}
|
|
2429
|
-
|
|
2430
|
-
|
|
3075
|
+
};
|
|
3076
|
+
}
|
|
3077
|
+
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", () => {
|
|
3078
|
+
setOrder([]);
|
|
3079
|
+
props.state.refresh();
|
|
3080
|
+
setChartRefresh((n) => n + 1);
|
|
3081
|
+
}), 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", () => {
|
|
3082
|
+
const row2 = selectedRow();
|
|
3083
|
+
if (row2)
|
|
3084
|
+
props.state.expand(row2.node.sessionId);
|
|
3085
|
+
}, () => !help() && view() === "overview" && expandable()), command("open", "Open selected session", "return", () => open(selectedRow()), () => !help() && !!selectedRow())];
|
|
3086
|
+
props.context.keymap.layer(() => ({
|
|
3087
|
+
enabled: () => props.input.focused,
|
|
3088
|
+
commands: commands()
|
|
3089
|
+
}));
|
|
3090
|
+
const shortcut = (name) => props.context.keymap.shortcuts(`context-guard.${name}`).join("/");
|
|
3091
|
+
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()));
|
|
3092
|
+
const statusLines = () => monitorStatusLines(props.state.connection(), props.state.health(), rows().some((row2) => row2.snapshot?.measurement !== undefined), width() < 28).flatMap((line) => wrap(line, width()));
|
|
3093
|
+
const notice = () => compactionLabel(selectedRow());
|
|
3094
|
+
const actions = () => {
|
|
3095
|
+
const action = (name, label) => ({
|
|
3096
|
+
id: name,
|
|
3097
|
+
label: ["help", "close"].includes(name) && cells(`${shortcut(name)} ${label}`) > Math.floor((width() - 1) / 2) ? label : `${shortcut(name) ? shortcut(name) + " " : ""}${label}`,
|
|
2431
3098
|
run: () => {
|
|
2432
|
-
|
|
2433
|
-
if (row2) {
|
|
2434
|
-
props.input.close();
|
|
2435
|
-
props.context.ui.router.navigate({
|
|
2436
|
-
type: "session",
|
|
2437
|
-
sessionID: row2.node.sessionId
|
|
2438
|
-
});
|
|
2439
|
-
}
|
|
3099
|
+
commands().find((c) => c.id === `context-guard.${name}`)?.run();
|
|
2440
3100
|
}
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
|
-
|
|
3101
|
+
});
|
|
3102
|
+
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")] : []];
|
|
3103
|
+
return footerActions([action("help", help() ? "back" : "help"), action("close", "close")], optional, width());
|
|
3104
|
+
};
|
|
3105
|
+
const hint = () => {
|
|
3106
|
+
if (help())
|
|
3107
|
+
return `${shortcut("previous")}/${shortcut("next")} scroll`;
|
|
3108
|
+
if (view() === "charts")
|
|
3109
|
+
return `${shortcut("refresh")} refresh \xB7 ${shortcut("chart-previous")}/${shortcut("chart-next")} metric ${shortcut("previous")}/${shortcut("next")} session ${shortcut("chart-shorter")}/${shortcut("chart-longer")} window`;
|
|
3110
|
+
if (view() === "details")
|
|
3111
|
+
return `${shortcut("previous")}/${shortcut("next")} scroll \xB7 ${shortcut("page-previous")}/${shortcut("page-next")} page`;
|
|
3112
|
+
return `${shortcut("previous")}/${shortcut("next")} select \xB7 ${shortcut("open")} open \xB7 ${inventory().canLoadMore ? shortcut("load-more") + " more" : shortcut("refresh") + " refresh"}`;
|
|
3113
|
+
};
|
|
2444
3114
|
return (() => {
|
|
2445
|
-
var _el$ = _$createElement4("box"), _el$2 = _$createElement4("
|
|
3115
|
+
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");
|
|
2446
3116
|
_$insertNode4(_el$, _el$2);
|
|
2447
|
-
_$insertNode4(_el$, _el$
|
|
3117
|
+
_$insertNode4(_el$, _el$6);
|
|
3118
|
+
_$insertNode4(_el$, _el$7);
|
|
2448
3119
|
_$setProp4(_el$, "flexDirection", "column");
|
|
2449
3120
|
_$setProp4(_el$, "flexGrow", 1);
|
|
3121
|
+
_$setProp4(_el$, "minHeight", 0);
|
|
2450
3122
|
_$setProp4(_el$, "paddingLeft", 2);
|
|
2451
3123
|
_$setProp4(_el$, "paddingRight", 2);
|
|
2452
|
-
_$setProp4(_el$, "
|
|
2453
|
-
|
|
3124
|
+
_$setProp4(_el$, "onSizeChange", function() {
|
|
3125
|
+
setHeight(this.height);
|
|
3126
|
+
});
|
|
2454
3127
|
_$insertNode4(_el$2, _el$3);
|
|
3128
|
+
_$setProp4(_el$2, "flexDirection", "column");
|
|
3129
|
+
_$setProp4(_el$2, "flexShrink", 0);
|
|
3130
|
+
_$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()));
|
|
3131
|
+
_$insert4(_el$2, _$createComponent5(For4, {
|
|
3132
|
+
get each() {
|
|
3133
|
+
return statusLines();
|
|
3134
|
+
},
|
|
3135
|
+
children: (line) => (() => {
|
|
3136
|
+
var _el$0 = _$createElement4("text");
|
|
3137
|
+
_$insert4(_el$0, line);
|
|
3138
|
+
_$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));
|
|
3139
|
+
return _el$0;
|
|
3140
|
+
})()
|
|
3141
|
+
}), null);
|
|
3142
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3143
|
+
get when() {
|
|
3144
|
+
return !["2.0.29", "2.1.2"].includes(props.context.app.version);
|
|
3145
|
+
},
|
|
3146
|
+
get children() {
|
|
3147
|
+
var _el$4 = _$createElement4("text");
|
|
3148
|
+
_$insert4(_el$4, () => clip(`Runtime ${props.context.app.version}: unverified`, width()));
|
|
3149
|
+
_$effect4((_$p) => _$setProp4(_el$4, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
3150
|
+
return _el$4;
|
|
3151
|
+
}
|
|
3152
|
+
}), null);
|
|
3153
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3154
|
+
get when() {
|
|
3155
|
+
return notice();
|
|
3156
|
+
},
|
|
3157
|
+
children: (message) => (() => {
|
|
3158
|
+
var _el$1 = _$createElement4("text");
|
|
3159
|
+
_$insert4(_el$1, () => clip(message(), width()));
|
|
3160
|
+
_$effect4((_$p) => _$setProp4(_el$1, "fg", props.context.theme.text.feedback.warning.base, _$p));
|
|
3161
|
+
return _el$1;
|
|
3162
|
+
})()
|
|
3163
|
+
}), null);
|
|
3164
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3165
|
+
get when() {
|
|
3166
|
+
return _$memo2(() => !!(help() || view() !== "overview"))() && selectedRow();
|
|
3167
|
+
},
|
|
3168
|
+
children: (row2) => (() => {
|
|
3169
|
+
var _el$10 = _$createElement4("text");
|
|
3170
|
+
_$insert4(_el$10, () => clip(`Selected: ${row2().node.agent ?? row2().node.sessionId}`, width()));
|
|
3171
|
+
_$effect4((_$p) => _$setProp4(_el$10, "fg", props.context.theme.text.base, _$p));
|
|
3172
|
+
return _el$10;
|
|
3173
|
+
})()
|
|
3174
|
+
}), null);
|
|
3175
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3176
|
+
get when() {
|
|
3177
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
3178
|
+
},
|
|
3179
|
+
get children() {
|
|
3180
|
+
return [_$createComponent5(For4, {
|
|
3181
|
+
get each() {
|
|
3182
|
+
return panelSummary(selectedRow(), width(), props.state.age(selected() ?? ""), compact());
|
|
3183
|
+
},
|
|
3184
|
+
children: (line) => (() => {
|
|
3185
|
+
var _el$11 = _$createElement4("text");
|
|
3186
|
+
_$insert4(_el$11, line);
|
|
3187
|
+
_$effect4((_$p) => _$setProp4(_el$11, "fg", props.context.theme.text.base, _$p));
|
|
3188
|
+
return _el$11;
|
|
3189
|
+
})()
|
|
3190
|
+
}), (() => {
|
|
3191
|
+
var _el$5 = _$createElement4("text");
|
|
3192
|
+
_$insert4(_el$5, () => panelRowHeading(`Family ${rows().length ? offset() + 1 : 0}/${rows().length}${props.state.complete() ? "" : " \xB7 partial"} \xB7 * current`, width()));
|
|
3193
|
+
_$effect4((_$p) => _$setProp4(_el$5, "fg", props.context.theme.text.muted, _$p));
|
|
3194
|
+
return _el$5;
|
|
3195
|
+
})()];
|
|
3196
|
+
}
|
|
3197
|
+
}), null);
|
|
3198
|
+
_$insert4(_el$2, _$createComponent5(Show3, {
|
|
3199
|
+
get when() {
|
|
3200
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
3201
|
+
},
|
|
3202
|
+
get children() {
|
|
3203
|
+
return _$createComponent5(For4, {
|
|
3204
|
+
get each() {
|
|
3205
|
+
return inventoryMessages(inventory());
|
|
3206
|
+
},
|
|
3207
|
+
children: (line) => (() => {
|
|
3208
|
+
var _el$12 = _$createElement4("text");
|
|
3209
|
+
_$insert4(_el$12, () => clip(line, width()));
|
|
3210
|
+
_$effect4((_$p) => _$setProp4(_el$12, "fg", props.context.theme.text.muted, _$p));
|
|
3211
|
+
return _el$12;
|
|
3212
|
+
})()
|
|
3213
|
+
});
|
|
3214
|
+
}
|
|
3215
|
+
}), null);
|
|
2455
3216
|
_$use((value) => {
|
|
2456
3217
|
scroll = value;
|
|
2457
|
-
}, _el$
|
|
2458
|
-
_$setProp4(_el$
|
|
3218
|
+
}, _el$6);
|
|
3219
|
+
_$setProp4(_el$6, "viewportOptions", {
|
|
2459
3220
|
onSizeChange: function() {
|
|
2460
3221
|
setViewportWidth(this.width);
|
|
2461
3222
|
}
|
|
2462
3223
|
});
|
|
2463
|
-
_$setProp4(_el$
|
|
2464
|
-
_$setProp4(_el$
|
|
2465
|
-
_$
|
|
2466
|
-
_$
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
return props.input.sessionID;
|
|
2470
|
-
},
|
|
2471
|
-
get state() {
|
|
2472
|
-
return props.state;
|
|
2473
|
-
},
|
|
2474
|
-
get context() {
|
|
2475
|
-
return props.context;
|
|
2476
|
-
},
|
|
2477
|
-
get width() {
|
|
2478
|
-
return width();
|
|
2479
|
-
},
|
|
2480
|
-
expanded: true,
|
|
2481
|
-
get family() {
|
|
2482
|
-
return rows();
|
|
2483
|
-
},
|
|
2484
|
-
get selectedId() {
|
|
2485
|
-
return selected();
|
|
3224
|
+
_$setProp4(_el$6, "flexGrow", 1);
|
|
3225
|
+
_$setProp4(_el$6, "minHeight", 0);
|
|
3226
|
+
_$setProp4(_el$6, "scrollX", false);
|
|
3227
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3228
|
+
get when() {
|
|
3229
|
+
return help();
|
|
2486
3230
|
},
|
|
2487
|
-
get
|
|
2488
|
-
return
|
|
3231
|
+
get children() {
|
|
3232
|
+
return _$createComponent5(For4, {
|
|
3233
|
+
get each() {
|
|
3234
|
+
return helpLines();
|
|
3235
|
+
},
|
|
3236
|
+
children: (line) => (() => {
|
|
3237
|
+
var _el$13 = _$createElement4("text");
|
|
3238
|
+
_$insert4(_el$13, line);
|
|
3239
|
+
_$effect4((_$p) => _$setProp4(_el$13, "fg", props.context.theme.text.base, _$p));
|
|
3240
|
+
return _el$13;
|
|
3241
|
+
})()
|
|
3242
|
+
});
|
|
2489
3243
|
}
|
|
2490
|
-
}),
|
|
2491
|
-
_$insert4(_el$
|
|
2492
|
-
_$insert4(_el$2, _$createComponent4(Show3, {
|
|
3244
|
+
}), null);
|
|
3245
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
2493
3246
|
get when() {
|
|
2494
|
-
return
|
|
3247
|
+
return _$memo2(() => !!!help())() && view() === "overview";
|
|
2495
3248
|
},
|
|
2496
3249
|
get children() {
|
|
2497
|
-
return _$
|
|
2498
|
-
get
|
|
3250
|
+
return _$createComponent5(PanelOverview, {
|
|
3251
|
+
get rows() {
|
|
3252
|
+
return rows();
|
|
3253
|
+
},
|
|
3254
|
+
get selectedId() {
|
|
2499
3255
|
return selected();
|
|
2500
3256
|
},
|
|
2501
|
-
get
|
|
2502
|
-
return
|
|
3257
|
+
get width() {
|
|
3258
|
+
return width();
|
|
2503
3259
|
},
|
|
2504
|
-
get
|
|
2505
|
-
return
|
|
3260
|
+
get context() {
|
|
3261
|
+
return props.context;
|
|
2506
3262
|
},
|
|
2507
|
-
|
|
2508
|
-
|
|
3263
|
+
open: (row2) => {
|
|
3264
|
+
if (row2.hidden)
|
|
3265
|
+
props.state.expand(row2.node.sessionId);
|
|
3266
|
+
else
|
|
3267
|
+
open(row2);
|
|
3268
|
+
}
|
|
3269
|
+
});
|
|
3270
|
+
}
|
|
3271
|
+
}), null);
|
|
3272
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3273
|
+
get when() {
|
|
3274
|
+
return _$memo2(() => !!!help())() && view() === "details";
|
|
3275
|
+
},
|
|
3276
|
+
get children() {
|
|
3277
|
+
return _$createComponent5(PanelDetails, {
|
|
3278
|
+
get row() {
|
|
3279
|
+
return selectedRow();
|
|
3280
|
+
},
|
|
3281
|
+
get rows() {
|
|
3282
|
+
return rows();
|
|
3283
|
+
},
|
|
3284
|
+
get routeID() {
|
|
3285
|
+
return props.input.sessionID;
|
|
3286
|
+
},
|
|
3287
|
+
get familyRows() {
|
|
3288
|
+
return family().rows;
|
|
3289
|
+
},
|
|
3290
|
+
get familyComplete() {
|
|
3291
|
+
return _$memo2(() => !!family().complete)() && props.state.complete();
|
|
3292
|
+
},
|
|
3293
|
+
get trace() {
|
|
3294
|
+
return trace();
|
|
2509
3295
|
},
|
|
2510
3296
|
get width() {
|
|
2511
3297
|
return width();
|
|
2512
3298
|
},
|
|
2513
|
-
get
|
|
2514
|
-
return props.state;
|
|
3299
|
+
get age() {
|
|
3300
|
+
return props.state.age(selected() ?? "");
|
|
2515
3301
|
},
|
|
2516
3302
|
get context() {
|
|
2517
3303
|
return props.context;
|
|
3304
|
+
},
|
|
3305
|
+
get reasons() {
|
|
3306
|
+
return props.state.health()?.reasons ?? [];
|
|
2518
3307
|
}
|
|
2519
3308
|
});
|
|
2520
3309
|
}
|
|
2521
3310
|
}), null);
|
|
2522
|
-
_$
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
3311
|
+
_$insert4(_el$6, _$createComponent5(Show3, {
|
|
3312
|
+
get when() {
|
|
3313
|
+
return _$memo2(() => !!(!help() && view() === "charts"))() && selected();
|
|
3314
|
+
},
|
|
3315
|
+
children: (id) => _$createComponent5(HistoryCharts, {
|
|
3316
|
+
get sessionId() {
|
|
3317
|
+
return id();
|
|
3318
|
+
},
|
|
3319
|
+
get windowMs() {
|
|
3320
|
+
return windows[windowIndex()] ?? 3600000;
|
|
3321
|
+
},
|
|
3322
|
+
get metricIndex() {
|
|
3323
|
+
return metricIndex();
|
|
3324
|
+
},
|
|
3325
|
+
get width() {
|
|
3326
|
+
return width();
|
|
3327
|
+
},
|
|
3328
|
+
get view() {
|
|
3329
|
+
return chartView();
|
|
3330
|
+
},
|
|
3331
|
+
get context() {
|
|
3332
|
+
return props.context;
|
|
3333
|
+
}
|
|
3334
|
+
})
|
|
3335
|
+
}), null);
|
|
3336
|
+
_$insertNode4(_el$7, _el$8);
|
|
3337
|
+
_$insertNode4(_el$7, _el$9);
|
|
3338
|
+
_$setProp4(_el$7, "flexDirection", "column");
|
|
3339
|
+
_$setProp4(_el$7, "flexShrink", 0);
|
|
3340
|
+
_$setProp4(_el$8, "flexDirection", "row");
|
|
3341
|
+
_$setProp4(_el$8, "flexShrink", 0);
|
|
3342
|
+
_$insert4(_el$8, _$createComponent5(For4, {
|
|
2526
3343
|
get each() {
|
|
2527
|
-
return
|
|
3344
|
+
return actions();
|
|
2528
3345
|
},
|
|
2529
|
-
children: (
|
|
2530
|
-
var _el$
|
|
2531
|
-
_$insert4(_el$
|
|
2532
|
-
_$effect4((
|
|
2533
|
-
|
|
3346
|
+
children: (action, index) => (() => {
|
|
3347
|
+
var _el$14 = _$createElement4("text");
|
|
3348
|
+
_$insert4(_el$14, () => `${index() ? " " : ""}${action.label}`);
|
|
3349
|
+
_$effect4((_p$) => {
|
|
3350
|
+
var _v$5 = props.context.theme.text.muted, _v$6 = action.run;
|
|
3351
|
+
_v$5 !== _p$.e && (_p$.e = _$setProp4(_el$14, "fg", _v$5, _p$.e));
|
|
3352
|
+
_v$6 !== _p$.t && (_p$.t = _$setProp4(_el$14, "onMouseDown", _v$6, _p$.t));
|
|
3353
|
+
return _p$;
|
|
3354
|
+
}, {
|
|
3355
|
+
e: undefined,
|
|
3356
|
+
t: undefined
|
|
3357
|
+
});
|
|
3358
|
+
return _el$14;
|
|
2534
3359
|
})()
|
|
2535
3360
|
}));
|
|
3361
|
+
_$insert4(_el$9, () => clip(hint(), width()));
|
|
2536
3362
|
_$effect4((_p$) => {
|
|
2537
|
-
var _v$ =
|
|
2538
|
-
_v$ !== _p$.e && (_p$.e = _$setProp4(_el
|
|
2539
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp4(_el
|
|
3363
|
+
var _v$ = compact() ? 0 : 1, _v$2 = compact() ? 0 : 1, _v$3 = props.context.theme.text.base, _v$4 = props.context.theme.text.muted;
|
|
3364
|
+
_v$ !== _p$.e && (_p$.e = _$setProp4(_el$, "paddingTop", _v$, _p$.e));
|
|
3365
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp4(_el$, "paddingBottom", _v$2, _p$.t));
|
|
3366
|
+
_v$3 !== _p$.a && (_p$.a = _$setProp4(_el$3, "fg", _v$3, _p$.a));
|
|
3367
|
+
_v$4 !== _p$.o && (_p$.o = _$setProp4(_el$9, "fg", _v$4, _p$.o));
|
|
2540
3368
|
return _p$;
|
|
2541
3369
|
}, {
|
|
2542
3370
|
e: undefined,
|
|
2543
|
-
t: undefined
|
|
3371
|
+
t: undefined,
|
|
3372
|
+
a: undefined,
|
|
3373
|
+
o: undefined
|
|
2544
3374
|
});
|
|
2545
3375
|
return _el$;
|
|
2546
3376
|
})();
|
|
@@ -2550,14 +3380,18 @@ function GuardPanel(props) {
|
|
|
2550
3380
|
var tui_default = Plugin.define({
|
|
2551
3381
|
id: "context-guard",
|
|
2552
3382
|
setup(context) {
|
|
2553
|
-
|
|
3383
|
+
const openShortcut = context.options.openShortcut;
|
|
3384
|
+
if (openShortcut !== undefined && (typeof openShortcut !== "string" || !openShortcut.trim() || openShortcut.length > 128 || /[\x00-\x1f\x7f-\x9f]/.test(openShortcut))) {
|
|
3385
|
+
throw new Error("Context Guard openShortcut must be a nonempty key sequence of at most 128 characters.");
|
|
3386
|
+
}
|
|
3387
|
+
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") {
|
|
2554
3388
|
throw new Error("Context Guard TUI requires OpenCode 2.0.29 public RPC and panel APIs; use the Guard inspect CLI on unsupported hosts.");
|
|
2555
3389
|
}
|
|
2556
3390
|
const state = createGuardState(context), unregister = [];
|
|
2557
3391
|
try {
|
|
2558
3392
|
unregister.push(context.ui.slot({
|
|
2559
3393
|
append: "sidebar.content",
|
|
2560
|
-
render: (input) => _$
|
|
3394
|
+
render: (input) => _$createComponent6(GuardView, {
|
|
2561
3395
|
get sessionID() {
|
|
2562
3396
|
return input.sessionID;
|
|
2563
3397
|
},
|
|
@@ -2568,12 +3402,12 @@ var tui_default = Plugin.define({
|
|
|
2568
3402
|
}));
|
|
2569
3403
|
unregister.push(context.ui.slot({
|
|
2570
3404
|
append: "session.panel",
|
|
2571
|
-
render: (input) => _$
|
|
3405
|
+
render: (input) => _$createComponent6(Show4, {
|
|
2572
3406
|
get when() {
|
|
2573
3407
|
return input.name === "context-guard.monitor";
|
|
2574
3408
|
},
|
|
2575
3409
|
get children() {
|
|
2576
|
-
return _$
|
|
3410
|
+
return _$createComponent6(GuardPanel, {
|
|
2577
3411
|
input,
|
|
2578
3412
|
state,
|
|
2579
3413
|
context
|
|
@@ -2583,14 +3417,14 @@ var tui_default = Plugin.define({
|
|
|
2583
3417
|
}));
|
|
2584
3418
|
unregister.push(context.ui.slot({
|
|
2585
3419
|
append: "session.composer.top",
|
|
2586
|
-
render: (input) => _$
|
|
3420
|
+
render: (input) => _$createComponent6(Show4, {
|
|
2587
3421
|
get when() {
|
|
2588
3422
|
return context.data.session.get(input.sessionID)?.parentID;
|
|
2589
3423
|
},
|
|
2590
3424
|
get children() {
|
|
2591
3425
|
var _el$ = _$createElement5("text");
|
|
2592
|
-
_$insertNode5(_el$, _$createTextNode3(`Context Guard: open panel`));
|
|
2593
3426
|
_$setProp5(_el$, "onMouseDown", () => context.ui.panel.open("context-guard.monitor"));
|
|
3427
|
+
_$insert5(_el$, () => `Context Guard: open panel${context.keymap.shortcuts("context-guard.show").length ? ` (${context.keymap.shortcuts("context-guard.show").join(" / ")})` : ""}`);
|
|
2594
3428
|
_$effect5((_$p) => _$setProp5(_el$, "fg", context.theme.text.muted, _$p));
|
|
2595
3429
|
return _el$;
|
|
2596
3430
|
}
|
|
@@ -2603,7 +3437,9 @@ var tui_default = Plugin.define({
|
|
|
2603
3437
|
title: "Open Context Guard",
|
|
2604
3438
|
group: "Context Guard",
|
|
2605
3439
|
palette: true,
|
|
2606
|
-
|
|
3440
|
+
...typeof openShortcut === "string" ? {
|
|
3441
|
+
bind: openShortcut
|
|
3442
|
+
} : {},
|
|
2607
3443
|
slash: {
|
|
2608
3444
|
name: "context-guard"
|
|
2609
3445
|
},
|