dsh-decision-layer 0.5.0 → 0.5.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/README.en.md +3 -2
- package/README.md +3 -2
- package/lib/client.js +683 -461
- package/package.json +4 -2
package/lib/client.js
CHANGED
|
@@ -24,6 +24,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
24
24
|
// src/client/index.tsx
|
|
25
25
|
var index_exports = {};
|
|
26
26
|
__export(index_exports, {
|
|
27
|
+
AnalysisView: () => AnalysisView,
|
|
27
28
|
ConfigForm: () => ConfigForm,
|
|
28
29
|
apply: () => apply,
|
|
29
30
|
inject: () => inject
|
|
@@ -165,7 +166,21 @@ var dictionaries = {
|
|
|
165
166
|
error: "\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
166
167
|
loading: "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u72B6\u6001",
|
|
167
168
|
destination: "\u88C1\u51B3\u65F6\u4F1A\u5411\u4EE5\u4E0B\u540E\u7AEF\u53D1\u9001\u5FC5\u8981\u7684\u8BC4\u4F30\u4E0A\u4E0B\u6587\uFF1A",
|
|
168
|
-
httpWarning: "\u6B64\u5730\u5740\u4F7F\u7528\u672A\u52A0\u5BC6\u7684 HTTP\u3002\u786E\u8BA4\u540E\uFF0CAPI Key \u4E0E\u8BC4\u4F30\u4E0A\u4E0B\u6587\u5C06\u4EE5\u660E\u6587\u53D1\u9001\u81F3\u8BE5\u5730\u5740\u3002"
|
|
169
|
+
httpWarning: "\u6B64\u5730\u5740\u4F7F\u7528\u672A\u52A0\u5BC6\u7684 HTTP\u3002\u786E\u8BA4\u540E\uFF0CAPI Key \u4E0E\u8BC4\u4F30\u4E0A\u4E0B\u6587\u5C06\u4EE5\u660E\u6587\u53D1\u9001\u81F3\u8BE5\u5730\u5740\u3002",
|
|
170
|
+
analysisTab: "\u51B3\u7B56\u5206\u6790",
|
|
171
|
+
analysisTitle: "\u51B3\u7B56\u5206\u6790",
|
|
172
|
+
analysisIntro: "\u57FA\u4E8E\u672C\u4F1A\u8BDD\u5DF2\u843D\u76D8\u7684\u51B3\u7B56\u65E5\u5FD7\u505A\u53EA\u8BFB\u805A\u5408\u4E0E\u4EBA\u5DE5\u6807\u6CE8\uFF0C\u4E0D\u6539\u53D8\u4EFB\u4F55 agent \u884C\u4E3A\u3002",
|
|
173
|
+
analysisProfile: "\u8FC7\u7A0B\u753B\u50CF",
|
|
174
|
+
analysisMeanScore: "\u5E73\u5747\u5206",
|
|
175
|
+
analysisTrend: "\u8D28\u91CF\u8D8B\u52BF\u56DE\u6D4B",
|
|
176
|
+
analysisTrendWarn: "\u544A\u8B66\u89E6\u53D1",
|
|
177
|
+
analysisTrendSevere: "\u4E25\u91CD\u89E6\u53D1",
|
|
178
|
+
analysisTrendMaxRun: "\u6700\u957F\u8FDE\u7EED\u4F4E\u5206",
|
|
179
|
+
analysisTrendNote: "\u7528\u5F53\u524D\u9608\u503C\u628A\u672C\u4F1A\u8BDD\u7684\u81EA\u68C0\u5206\u6570\u6309\u65F6\u95F4\u91CD\u653E\uFF0C\u7EDF\u8BA1\u544A\u8B66\u672C\u4F1A\u300C\u4F1A\u300D\u89E6\u53D1\u51E0\u6B21\uFF0C\u7528\u4E8E\u6821\u51C6\u9608\u503C\uFF0C\u4E0D\u662F\u5B9E\u65F6\u4FE1\u53F7\u3002",
|
|
180
|
+
analysisAccuracy: "\u5224\u65AD\u51C6\u786E\u5EA6",
|
|
181
|
+
analysisAccuracyEmpty: "\u5C1A\u672A\u6807\u6CE8\u4EFB\u4F55\u51B3\u7B56\u3002\u5728\u4E0B\u65B9\u51B3\u7B56\u5217\u8868\u9010\u6761\u6807\u6CE8\u300C\u5224\u5BF9 / \u5224\u9519 / \u8BF4\u4E0D\u51C6\u300D\u540E\uFF0C\u8FD9\u91CC\u7ED9\u51FA\u6C47\u603B\u3002",
|
|
182
|
+
analysisLogNote: "\u6807\u6CE8\u5728\u6B64\u4E0E\u4ECB\u5165\u9762\u677F\u540C\u6E90\uFF1A\u4EFB\u4E00\u5904\u6807\u6CE8\u90FD\u5199\u5165\u540C\u4E00\u4EFD\u65E5\u5FD7\u3001\u6309\u51B3\u7B56 id \u5173\u8054\u3001\u53D6\u6700\u65B0\u3002",
|
|
183
|
+
analysisLogTruncated: "\u672C\u4F1A\u8BDD\u6682\u65E0\u53EF\u5C55\u793A\u7684\u51B3\u7B56\u8BB0\u5F55\uFF08\u5185\u5B58\u65E5\u5FD7\u53EF\u80FD\u5DF2\u6EDA\u52A8\u6E05\u7406\uFF09\u3002"
|
|
169
184
|
},
|
|
170
185
|
en: {
|
|
171
186
|
summary: "A danger-call gate, output self-check, and loop guard driven by a pluggable adjudication model.",
|
|
@@ -300,46 +315,315 @@ var dictionaries = {
|
|
|
300
315
|
error: "Request failed. Please retry.",
|
|
301
316
|
loading: "Loading session settings",
|
|
302
317
|
destination: "Decisions send the necessary evaluation context to this backend:",
|
|
303
|
-
httpWarning: "This address uses unencrypted HTTP. Your API key and evaluation context will be sent in plaintext to this address."
|
|
318
|
+
httpWarning: "This address uses unencrypted HTTP. Your API key and evaluation context will be sent in plaintext to this address.",
|
|
319
|
+
analysisTab: "Decision analysis",
|
|
320
|
+
analysisTitle: "Decision analysis",
|
|
321
|
+
analysisIntro: "A read-only aggregate and manual annotation over this session\u2019s persisted decision log. It changes no agent behavior.",
|
|
322
|
+
analysisProfile: "Process profile",
|
|
323
|
+
analysisMeanScore: "Mean score",
|
|
324
|
+
analysisTrend: "Quality-trend backtest",
|
|
325
|
+
analysisTrendWarn: "Warn fires",
|
|
326
|
+
analysisTrendSevere: "Severe fires",
|
|
327
|
+
analysisTrendMaxRun: "Longest low run",
|
|
328
|
+
analysisTrendNote: "Replays this session\u2019s self-check scores in time order under the current thresholds to count how often the alarm would fire \u2014 a calibration aid, not a live signal.",
|
|
329
|
+
analysisAccuracy: "Decision accuracy",
|
|
330
|
+
analysisAccuracyEmpty: "No decisions rated yet. Rate rows below as correct / wrong / unsure and a summary appears here.",
|
|
331
|
+
analysisLogNote: "Ratings here share one source with the intervention panel: a rating on either surface writes to the same log, keyed by decision id, latest wins.",
|
|
332
|
+
analysisLogTruncated: "No decision rows to show for this session (the in-memory log may have rolled over)."
|
|
304
333
|
}
|
|
305
334
|
};
|
|
306
335
|
|
|
307
336
|
// src/client/panel.tsx
|
|
308
|
-
var
|
|
309
|
-
|
|
310
|
-
|
|
337
|
+
var import_react2 = require("react");
|
|
338
|
+
|
|
339
|
+
// src/client/api.ts
|
|
340
|
+
var API_BASE = "/plugins/dsh-decision-layer/api";
|
|
311
341
|
async function request(path, init) {
|
|
312
|
-
const response = await fetch(`${
|
|
342
|
+
const response = await fetch(`${API_BASE}/${path}`, init);
|
|
313
343
|
const body = await response.json();
|
|
314
344
|
if (!response.ok || !body.ok || body.value === void 0) throw new Error(body.error || "Request failed");
|
|
315
345
|
return body.value;
|
|
316
346
|
}
|
|
347
|
+
|
|
348
|
+
// src/client/decision-log.tsx
|
|
349
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
350
|
+
var time = (at) => new Date(at).toLocaleTimeString();
|
|
351
|
+
function reasonText(t, reason) {
|
|
352
|
+
return reason === "unavailable" || reason === "unreachable" ? t("reasonUnavailable") : reason === "http-error" ? t("reasonHttpError") : reason === "invalid-response" ? t("reasonInvalidResponse") : reason === "low-confidence" ? t("reasonLowConfidence") : reason === "too-many-candidates" ? t("reasonTooMany") : reason === "low-keep" ? t("reasonLowKeep") : reason === "config" ? t("reasonConfig") : reason;
|
|
353
|
+
}
|
|
354
|
+
function actionText(t, action) {
|
|
355
|
+
return action === "deny" ? t("actionDeny") : action === "ask" ? t("actionAsk") : action === "pass" ? t("actionPass") : action;
|
|
356
|
+
}
|
|
357
|
+
function failDetail(t, entry) {
|
|
358
|
+
const reason = reasonText(t, entry.reason);
|
|
359
|
+
if (entry.reason === "low-confidence" && typeof entry.confidence === "number") return `${reason}\uFF08${t("logConfidence")} ${entry.confidence}\uFF09`;
|
|
360
|
+
return reason;
|
|
361
|
+
}
|
|
362
|
+
function renderGate({ t }, entry) {
|
|
363
|
+
const tool = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: "decision-log-tool", children: entry.tool ?? "\u2014" });
|
|
364
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
365
|
+
t("logGate"),
|
|
366
|
+
" \xB7 ",
|
|
367
|
+
tool,
|
|
368
|
+
" ",
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
370
|
+
t("gatePassThrough"),
|
|
371
|
+
entry.reason ? ` \xB7 ${failDetail(t, entry)}` : ""
|
|
372
|
+
] })
|
|
373
|
+
] });
|
|
374
|
+
if (entry.outcome === "deny") {
|
|
375
|
+
const suggestion2 = entry.suggestion && entry.suggestion !== "deny" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
376
|
+
" \xB7 ",
|
|
377
|
+
t("logSuggested"),
|
|
378
|
+
" ",
|
|
379
|
+
actionText(t, entry.suggestion)
|
|
380
|
+
] }) : null;
|
|
381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
382
|
+
t("logGate"),
|
|
383
|
+
" \xB7 ",
|
|
384
|
+
tool,
|
|
385
|
+
" ",
|
|
386
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
387
|
+
"\u2192 ",
|
|
388
|
+
t("actionDeny")
|
|
389
|
+
] }),
|
|
390
|
+
suggestion2
|
|
391
|
+
] });
|
|
392
|
+
}
|
|
393
|
+
const suggestion = entry.suggestion ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
394
|
+
" \xB7 ",
|
|
395
|
+
t("logSuggested"),
|
|
396
|
+
" ",
|
|
397
|
+
actionText(t, entry.suggestion)
|
|
398
|
+
] }) : null;
|
|
399
|
+
const lowConf = entry.reason === "low-confidence" && typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
400
|
+
" \xB7 ",
|
|
401
|
+
t("reasonLowConfidence"),
|
|
402
|
+
" ",
|
|
403
|
+
entry.confidence
|
|
404
|
+
] }) : null;
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
406
|
+
t("logGate"),
|
|
407
|
+
" \xB7 ",
|
|
408
|
+
tool,
|
|
409
|
+
" ",
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: t("gatePassThrough") }),
|
|
411
|
+
suggestion,
|
|
412
|
+
lowConf
|
|
413
|
+
] });
|
|
414
|
+
}
|
|
415
|
+
function renderCheck({ t }, entry) {
|
|
416
|
+
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logCheckHint"), children: t("logCheck") });
|
|
417
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
418
|
+
label,
|
|
419
|
+
" ",
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
421
|
+
t("logEvalFailed"),
|
|
422
|
+
entry.reason ? ` \xB7 ${failDetail(t, entry)}` : ""
|
|
423
|
+
] })
|
|
424
|
+
] });
|
|
425
|
+
const result = entry.outcome === "low" ? t("checkResultLow") : t("checkResultOk");
|
|
426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
427
|
+
label,
|
|
428
|
+
" \xB7 ",
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: result }),
|
|
430
|
+
entry.score !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", title: t("logScoreHint"), children: [
|
|
431
|
+
" \xB7 ",
|
|
432
|
+
t("logScore"),
|
|
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
|
|
443
|
+
] });
|
|
444
|
+
}
|
|
445
|
+
function renderNarrow({ t }, entry) {
|
|
446
|
+
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logNarrowHint"), children: t("logNarrow") });
|
|
447
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
448
|
+
label,
|
|
449
|
+
" ",
|
|
450
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
451
|
+
t("logEvalFailed"),
|
|
452
|
+
entry.reason ? ` \xB7 ${failDetail(t, entry)}` : ""
|
|
453
|
+
] })
|
|
454
|
+
] });
|
|
455
|
+
const dropped = entry.dropped ?? 0;
|
|
456
|
+
const kept = typeof entry.kept === "number" ? entry.kept : void 0;
|
|
457
|
+
const guardText = entry.reason === "too-many-candidates" ? typeof entry.candidates === "number" ? t("reasonTooManyCount", { count: entry.candidates }) : t("reasonTooMany") : entry.reason === "low-keep" ? t("reasonLowKeep") : void 0;
|
|
458
|
+
const guard = guardText ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
459
|
+
" \xB7 ",
|
|
460
|
+
guardText
|
|
461
|
+
] }) : null;
|
|
462
|
+
const modeTag = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
463
|
+
" \xB7 ",
|
|
464
|
+
entry.mode === "enforce" ? t("narrowEnforce") : t("narrowObserve")
|
|
465
|
+
] });
|
|
466
|
+
if (dropped === 0) {
|
|
467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
468
|
+
label,
|
|
469
|
+
" \xB7 ",
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: t("narrowKept") }),
|
|
471
|
+
kept !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
472
|
+
" \xB7 ",
|
|
473
|
+
t("narrowKeptCount"),
|
|
474
|
+
" ",
|
|
475
|
+
kept
|
|
476
|
+
] }) : null,
|
|
477
|
+
guard,
|
|
478
|
+
modeTag
|
|
479
|
+
] });
|
|
480
|
+
}
|
|
481
|
+
const names = Array.isArray(entry.tools) && entry.tools.length > 0 ? entry.tools.join("\u3001") : void 0;
|
|
482
|
+
const overflow = names && Array.isArray(entry.tools) && entry.tools.length < dropped ? t("narrowMore", { count: dropped }) : "";
|
|
483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
484
|
+
label,
|
|
485
|
+
" \xB7 ",
|
|
486
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
487
|
+
t("narrowDropped"),
|
|
488
|
+
" ",
|
|
489
|
+
dropped,
|
|
490
|
+
kept !== void 0 ? ` / ${t("narrowKeptCount")} ${kept}` : ""
|
|
491
|
+
] }),
|
|
492
|
+
names ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
493
|
+
" \xB7 ",
|
|
494
|
+
names,
|
|
495
|
+
overflow
|
|
496
|
+
] }) : null,
|
|
497
|
+
guard,
|
|
498
|
+
modeTag
|
|
499
|
+
] });
|
|
500
|
+
}
|
|
501
|
+
function renderComplete({ t }, entry) {
|
|
502
|
+
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("logComplete") });
|
|
503
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
504
|
+
label,
|
|
505
|
+
" ",
|
|
506
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
507
|
+
t("logEvalFailed"),
|
|
508
|
+
entry.reason ? ` \xB7 ${failDetail(t, entry)}` : ""
|
|
509
|
+
] })
|
|
510
|
+
] });
|
|
511
|
+
const result = entry.outcome === "unsatisfied" ? t("completeResultUnsatisfied") : t("completeResultOk");
|
|
512
|
+
const parts = [];
|
|
513
|
+
if (typeof entry.satisfied === "number") parts.push(`${t("completeSatisfied")} ${entry.satisfied}`);
|
|
514
|
+
if (typeof entry.unsatisfied === "number" && entry.unsatisfied > 0) parts.push(`${t("completeUnsatisfied")} ${entry.unsatisfied}`);
|
|
515
|
+
if (typeof entry.insufficient === "number" && entry.insufficient > 0) parts.push(`${t("completeInsufficient")} ${entry.insufficient}`);
|
|
516
|
+
const tally = parts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
517
|
+
" \xB7 ",
|
|
518
|
+
parts.join(" / ")
|
|
519
|
+
] }) : null;
|
|
520
|
+
const steer = entry.steered ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
521
|
+
" \xB7 ",
|
|
522
|
+
t("completeSteered")
|
|
523
|
+
] }) : null;
|
|
524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
525
|
+
label,
|
|
526
|
+
" \xB7 ",
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: result }),
|
|
528
|
+
typeof entry.conditions === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
529
|
+
" \xB7 ",
|
|
530
|
+
t("completeConditions"),
|
|
531
|
+
" ",
|
|
532
|
+
entry.conditions
|
|
533
|
+
] }) : null,
|
|
534
|
+
tally,
|
|
535
|
+
steer
|
|
536
|
+
] });
|
|
537
|
+
}
|
|
538
|
+
function outcomeTagOf(entry) {
|
|
539
|
+
if (entry.kind === "narrow") return entry.outcome === "error" ? "error" : "ok";
|
|
540
|
+
if (entry.kind === "complete") return entry.outcome === "error" ? "error" : entry.outcome === "unsatisfied" ? "warn" : "ok";
|
|
541
|
+
return entry.outcome === "deny" ? "deny" : entry.outcome === "error" ? "error" : entry.outcome === "low" ? "warn" : "ok";
|
|
542
|
+
}
|
|
543
|
+
function renderBody(props, entry) {
|
|
544
|
+
return entry.kind === "gate" ? renderGate(props, entry) : entry.kind === "narrow" ? renderNarrow(props, entry) : entry.kind === "complete" ? renderComplete(props, entry) : renderCheck(props, entry);
|
|
545
|
+
}
|
|
546
|
+
function RatingButtons({ id, t, ratings, onRate }) {
|
|
547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-rate", role: "group", "aria-label": t("rateGroup"), children: [
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[id] === "good" ? " decision-rate-on decision-rate-good" : ""}`, "aria-label": t("rateGood"), title: t("rateGood"), "aria-pressed": ratings[id] === "good", onClick: () => onRate(id, "good"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
549
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 7.2 8.1 2.4c.6-.9 2-.5 2 .6V6h3.2c.9 0 1.5.8 1.3 1.6l-1.1 4.6c-.2.8-.9 1.3-1.7 1.3H5V7.2Z", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" }),
|
|
550
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 7.2H2.6v6.3H5", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" })
|
|
551
|
+
] }) }),
|
|
552
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[id] === "bad" ? " decision-rate-on decision-rate-bad" : ""}`, "aria-label": t("rateBad"), title: t("rateBad"), "aria-pressed": ratings[id] === "bad", onClick: () => onRate(id, "bad"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
553
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 8.8 7.9 13.6c-.6.9-2 .5-2-.6V10H2.7c-.9 0-1.5-.8-1.3-1.6l1.1-4.6C2.7 3 3.4 2.5 4.2 2.5H11v6.3Z", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" }),
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 8.8h2.4V2.5H11", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" })
|
|
555
|
+
] }) }),
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[id] === "unsure" ? " decision-rate-on decision-rate-unsure" : ""}`, "aria-label": t("rateUnsure"), title: t("rateUnsure"), "aria-pressed": ratings[id] === "unsure", onClick: () => onRate(id, "unsure"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "8", r: "6.2", stroke: "currentColor", "stroke-width": "1.2" }),
|
|
558
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6.3 6.2c0-1 .8-1.7 1.7-1.7s1.7.7 1.7 1.6c0 1.3-1.6 1.4-1.7 2.6", stroke: "currentColor", "stroke-width": "1.2", "stroke-linecap": "round", "stroke-linejoin": "round" }),
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "11.4", r: ".8", fill: "currentColor" })
|
|
560
|
+
] }) })
|
|
561
|
+
] });
|
|
562
|
+
}
|
|
563
|
+
function DecisionLogList({ entries, ratings, onRate, t, newestFirst = true }) {
|
|
564
|
+
const rows = newestFirst ? entries.slice().reverse() : entries.slice();
|
|
565
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "decision-log", children: rows.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: `decision-log-item decision-log-${outcomeTagOf(entry)}`, children: [
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-time", children: time(entry.at) }),
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-body", children: renderBody({ t }, entry) }),
|
|
568
|
+
entry.id && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RatingButtons, { id: entry.id, t, ratings, onRate })
|
|
569
|
+
] }, entry.id ?? `${entry.at}-${index}`)) });
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/client/use-annotations.ts
|
|
573
|
+
var import_react = require("react");
|
|
574
|
+
function useAnnotations(sessionId, onFail) {
|
|
575
|
+
const [ratings, setRatings] = (0, import_react.useState)({});
|
|
576
|
+
const seed = (0, import_react.useCallback)((analysis) => {
|
|
577
|
+
setRatings(analysis?.ratings ?? {});
|
|
578
|
+
}, []);
|
|
579
|
+
const annotate = (0, import_react.useCallback)(async (id, rating) => {
|
|
580
|
+
setRatings((prev) => ({ ...prev, [id]: rating }));
|
|
581
|
+
try {
|
|
582
|
+
await request("annotate", {
|
|
583
|
+
method: "POST",
|
|
584
|
+
headers: { "content-type": "application/json" },
|
|
585
|
+
body: JSON.stringify({ sessionId, target: id, rating })
|
|
586
|
+
});
|
|
587
|
+
} catch {
|
|
588
|
+
onFail();
|
|
589
|
+
setRatings((prev) => {
|
|
590
|
+
const next = { ...prev };
|
|
591
|
+
delete next[id];
|
|
592
|
+
return next;
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
}, [sessionId, onFail]);
|
|
596
|
+
return { ratings, seed, annotate };
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// src/client/panel.tsx
|
|
600
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
317
601
|
function DecisionPanel(props) {
|
|
318
|
-
return /* @__PURE__ */ (0,
|
|
602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SessionPanel, { ...props }, props.sessionId);
|
|
319
603
|
}
|
|
320
604
|
function Bar({ allow, ask, deny }) {
|
|
321
605
|
const total = allow + ask + deny;
|
|
322
|
-
if (total === 0) return /* @__PURE__ */ (0,
|
|
606
|
+
if (total === 0) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "decision-bar decision-bar-empty", "aria-hidden": "true" });
|
|
323
607
|
const pct = (n) => `${n / total * 100}%`;
|
|
324
|
-
return /* @__PURE__ */ (0,
|
|
325
|
-
allow > 0 && /* @__PURE__ */ (0,
|
|
326
|
-
ask > 0 && /* @__PURE__ */ (0,
|
|
327
|
-
deny > 0 && /* @__PURE__ */ (0,
|
|
608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-bar", "aria-hidden": "true", children: [
|
|
609
|
+
allow > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-bar-allow", style: { width: pct(allow) } }),
|
|
610
|
+
ask > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-bar-ask", style: { width: pct(ask) } }),
|
|
611
|
+
deny > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-bar-deny", style: { width: pct(deny) } })
|
|
328
612
|
] });
|
|
329
613
|
}
|
|
330
614
|
function SessionPanel({ sessionId, t }) {
|
|
331
|
-
const dialog = (0,
|
|
332
|
-
const trigger = (0,
|
|
333
|
-
const [open, setOpen] = (0,
|
|
334
|
-
const [enabled, setEnabled] = (0,
|
|
335
|
-
const [busy, setBusy] = (0,
|
|
336
|
-
const [metrics, setMetrics] = (0,
|
|
337
|
-
const [log, setLog] = (0,
|
|
338
|
-
const [analysis, setAnalysis] = (0,
|
|
339
|
-
const [
|
|
340
|
-
const [
|
|
341
|
-
const
|
|
342
|
-
(0,
|
|
615
|
+
const dialog = (0, import_react2.useRef)(null);
|
|
616
|
+
const trigger = (0, import_react2.useRef)(null);
|
|
617
|
+
const [open, setOpen] = (0, import_react2.useState)(false);
|
|
618
|
+
const [enabled, setEnabled] = (0, import_react2.useState)(null);
|
|
619
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
620
|
+
const [metrics, setMetrics] = (0, import_react2.useState)(null);
|
|
621
|
+
const [log, setLog] = (0, import_react2.useState)([]);
|
|
622
|
+
const [analysis, setAnalysis] = (0, import_react2.useState)(null);
|
|
623
|
+
const [status, setStatus] = (0, import_react2.useState)("idle");
|
|
624
|
+
const [message, setMessage] = (0, import_react2.useState)("");
|
|
625
|
+
const { ratings, seed, annotate } = useAnnotations(sessionId, () => setMessage(t("annotateFailed")));
|
|
626
|
+
(0, import_react2.useEffect)(() => {
|
|
343
627
|
let live = true;
|
|
344
628
|
void request(`session?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
345
629
|
if (live) setEnabled(value.enabled);
|
|
@@ -363,7 +647,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
363
647
|
if (live()) setStatus("down");
|
|
364
648
|
});
|
|
365
649
|
};
|
|
366
|
-
(0,
|
|
650
|
+
(0, import_react2.useEffect)(() => {
|
|
367
651
|
if (!open) return;
|
|
368
652
|
const element = dialog.current;
|
|
369
653
|
if (!element) return;
|
|
@@ -381,7 +665,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
381
665
|
void request(`logs?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
382
666
|
if (alive) {
|
|
383
667
|
setAnalysis(value);
|
|
384
|
-
|
|
668
|
+
seed(value);
|
|
385
669
|
}
|
|
386
670
|
}).catch(() => {
|
|
387
671
|
});
|
|
@@ -389,24 +673,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
389
673
|
alive = false;
|
|
390
674
|
element.close();
|
|
391
675
|
};
|
|
392
|
-
}, [open, t, sessionId]);
|
|
393
|
-
const annotate = async (id, rating) => {
|
|
394
|
-
setRatings((prev) => ({ ...prev, [id]: rating }));
|
|
395
|
-
try {
|
|
396
|
-
await request("annotate", {
|
|
397
|
-
method: "POST",
|
|
398
|
-
headers: { "content-type": "application/json" },
|
|
399
|
-
body: JSON.stringify({ sessionId, target: id, rating })
|
|
400
|
-
});
|
|
401
|
-
} catch {
|
|
402
|
-
setMessage(t("annotateFailed"));
|
|
403
|
-
setRatings((prev) => {
|
|
404
|
-
const next = { ...prev };
|
|
405
|
-
delete next[id];
|
|
406
|
-
return next;
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
};
|
|
676
|
+
}, [open, t, sessionId, seed]);
|
|
410
677
|
const updateEnabled = async (next) => {
|
|
411
678
|
setBusy(true);
|
|
412
679
|
try {
|
|
@@ -422,192 +689,7 @@ function SessionPanel({ sessionId, t }) {
|
|
|
422
689
|
setBusy(false);
|
|
423
690
|
}
|
|
424
691
|
};
|
|
425
|
-
const
|
|
426
|
-
const reasonText = (reason) => reason === "unavailable" || reason === "unreachable" ? t("reasonUnavailable") : reason === "http-error" ? t("reasonHttpError") : reason === "invalid-response" ? t("reasonInvalidResponse") : reason === "low-confidence" ? t("reasonLowConfidence") : reason === "too-many-candidates" ? t("reasonTooMany") : reason === "low-keep" ? t("reasonLowKeep") : reason === "config" ? t("reasonConfig") : reason;
|
|
427
|
-
const actionText = (action) => action === "deny" ? t("actionDeny") : action === "ask" ? t("actionAsk") : action === "pass" ? t("actionPass") : action;
|
|
428
|
-
const failDetail = (entry) => {
|
|
429
|
-
const reason = reasonText(entry.reason);
|
|
430
|
-
if (entry.reason === "low-confidence" && typeof entry.confidence === "number") return `${reason}\uFF08${t("logConfidence")} ${entry.confidence}\uFF09`;
|
|
431
|
-
return reason;
|
|
432
|
-
};
|
|
433
|
-
const outcomeTag = (entry) => entry.outcome === "deny" ? "deny" : entry.outcome === "error" ? "error" : entry.outcome === "low" ? "warn" : "ok";
|
|
434
|
-
const renderGate = (entry) => {
|
|
435
|
-
const tool = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: "decision-log-tool", children: entry.tool ?? "\u2014" });
|
|
436
|
-
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
437
|
-
t("logGate"),
|
|
438
|
-
" \xB7 ",
|
|
439
|
-
tool,
|
|
440
|
-
" ",
|
|
441
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
442
|
-
t("gatePassThrough"),
|
|
443
|
-
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
444
|
-
] })
|
|
445
|
-
] });
|
|
446
|
-
if (entry.outcome === "deny") {
|
|
447
|
-
const suggestion2 = entry.suggestion && entry.suggestion !== "deny" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
448
|
-
" \xB7 ",
|
|
449
|
-
t("logSuggested"),
|
|
450
|
-
" ",
|
|
451
|
-
actionText(entry.suggestion)
|
|
452
|
-
] }) : null;
|
|
453
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
454
|
-
t("logGate"),
|
|
455
|
-
" \xB7 ",
|
|
456
|
-
tool,
|
|
457
|
-
" ",
|
|
458
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
459
|
-
"\u2192 ",
|
|
460
|
-
t("actionDeny")
|
|
461
|
-
] }),
|
|
462
|
-
suggestion2
|
|
463
|
-
] });
|
|
464
|
-
}
|
|
465
|
-
const suggestion = entry.suggestion ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
466
|
-
" \xB7 ",
|
|
467
|
-
t("logSuggested"),
|
|
468
|
-
" ",
|
|
469
|
-
actionText(entry.suggestion)
|
|
470
|
-
] }) : null;
|
|
471
|
-
const lowConf = entry.reason === "low-confidence" && typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
472
|
-
" \xB7 ",
|
|
473
|
-
t("reasonLowConfidence"),
|
|
474
|
-
" ",
|
|
475
|
-
entry.confidence
|
|
476
|
-
] }) : null;
|
|
477
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
478
|
-
t("logGate"),
|
|
479
|
-
" \xB7 ",
|
|
480
|
-
tool,
|
|
481
|
-
" ",
|
|
482
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: t("gatePassThrough") }),
|
|
483
|
-
suggestion,
|
|
484
|
-
lowConf
|
|
485
|
-
] });
|
|
486
|
-
};
|
|
487
|
-
const renderCheck = (entry) => {
|
|
488
|
-
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logCheckHint"), children: t("logCheck") });
|
|
489
|
-
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
490
|
-
label,
|
|
491
|
-
" ",
|
|
492
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
493
|
-
t("logEvalFailed"),
|
|
494
|
-
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
495
|
-
] })
|
|
496
|
-
] });
|
|
497
|
-
const result = entry.outcome === "low" ? t("checkResultLow") : t("checkResultOk");
|
|
498
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
499
|
-
label,
|
|
500
|
-
" \xB7 ",
|
|
501
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: result }),
|
|
502
|
-
entry.score !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", title: t("logScoreHint"), children: [
|
|
503
|
-
" \xB7 ",
|
|
504
|
-
t("logScore"),
|
|
505
|
-
" ",
|
|
506
|
-
entry.score,
|
|
507
|
-
"/2"
|
|
508
|
-
] }) : null,
|
|
509
|
-
typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
510
|
-
" \xB7 ",
|
|
511
|
-
t("logConfidence"),
|
|
512
|
-
" ",
|
|
513
|
-
entry.confidence
|
|
514
|
-
] }) : null
|
|
515
|
-
] });
|
|
516
|
-
};
|
|
517
|
-
const renderNarrow = (entry) => {
|
|
518
|
-
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logNarrowHint"), children: t("logNarrow") });
|
|
519
|
-
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
520
|
-
label,
|
|
521
|
-
" ",
|
|
522
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
523
|
-
t("logEvalFailed"),
|
|
524
|
-
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
525
|
-
] })
|
|
526
|
-
] });
|
|
527
|
-
const dropped = entry.dropped ?? 0;
|
|
528
|
-
const kept = typeof entry.kept === "number" ? entry.kept : void 0;
|
|
529
|
-
const guardText = entry.reason === "too-many-candidates" ? typeof entry.candidates === "number" ? t("reasonTooManyCount", { count: entry.candidates }) : t("reasonTooMany") : entry.reason === "low-keep" ? t("reasonLowKeep") : void 0;
|
|
530
|
-
const guard = guardText ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
531
|
-
" \xB7 ",
|
|
532
|
-
guardText
|
|
533
|
-
] }) : null;
|
|
534
|
-
const modeTag = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
535
|
-
" \xB7 ",
|
|
536
|
-
entry.mode === "enforce" ? t("narrowEnforce") : t("narrowObserve")
|
|
537
|
-
] });
|
|
538
|
-
if (dropped === 0) {
|
|
539
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
540
|
-
label,
|
|
541
|
-
" \xB7 ",
|
|
542
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: t("narrowKept") }),
|
|
543
|
-
kept !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
544
|
-
" \xB7 ",
|
|
545
|
-
t("narrowKeptCount"),
|
|
546
|
-
" ",
|
|
547
|
-
kept
|
|
548
|
-
] }) : null,
|
|
549
|
-
guard,
|
|
550
|
-
modeTag
|
|
551
|
-
] });
|
|
552
|
-
}
|
|
553
|
-
const names = Array.isArray(entry.tools) && entry.tools.length > 0 ? entry.tools.join("\u3001") : void 0;
|
|
554
|
-
const overflow = names && Array.isArray(entry.tools) && entry.tools.length < dropped ? t("narrowMore", { count: dropped }) : "";
|
|
555
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
556
|
-
label,
|
|
557
|
-
" \xB7 ",
|
|
558
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
559
|
-
t("narrowDropped"),
|
|
560
|
-
" ",
|
|
561
|
-
dropped,
|
|
562
|
-
kept !== void 0 ? ` / ${t("narrowKeptCount")} ${kept}` : ""
|
|
563
|
-
] }),
|
|
564
|
-
names ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
565
|
-
" \xB7 ",
|
|
566
|
-
names,
|
|
567
|
-
overflow
|
|
568
|
-
] }) : null,
|
|
569
|
-
guard,
|
|
570
|
-
modeTag
|
|
571
|
-
] });
|
|
572
|
-
};
|
|
573
|
-
const renderComplete = (entry) => {
|
|
574
|
-
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("logComplete") });
|
|
575
|
-
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
576
|
-
label,
|
|
577
|
-
" ",
|
|
578
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
579
|
-
t("logEvalFailed"),
|
|
580
|
-
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
581
|
-
] })
|
|
582
|
-
] });
|
|
583
|
-
const result = entry.outcome === "unsatisfied" ? t("completeResultUnsatisfied") : t("completeResultOk");
|
|
584
|
-
const parts = [];
|
|
585
|
-
if (typeof entry.satisfied === "number") parts.push(`${t("completeSatisfied")} ${entry.satisfied}`);
|
|
586
|
-
if (typeof entry.unsatisfied === "number" && entry.unsatisfied > 0) parts.push(`${t("completeUnsatisfied")} ${entry.unsatisfied}`);
|
|
587
|
-
if (typeof entry.insufficient === "number" && entry.insufficient > 0) parts.push(`${t("completeInsufficient")} ${entry.insufficient}`);
|
|
588
|
-
const tally = parts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
589
|
-
" \xB7 ",
|
|
590
|
-
parts.join(" / ")
|
|
591
|
-
] }) : null;
|
|
592
|
-
const steer = entry.steered ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
593
|
-
" \xB7 ",
|
|
594
|
-
t("completeSteered")
|
|
595
|
-
] }) : null;
|
|
596
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
597
|
-
label,
|
|
598
|
-
" \xB7 ",
|
|
599
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: result }),
|
|
600
|
-
typeof entry.conditions === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
601
|
-
" \xB7 ",
|
|
602
|
-
t("completeConditions"),
|
|
603
|
-
" ",
|
|
604
|
-
entry.conditions
|
|
605
|
-
] }) : null,
|
|
606
|
-
tally,
|
|
607
|
-
steer
|
|
608
|
-
] });
|
|
609
|
-
};
|
|
610
|
-
const outcomeTagOf = (entry) => entry.kind === "narrow" ? entry.outcome === "error" ? "error" : entry.outcome === "applied" ? "ok" : "ok" : entry.kind === "complete" ? entry.outcome === "error" ? "error" : entry.outcome === "unsatisfied" ? "warn" : "ok" : outcomeTag(entry);
|
|
692
|
+
const time2 = (at) => new Date(at).toLocaleTimeString();
|
|
611
693
|
const statusLabel = status === "ok" ? t("statusOk") : status === "down" ? t("statusDown") : status === "checking" ? t("statusChecking") : t("statusIdle");
|
|
612
694
|
const attempts = metrics?.attempts ?? 0;
|
|
613
695
|
const severity = metrics?.check?.trend?.severity ?? "normal";
|
|
@@ -616,19 +698,19 @@ function SessionPanel({ sessionId, t }) {
|
|
|
616
698
|
const checkPassRate = metrics?.check && checkValid > 0 ? Math.round((checkValid - metrics.check.low) / checkValid * 100) : null;
|
|
617
699
|
const narrowValid = metrics?.narrow ? metrics.narrow.attempts - metrics.narrow.failures : 0;
|
|
618
700
|
const narrowApplyRate = metrics?.narrow && narrowValid > 0 ? Math.round(metrics.narrow.applied / narrowValid * 100) : null;
|
|
619
|
-
return /* @__PURE__ */ (0,
|
|
620
|
-
/* @__PURE__ */ (0,
|
|
621
|
-
/* @__PURE__ */ (0,
|
|
622
|
-
/* @__PURE__ */ (0,
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
702
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.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: [
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "decision-trigger-icon", width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "8", r: "6.4", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 4.6 11.3 11H4.7L8 4.6Z", fill: "currentColor", stroke: "none" })
|
|
624
706
|
] }),
|
|
625
|
-
/* @__PURE__ */ (0,
|
|
707
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-trigger-text", children: [
|
|
626
708
|
t("triggerDecisions"),
|
|
627
709
|
" ",
|
|
628
|
-
/* @__PURE__ */ (0,
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: attempts })
|
|
629
711
|
] })
|
|
630
712
|
] }),
|
|
631
|
-
/* @__PURE__ */ (0,
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
632
714
|
"dialog",
|
|
633
715
|
{
|
|
634
716
|
ref: dialog,
|
|
@@ -653,19 +735,19 @@ function SessionPanel({ sessionId, t }) {
|
|
|
653
735
|
trigger.current?.focus();
|
|
654
736
|
},
|
|
655
737
|
children: [
|
|
656
|
-
/* @__PURE__ */ (0,
|
|
657
|
-
/* @__PURE__ */ (0,
|
|
658
|
-
/* @__PURE__ */ (0,
|
|
738
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-head", children: [
|
|
739
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { id: "decision-panel-title", children: t("title") }),
|
|
740
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: () => {
|
|
659
741
|
dialog.current?.close();
|
|
660
742
|
}, "aria-label": t("close"), children: "\xD7" })
|
|
661
743
|
] }),
|
|
662
|
-
/* @__PURE__ */ (0,
|
|
663
|
-
/* @__PURE__ */ (0,
|
|
664
|
-
enabled === null && /* @__PURE__ */ (0,
|
|
665
|
-
/* @__PURE__ */ (0,
|
|
666
|
-
/* @__PURE__ */ (0,
|
|
667
|
-
/* @__PURE__ */ (0,
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
744
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-body", children: [
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
746
|
+
enabled === null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", children: t("loading") }),
|
|
747
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-toggle", children: [
|
|
748
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-toggle-text", children: t("enabled") }),
|
|
749
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
750
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
669
751
|
"input",
|
|
670
752
|
{
|
|
671
753
|
className: "decision-toggle-input",
|
|
@@ -675,170 +757,152 @@ function SessionPanel({ sessionId, t }) {
|
|
|
675
757
|
onChange: (event) => void updateEnabled(event.target.checked)
|
|
676
758
|
}
|
|
677
759
|
),
|
|
678
|
-
/* @__PURE__ */ (0,
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
679
761
|
] })
|
|
680
762
|
] }),
|
|
681
|
-
/* @__PURE__ */ (0,
|
|
682
|
-
/* @__PURE__ */ (0,
|
|
683
|
-
/* @__PURE__ */ (0,
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-status", children: [
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `decision-status-dot decision-status-${status}`, "aria-hidden": "true" }),
|
|
765
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-status-label", children: [
|
|
684
766
|
t("backendStatus"),
|
|
685
767
|
"\uFF1A",
|
|
686
768
|
statusLabel
|
|
687
769
|
] }),
|
|
688
|
-
/* @__PURE__ */ (0,
|
|
770
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "decision-status-recheck", disabled: status === "checking", onClick: () => checkStatus(() => true), children: t("recheck") })
|
|
689
771
|
] })
|
|
690
772
|
] }),
|
|
691
|
-
/* @__PURE__ */ (0,
|
|
692
|
-
/* @__PURE__ */ (0,
|
|
693
|
-
!metrics?.gate && !metrics?.check && !metrics?.narrow && !metrics?.complete ? /* @__PURE__ */ (0,
|
|
694
|
-
metrics.gate && /* @__PURE__ */ (0,
|
|
695
|
-
/* @__PURE__ */ (0,
|
|
696
|
-
/* @__PURE__ */ (0,
|
|
697
|
-
/* @__PURE__ */ (0,
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("metrics") }),
|
|
775
|
+
!metrics?.gate && !metrics?.check && !metrics?.narrow && !metrics?.complete ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-empty", role: "status", children: t("empty") }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-cards", children: [
|
|
776
|
+
metrics.gate && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("article", { className: "decision-card decision-card-wide", children: [
|
|
777
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "decision-card-head", children: [
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-card-title", children: t("cardGate") }),
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-total", children: [
|
|
698
780
|
metrics.gate.attempts,
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: t("cardTimes") })
|
|
700
782
|
] })
|
|
701
783
|
] }),
|
|
702
|
-
/* @__PURE__ */ (0,
|
|
703
|
-
/* @__PURE__ */ (0,
|
|
704
|
-
/* @__PURE__ */ (0,
|
|
705
|
-
/* @__PURE__ */ (0,
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Bar, { allow: metrics.gate.allow, ask: metrics.gate.ask, deny: metrics.gate.deny }),
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "decision-legend", children: [
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-legend-dot decision-dot-allow", "aria-hidden": "true" }),
|
|
706
788
|
t("allow"),
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
789
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: metrics.gate.allow })
|
|
708
790
|
] }),
|
|
709
|
-
/* @__PURE__ */ (0,
|
|
710
|
-
/* @__PURE__ */ (0,
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
|
|
792
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-legend-dot decision-dot-ask", "aria-hidden": "true" }),
|
|
711
793
|
t("ask"),
|
|
712
|
-
/* @__PURE__ */ (0,
|
|
794
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: metrics.gate.ask })
|
|
713
795
|
] }),
|
|
714
|
-
/* @__PURE__ */ (0,
|
|
715
|
-
/* @__PURE__ */ (0,
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-legend-dot decision-dot-deny", "aria-hidden": "true" }),
|
|
716
798
|
t("deny"),
|
|
717
|
-
/* @__PURE__ */ (0,
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: metrics.gate.deny })
|
|
718
800
|
] })
|
|
719
801
|
] }),
|
|
720
|
-
/* @__PURE__ */ (0,
|
|
721
|
-
/* @__PURE__ */ (0,
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("footer", { className: "decision-card-foot", children: [
|
|
803
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
722
804
|
t("actualShort"),
|
|
723
|
-
/* @__PURE__ */ (0,
|
|
805
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("b", { children: [
|
|
724
806
|
metrics.gate.actual.allow,
|
|
725
807
|
" / ",
|
|
726
808
|
metrics.gate.actual.deny
|
|
727
809
|
] })
|
|
728
810
|
] }),
|
|
729
|
-
/* @__PURE__ */ (0,
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
730
812
|
t("failures"),
|
|
731
|
-
/* @__PURE__ */ (0,
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: metrics.gate.failures })
|
|
732
814
|
] })
|
|
733
815
|
] })
|
|
734
816
|
] }),
|
|
735
|
-
metrics.check && /* @__PURE__ */ (0,
|
|
736
|
-
/* @__PURE__ */ (0,
|
|
737
|
-
/* @__PURE__ */ (0,
|
|
738
|
-
/* @__PURE__ */ (0,
|
|
817
|
+
metrics.check && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("article", { className: "decision-card", children: [
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "decision-card-head", children: [
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-card-title", children: t("cardCheck") }),
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-total", children: [
|
|
739
821
|
metrics.check.attempts,
|
|
740
|
-
/* @__PURE__ */ (0,
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: t("cardTimes") })
|
|
741
823
|
] })
|
|
742
824
|
] }),
|
|
743
|
-
/* @__PURE__ */ (0,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
745
|
-
/* @__PURE__ */ (0,
|
|
746
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
826
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-warn", children: metrics.check.low }),
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("checkLow") })
|
|
747
829
|
] }),
|
|
748
|
-
/* @__PURE__ */ (0,
|
|
749
|
-
/* @__PURE__ */ (0,
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.check.attempts - metrics.check.low - metrics.check.failures }),
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("checkOk") })
|
|
751
833
|
] }),
|
|
752
|
-
/* @__PURE__ */ (0,
|
|
753
|
-
/* @__PURE__ */ (0,
|
|
754
|
-
/* @__PURE__ */ (0,
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
835
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.check.failures }),
|
|
836
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
755
837
|
] })
|
|
756
838
|
] }),
|
|
757
|
-
/* @__PURE__ */ (0,
|
|
839
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("footer", { className: "decision-card-foot decision-card-rate", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
758
840
|
t("checkPassRate"),
|
|
759
|
-
/* @__PURE__ */ (0,
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: checkPassRate === null ? t("rateNa") : `${checkPassRate}%` })
|
|
760
842
|
] }) })
|
|
761
843
|
] }),
|
|
762
|
-
metrics.narrow && /* @__PURE__ */ (0,
|
|
763
|
-
/* @__PURE__ */ (0,
|
|
764
|
-
/* @__PURE__ */ (0,
|
|
765
|
-
/* @__PURE__ */ (0,
|
|
844
|
+
metrics.narrow && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("article", { className: "decision-card", children: [
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "decision-card-head", children: [
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-card-title", children: t("cardNarrow") }),
|
|
847
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-total", children: [
|
|
766
848
|
metrics.narrow.attempts,
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: t("cardTimes") })
|
|
768
850
|
] })
|
|
769
851
|
] }),
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
771
|
-
/* @__PURE__ */ (0,
|
|
772
|
-
/* @__PURE__ */ (0,
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
853
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.applied }),
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("narrowAppliedLabel") })
|
|
774
856
|
] }),
|
|
775
|
-
/* @__PURE__ */ (0,
|
|
776
|
-
/* @__PURE__ */ (0,
|
|
777
|
-
/* @__PURE__ */ (0,
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
858
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.dropped }),
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("narrowDroppedLabel") })
|
|
778
860
|
] }),
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
861
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
862
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.narrow.failures }),
|
|
863
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
782
864
|
] })
|
|
783
865
|
] }),
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
866
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("footer", { className: "decision-card-foot decision-card-rate", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
785
867
|
t("narrowApplyRate"),
|
|
786
|
-
/* @__PURE__ */ (0,
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: narrowApplyRate === null ? t("rateNa") : `${narrowApplyRate}%` })
|
|
787
869
|
] }) })
|
|
788
870
|
] }),
|
|
789
|
-
metrics.complete && /* @__PURE__ */ (0,
|
|
790
|
-
/* @__PURE__ */ (0,
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
871
|
+
metrics.complete && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("article", { className: "decision-card", children: [
|
|
872
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "decision-card-head", children: [
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-card-title", children: t("cardComplete") }),
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-card-total", children: [
|
|
793
875
|
metrics.complete.attempts,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
876
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: t("cardTimes") })
|
|
795
877
|
] })
|
|
796
878
|
] }),
|
|
797
|
-
/* @__PURE__ */ (0,
|
|
798
|
-
/* @__PURE__ */ (0,
|
|
799
|
-
/* @__PURE__ */ (0,
|
|
800
|
-
/* @__PURE__ */ (0,
|
|
879
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-card-stats", children: [
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num", children: metrics.complete.satisfied }),
|
|
882
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeSatisfied") })
|
|
801
883
|
] }),
|
|
802
|
-
/* @__PURE__ */ (0,
|
|
803
|
-
/* @__PURE__ */ (0,
|
|
804
|
-
/* @__PURE__ */ (0,
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
885
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-warn", children: metrics.complete.unsatisfied }),
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeUnsatisfied") })
|
|
805
887
|
] }),
|
|
806
|
-
/* @__PURE__ */ (0,
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-stat", children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.complete.insufficient }),
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-stat-label", children: t("completeInsufficient") })
|
|
809
891
|
] })
|
|
810
892
|
] }),
|
|
811
|
-
/* @__PURE__ */ (0,
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("footer", { className: "decision-card-foot decision-card-rate", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
812
894
|
t("failures"),
|
|
813
|
-
/* @__PURE__ */ (0,
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: metrics.complete.failures })
|
|
814
896
|
] }) })
|
|
815
897
|
] })
|
|
816
898
|
] })
|
|
817
899
|
] }),
|
|
818
|
-
/* @__PURE__ */ (0,
|
|
819
|
-
/* @__PURE__ */ (0,
|
|
820
|
-
log.length === 0 ? /* @__PURE__ */ (0,
|
|
821
|
-
|
|
822
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-body", children: entry.kind === "gate" ? renderGate(entry) : entry.kind === "narrow" ? renderNarrow(entry) : entry.kind === "complete" ? renderComplete(entry) : renderCheck(entry) }),
|
|
823
|
-
entry.id && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-rate", role: "group", "aria-label": t("rateGroup"), children: [
|
|
824
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[entry.id] === "good" ? " decision-rate-on decision-rate-good" : ""}`, "aria-label": t("rateGood"), title: t("rateGood"), "aria-pressed": ratings[entry.id] === "good", onClick: () => void annotate(entry.id, "good"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
825
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 7.2 8.1 2.4c.6-.9 2-.5 2 .6V6h3.2c.9 0 1.5.8 1.3 1.6l-1.1 4.6c-.2.8-.9 1.3-1.7 1.3H5V7.2Z", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" }),
|
|
826
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 7.2H2.6v6.3H5", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" })
|
|
827
|
-
] }) }),
|
|
828
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[entry.id] === "bad" ? " decision-rate-on decision-rate-bad" : ""}`, "aria-label": t("rateBad"), title: t("rateBad"), "aria-pressed": ratings[entry.id] === "bad", onClick: () => void annotate(entry.id, "bad"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
829
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 8.8 7.9 13.6c-.6.9-2 .5-2-.6V10H2.7c-.9 0-1.5-.8-1.3-1.6l1.1-4.6C2.7 3 3.4 2.5 4.2 2.5H11v6.3Z", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" }),
|
|
830
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 8.8h2.4V2.5H11", stroke: "currentColor", "stroke-width": "1.2", "stroke-linejoin": "round" })
|
|
831
|
-
] }) }),
|
|
832
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: `decision-rate-btn${ratings[entry.id] === "unsure" ? " decision-rate-on decision-rate-unsure" : ""}`, "aria-label": t("rateUnsure"), title: t("rateUnsure"), "aria-pressed": ratings[entry.id] === "unsure", onClick: () => void annotate(entry.id, "unsure"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
833
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "8", r: "6.2", stroke: "currentColor", "stroke-width": "1.2" }),
|
|
834
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6.3 6.2c0-1 .8-1.7 1.7-1.7s1.7.7 1.7 1.6c0 1.3-1.6 1.4-1.7 2.6", stroke: "currentColor", "stroke-width": "1.2", "stroke-linecap": "round", "stroke-linejoin": "round" }),
|
|
835
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "11.4", r: ".8", fill: "currentColor" })
|
|
836
|
-
] }) })
|
|
837
|
-
] })
|
|
838
|
-
] }, entry.id ?? `${entry.at}-${index}`)) }),
|
|
839
|
-
analysis && analysis.annotations.rated > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "decision-muted decision-rate-summary", children: t("rateSummary", { rated: analysis.annotations.rated, good: analysis.annotations.good, bad: analysis.annotations.bad, unsure: analysis.annotations.unsure }) })
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
901
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("log") }),
|
|
902
|
+
log.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-empty", role: "status", children: t("logEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DecisionLogList, { entries: log, ratings, onRate: (id, rating) => void annotate(id, rating), t }),
|
|
903
|
+
analysis && analysis.annotations.rated > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted decision-rate-summary", children: t("rateSummary", { rated: analysis.annotations.rated, good: analysis.annotations.good, bad: analysis.annotations.bad, unsure: analysis.annotations.unsure }) })
|
|
840
904
|
] }),
|
|
841
|
-
message && /* @__PURE__ */ (0,
|
|
905
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", className: "decision-message decision-message-warn", children: message })
|
|
842
906
|
] })
|
|
843
907
|
]
|
|
844
908
|
}
|
|
@@ -846,12 +910,144 @@ function SessionPanel({ sessionId, t }) {
|
|
|
846
910
|
] });
|
|
847
911
|
}
|
|
848
912
|
|
|
913
|
+
// src/client/analysis-view.tsx
|
|
914
|
+
var import_react3 = require("react");
|
|
915
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
916
|
+
function Stat({ label, value, tone }) {
|
|
917
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-stat", children: [
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `decision-stat-num${tone ? ` decision-stat-${tone}` : ""}`, children: value }),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-stat-label", children: label })
|
|
920
|
+
] });
|
|
921
|
+
}
|
|
922
|
+
function AnalysisView({ sessionId, t }) {
|
|
923
|
+
const [analysis, setAnalysis] = (0, import_react3.useState)(null);
|
|
924
|
+
const [log, setLog] = (0, import_react3.useState)([]);
|
|
925
|
+
const [loaded, setLoaded] = (0, import_react3.useState)(false);
|
|
926
|
+
const [message, setMessage] = (0, import_react3.useState)("");
|
|
927
|
+
const { ratings, seed, annotate } = useAnnotations(sessionId, () => setMessage(t("annotateFailed")));
|
|
928
|
+
(0, import_react3.useEffect)(() => {
|
|
929
|
+
let alive = true;
|
|
930
|
+
setMessage("");
|
|
931
|
+
setLoaded(false);
|
|
932
|
+
void Promise.allSettled([
|
|
933
|
+
request(`logs?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
934
|
+
if (alive) {
|
|
935
|
+
setAnalysis(value);
|
|
936
|
+
seed(value);
|
|
937
|
+
}
|
|
938
|
+
}),
|
|
939
|
+
request(`log?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
940
|
+
if (alive) setLog(value.entries);
|
|
941
|
+
})
|
|
942
|
+
]).finally(() => {
|
|
943
|
+
if (alive) setLoaded(true);
|
|
944
|
+
});
|
|
945
|
+
return () => {
|
|
946
|
+
alive = false;
|
|
947
|
+
};
|
|
948
|
+
}, [sessionId, seed]);
|
|
949
|
+
const profile = analysis?.profile;
|
|
950
|
+
const backtest = analysis?.trendBacktest;
|
|
951
|
+
const annotations = analysis?.annotations;
|
|
952
|
+
const meanScore = profile && profile.check.scoreCount > 0 ? Math.round(profile.check.scoreSum / profile.check.scoreCount * 10) / 10 : null;
|
|
953
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "decision-analysis", role: "region", "aria-label": t("analysisTitle"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-analysis-inner", children: [
|
|
954
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "decision-analysis-title", children: t("analysisTitle") }),
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-muted decision-analysis-intro", children: t("analysisIntro") }),
|
|
956
|
+
loaded && (!analysis || analysis.totalDecisions === 0) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-empty", role: "status", children: t("logEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
957
|
+
profile && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("analysisProfile") }),
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-analysis-cards", children: [
|
|
960
|
+
profile.gate.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "decision-card-head", children: [
|
|
962
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-card-title", children: t("cardGate") }),
|
|
963
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-card-total", children: [
|
|
964
|
+
profile.gate.attempts,
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: t("cardTimes") })
|
|
966
|
+
] })
|
|
967
|
+
] }),
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("deny"), value: profile.gate.deny, tone: "warn" }),
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("allow"), value: profile.gate.allow }),
|
|
971
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("ask"), value: profile.gate.ask }),
|
|
972
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.gate.error, tone: "muted" })
|
|
973
|
+
] })
|
|
974
|
+
] }),
|
|
975
|
+
profile.check.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "decision-card-head", children: [
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-card-title", children: t("cardCheck") }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-card-total", children: [
|
|
979
|
+
profile.check.attempts,
|
|
980
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: t("cardTimes") })
|
|
981
|
+
] })
|
|
982
|
+
] }),
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkLow"), value: profile.check.low, tone: "warn" }),
|
|
985
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("checkOk"), value: profile.check.ok }),
|
|
986
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("analysisMeanScore"), value: meanScore === null ? t("rateNa") : `${meanScore}/2` }),
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.check.error, tone: "muted" })
|
|
988
|
+
] })
|
|
989
|
+
] }),
|
|
990
|
+
profile.narrow.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
991
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "decision-card-head", children: [
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-card-title", children: t("cardNarrow") }),
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-card-total", children: [
|
|
994
|
+
profile.narrow.attempts,
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: t("cardTimes") })
|
|
996
|
+
] })
|
|
997
|
+
] }),
|
|
998
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
999
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowAppliedLabel"), value: profile.narrow.applied }),
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("narrowDroppedLabel"), value: profile.narrow.droppedSum }),
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("failures"), value: profile.narrow.error, tone: "muted" })
|
|
1002
|
+
] })
|
|
1003
|
+
] }),
|
|
1004
|
+
profile.complete.attempts > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "decision-card", children: [
|
|
1005
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "decision-card-head", children: [
|
|
1006
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "decision-card-title", children: t("cardComplete") }),
|
|
1007
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "decision-card-total", children: [
|
|
1008
|
+
profile.complete.attempts,
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: t("cardTimes") })
|
|
1010
|
+
] })
|
|
1011
|
+
] }),
|
|
1012
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats", children: [
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeSatisfied"), value: profile.complete.satisfied }),
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeUnsatisfied"), value: profile.complete.unsatisfied, tone: "warn" }),
|
|
1015
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("completeInsufficient"), value: profile.complete.insufficient, tone: "muted" })
|
|
1016
|
+
] })
|
|
1017
|
+
] })
|
|
1018
|
+
] })
|
|
1019
|
+
] }),
|
|
1020
|
+
backtest && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("analysisTrend") }),
|
|
1022
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "decision-card-stats decision-analysis-trend", children: [
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("analysisTrendWarn"), value: backtest.warnHits }),
|
|
1024
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("analysisTrendSevere"), value: backtest.severeHits, tone: "warn" }),
|
|
1025
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Stat, { label: t("analysisTrendMaxRun"), value: backtest.maxRun })
|
|
1026
|
+
] }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-muted decision-analysis-note", children: t("analysisTrendNote") })
|
|
1028
|
+
] }),
|
|
1029
|
+
annotations && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1030
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("analysisAccuracy") }),
|
|
1031
|
+
annotations.rated === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-muted", children: t("analysisAccuracyEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-muted decision-rate-summary", children: t("rateSummary", { rated: annotations.rated, good: annotations.good, bad: annotations.bad, unsure: annotations.unsure }) })
|
|
1032
|
+
] }),
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "decision-analysis-section", children: [
|
|
1034
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t("log") }),
|
|
1035
|
+
log.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-empty", role: "status", children: t("analysisLogTruncated") }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1036
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DecisionLogList, { entries: log, ratings, onRate: (id, rating) => void annotate(id, rating), t }),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "decision-muted decision-analysis-note", children: t("analysisLogNote") })
|
|
1038
|
+
] })
|
|
1039
|
+
] })
|
|
1040
|
+
] }),
|
|
1041
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", className: "decision-message decision-message-warn", children: message })
|
|
1042
|
+
] }) });
|
|
1043
|
+
}
|
|
1044
|
+
|
|
849
1045
|
// src/client/config-form.tsx
|
|
850
|
-
var
|
|
851
|
-
var
|
|
852
|
-
var
|
|
1046
|
+
var import_react4 = require("react");
|
|
1047
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1048
|
+
var api = "/plugins/dsh-decision-layer/api";
|
|
853
1049
|
async function request2(path, fetchFn, init) {
|
|
854
|
-
const response = await fetchFn(`${
|
|
1050
|
+
const response = await fetchFn(`${api}/${path}`, init);
|
|
855
1051
|
const body = await response.json();
|
|
856
1052
|
if (!response.ok || !body.ok || body.value === void 0) throw new Error(body.error || "Request failed");
|
|
857
1053
|
return body.value;
|
|
@@ -865,31 +1061,31 @@ var maxCandidatesOf = (settings) => settings?.maxCandidates ?? DEFAULT_MAX_CANDI
|
|
|
865
1061
|
var thresholdOf = (settings) => settings?.threshold ?? DEFAULT_THRESHOLD;
|
|
866
1062
|
function HeadIcon({ name }) {
|
|
867
1063
|
const glyphs = {
|
|
868
|
-
features: /* @__PURE__ */ (0,
|
|
869
|
-
/* @__PURE__ */ (0,
|
|
870
|
-
/* @__PURE__ */ (0,
|
|
871
|
-
/* @__PURE__ */ (0,
|
|
872
|
-
/* @__PURE__ */ (0,
|
|
1064
|
+
features: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "2", y: "3", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1066
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "11.9", cy: "5.1", r: "1.25", fill: "currentColor" }),
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "2", y: "8.8", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1068
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "4.1", cy: "10.9", r: "1.25", fill: "currentColor" })
|
|
873
1069
|
] }),
|
|
874
|
-
advanced: /* @__PURE__ */ (0,
|
|
875
|
-
/* @__PURE__ */ (0,
|
|
876
|
-
/* @__PURE__ */ (0,
|
|
877
|
-
/* @__PURE__ */ (0,
|
|
1070
|
+
advanced: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M2.5 5h11M2.5 11h11", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round" }),
|
|
1072
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "10.5", cy: "5", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "5.5", cy: "11", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" })
|
|
878
1074
|
] }),
|
|
879
|
-
backend: /* @__PURE__ */ (0,
|
|
880
|
-
/* @__PURE__ */ (0,
|
|
881
|
-
/* @__PURE__ */ (0,
|
|
882
|
-
/* @__PURE__ */ (0,
|
|
883
|
-
/* @__PURE__ */ (0,
|
|
1075
|
+
backend: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "2.3", y: "2.6", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "2.3", y: "8.8", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
1078
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "5", cy: "4.9", r: ".7", fill: "currentColor" }),
|
|
1079
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "5", cy: "11.1", r: ".7", fill: "currentColor" })
|
|
884
1080
|
] })
|
|
885
1081
|
};
|
|
886
|
-
return /* @__PURE__ */ (0,
|
|
1082
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `decision-head-icon decision-head-icon-${name}`, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", children: glyphs[name] }) });
|
|
887
1083
|
}
|
|
888
1084
|
function Toggle({ label, checked, disabled, onChange }) {
|
|
889
|
-
return /* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
1085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-toggle", children: [
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-toggle-text", children: label }),
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
1088
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
893
1089
|
"input",
|
|
894
1090
|
{
|
|
895
1091
|
className: "decision-toggle-input",
|
|
@@ -899,29 +1095,29 @@ function Toggle({ label, checked, disabled, onChange }) {
|
|
|
899
1095
|
onChange: (event) => onChange(event.target.checked)
|
|
900
1096
|
}
|
|
901
1097
|
),
|
|
902
|
-
/* @__PURE__ */ (0,
|
|
1098
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
903
1099
|
] })
|
|
904
1100
|
] });
|
|
905
1101
|
}
|
|
906
1102
|
function ConfigForm({ t, fetchFn = fetch }) {
|
|
907
|
-
const [config, setConfig] = (0,
|
|
908
|
-
const [checkMode, setCheckMode] = (0,
|
|
909
|
-
const [narrowMode, setNarrowMode] = (0,
|
|
910
|
-
const [keepPrefixes, setKeepPrefixes] = (0,
|
|
911
|
-
const [maxCandidates, setMaxCandidates] = (0,
|
|
912
|
-
const [threshold, setThreshold] = (0,
|
|
913
|
-
const [gateOn, setGateOn] = (0,
|
|
914
|
-
const [checkOn, setCheckOn] = (0,
|
|
915
|
-
const [narrowOn, setNarrowOn] = (0,
|
|
916
|
-
const [completeOn, setCompleteOn] = (0,
|
|
917
|
-
const [completeMode, setCompleteMode] = (0,
|
|
918
|
-
const [key, setKey] = (0,
|
|
919
|
-
const [busy, setBusy] = (0,
|
|
920
|
-
const [advancedDirty, setAdvancedDirty] = (0,
|
|
921
|
-
const [backendDirty, setBackendDirty] = (0,
|
|
922
|
-
const [ready, setReady] = (0,
|
|
923
|
-
const [message, setMessage] = (0,
|
|
924
|
-
const [probeResult, setProbeResult] = (0,
|
|
1103
|
+
const [config, setConfig] = (0, import_react4.useState)({ url: "", model: "", apiKeySet: false, httpApprovedUrl: "", effectiveUrl: "https://api.typesafe.ai" });
|
|
1104
|
+
const [checkMode, setCheckMode] = (0, import_react4.useState)("observe");
|
|
1105
|
+
const [narrowMode, setNarrowMode] = (0, import_react4.useState)("enforce");
|
|
1106
|
+
const [keepPrefixes, setKeepPrefixes] = (0, import_react4.useState)(DEFAULT_KEEP_PREFIXES.join("\n"));
|
|
1107
|
+
const [maxCandidates, setMaxCandidates] = (0, import_react4.useState)(String(DEFAULT_MAX_CANDIDATES));
|
|
1108
|
+
const [threshold, setThreshold] = (0, import_react4.useState)(String(DEFAULT_THRESHOLD));
|
|
1109
|
+
const [gateOn, setGateOn] = (0, import_react4.useState)(true);
|
|
1110
|
+
const [checkOn, setCheckOn] = (0, import_react4.useState)(true);
|
|
1111
|
+
const [narrowOn, setNarrowOn] = (0, import_react4.useState)(true);
|
|
1112
|
+
const [completeOn, setCompleteOn] = (0, import_react4.useState)(true);
|
|
1113
|
+
const [completeMode, setCompleteMode] = (0, import_react4.useState)("observe");
|
|
1114
|
+
const [key, setKey] = (0, import_react4.useState)("");
|
|
1115
|
+
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
1116
|
+
const [advancedDirty, setAdvancedDirty] = (0, import_react4.useState)(false);
|
|
1117
|
+
const [backendDirty, setBackendDirty] = (0, import_react4.useState)(false);
|
|
1118
|
+
const [ready, setReady] = (0, import_react4.useState)(false);
|
|
1119
|
+
const [message, setMessage] = (0, import_react4.useState)(null);
|
|
1120
|
+
const [probeResult, setProbeResult] = (0, import_react4.useState)(null);
|
|
925
1121
|
const applyFeatures = (features) => {
|
|
926
1122
|
setGateOn(features?.gate !== false);
|
|
927
1123
|
setCheckOn(features?.check !== false);
|
|
@@ -938,7 +1134,7 @@ function ConfigForm({ t, fetchFn = fetch }) {
|
|
|
938
1134
|
setThreshold(String(thresholdOf(value.narrowSettings)));
|
|
939
1135
|
applyFeatures(value.features);
|
|
940
1136
|
};
|
|
941
|
-
(0,
|
|
1137
|
+
(0, import_react4.useEffect)(() => {
|
|
942
1138
|
let live = true;
|
|
943
1139
|
setMessage(null);
|
|
944
1140
|
setReady(false);
|
|
@@ -1041,17 +1237,17 @@ ${url}`)) return;
|
|
|
1041
1237
|
setBusy(false);
|
|
1042
1238
|
}
|
|
1043
1239
|
};
|
|
1044
|
-
return /* @__PURE__ */ (0,
|
|
1045
|
-
/* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1048
|
-
/* @__PURE__ */ (0,
|
|
1240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-config", children: [
|
|
1241
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { className: "decision-collapse", open: true, children: [
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { children: [
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeadIcon, { name: "features" }),
|
|
1049
1245
|
t("basicFeatures")
|
|
1050
1246
|
] }),
|
|
1051
|
-
/* @__PURE__ */ (0,
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
1052
1248
|
] }),
|
|
1053
|
-
/* @__PURE__ */ (0,
|
|
1054
|
-
/* @__PURE__ */ (0,
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-collapse-body", children: [
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1055
1251
|
Toggle,
|
|
1056
1252
|
{
|
|
1057
1253
|
label: t("featureGate"),
|
|
@@ -1063,8 +1259,8 @@ ${url}`)) return;
|
|
|
1063
1259
|
}
|
|
1064
1260
|
}
|
|
1065
1261
|
),
|
|
1066
|
-
/* @__PURE__ */ (0,
|
|
1067
|
-
/* @__PURE__ */ (0,
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("featureGateHint") }),
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1068
1264
|
Toggle,
|
|
1069
1265
|
{
|
|
1070
1266
|
label: t("featureCheck"),
|
|
@@ -1076,8 +1272,8 @@ ${url}`)) return;
|
|
|
1076
1272
|
}
|
|
1077
1273
|
}
|
|
1078
1274
|
),
|
|
1079
|
-
/* @__PURE__ */ (0,
|
|
1080
|
-
/* @__PURE__ */ (0,
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("featureCheckHint") }),
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1081
1277
|
Toggle,
|
|
1082
1278
|
{
|
|
1083
1279
|
label: t("featureNarrow"),
|
|
@@ -1089,8 +1285,8 @@ ${url}`)) return;
|
|
|
1089
1285
|
}
|
|
1090
1286
|
}
|
|
1091
1287
|
),
|
|
1092
|
-
/* @__PURE__ */ (0,
|
|
1093
|
-
/* @__PURE__ */ (0,
|
|
1288
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("featureNarrowHint") }),
|
|
1289
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1094
1290
|
Toggle,
|
|
1095
1291
|
{
|
|
1096
1292
|
label: t("featureComplete"),
|
|
@@ -1102,22 +1298,22 @@ ${url}`)) return;
|
|
|
1102
1298
|
}
|
|
1103
1299
|
}
|
|
1104
1300
|
),
|
|
1105
|
-
/* @__PURE__ */ (0,
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("featureCompleteHint") })
|
|
1106
1302
|
] })
|
|
1107
1303
|
] }),
|
|
1108
|
-
/* @__PURE__ */ (0,
|
|
1109
|
-
/* @__PURE__ */ (0,
|
|
1110
|
-
/* @__PURE__ */ (0,
|
|
1111
|
-
/* @__PURE__ */ (0,
|
|
1304
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { className: "decision-collapse", children: [
|
|
1305
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeadIcon, { name: "advanced" }),
|
|
1112
1308
|
t("advancedConfig")
|
|
1113
1309
|
] }),
|
|
1114
|
-
/* @__PURE__ */ (0,
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
1115
1311
|
] }),
|
|
1116
|
-
/* @__PURE__ */ (0,
|
|
1117
|
-
/* @__PURE__ */ (0,
|
|
1118
|
-
/* @__PURE__ */ (0,
|
|
1119
|
-
/* @__PURE__ */ (0,
|
|
1120
|
-
/* @__PURE__ */ (0,
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { className: "decision-collapse-body", onSubmit: (event) => void saveAdvanced(event), children: [
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-advanced-grid", children: [
|
|
1314
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-field-block", children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-subhead", children: t("advancedSwitches") }),
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1121
1317
|
Toggle,
|
|
1122
1318
|
{
|
|
1123
1319
|
label: t("selfCheckSteer"),
|
|
@@ -1129,8 +1325,8 @@ ${url}`)) return;
|
|
|
1129
1325
|
}
|
|
1130
1326
|
}
|
|
1131
1327
|
),
|
|
1132
|
-
/* @__PURE__ */ (0,
|
|
1133
|
-
/* @__PURE__ */ (0,
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("selfCheckHint") }),
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1134
1330
|
Toggle,
|
|
1135
1331
|
{
|
|
1136
1332
|
label: t("narrowObserveLabel"),
|
|
@@ -1142,8 +1338,8 @@ ${url}`)) return;
|
|
|
1142
1338
|
}
|
|
1143
1339
|
}
|
|
1144
1340
|
),
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("narrowHint") }),
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1147
1343
|
Toggle,
|
|
1148
1344
|
{
|
|
1149
1345
|
label: t("completeSteer"),
|
|
@@ -1155,13 +1351,13 @@ ${url}`)) return;
|
|
|
1155
1351
|
}
|
|
1156
1352
|
}
|
|
1157
1353
|
),
|
|
1158
|
-
/* @__PURE__ */ (0,
|
|
1354
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "decision-muted", children: t("completeHint") })
|
|
1159
1355
|
] }),
|
|
1160
|
-
/* @__PURE__ */ (0,
|
|
1161
|
-
/* @__PURE__ */ (0,
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-field-block", children: [
|
|
1357
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-subhead", children: t("advancedParams") }),
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field", children: [
|
|
1163
1359
|
t("narrowKeepLabel"),
|
|
1164
|
-
/* @__PURE__ */ (0,
|
|
1360
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1165
1361
|
"textarea",
|
|
1166
1362
|
{
|
|
1167
1363
|
className: "decision-prefixes",
|
|
@@ -1175,11 +1371,11 @@ ${url}`)) return;
|
|
|
1175
1371
|
}
|
|
1176
1372
|
}
|
|
1177
1373
|
),
|
|
1178
|
-
/* @__PURE__ */ (0,
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "decision-muted", children: t("narrowKeepHint") })
|
|
1179
1375
|
] }),
|
|
1180
|
-
/* @__PURE__ */ (0,
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
1181
1377
|
t("narrowMaxLabel"),
|
|
1182
|
-
/* @__PURE__ */ (0,
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1183
1379
|
"input",
|
|
1184
1380
|
{
|
|
1185
1381
|
className: "decision-narrow-cap",
|
|
@@ -1196,11 +1392,11 @@ ${url}`)) return;
|
|
|
1196
1392
|
}
|
|
1197
1393
|
}
|
|
1198
1394
|
),
|
|
1199
|
-
/* @__PURE__ */ (0,
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "decision-muted", children: t("narrowMaxHint") })
|
|
1200
1396
|
] }),
|
|
1201
|
-
/* @__PURE__ */ (0,
|
|
1397
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
1202
1398
|
t("narrowThresholdLabel"),
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1204
1400
|
"input",
|
|
1205
1401
|
{
|
|
1206
1402
|
className: "decision-narrow-cap",
|
|
@@ -1217,26 +1413,26 @@ ${url}`)) return;
|
|
|
1217
1413
|
}
|
|
1218
1414
|
}
|
|
1219
1415
|
),
|
|
1220
|
-
/* @__PURE__ */ (0,
|
|
1416
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "decision-muted", children: t("narrowThresholdHint") })
|
|
1221
1417
|
] })
|
|
1222
1418
|
] })
|
|
1223
1419
|
] }),
|
|
1224
|
-
/* @__PURE__ */ (0,
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "decision-actions", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { disabled: busy || !ready || !advancedDirty, type: "submit", children: t("saveAdvanced") }) })
|
|
1225
1421
|
] })
|
|
1226
1422
|
] }),
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
/* @__PURE__ */ (0,
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { children: [
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { children: [
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeadIcon, { name: "backend" }),
|
|
1230
1426
|
t("backend")
|
|
1231
1427
|
] }),
|
|
1232
|
-
ready && /* @__PURE__ */ (0,
|
|
1428
|
+
ready && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "decision-muted decision-destination", children: [
|
|
1233
1429
|
t("destination"),
|
|
1234
|
-
/* @__PURE__ */ (0,
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { children: config.effectiveUrl })
|
|
1235
1431
|
] }),
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { onSubmit: (event) => void saveBackend(event), children: [
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field", children: [
|
|
1238
1434
|
t("url"),
|
|
1239
|
-
/* @__PURE__ */ (0,
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1240
1436
|
"input",
|
|
1241
1437
|
{
|
|
1242
1438
|
type: "url",
|
|
@@ -1251,9 +1447,9 @@ ${url}`)) return;
|
|
|
1251
1447
|
}
|
|
1252
1448
|
)
|
|
1253
1449
|
] }),
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field", children: [
|
|
1255
1451
|
t("model"),
|
|
1256
|
-
/* @__PURE__ */ (0,
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1257
1453
|
"input",
|
|
1258
1454
|
{
|
|
1259
1455
|
value: config.model,
|
|
@@ -1267,9 +1463,9 @@ ${url}`)) return;
|
|
|
1267
1463
|
}
|
|
1268
1464
|
)
|
|
1269
1465
|
] }),
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "decision-field", children: [
|
|
1271
1467
|
t("key"),
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1273
1469
|
"input",
|
|
1274
1470
|
{
|
|
1275
1471
|
type: "password",
|
|
@@ -1284,23 +1480,23 @@ ${url}`)) return;
|
|
|
1284
1480
|
}
|
|
1285
1481
|
}
|
|
1286
1482
|
),
|
|
1287
|
-
/* @__PURE__ */ (0,
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "decision-muted", children: config.apiKeySet ? t("keyHintSaved") : t("keyHintEmpty") })
|
|
1288
1484
|
] }),
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1292
|
-
probeResult && /* @__PURE__ */ (0,
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-actions", children: [
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { disabled: busy || !ready, type: "submit", children: t("save") }),
|
|
1487
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "decision-secondary", disabled: busy || !ready || backendDirty, type: "button", onClick: () => void probe(), children: t("probe") }),
|
|
1488
|
+
probeResult && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { role: "status", className: `decision-probe-result${probeResult.ok ? " decision-message-ok" : " decision-message-warn"}`, children: probeResult.text })
|
|
1293
1489
|
] })
|
|
1294
1490
|
] }),
|
|
1295
|
-
config.apiKeySet && /* @__PURE__ */ (0,
|
|
1296
|
-
/* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1491
|
+
config.apiKeySet && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-danger-row", children: [
|
|
1492
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "decision-danger-text", children: [
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "decision-danger-title", children: t("removeKey") }),
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "decision-muted", children: t("removeKeyHint") })
|
|
1299
1495
|
] }),
|
|
1300
|
-
/* @__PURE__ */ (0,
|
|
1496
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "decision-danger-button", disabled: busy || !ready, onClick: () => void removeSavedKey(), children: t("removeKeyButton") })
|
|
1301
1497
|
] })
|
|
1302
1498
|
] }),
|
|
1303
|
-
message && /* @__PURE__ */ (0,
|
|
1499
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { role: "status", className: `decision-message${message.ok ? " decision-message-ok" : " decision-message-warn"}`, children: message.text })
|
|
1304
1500
|
] });
|
|
1305
1501
|
}
|
|
1306
1502
|
|
|
@@ -1467,6 +1663,22 @@ var css = `
|
|
|
1467
1663
|
.decision-message{font-size:.82rem;margin:.2rem 0 0}
|
|
1468
1664
|
.decision-message-ok{color:#1f6f57}
|
|
1469
1665
|
.decision-message-warn{color:#9d4b1f}
|
|
1666
|
+
/* Conversation-view "Decision analysis" tab. It reuses the card / stat / log
|
|
1667
|
+
primitives above; this block only supplies the scroll container and section
|
|
1668
|
+
rhythm, since the tab is not inside the modal's .decision-body wrapper. */
|
|
1669
|
+
.decision-analysis{height:100%;overflow:auto;color:var(--dsw-alias-label-primary,#202124);font:inherit}
|
|
1670
|
+
.decision-analysis-inner{max-width:52rem;margin:0 auto;padding:1.4rem 1.5rem 3rem}
|
|
1671
|
+
.decision-analysis-title{font-size:1.15rem;margin:0 0 .3rem}
|
|
1672
|
+
.decision-analysis-intro{margin:0 0 .4rem}
|
|
1673
|
+
.decision-analysis-section{border-top:1px solid var(--dsw-alias-border-l2,#eceff1);margin-top:1.1rem;padding-top:1rem}
|
|
1674
|
+
.decision-analysis-section>h3{font-size:.92rem;margin:0 0 .6rem}
|
|
1675
|
+
.decision-analysis-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:.7rem}
|
|
1676
|
+
.decision-analysis-cards .decision-card-stats{flex-wrap:wrap}
|
|
1677
|
+
.decision-analysis-trend{max-width:26rem}
|
|
1678
|
+
.decision-analysis-note{margin:.5rem 0 0}
|
|
1679
|
+
@media (prefers-color-scheme:dark){
|
|
1680
|
+
.decision-analysis{color:var(--dsw-alias-label-primary,#e6eaee)}
|
|
1681
|
+
}
|
|
1470
1682
|
`;
|
|
1471
1683
|
function installStyles() {
|
|
1472
1684
|
if (typeof document === "undefined" || document.querySelector('style[data-plugin="dsh-decision-layer"]')) return () => {
|
|
@@ -1479,9 +1691,10 @@ function installStyles() {
|
|
|
1479
1691
|
}
|
|
1480
1692
|
|
|
1481
1693
|
// src/client/index.tsx
|
|
1482
|
-
var
|
|
1694
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1483
1695
|
var inject = ["slots", "locale"];
|
|
1484
1696
|
function apply(ctx) {
|
|
1697
|
+
const t = ctx.locale.bind("dsh-decision-layer");
|
|
1485
1698
|
ctx.effect(installStyles);
|
|
1486
1699
|
ctx.effect(() => ctx.locale.register("dsh-decision-layer", dictionaries));
|
|
1487
1700
|
ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
|
|
@@ -1492,9 +1705,18 @@ function apply(ctx) {
|
|
|
1492
1705
|
registrant: "dsh-decision-layer",
|
|
1493
1706
|
inject: (sessionId) => ({ sessionId })
|
|
1494
1707
|
}, DecisionPanel));
|
|
1708
|
+
ctx.slots.inject("conversation.view", () => ctx.slots.register({
|
|
1709
|
+
name: "conversation.view",
|
|
1710
|
+
id: "decision-layer-analysis",
|
|
1711
|
+
order: 40,
|
|
1712
|
+
locale: "dsh-decision-layer",
|
|
1713
|
+
registrant: "dsh-decision-layer",
|
|
1714
|
+
label: () => t("analysisTab"),
|
|
1715
|
+
inject: (sessionId) => ({ sessionId })
|
|
1716
|
+
}, AnalysisView));
|
|
1495
1717
|
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register(
|
|
1496
1718
|
{ name: "plugins.bundle.config", key: "dsh-decision-layer", locale: "dsh-decision-layer" },
|
|
1497
|
-
(props) => props.view === "summary" ? props.t("summary") : /* @__PURE__ */ (0,
|
|
1719
|
+
(props) => props.view === "summary" ? props.t("summary") : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ConfigForm, { t: props.t })
|
|
1498
1720
|
));
|
|
1499
1721
|
}
|
|
1500
1722
|
|