dsh-decision-layer 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/lib/client.js +324 -340
- package/package.json +1 -1
- package/service/manager-api.mjs +11 -2
- package/service/narrowing.mjs +18 -6
- package/service/self-check.mjs +13 -16
- package/service/session-state.mjs +1 -0
- package/service/steer-once.mjs +25 -0
- package/service/task-completion.mjs +17 -19
package/lib/client.js
CHANGED
|
@@ -96,6 +96,9 @@ var dictionaries = {
|
|
|
96
96
|
gatePassThrough: "\u672A\u5E72\u9884\uFF08\u6309\u539F\u8DEF\u5F84\u6267\u884C\uFF09",
|
|
97
97
|
checkResultLow: "\u5F97\u5206\u504F\u4F4E",
|
|
98
98
|
checkResultOk: "\u901A\u8FC7",
|
|
99
|
+
checkResultLowNoisy: "\u5F97\u5206\u504F\u4F4E\uFF08\u4F4E\u7F6E\u4FE1\uFF09",
|
|
100
|
+
checkNoiseTag: "\u566A\u58F0\uFF0C\u53EF\u5FFD\u7565",
|
|
101
|
+
checkNoiseHint: "\u6A21\u578B\u5BF9\u8FD9\u6B21\u6253\u5206\u51E0\u4E4E\u6CA1\u6709\u628A\u63E1\uFF08\u7F6E\u4FE1\u5EA6\u6781\u4F4E\uFF09\uFF0C\u8FD9\u6761\u4F4E\u5206\u4E0D\u8BA1\u5165\u8D28\u91CF\u8D8B\u52BF\u3001\u4E5F\u4E0D\u89E6\u53D1\u4EFB\u4F55\u8865\u5B8C\uFF0C\u89C6\u4F5C\u566A\u58F0\u5FFD\u7565\u5373\u53EF\u3002\u771F\u6B63\u503C\u5F97\u5173\u6CE8\u7684\u662F\u8FDE\u7EED\u591A\u6B21\u9AD8\u7F6E\u4FE1\u7684\u4F4E\u5206\u3002",
|
|
99
102
|
reasonUnavailable: "\u540E\u7AEF\u4E0D\u53EF\u8FBE",
|
|
100
103
|
reasonHttpError: "\u540E\u7AEF\u8FD4\u56DE\u9519\u8BEF",
|
|
101
104
|
reasonInvalidResponse: "\u54CD\u5E94\u683C\u5F0F\u4E0D\u7B26",
|
|
@@ -245,6 +248,9 @@ var dictionaries = {
|
|
|
245
248
|
gatePassThrough: "no intervention (proceeded on its original path)",
|
|
246
249
|
checkResultLow: "low score",
|
|
247
250
|
checkResultOk: "passed",
|
|
251
|
+
checkResultLowNoisy: "low score (low confidence)",
|
|
252
|
+
checkNoiseTag: "noise, ignore",
|
|
253
|
+
checkNoiseHint: "The model had almost no confidence in this score (near-zero confidence). This low score does not count toward the quality trend and triggers no re-prompt \u2014 treat it as noise. What matters is several consecutive high-confidence low scores.",
|
|
248
254
|
reasonUnavailable: "backend unreachable",
|
|
249
255
|
reasonHttpError: "backend returned an error",
|
|
250
256
|
reasonInvalidResponse: "unexpected response shape",
|
|
@@ -422,24 +428,33 @@ function renderCheck({ t }, entry) {
|
|
|
422
428
|
entry.reason ? ` \xB7 ${failDetail(t, entry)}` : ""
|
|
423
429
|
] })
|
|
424
430
|
] });
|
|
425
|
-
const
|
|
431
|
+
const noisy = entry.outcome === "low" && entry.lowConfidence === true;
|
|
432
|
+
const result = entry.outcome === "low" ? noisy ? t("checkResultLowNoisy") : t("checkResultLow") : t("checkResultOk");
|
|
433
|
+
const verdict = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: noisy ? "decision-log-muted-verdict" : "decision-log-verdict", children: result });
|
|
434
|
+
const score = entry.score !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", title: t("logScoreHint"), children: [
|
|
435
|
+
" \xB7 ",
|
|
436
|
+
t("logScore"),
|
|
437
|
+
" ",
|
|
438
|
+
entry.score,
|
|
439
|
+
"/2"
|
|
440
|
+
] }) : null;
|
|
441
|
+
const conf = typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
442
|
+
" \xB7 ",
|
|
443
|
+
t("logConfidence"),
|
|
444
|
+
" ",
|
|
445
|
+
entry.confidence
|
|
446
|
+
] }) : null;
|
|
447
|
+
const hint = noisy ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", title: t("checkNoiseHint"), children: [
|
|
448
|
+
" \xB7 ",
|
|
449
|
+
t("checkNoiseTag")
|
|
450
|
+
] }) : null;
|
|
426
451
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
427
452
|
label,
|
|
428
453
|
" \xB7 ",
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
" ",
|
|
434
|
-
entry.score,
|
|
435
|
-
"/2"
|
|
436
|
-
] }) : null,
|
|
437
|
-
typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
438
|
-
" \xB7 ",
|
|
439
|
-
t("logConfidence"),
|
|
440
|
-
" ",
|
|
441
|
-
entry.confidence
|
|
442
|
-
] }) : null
|
|
454
|
+
verdict,
|
|
455
|
+
score,
|
|
456
|
+
conf,
|
|
457
|
+
hint
|
|
443
458
|
] });
|
|
444
459
|
}
|
|
445
460
|
function renderNarrow({ t }, entry) {
|
|
@@ -538,7 +553,10 @@ function renderComplete({ t }, entry) {
|
|
|
538
553
|
function outcomeTagOf(entry) {
|
|
539
554
|
if (entry.kind === "narrow") return entry.outcome === "error" ? "error" : "ok";
|
|
540
555
|
if (entry.kind === "complete") return entry.outcome === "error" ? "error" : entry.outcome === "unsatisfied" ? "warn" : "ok";
|
|
541
|
-
|
|
556
|
+
if (entry.outcome === "deny") return "deny";
|
|
557
|
+
if (entry.outcome === "error") return "error";
|
|
558
|
+
if (entry.outcome === "low") return entry.kind === "check" && entry.lowConfidence === true ? "muted" : "warn";
|
|
559
|
+
return "ok";
|
|
542
560
|
}
|
|
543
561
|
function renderBody(props, entry) {
|
|
544
562
|
return entry.kind === "gate" ? renderGate(props, entry) : entry.kind === "narrow" ? renderNarrow(props, entry) : entry.kind === "complete" ? renderComplete(props, entry) : renderCheck(props, entry);
|
|
@@ -569,6 +587,37 @@ function DecisionLogList({ entries, ratings, onRate, t, newestFirst = true }) {
|
|
|
569
587
|
] }, entry.id ?? `${entry.at}-${index}`)) });
|
|
570
588
|
}
|
|
571
589
|
|
|
590
|
+
// src/client/cards.tsx
|
|
591
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
592
|
+
function CardHead({ title, total, unit, rate }) {
|
|
593
|
+
const totalSpan = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-total", children: [
|
|
594
|
+
total,
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: unit })
|
|
596
|
+
] });
|
|
597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "decision-card-head", children: [
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-card-title", children: title }),
|
|
599
|
+
rate ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-head-metrics", children: [
|
|
600
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-rate-inline", children: [
|
|
601
|
+
rate.label,
|
|
602
|
+
" ",
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: rate.value })
|
|
604
|
+
] }),
|
|
605
|
+
totalSpan
|
|
606
|
+
] }) : totalSpan
|
|
607
|
+
] });
|
|
608
|
+
}
|
|
609
|
+
function Stat({ label, value, pct, tone }) {
|
|
610
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `decision-stat-num${tone ? ` decision-stat-${tone}` : ""}`, children: value }),
|
|
612
|
+
typeof pct === "number" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-stat-pct", children: [
|
|
613
|
+
pct,
|
|
614
|
+
"%"
|
|
615
|
+
] }),
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: label })
|
|
617
|
+
] });
|
|
618
|
+
}
|
|
619
|
+
var share = (n, total) => total > 0 ? Math.round(n / total * 100) : null;
|
|
620
|
+
|
|
572
621
|
// src/client/use-annotations.ts
|
|
573
622
|
var import_react = require("react");
|
|
574
623
|
function useAnnotations(sessionId, onFail) {
|
|
@@ -577,7 +626,11 @@ function useAnnotations(sessionId, onFail) {
|
|
|
577
626
|
setRatings(analysis?.ratings ?? {});
|
|
578
627
|
}, []);
|
|
579
628
|
const annotate = (0, import_react.useCallback)(async (id, rating) => {
|
|
580
|
-
|
|
629
|
+
let previous;
|
|
630
|
+
setRatings((prev) => {
|
|
631
|
+
previous = prev[id];
|
|
632
|
+
return { ...prev, [id]: rating };
|
|
633
|
+
});
|
|
581
634
|
try {
|
|
582
635
|
await request("annotate", {
|
|
583
636
|
method: "POST",
|
|
@@ -588,7 +641,8 @@ function useAnnotations(sessionId, onFail) {
|
|
|
588
641
|
onFail();
|
|
589
642
|
setRatings((prev) => {
|
|
590
643
|
const next = { ...prev };
|
|
591
|
-
delete next[id];
|
|
644
|
+
if (previous === void 0) delete next[id];
|
|
645
|
+
else next[id] = previous;
|
|
592
646
|
return next;
|
|
593
647
|
});
|
|
594
648
|
}
|
|
@@ -597,23 +651,27 @@ function useAnnotations(sessionId, onFail) {
|
|
|
597
651
|
}
|
|
598
652
|
|
|
599
653
|
// src/client/panel.tsx
|
|
600
|
-
var
|
|
654
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
601
655
|
function DecisionPanel(props) {
|
|
602
|
-
return /* @__PURE__ */ (0,
|
|
656
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionPanel, { ...props }, props.sessionId);
|
|
603
657
|
}
|
|
604
658
|
function Bar({ allow, ask, deny }) {
|
|
605
659
|
const total = allow + ask + deny;
|
|
606
|
-
if (total === 0) return /* @__PURE__ */ (0,
|
|
660
|
+
if (total === 0) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "decision-bar decision-bar-empty", "aria-hidden": "true" });
|
|
607
661
|
const pct = (n) => `${n / total * 100}%`;
|
|
608
|
-
return /* @__PURE__ */ (0,
|
|
609
|
-
allow > 0 && /* @__PURE__ */ (0,
|
|
610
|
-
ask > 0 && /* @__PURE__ */ (0,
|
|
611
|
-
deny > 0 && /* @__PURE__ */ (0,
|
|
662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-bar", "aria-hidden": "true", children: [
|
|
663
|
+
allow > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-bar-allow", style: { width: pct(allow) } }),
|
|
664
|
+
ask > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-bar-ask", style: { width: pct(ask) } }),
|
|
665
|
+
deny > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-bar-deny", style: { width: pct(deny) } })
|
|
612
666
|
] });
|
|
613
667
|
}
|
|
614
668
|
function SessionPanel({ sessionId, t }) {
|
|
615
669
|
const dialog = (0, import_react2.useRef)(null);
|
|
616
670
|
const trigger = (0, import_react2.useRef)(null);
|
|
671
|
+
const mounted = (0, import_react2.useRef)(true);
|
|
672
|
+
(0, import_react2.useEffect)(() => () => {
|
|
673
|
+
mounted.current = false;
|
|
674
|
+
}, []);
|
|
617
675
|
const [open, setOpen] = (0, import_react2.useState)(false);
|
|
618
676
|
const [enabled, setEnabled] = (0, import_react2.useState)(null);
|
|
619
677
|
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
@@ -637,13 +695,12 @@ function SessionPanel({ sessionId, t }) {
|
|
|
637
695
|
live = false;
|
|
638
696
|
};
|
|
639
697
|
}, [sessionId, t]);
|
|
640
|
-
const checkStatus = (
|
|
698
|
+
const checkStatus = () => {
|
|
641
699
|
setStatus("checking");
|
|
642
700
|
void request("probe", { method: "POST" }).then((value) => {
|
|
643
|
-
if (
|
|
644
|
-
setStatus(value.connected ? "ok" : "down");
|
|
701
|
+
if (mounted.current) setStatus(value.connected ? "ok" : "down");
|
|
645
702
|
}).catch(() => {
|
|
646
|
-
if (
|
|
703
|
+
if (mounted.current) setStatus("down");
|
|
647
704
|
});
|
|
648
705
|
};
|
|
649
706
|
(0, import_react2.useEffect)(() => {
|
|
@@ -669,7 +726,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
669
726
|
alive = false;
|
|
670
727
|
element.close();
|
|
671
728
|
};
|
|
672
|
-
}, [open,
|
|
729
|
+
}, [open, sessionId, seed]);
|
|
673
730
|
const updateEnabled = async (next) => {
|
|
674
731
|
setBusy(true);
|
|
675
732
|
try {
|
|
@@ -685,7 +742,6 @@ function SessionPanel({ sessionId, t }) {
|
|
|
685
742
|
setBusy(false);
|
|
686
743
|
}
|
|
687
744
|
};
|
|
688
|
-
const time2 = (at) => new Date(at).toLocaleTimeString();
|
|
689
745
|
const statusLabel = status === "ok" ? t("statusOk") : status === "down" ? t("statusDown") : status === "checking" ? t("statusChecking") : t("statusIdle");
|
|
690
746
|
const attempts = metrics?.attempts ?? 0;
|
|
691
747
|
const severity = metrics?.check?.trend?.severity ?? "normal";
|
|
@@ -694,19 +750,19 @@ function SessionPanel({ sessionId, t }) {
|
|
|
694
750
|
const checkPassRate = metrics?.check && checkValid > 0 ? Math.round((checkValid - metrics.check.low) / checkValid * 100) : null;
|
|
695
751
|
const narrowValid = metrics?.narrow ? metrics.narrow.attempts - metrics.narrow.failures : 0;
|
|
696
752
|
const narrowApplyRate = metrics?.narrow && narrowValid > 0 ? Math.round(metrics.narrow.applied / narrowValid * 100) : null;
|
|
697
|
-
return /* @__PURE__ */ (0,
|
|
698
|
-
/* @__PURE__ */ (0,
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
700
|
-
/* @__PURE__ */ (0,
|
|
701
|
-
/* @__PURE__ */ (0,
|
|
753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
754
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { ref: trigger, className: `decision-trigger decision-trend-${severity}`, type: "button", "aria-haspopup": "dialog", "aria-expanded": open, "aria-busy": enabled === null, "aria-label": t("button"), title: trendTitle, onClick: () => setOpen(true), children: [
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "decision-trigger-icon", width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "8", r: "6.4", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
757
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 4.6 11.3 11H4.7L8 4.6Z", fill: "currentColor", stroke: "none" })
|
|
702
758
|
] }),
|
|
703
|
-
/* @__PURE__ */ (0,
|
|
759
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-trigger-text", children: [
|
|
704
760
|
t("triggerDecisions"),
|
|
705
761
|
" ",
|
|
706
|
-
/* @__PURE__ */ (0,
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: attempts })
|
|
707
763
|
] })
|
|
708
764
|
] }),
|
|
709
|
-
/* @__PURE__ */ (0,
|
|
765
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
710
766
|
"dialog",
|
|
711
767
|
{
|
|
712
768
|
ref: dialog,
|
|
@@ -731,19 +787,19 @@ function SessionPanel({ sessionId, t }) {
|
|
|
731
787
|
trigger.current?.focus();
|
|
732
788
|
},
|
|
733
789
|
children: [
|
|
734
|
-
/* @__PURE__ */ (0,
|
|
735
|
-
/* @__PURE__ */ (0,
|
|
736
|
-
/* @__PURE__ */ (0,
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-head", children: [
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { id: "decision-panel-title", children: t("title") }),
|
|
792
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: () => {
|
|
737
793
|
dialog.current?.close();
|
|
738
794
|
}, "aria-label": t("close"), children: "\xD7" })
|
|
739
795
|
] }),
|
|
740
|
-
/* @__PURE__ */ (0,
|
|
741
|
-
/* @__PURE__ */ (0,
|
|
742
|
-
enabled === null && /* @__PURE__ */ (0,
|
|
743
|
-
/* @__PURE__ */ (0,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
745
|
-
/* @__PURE__ */ (0,
|
|
746
|
-
/* @__PURE__ */ (0,
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-body", children: [
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { children: [
|
|
798
|
+
enabled === null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", children: t("loading") }),
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "decision-toggle", children: [
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-toggle-text", children: t("enabled") }),
|
|
801
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
747
803
|
"input",
|
|
748
804
|
{
|
|
749
805
|
className: "decision-toggle-input",
|
|
@@ -753,160 +809,118 @@ function SessionPanel({ sessionId, t }) {
|
|
|
753
809
|
onChange: (event) => void updateEnabled(event.target.checked)
|
|
754
810
|
}
|
|
755
811
|
),
|
|
756
|
-
/* @__PURE__ */ (0,
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
757
813
|
] })
|
|
758
814
|
] }),
|
|
759
|
-
/* @__PURE__ */ (0,
|
|
760
|
-
/* @__PURE__ */ (0,
|
|
761
|
-
/* @__PURE__ */ (0,
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-status", children: [
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `decision-status-dot decision-status-${status}`, "aria-hidden": "true" }),
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-status-label", children: [
|
|
762
818
|
t("backendStatus"),
|
|
763
819
|
"\uFF1A",
|
|
764
820
|
statusLabel
|
|
765
821
|
] }),
|
|
766
|
-
/* @__PURE__ */ (0,
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "decision-status-recheck", disabled: status === "checking", onClick: () => checkStatus(), children: t("recheck") })
|
|
767
823
|
] })
|
|
768
824
|
] }),
|
|
769
|
-
/* @__PURE__ */ (0,
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
771
|
-
!metrics?.gate && !metrics?.check && !metrics?.narrow && !metrics?.complete ? /* @__PURE__ */ (0,
|
|
772
|
-
metrics.gate && /* @__PURE__ */ (0,
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
775
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { children: [
|
|
826
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("metrics") }),
|
|
827
|
+
!metrics?.gate && !metrics?.check && !metrics?.narrow && !metrics?.complete ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-empty", role: "status", children: t("empty") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-cards", children: [
|
|
828
|
+
metrics.gate && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card decision-card-wide", children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "decision-card-head", children: [
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-card-title", children: t("cardGate") }),
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-card-total", children: [
|
|
776
832
|
metrics.gate.attempts,
|
|
777
|
-
/* @__PURE__ */ (0,
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: t("cardTimes") })
|
|
778
834
|
] })
|
|
779
835
|
] }),
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
782
|
-
/* @__PURE__ */ (0,
|
|
783
|
-
/* @__PURE__ */ (0,
|
|
836
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Bar, { allow: metrics.gate.allow, ask: metrics.gate.ask, deny: metrics.gate.deny }),
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("ul", { className: "decision-legend", children: [
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
839
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-legend-dot decision-dot-allow", "aria-hidden": "true" }),
|
|
784
840
|
t("allow"),
|
|
785
|
-
/* @__PURE__ */ (0,
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: metrics.gate.allow })
|
|
786
842
|
] }),
|
|
787
|
-
/* @__PURE__ */ (0,
|
|
788
|
-
/* @__PURE__ */ (0,
|
|
843
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-legend-dot decision-dot-ask", "aria-hidden": "true" }),
|
|
789
845
|
t("ask"),
|
|
790
|
-
/* @__PURE__ */ (0,
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: metrics.gate.ask })
|
|
791
847
|
] }),
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
848
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-legend-dot decision-dot-deny", "aria-hidden": "true" }),
|
|
794
850
|
t("deny"),
|
|
795
|
-
/* @__PURE__ */ (0,
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: metrics.gate.deny })
|
|
796
852
|
] })
|
|
797
853
|
] }),
|
|
798
|
-
/* @__PURE__ */ (0,
|
|
799
|
-
/* @__PURE__ */ (0,
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("footer", { className: "decision-card-foot", children: [
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
800
856
|
t("actualShort"),
|
|
801
|
-
/* @__PURE__ */ (0,
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("b", { children: [
|
|
802
858
|
metrics.gate.actual.allow,
|
|
803
859
|
" / ",
|
|
804
860
|
metrics.gate.actual.deny
|
|
805
861
|
] })
|
|
806
862
|
] }),
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
863
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
808
864
|
t("failures"),
|
|
809
|
-
/* @__PURE__ */ (0,
|
|
865
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: metrics.gate.failures })
|
|
810
866
|
] })
|
|
811
867
|
] })
|
|
812
868
|
] }),
|
|
813
|
-
metrics.check && /* @__PURE__ */ (0,
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
] }),
|
|
828
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
829
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
830
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-warn", children: metrics.check.low }),
|
|
831
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("checkLow") })
|
|
832
|
-
] }),
|
|
833
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
834
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.check.attempts - metrics.check.low - metrics.check.failures }),
|
|
835
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("checkOk") })
|
|
836
|
-
] }),
|
|
837
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
838
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.check.failures }),
|
|
839
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
840
|
-
] })
|
|
869
|
+
metrics.check && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
871
|
+
CardHead,
|
|
872
|
+
{
|
|
873
|
+
title: t("cardCheck"),
|
|
874
|
+
total: metrics.check.attempts,
|
|
875
|
+
unit: t("cardTimes"),
|
|
876
|
+
rate: { label: t("checkPassRate"), value: checkPassRate === null ? t("rateNa") : `${checkPassRate}%` }
|
|
877
|
+
}
|
|
878
|
+
),
|
|
879
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkLow"), value: metrics.check.low, tone: "warn" }),
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkOk"), value: metrics.check.attempts - metrics.check.low - metrics.check.failures }),
|
|
882
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: metrics.check.failures, tone: "muted" })
|
|
841
883
|
] })
|
|
842
884
|
] }),
|
|
843
|
-
metrics.narrow && /* @__PURE__ */ (0,
|
|
844
|
-
/* @__PURE__ */ (0,
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
] }),
|
|
858
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
859
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
860
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.applied }),
|
|
861
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("narrowAppliedLabel") })
|
|
862
|
-
] }),
|
|
863
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
864
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.dropped }),
|
|
865
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("narrowDroppedLabel") })
|
|
866
|
-
] }),
|
|
867
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
868
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.narrow.failures }),
|
|
869
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
870
|
-
] })
|
|
885
|
+
metrics.narrow && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
887
|
+
CardHead,
|
|
888
|
+
{
|
|
889
|
+
title: t("cardNarrow"),
|
|
890
|
+
total: metrics.narrow.attempts,
|
|
891
|
+
unit: t("cardTimes"),
|
|
892
|
+
rate: { label: t("narrowApplyRate"), value: narrowApplyRate === null ? t("rateNa") : `${narrowApplyRate}%` }
|
|
893
|
+
}
|
|
894
|
+
),
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowAppliedLabel"), value: metrics.narrow.applied }),
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowDroppedLabel"), value: metrics.narrow.dropped }),
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: metrics.narrow.failures, tone: "muted" })
|
|
871
899
|
] })
|
|
872
900
|
] }),
|
|
873
|
-
metrics.complete && /* @__PURE__ */ (0,
|
|
874
|
-
/* @__PURE__ */ (0,
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
] }),
|
|
888
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
889
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
890
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.complete.satisfied }),
|
|
891
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeSatisfied") })
|
|
892
|
-
] }),
|
|
893
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
894
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-warn", children: metrics.complete.unsatisfied }),
|
|
895
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeUnsatisfied") })
|
|
896
|
-
] }),
|
|
897
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
898
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.complete.insufficient }),
|
|
899
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeInsufficient") })
|
|
900
|
-
] })
|
|
901
|
+
metrics.complete && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
903
|
+
CardHead,
|
|
904
|
+
{
|
|
905
|
+
title: t("cardComplete"),
|
|
906
|
+
total: metrics.complete.attempts,
|
|
907
|
+
unit: t("cardTimes"),
|
|
908
|
+
rate: { label: t("failures"), value: `${metrics.complete.failures}` }
|
|
909
|
+
}
|
|
910
|
+
),
|
|
911
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
912
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeSatisfied"), value: metrics.complete.satisfied }),
|
|
913
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeUnsatisfied"), value: metrics.complete.unsatisfied, tone: "warn" }),
|
|
914
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeInsufficient"), value: metrics.complete.insufficient, tone: "muted" })
|
|
901
915
|
] })
|
|
902
916
|
] })
|
|
903
917
|
] })
|
|
904
918
|
] }),
|
|
905
|
-
/* @__PURE__ */ (0,
|
|
906
|
-
/* @__PURE__ */ (0,
|
|
907
|
-
log.length === 0 ? /* @__PURE__ */ (0,
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { children: [
|
|
920
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("log") }),
|
|
921
|
+
log.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-empty", role: "status", children: t("logEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DecisionLogList, { entries: log, ratings, onRate: (id, rating) => void annotate(id, rating), t })
|
|
908
922
|
] }),
|
|
909
|
-
message && /* @__PURE__ */ (0,
|
|
923
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", className: "decision-message decision-message-warn", children: message })
|
|
910
924
|
] })
|
|
911
925
|
]
|
|
912
926
|
}
|
|
@@ -916,18 +930,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
916
930
|
|
|
917
931
|
// src/client/analysis-view.tsx
|
|
918
932
|
var import_react3 = require("react");
|
|
919
|
-
var
|
|
920
|
-
function Stat({ label, value, pct, tone }) {
|
|
921
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-stat", children: [
|
|
922
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `decision-stat-num${tone ? ` decision-stat-${tone}` : ""}`, children: value }),
|
|
923
|
-
typeof pct === "number" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-stat-pct", children: [
|
|
924
|
-
pct,
|
|
925
|
-
"%"
|
|
926
|
-
] }),
|
|
927
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-stat-label", children: label })
|
|
928
|
-
] });
|
|
929
|
-
}
|
|
930
|
-
var share = (n, total) => total > 0 ? Math.round(n / total * 100) : null;
|
|
933
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
931
934
|
function AnalysisView({ sessionId, t }) {
|
|
932
935
|
const [analysis, setAnalysis] = (0, import_react3.useState)(null);
|
|
933
936
|
const [log, setLog] = (0, import_react3.useState)([]);
|
|
@@ -960,101 +963,77 @@ function AnalysisView({ sessionId, t }) {
|
|
|
960
963
|
const annotations = analysis?.annotations;
|
|
961
964
|
const meanScore = profile && profile.check.scoreCount > 0 ? Math.round(profile.check.scoreSum / profile.check.scoreCount * 10) / 10 : null;
|
|
962
965
|
const completeTotal = profile ? profile.complete.satisfied + profile.complete.unsatisfied + profile.complete.insufficient : 0;
|
|
963
|
-
return /* @__PURE__ */ (0,
|
|
964
|
-
/* @__PURE__ */ (0,
|
|
965
|
-
/* @__PURE__ */ (0,
|
|
966
|
-
loaded && (!analysis || analysis.totalDecisions === 0) ? /* @__PURE__ */ (0,
|
|
967
|
-
profile && /* @__PURE__ */ (0,
|
|
968
|
-
/* @__PURE__ */ (0,
|
|
969
|
-
/* @__PURE__ */ (0,
|
|
970
|
-
profile.gate.attempts > 0 && /* @__PURE__ */ (0,
|
|
971
|
-
/* @__PURE__ */ (0,
|
|
972
|
-
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
] }),
|
|
978
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
979
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("deny"), value: profile.gate.deny, pct: share(profile.gate.deny, profile.gate.attempts), tone: "warn" }),
|
|
980
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("allow"), value: profile.gate.allow, pct: share(profile.gate.allow, profile.gate.attempts) }),
|
|
981
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("ask"), value: profile.gate.ask, pct: share(profile.gate.ask, profile.gate.attempts) }),
|
|
982
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.gate.error, pct: share(profile.gate.error, profile.gate.attempts), tone: "muted" })
|
|
966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "decision-analysis", role: "region", "aria-label": t("analysisTitle"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-analysis-inner", children: [
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "decision-analysis-title", children: t("analysisTitle") }),
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted decision-analysis-intro", children: t("analysisIntro") }),
|
|
969
|
+
loaded && (!analysis || analysis.totalDecisions === 0) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-empty", role: "status", children: t("logEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
970
|
+
profile && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
971
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t("analysisProfile") }),
|
|
972
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-analysis-cards", children: [
|
|
973
|
+
profile.gate.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "decision-card", children: [
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardHead, { title: t("cardGate"), total: profile.gate.attempts, unit: t("cardTimes") }),
|
|
975
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-card-stats", children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("deny"), value: profile.gate.deny, pct: share(profile.gate.deny, profile.gate.attempts), tone: "warn" }),
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("allow"), value: profile.gate.allow, pct: share(profile.gate.allow, profile.gate.attempts) }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("ask"), value: profile.gate.ask, pct: share(profile.gate.ask, profile.gate.attempts) }),
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("failures"), value: profile.gate.error, pct: share(profile.gate.error, profile.gate.attempts), tone: "muted" })
|
|
983
980
|
] })
|
|
984
981
|
] }),
|
|
985
|
-
profile.check.attempts > 0 && /* @__PURE__ */ (0,
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
987
|
-
|
|
988
|
-
/* @__PURE__ */ (0,
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
] }),
|
|
993
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
994
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkLow"), value: profile.check.low, pct: share(profile.check.low, profile.check.attempts), tone: "warn" }),
|
|
995
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkOk"), value: profile.check.ok, pct: share(profile.check.ok, profile.check.attempts) }),
|
|
996
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("analysisMeanScore"), value: meanScore === null ? t("rateNa") : `${meanScore}/2` }),
|
|
997
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.check.error, pct: share(profile.check.error, profile.check.attempts), tone: "muted" })
|
|
982
|
+
profile.check.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "decision-card", children: [
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardHead, { title: t("cardCheck"), total: profile.check.attempts, unit: t("cardTimes") }),
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-card-stats", children: [
|
|
985
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("checkLow"), value: profile.check.low, pct: share(profile.check.low, profile.check.attempts), tone: "warn" }),
|
|
986
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("checkOk"), value: profile.check.ok, pct: share(profile.check.ok, profile.check.attempts) }),
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("analysisMeanScore"), value: meanScore === null ? t("rateNa") : `${meanScore}/2` }),
|
|
988
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("failures"), value: profile.check.error, pct: share(profile.check.error, profile.check.attempts), tone: "muted" })
|
|
998
989
|
] })
|
|
999
990
|
] }),
|
|
1000
|
-
profile.narrow.attempts > 0 && /* @__PURE__ */ (0,
|
|
1001
|
-
/* @__PURE__ */ (0,
|
|
1002
|
-
|
|
1003
|
-
/* @__PURE__ */ (0,
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
] })
|
|
1007
|
-
] }),
|
|
1008
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
1009
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowAppliedLabel"), value: profile.narrow.applied, pct: share(profile.narrow.applied, profile.narrow.attempts) }),
|
|
1010
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowDroppedLabel"), value: profile.narrow.droppedSum }),
|
|
1011
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.narrow.error, pct: share(profile.narrow.error, profile.narrow.attempts), tone: "muted" })
|
|
991
|
+
profile.narrow.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "decision-card", children: [
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardHead, { title: t("cardNarrow"), total: profile.narrow.attempts, unit: t("cardTimes") }),
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-card-stats", children: [
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("narrowAppliedLabel"), value: profile.narrow.applied, pct: share(profile.narrow.applied, profile.narrow.attempts) }),
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("narrowDroppedLabel"), value: profile.narrow.droppedSum }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("failures"), value: profile.narrow.error, pct: share(profile.narrow.error, profile.narrow.attempts), tone: "muted" })
|
|
1012
997
|
] })
|
|
1013
998
|
] }),
|
|
1014
|
-
profile.complete.attempts > 0 && /* @__PURE__ */ (0,
|
|
1015
|
-
/* @__PURE__ */ (0,
|
|
1016
|
-
|
|
1017
|
-
/* @__PURE__ */ (0,
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
] })
|
|
1021
|
-
] }),
|
|
1022
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
1023
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeSatisfied"), value: profile.complete.satisfied, pct: share(profile.complete.satisfied, completeTotal) }),
|
|
1024
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeUnsatisfied"), value: profile.complete.unsatisfied, pct: share(profile.complete.unsatisfied, completeTotal), tone: "warn" }),
|
|
1025
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeInsufficient"), value: profile.complete.insufficient, pct: share(profile.complete.insufficient, completeTotal), tone: "muted" })
|
|
999
|
+
profile.complete.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("article", { className: "decision-card", children: [
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardHead, { title: t("cardComplete"), total: profile.complete.attempts, unit: t("cardTimes") }),
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-card-stats", children: [
|
|
1002
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("completeSatisfied"), value: profile.complete.satisfied, pct: share(profile.complete.satisfied, completeTotal) }),
|
|
1003
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("completeUnsatisfied"), value: profile.complete.unsatisfied, pct: share(profile.complete.unsatisfied, completeTotal), tone: "warn" }),
|
|
1004
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("completeInsufficient"), value: profile.complete.insufficient, pct: share(profile.complete.insufficient, completeTotal), tone: "muted" })
|
|
1026
1005
|
] })
|
|
1027
1006
|
] })
|
|
1028
1007
|
] })
|
|
1029
1008
|
] }),
|
|
1030
|
-
backtest && /* @__PURE__ */ (0,
|
|
1031
|
-
/* @__PURE__ */ (0,
|
|
1032
|
-
/* @__PURE__ */ (0,
|
|
1033
|
-
/* @__PURE__ */ (0,
|
|
1034
|
-
/* @__PURE__ */ (0,
|
|
1035
|
-
/* @__PURE__ */ (0,
|
|
1009
|
+
backtest && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t("analysisTrend") }),
|
|
1011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-card-stats decision-analysis-trend", children: [
|
|
1012
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("analysisTrendWarn"), value: backtest.warnHits }),
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("analysisTrendSevere"), value: backtest.severeHits, tone: "warn" }),
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stat, { label: t("analysisTrendMaxRun"), value: backtest.maxRun })
|
|
1036
1015
|
] }),
|
|
1037
|
-
/* @__PURE__ */ (0,
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted decision-analysis-note", children: t("analysisTrendNote") })
|
|
1038
1017
|
] }),
|
|
1039
|
-
annotations && /* @__PURE__ */ (0,
|
|
1040
|
-
/* @__PURE__ */ (0,
|
|
1041
|
-
annotations.rated === 0 ? /* @__PURE__ */ (0,
|
|
1018
|
+
annotations && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t("analysisAccuracy") }),
|
|
1020
|
+
annotations.rated === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("analysisAccuracyEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted decision-rate-summary", children: t("rateSummary", { rated: annotations.rated, good: annotations.good, bad: annotations.bad, unsure: annotations.unsure }) })
|
|
1042
1021
|
] }),
|
|
1043
|
-
/* @__PURE__ */ (0,
|
|
1044
|
-
/* @__PURE__ */ (0,
|
|
1045
|
-
log.length === 0 ? /* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1022
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t("log") }),
|
|
1024
|
+
log.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-empty", role: "status", children: t("analysisLogTruncated") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DecisionLogList, { entries: log, ratings, onRate: (id, rating) => void annotate(id, rating), t }),
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted decision-analysis-note", children: t("analysisLogNote") })
|
|
1048
1027
|
] })
|
|
1049
1028
|
] })
|
|
1050
1029
|
] }),
|
|
1051
|
-
message && /* @__PURE__ */ (0,
|
|
1030
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { role: "status", className: "decision-message decision-message-warn", children: message })
|
|
1052
1031
|
] }) });
|
|
1053
1032
|
}
|
|
1054
1033
|
|
|
1055
1034
|
// src/client/config-form.tsx
|
|
1056
1035
|
var import_react4 = require("react");
|
|
1057
|
-
var
|
|
1036
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1058
1037
|
var api = "/plugins/dsh-decision-layer/api";
|
|
1059
1038
|
async function request2(path, fetchFn, init) {
|
|
1060
1039
|
const response = await fetchFn(`${api}/${path}`, init);
|
|
@@ -1071,31 +1050,31 @@ var maxCandidatesOf = (settings) => settings?.maxCandidates ?? DEFAULT_MAX_CANDI
|
|
|
1071
1050
|
var thresholdOf = (settings) => settings?.threshold ?? DEFAULT_THRESHOLD;
|
|
1072
1051
|
function HeadIcon({ name }) {
|
|
1073
1052
|
const glyphs = {
|
|
1074
|
-
features: /* @__PURE__ */ (0,
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1076
|
-
/* @__PURE__ */ (0,
|
|
1077
|
-
/* @__PURE__ */ (0,
|
|
1078
|
-
/* @__PURE__ */ (0,
|
|
1053
|
+
features: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "2", y: "3", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "11.9", cy: "5.1", r: "1.25", fill: "currentColor" }),
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "2", y: "8.8", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "4.1", cy: "10.9", r: "1.25", fill: "currentColor" })
|
|
1079
1058
|
] }),
|
|
1080
|
-
advanced: /* @__PURE__ */ (0,
|
|
1081
|
-
/* @__PURE__ */ (0,
|
|
1082
|
-
/* @__PURE__ */ (0,
|
|
1083
|
-
/* @__PURE__ */ (0,
|
|
1059
|
+
advanced: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1060
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M2.5 5h11M2.5 11h11", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round" }),
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "10.5", cy: "5", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1062
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "5.5", cy: "11", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" })
|
|
1084
1063
|
] }),
|
|
1085
|
-
backend: /* @__PURE__ */ (0,
|
|
1086
|
-
/* @__PURE__ */ (0,
|
|
1087
|
-
/* @__PURE__ */ (0,
|
|
1088
|
-
/* @__PURE__ */ (0,
|
|
1089
|
-
/* @__PURE__ */ (0,
|
|
1064
|
+
backend: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1065
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "2.3", y: "2.6", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1066
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "2.3", y: "8.8", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "5", cy: "4.9", r: ".7", fill: "currentColor" }),
|
|
1068
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "5", cy: "11.1", r: ".7", fill: "currentColor" })
|
|
1090
1069
|
] })
|
|
1091
1070
|
};
|
|
1092
|
-
return /* @__PURE__ */ (0,
|
|
1071
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `decision-head-icon decision-head-icon-${name}`, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", children: glyphs[name] }) });
|
|
1093
1072
|
}
|
|
1094
1073
|
function Toggle({ label, checked, disabled, onChange }) {
|
|
1095
|
-
return /* @__PURE__ */ (0,
|
|
1096
|
-
/* @__PURE__ */ (0,
|
|
1097
|
-
/* @__PURE__ */ (0,
|
|
1098
|
-
/* @__PURE__ */ (0,
|
|
1074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-toggle", children: [
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-toggle-text", children: label }),
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1099
1078
|
"input",
|
|
1100
1079
|
{
|
|
1101
1080
|
className: "decision-toggle-input",
|
|
@@ -1105,7 +1084,7 @@ function Toggle({ label, checked, disabled, onChange }) {
|
|
|
1105
1084
|
onChange: (event) => onChange(event.target.checked)
|
|
1106
1085
|
}
|
|
1107
1086
|
),
|
|
1108
|
-
/* @__PURE__ */ (0,
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
1109
1088
|
] })
|
|
1110
1089
|
] });
|
|
1111
1090
|
}
|
|
@@ -1247,17 +1226,17 @@ ${url}`)) return;
|
|
|
1247
1226
|
setBusy(false);
|
|
1248
1227
|
}
|
|
1249
1228
|
};
|
|
1250
|
-
return /* @__PURE__ */ (0,
|
|
1251
|
-
/* @__PURE__ */ (0,
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-config", children: [
|
|
1230
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "decision-collapse", open: true, children: [
|
|
1231
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { children: [
|
|
1233
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HeadIcon, { name: "features" }),
|
|
1255
1234
|
t("basicFeatures")
|
|
1256
1235
|
] }),
|
|
1257
|
-
/* @__PURE__ */ (0,
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
1258
1237
|
] }),
|
|
1259
|
-
/* @__PURE__ */ (0,
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-collapse-body", children: [
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1261
1240
|
Toggle,
|
|
1262
1241
|
{
|
|
1263
1242
|
label: t("featureGate"),
|
|
@@ -1269,8 +1248,8 @@ ${url}`)) return;
|
|
|
1269
1248
|
}
|
|
1270
1249
|
}
|
|
1271
1250
|
),
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1273
|
-
/* @__PURE__ */ (0,
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("featureGateHint") }),
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1274
1253
|
Toggle,
|
|
1275
1254
|
{
|
|
1276
1255
|
label: t("featureCheck"),
|
|
@@ -1282,8 +1261,8 @@ ${url}`)) return;
|
|
|
1282
1261
|
}
|
|
1283
1262
|
}
|
|
1284
1263
|
),
|
|
1285
|
-
/* @__PURE__ */ (0,
|
|
1286
|
-
/* @__PURE__ */ (0,
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("featureCheckHint") }),
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1287
1266
|
Toggle,
|
|
1288
1267
|
{
|
|
1289
1268
|
label: t("featureNarrow"),
|
|
@@ -1295,8 +1274,8 @@ ${url}`)) return;
|
|
|
1295
1274
|
}
|
|
1296
1275
|
}
|
|
1297
1276
|
),
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1299
|
-
/* @__PURE__ */ (0,
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("featureNarrowHint") }),
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1300
1279
|
Toggle,
|
|
1301
1280
|
{
|
|
1302
1281
|
label: t("featureComplete"),
|
|
@@ -1308,22 +1287,22 @@ ${url}`)) return;
|
|
|
1308
1287
|
}
|
|
1309
1288
|
}
|
|
1310
1289
|
),
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("featureCompleteHint") })
|
|
1312
1291
|
] })
|
|
1313
1292
|
] }),
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1316
|
-
/* @__PURE__ */ (0,
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
1293
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "decision-collapse", children: [
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
1295
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { children: [
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HeadIcon, { name: "advanced" }),
|
|
1318
1297
|
t("advancedConfig")
|
|
1319
1298
|
] }),
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
1321
1300
|
] }),
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1323
|
-
/* @__PURE__ */ (0,
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1326
|
-
/* @__PURE__ */ (0,
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { className: "decision-collapse-body", onSubmit: (event) => void saveAdvanced(event), children: [
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-advanced-grid", children: [
|
|
1303
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-field-block", children: [
|
|
1304
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-subhead", children: t("advancedSwitches") }),
|
|
1305
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1327
1306
|
Toggle,
|
|
1328
1307
|
{
|
|
1329
1308
|
label: t("selfCheckSteer"),
|
|
@@ -1335,8 +1314,8 @@ ${url}`)) return;
|
|
|
1335
1314
|
}
|
|
1336
1315
|
}
|
|
1337
1316
|
),
|
|
1338
|
-
/* @__PURE__ */ (0,
|
|
1339
|
-
/* @__PURE__ */ (0,
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("selfCheckHint") }),
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1340
1319
|
Toggle,
|
|
1341
1320
|
{
|
|
1342
1321
|
label: t("narrowObserveLabel"),
|
|
@@ -1348,8 +1327,8 @@ ${url}`)) return;
|
|
|
1348
1327
|
}
|
|
1349
1328
|
}
|
|
1350
1329
|
),
|
|
1351
|
-
/* @__PURE__ */ (0,
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1330
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("narrowHint") }),
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1353
1332
|
Toggle,
|
|
1354
1333
|
{
|
|
1355
1334
|
label: t("completeSteer"),
|
|
@@ -1361,13 +1340,13 @@ ${url}`)) return;
|
|
|
1361
1340
|
}
|
|
1362
1341
|
}
|
|
1363
1342
|
),
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1343
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "decision-muted", children: t("completeHint") })
|
|
1365
1344
|
] }),
|
|
1366
|
-
/* @__PURE__ */ (0,
|
|
1367
|
-
/* @__PURE__ */ (0,
|
|
1368
|
-
/* @__PURE__ */ (0,
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-field-block", children: [
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-subhead", children: t("advancedParams") }),
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field", children: [
|
|
1369
1348
|
t("narrowKeepLabel"),
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1371
1350
|
"textarea",
|
|
1372
1351
|
{
|
|
1373
1352
|
className: "decision-prefixes",
|
|
@@ -1381,11 +1360,11 @@ ${url}`)) return;
|
|
|
1381
1360
|
}
|
|
1382
1361
|
}
|
|
1383
1362
|
),
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "decision-muted", children: t("narrowKeepHint") })
|
|
1385
1364
|
] }),
|
|
1386
|
-
/* @__PURE__ */ (0,
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
1387
1366
|
t("narrowMaxLabel"),
|
|
1388
|
-
/* @__PURE__ */ (0,
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1389
1368
|
"input",
|
|
1390
1369
|
{
|
|
1391
1370
|
className: "decision-narrow-cap",
|
|
@@ -1402,11 +1381,11 @@ ${url}`)) return;
|
|
|
1402
1381
|
}
|
|
1403
1382
|
}
|
|
1404
1383
|
),
|
|
1405
|
-
/* @__PURE__ */ (0,
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "decision-muted", children: t("narrowMaxHint") })
|
|
1406
1385
|
] }),
|
|
1407
|
-
/* @__PURE__ */ (0,
|
|
1386
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
1408
1387
|
t("narrowThresholdLabel"),
|
|
1409
|
-
/* @__PURE__ */ (0,
|
|
1388
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1410
1389
|
"input",
|
|
1411
1390
|
{
|
|
1412
1391
|
className: "decision-narrow-cap",
|
|
@@ -1423,26 +1402,26 @@ ${url}`)) return;
|
|
|
1423
1402
|
}
|
|
1424
1403
|
}
|
|
1425
1404
|
),
|
|
1426
|
-
/* @__PURE__ */ (0,
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "decision-muted", children: t("narrowThresholdHint") })
|
|
1427
1406
|
] })
|
|
1428
1407
|
] })
|
|
1429
1408
|
] }),
|
|
1430
|
-
/* @__PURE__ */ (0,
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "decision-actions", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { disabled: busy || !ready || !advancedDirty, type: "submit", children: t("saveAdvanced") }) })
|
|
1431
1410
|
] })
|
|
1432
1411
|
] }),
|
|
1433
|
-
/* @__PURE__ */ (0,
|
|
1434
|
-
/* @__PURE__ */ (0,
|
|
1435
|
-
/* @__PURE__ */ (0,
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HeadIcon, { name: "backend" }),
|
|
1436
1415
|
t("backend")
|
|
1437
1416
|
] }),
|
|
1438
|
-
ready && /* @__PURE__ */ (0,
|
|
1417
|
+
ready && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "decision-muted decision-destination", children: [
|
|
1439
1418
|
t("destination"),
|
|
1440
|
-
/* @__PURE__ */ (0,
|
|
1419
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: config.effectiveUrl })
|
|
1441
1420
|
] }),
|
|
1442
|
-
/* @__PURE__ */ (0,
|
|
1443
|
-
/* @__PURE__ */ (0,
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { onSubmit: (event) => void saveBackend(event), children: [
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field", children: [
|
|
1444
1423
|
t("url"),
|
|
1445
|
-
/* @__PURE__ */ (0,
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1446
1425
|
"input",
|
|
1447
1426
|
{
|
|
1448
1427
|
type: "url",
|
|
@@ -1457,9 +1436,9 @@ ${url}`)) return;
|
|
|
1457
1436
|
}
|
|
1458
1437
|
)
|
|
1459
1438
|
] }),
|
|
1460
|
-
/* @__PURE__ */ (0,
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field", children: [
|
|
1461
1440
|
t("model"),
|
|
1462
|
-
/* @__PURE__ */ (0,
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1463
1442
|
"input",
|
|
1464
1443
|
{
|
|
1465
1444
|
value: config.model,
|
|
@@ -1473,9 +1452,9 @@ ${url}`)) return;
|
|
|
1473
1452
|
}
|
|
1474
1453
|
)
|
|
1475
1454
|
] }),
|
|
1476
|
-
/* @__PURE__ */ (0,
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "decision-field", children: [
|
|
1477
1456
|
t("key"),
|
|
1478
|
-
/* @__PURE__ */ (0,
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1479
1458
|
"input",
|
|
1480
1459
|
{
|
|
1481
1460
|
type: "password",
|
|
@@ -1490,23 +1469,23 @@ ${url}`)) return;
|
|
|
1490
1469
|
}
|
|
1491
1470
|
}
|
|
1492
1471
|
),
|
|
1493
|
-
/* @__PURE__ */ (0,
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "decision-muted", children: config.apiKeySet ? t("keyHintSaved") : t("keyHintEmpty") })
|
|
1494
1473
|
] }),
|
|
1495
|
-
/* @__PURE__ */ (0,
|
|
1496
|
-
/* @__PURE__ */ (0,
|
|
1497
|
-
/* @__PURE__ */ (0,
|
|
1498
|
-
probeResult && /* @__PURE__ */ (0,
|
|
1474
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-actions", children: [
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { disabled: busy || !ready, type: "submit", children: t("save") }),
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "decision-secondary", disabled: busy || !ready || backendDirty, type: "button", onClick: () => void probe(), children: t("probe") }),
|
|
1477
|
+
probeResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { role: "status", className: `decision-probe-result${probeResult.ok ? " decision-message-ok" : " decision-message-warn"}`, children: probeResult.text })
|
|
1499
1478
|
] })
|
|
1500
1479
|
] }),
|
|
1501
|
-
config.apiKeySet && /* @__PURE__ */ (0,
|
|
1502
|
-
/* @__PURE__ */ (0,
|
|
1503
|
-
/* @__PURE__ */ (0,
|
|
1504
|
-
/* @__PURE__ */ (0,
|
|
1480
|
+
config.apiKeySet && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-danger-row", children: [
|
|
1481
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "decision-danger-text", children: [
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "decision-danger-title", children: t("removeKey") }),
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "decision-muted", children: t("removeKeyHint") })
|
|
1505
1484
|
] }),
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "decision-danger-button", disabled: busy || !ready, onClick: () => void removeSavedKey(), children: t("removeKeyButton") })
|
|
1507
1486
|
] })
|
|
1508
1487
|
] }),
|
|
1509
|
-
message && /* @__PURE__ */ (0,
|
|
1488
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { role: "status", className: `decision-message${message.ok ? " decision-message-ok" : " decision-message-warn"}`, children: message.text })
|
|
1510
1489
|
] });
|
|
1511
1490
|
}
|
|
1512
1491
|
|
|
@@ -1565,7 +1544,6 @@ var css = `
|
|
|
1565
1544
|
.decision-dot-deny{background:#c0392b}
|
|
1566
1545
|
.decision-card-foot{display:flex;justify-content:space-between;gap:1rem;margin-top:.7rem;padding-top:.6rem;border-top:1px solid var(--dsw-alias-border-l2,#eef1f3);font-size:.76rem;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1567
1546
|
.decision-card-foot b{color:var(--dsw-alias-label-primary,#202124);font-variant-numeric:tabular-nums;margin-left:.3rem}
|
|
1568
|
-
.decision-card-rate{justify-content:center}
|
|
1569
1547
|
.decision-card-stats{display:flex;gap:.6rem}
|
|
1570
1548
|
.decision-stat{flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:.2rem;padding:.5rem .3rem;border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f6f8fa)}
|
|
1571
1549
|
.decision-stat-num{font-size:1.35rem;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#202124)}
|
|
@@ -1578,6 +1556,7 @@ var css = `
|
|
|
1578
1556
|
.decision-log-item.decision-log-deny{border-left-color:#c0392b}
|
|
1579
1557
|
.decision-log-item.decision-log-error,.decision-log-item.decision-log-warn{border-left-color:#c98a1e}
|
|
1580
1558
|
.decision-log-item.decision-log-ok{border-left-color:#1f8a70}
|
|
1559
|
+
.decision-log-item.decision-log-muted{border-left-color:var(--dsw-alias-border-l2,#dce1e6)}
|
|
1581
1560
|
.decision-log-time{color:var(--dsw-alias-label-tertiary,#77818b);font-variant-numeric:tabular-nums;flex:0 0 auto}
|
|
1582
1561
|
.decision-log-body{color:var(--dsw-alias-label-primary,#202124);flex:1 1 auto;min-width:0}
|
|
1583
1562
|
.decision-rate{flex:0 0 auto;display:inline-flex;gap:1px;align-self:center}
|
|
@@ -1594,6 +1573,11 @@ var css = `
|
|
|
1594
1573
|
.decision-log-ok .decision-log-verdict{color:#1f8a70}
|
|
1595
1574
|
.decision-log-warn .decision-log-verdict{color:#c98a1e}
|
|
1596
1575
|
.decision-log-detail{color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1576
|
+
/* A low-confidence low score is noise: its verdict is shown muted (not the amber
|
|
1577
|
+
warn accent) and a "noise, ignore" tag hangs off the row so it never reads as a
|
|
1578
|
+
real quality dip. */
|
|
1579
|
+
.decision-log-muted-verdict{font-weight:600;color:var(--dsw-alias-label-tertiary,#9aa5b1)}
|
|
1580
|
+
.decision-log-muted .decision-log-time{opacity:.75}
|
|
1597
1581
|
|
|
1598
1582
|
.decision-status{display:flex;align-items:center;gap:.5rem;margin-top:.7rem;font-size:.82rem}
|
|
1599
1583
|
.decision-status-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:#9aa5b1}
|
|
@@ -1705,7 +1689,7 @@ function installStyles() {
|
|
|
1705
1689
|
}
|
|
1706
1690
|
|
|
1707
1691
|
// src/client/index.tsx
|
|
1708
|
-
var
|
|
1692
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1709
1693
|
var inject = ["slots", "locale"];
|
|
1710
1694
|
function apply(ctx) {
|
|
1711
1695
|
const t = ctx.locale.bind("dsh-decision-layer");
|
|
@@ -1730,7 +1714,7 @@ function apply(ctx) {
|
|
|
1730
1714
|
}, AnalysisView));
|
|
1731
1715
|
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register(
|
|
1732
1716
|
{ name: "plugins.bundle.config", key: "dsh-decision-layer", locale: "dsh-decision-layer" },
|
|
1733
|
-
(props) => props.view === "summary" ? props.t("summary") : /* @__PURE__ */ (0,
|
|
1717
|
+
(props) => props.view === "summary" ? props.t("summary") : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ConfigForm, { t: props.t })
|
|
1734
1718
|
));
|
|
1735
1719
|
}
|
|
1736
1720
|
|