dsh-decision-layer 0.4.0
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/LICENSE +21 -0
- package/README.en.md +49 -0
- package/README.md +53 -0
- package/cordis.patch.yml +3 -0
- package/icon.svg +18 -0
- package/lib/client.js +1288 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +78 -0
- package/service/.gitkeep +0 -0
- package/service/backend.mjs +127 -0
- package/service/config-store.mjs +203 -0
- package/service/danger-gate.mjs +143 -0
- package/service/dsh.mjs +175 -0
- package/service/log-store.mjs +70 -0
- package/service/loop-guard.mjs +52 -0
- package/service/manager-api.mjs +87 -0
- package/service/narrowing.mjs +149 -0
- package/service/self-check.mjs +94 -0
- package/service/session-state.mjs +116 -0
- package/skills/decision-layer/SKILL.md +15 -0
package/lib/client.js
ADDED
|
@@ -0,0 +1,1288 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: 'dsh-decision-layer',
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
+
|
|
24
|
+
// src/client/index.tsx
|
|
25
|
+
var index_exports = {};
|
|
26
|
+
__export(index_exports, {
|
|
27
|
+
ConfigForm: () => ConfigForm,
|
|
28
|
+
apply: () => apply,
|
|
29
|
+
inject: () => inject
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
|
|
33
|
+
// src/client/i18n.ts
|
|
34
|
+
var dictionaries = {
|
|
35
|
+
zh: {
|
|
36
|
+
summary: "\u5371\u9669\u8C03\u7528\u95E8\u63A7\u3001\u4EA7\u51FA\u81EA\u68C0\u4E0E\u9632\u5FAA\u73AF\uFF0C\u7531\u53EF\u63D2\u62D4\u88C1\u51B3\u6A21\u578B\u9A71\u52A8\u3002",
|
|
37
|
+
button: "\u51B3\u7B56\u5C42",
|
|
38
|
+
title: "\u51B3\u7B56\u5C42",
|
|
39
|
+
close: "\u5173\u95ED",
|
|
40
|
+
metrics: "\u81EA\u52A8\u88C1\u51B3\u7EDF\u8BA1",
|
|
41
|
+
triggerDecisions: "\u51B3\u7B56",
|
|
42
|
+
empty: "\u5C1A\u65E0\u81EA\u52A8\u88C1\u51B3\u3002\u624B\u52A8\u88C1\u51B3\u4E0D\u8BA1\u5165\u8FD9\u91CC\u3002",
|
|
43
|
+
attempts: "\u8BC4\u4F30\u6B21\u6570",
|
|
44
|
+
failures: "\u5931\u8D25\u56DE\u9000",
|
|
45
|
+
suggestions: "\u6A21\u578B\u5EFA\u8BAE\uFF08\u653E\u884C / \u8BE2\u95EE / \u62D2\u7EDD\uFF09",
|
|
46
|
+
actual: "\u5B9E\u9645\u5BBF\u4E3B\u7ED3\u679C\uFF08\u653E\u884C / \u62D2\u7EDD\uFF09",
|
|
47
|
+
checkAttempts: "\u81EA\u68C0\u8BC4\u4F30\u6B21\u6570",
|
|
48
|
+
checkLow: "\u4F4E\u5206",
|
|
49
|
+
checkOk: "\u901A\u8FC7",
|
|
50
|
+
settings: "\u4F1A\u8BDD\u8BBE\u7F6E",
|
|
51
|
+
cardGate: "\u5371\u9669\u95E8\u63A7",
|
|
52
|
+
cardCheck: "\u4EA7\u51FA\u81EA\u68C0",
|
|
53
|
+
cardNarrow: "\u5DE5\u5177\u6536\u7A84",
|
|
54
|
+
cardTimes: " \u6B21",
|
|
55
|
+
allow: "\u653E\u884C",
|
|
56
|
+
ask: "\u8BE2\u95EE",
|
|
57
|
+
deny: "\u62D2\u7EDD",
|
|
58
|
+
actualShort: "\u5B9E\u9645\u7ED3\u679C",
|
|
59
|
+
narrowAppliedLabel: "\u6536\u7A84",
|
|
60
|
+
narrowDroppedLabel: "\u6458\u9664\u5DE5\u5177",
|
|
61
|
+
narrowDropped: "\u6458\u9664",
|
|
62
|
+
narrowKept: "\u672A\u6536\u7A84",
|
|
63
|
+
narrowKeptCount: "\u4FDD\u7559",
|
|
64
|
+
narrowMore: " \u7B49 {count} \u4E2A",
|
|
65
|
+
narrowObserve: "\u4EC5\u89C2\u5BDF",
|
|
66
|
+
narrowEnforce: "\u5DF2\u751F\u6548",
|
|
67
|
+
checkPassRate: "\u901A\u8FC7\u7387",
|
|
68
|
+
narrowApplyRate: "\u6536\u7A84\u7387",
|
|
69
|
+
rateNa: "\u2014",
|
|
70
|
+
enabled: "\u542F\u7528\u81EA\u52A8\u4ECB\u5165",
|
|
71
|
+
backendStatus: "\u540E\u7AEF\u8FDE\u63A5",
|
|
72
|
+
statusChecking: "\u68C0\u6D4B\u4E2D\u2026",
|
|
73
|
+
statusIdle: "\u672A\u68C0\u6D4B",
|
|
74
|
+
statusOk: "\u6B63\u5E38",
|
|
75
|
+
statusDown: "\u4E0D\u53EF\u7528",
|
|
76
|
+
recheck: "\u91CD\u65B0\u68C0\u6D4B",
|
|
77
|
+
log: "\u51B3\u7B56\u65E5\u5FD7",
|
|
78
|
+
logEmpty: "\u672C\u4F1A\u8BDD\u5C1A\u65E0\u51B3\u7B56\u8BB0\u5F55\u3002",
|
|
79
|
+
logGate: "\u95E8\u63A7",
|
|
80
|
+
logCheck: "\u81EA\u68C0",
|
|
81
|
+
logNarrow: "\u6536\u7A84",
|
|
82
|
+
logSuggested: "\u6A21\u578B\u5EFA\u8BAE",
|
|
83
|
+
logEvalFailed: "\u8BC4\u4F30\u5931\u8D25",
|
|
84
|
+
logScore: "\u5F97\u5206",
|
|
85
|
+
logConnection: "\u8FDE\u63A5",
|
|
86
|
+
logConfidence: "\u7F6E\u4FE1\u5EA6",
|
|
87
|
+
logScoreHint: "\u5F97\u5206\u4E3A\u5404\u6863\u4F4D\u6309\u6982\u7387\u52A0\u6743\u7684\u7ED3\u679C\uFF0C\u53EF\u80FD\u662F\u5C0F\u6570\uFF08\u5982 1.4\uFF09\uFF0C\u6EE1\u5206\u4E3A\u9876\u6863\u53F7 2\u3002",
|
|
88
|
+
logCheckHint: "\u6BCF\u56DE\u5408\u7ED3\u675F\u540E\uFF0C\u628A\u8FD9\u8F6E AI \u7684\u6700\u7EC8\u56DE\u590D\u4EA4\u7ED9\u88C1\u51B3\u6A21\u578B\uFF0C\u6309\u300C\u4E25\u91CD\u9057\u6F0F/\u81EA\u76F8\u77DB\u76FE \u2192 \u6709\u5C0F\u9057\u6F0F \u2192 \u5B8C\u6574\u51C6\u786E\u300D\u4E09\u6863\u6253\u4E00\u4E2A 0\u20132 \u7684\u8D28\u91CF\u5206\uFF0C\u7528\u6765\u53D1\u73B0\u9057\u6F0F\u6216\u77DB\u76FE\u3002",
|
|
89
|
+
logNarrowHint: "\u6BCF\u56DE\u5408\u5F00\u59CB\u65F6\uFF0C\u628A\u8FD9\u8F6E\u4EFB\u52A1\u4E0E\u5F53\u524D\u53EF\u7528\u5DE5\u5177\u9010\u4E2A\u4EA4\u7ED9\u88C1\u51B3\u6A21\u578B\u5224\u65AD\u76F8\u5173\u6027\uFF08noul\uFF09\uFF0C\u6458\u6389\u660E\u663E\u7528\u4E0D\u4E0A\u7684\u5DE5\u5177\uFF0C\u53EA\u5728\u5F53\u524D\u5BBF\u4E3B\u5DF2\u5141\u8BB8\u7684\u96C6\u5408\u5185\u53D6\u4EA4\u96C6\u3001\u7EDD\u4E0D\u6269\u6743\uFF1B\u300C\u4EC5\u89C2\u5BDF\u300D\u53EA\u8BB0\u5F55\u5EFA\u8BAE\uFF0C\u300C\u5DF2\u751F\u6548\u300D\u624D\u771F\u6B63\u5BF9\u672C\u56DE\u5408\u9650\u5236\u5DE5\u5177\u3002",
|
|
90
|
+
actionDeny: "\u5DF2\u62D2\u7EDD",
|
|
91
|
+
actionAsk: "\u8F6C\u4EA4\u5BA1\u6279",
|
|
92
|
+
checkResultLow: "\u5F97\u5206\u504F\u4F4E",
|
|
93
|
+
checkResultOk: "\u901A\u8FC7",
|
|
94
|
+
reasonUnavailable: "\u540E\u7AEF\u4E0D\u53EF\u8FBE",
|
|
95
|
+
reasonHttpError: "\u540E\u7AEF\u8FD4\u56DE\u9519\u8BEF",
|
|
96
|
+
reasonInvalidResponse: "\u54CD\u5E94\u683C\u5F0F\u4E0D\u7B26",
|
|
97
|
+
reasonLowConfidence: "\u7F6E\u4FE1\u5EA6\u4E0D\u8DB3",
|
|
98
|
+
reasonCapacity: "\u4F1A\u8BDD\u72B6\u6001\u5DF2\u6EE1",
|
|
99
|
+
reasonConfig: "\u914D\u7F6E\u65E0\u6548",
|
|
100
|
+
reasonTooMany: "\u5019\u9009\u8FC7\u591A",
|
|
101
|
+
reasonTooManyCount: "\u5019\u9009 {count} \u4E2A\u504F\u591A",
|
|
102
|
+
reasonLowKeep: "\u4FDD\u7559\u8FC7\u5C11\uFF0C\u672A\u751F\u6548",
|
|
103
|
+
selfCheck: "\u4EA7\u51FA\u81EA\u68C0",
|
|
104
|
+
advancedSwitches: "\u4ECB\u5165\u5F00\u5173",
|
|
105
|
+
advancedParams: "\u6536\u7A84\u53C2\u6570",
|
|
106
|
+
selfCheckSteer: "\u5F97\u5206\u504F\u4F4E\u65F6\u81EA\u52A8\u8865\u4E00\u8F6E",
|
|
107
|
+
selfCheckHint: "\u6BCF\u56DE\u5408\u7ED3\u675F\u7ED9\u6700\u7EC8\u56DE\u590D\u6253\u5206\uFF080\u20132\uFF0C\u6309\u5404\u6863\u4F4D\u6982\u7387\u52A0\u6743\uFF0C\u53EF\u80FD\u662F\u5C0F\u6570\u5982 1.4\uFF09\u3002\u5173\u95ED\uFF1A\u53EA\u628A\u4F4E\u5206\u8BB0\u8FDB\u65E5\u5FD7\u548C\u7EDF\u8BA1\uFF0C\u4E0D\u6253\u65AD\u5BF9\u8BDD\u3002\u5F00\u542F\uFF1A\u5F97\u5206\u504F\u4F4E\uFF08\u22641\uFF09\u4E14\u6A21\u578B\u6709\u628A\u63E1\u65F6\uFF0C\u81EA\u52A8\u4EE5\u4F60\u7684\u540D\u4E49\u8FFD\u52A0\u4E00\u6761\u63D0\u793A\uFF0C\u8BA9 AI \u590D\u6838\u6709\u65E0\u9057\u6F0F\u6216\u77DB\u76FE\u5E76\u8865\u5B8C\uFF1B\u7F6E\u4FE1\u5EA6\u504F\u4F4E\u7684\u6253\u5206\u53EA\u8BB0\u5F55\u3001\u4E0D\u6253\u65AD\uFF0C\u540C\u4E00\u56DE\u5408\u6700\u591A\u8865\u4E00\u6B21\u3002",
|
|
108
|
+
narrow: "\u5DE5\u5177\u6536\u7A84",
|
|
109
|
+
narrowObserveLabel: "\u4EC5\u89C2\u5BDF\uFF08\u4E0D\u771F\u6B63\u9650\u5236\u5DE5\u5177\uFF09",
|
|
110
|
+
narrowHint: "\u6BCF\u56DE\u5408\u5F00\u59CB\u65F6\uFF0C\u7528\u88C1\u51B3\u6A21\u578B\u5224\u65AD\u5F53\u524D\u53EF\u9009\u5DE5\u5177\u4E0E\u8FD9\u8F6E\u4EFB\u52A1\u7684\u76F8\u5173\u6027\uFF0C\u6458\u6389\u7528\u4E0D\u4E0A\u7684\uFF1B\u8BFB\u5199\u3001\u7F16\u8F91\u3001Shell\u3001\u68C0\u7D22\u3001\u5F85\u529E\u7B49\u6838\u5FC3\u5DE5\u5177\u59CB\u7EC8\u4FDD\u7559\u3001\u4E0D\u53C2\u4E0E\u5224\u5B9A\u3002\u9ED8\u8BA4\u771F\u6B63\u751F\u6548\uFF1A\u672C\u56DE\u5408\u53EA\u4FDD\u7559\u5224\u4E3A\u76F8\u5173\u7684\u5DE5\u5177\uFF0C\u4E14\u53EA\u5728\u5BBF\u4E3B\u5DF2\u5141\u8BB8\u7684\u8303\u56F4\u5185\u53D6\u4EA4\u96C6\u3001\u4E0D\u6269\u6743\u3002\u5F00\u542F\u300C\u4EC5\u89C2\u5BDF\u300D\u540E\u53EA\u628A\u53EF\u6458\u6389\u7684\u5DE5\u5177\u8BB0\u8FDB\u65E5\u5FD7\u548C\u7EDF\u8BA1\uFF0C\u4E0D\u6539\u52A8\u5DE5\u5177\u96C6\u3002\u4E09\u91CD\u4FDD\u62A4\uFF1A\u6838\u5FC3\u5DE5\u5177\u59CB\u7EC8\u4FDD\u7559\uFF1B\u53EF\u9009\u5DE5\u5177\u8D85\u8FC7 20 \u4E2A\u65F6\u81EA\u52A8\u53EA\u89C2\u5BDF\u4E0D\u9650\u5236\uFF1B\u4FDD\u7559\u4E0B\u6765\u4E0D\u8DB3 5 \u4E2A\u65F6\u89C6\u4E3A\u5224\u5B9A\u4E0D\u53EF\u4FE1\u3001\u8DF3\u8FC7\u3002",
|
|
111
|
+
narrowKeepLabel: "\u59CB\u7EC8\u4FDD\u7559\u7684\u5DE5\u5177\u524D\u7F00",
|
|
112
|
+
narrowKeepHint: "\u540D\u5B57\u4EE5\u8FD9\u4E9B\u524D\u7F00\u5F00\u5934\u7684\u5DE5\u5177\u6C38\u8FDC\u4FDD\u7559\u3001\u4E0D\u53C2\u4E0E\u76F8\u5173\u6027\u5224\u5B9A\uFF0C\u9002\u5408\u8BB0\u5FC6/\u68C0\u7D22\u8FD9\u7C7B\u300C\u5E38\u9A7B\u3001\u6309\u9700\u89E6\u53D1\u300D\u7684\u5DE5\u5177\uFF08\u9ED8\u8BA4\u542B mcp__openviking\u3001team_task_\uFF09\u3002\u7528\u82F1\u6587\u9017\u53F7\u6216\u6362\u884C\u5206\u9694\u591A\u4E2A\u524D\u7F00\uFF1B\u7559\u7A7A\u5219\u4E0D\u989D\u5916\u4FDD\u7559\u3002",
|
|
113
|
+
narrowMaxLabel: "\u5019\u9009\u5DE5\u5177\u4E0A\u9650",
|
|
114
|
+
narrowMaxHint: "\u4E00\u56DE\u5408\u91CC\u53C2\u4E0E\u5224\u5B9A\u7684\u300C\u53EF\u9009\u5DE5\u5177\u300D\u8D85\u8FC7\u8FD9\u4E2A\u6570\uFF08\u9ED8\u8BA4 20\uFF09\uFF0C\u5C31\u81EA\u52A8\u964D\u7EA7\u4E3A\u4EC5\u89C2\u5BDF\u3001\u4E0D\u771F\u6B63\u6536\u7A84\uFF0C\u907F\u514D\u4E00\u6B21\u585E\u592A\u591A\u5DE5\u5177\u8BA9\u6A21\u578B\u8BEF\u6458\u3002\u53D6\u503C 1\u2013200\uFF0C\u8C03\u5927\u66F4\u503E\u5411\u771F\u6B63\u6536\u7A84\u3002\u6838\u5FC3\u5DE5\u5177\u4E0E\u4FDD\u7559\u524D\u7F00\u547D\u4E2D\u7684\u5DE5\u5177\u4E0D\u8BA1\u5165\u3002",
|
|
115
|
+
narrowThresholdLabel: "\u6458\u9664\u9608\u503C",
|
|
116
|
+
narrowThresholdHint: "\u76F8\u5173\u6027\u6982\u7387\u4F4E\u4E8E\u8FD9\u4E2A\u503C\u624D\u6458\u6389\u5DE5\u5177\uFF08\u9ED8\u8BA4 0.3\uFF09\u3002\u6982\u7387\u63A5\u8FD1 0.5 \u8868\u793A\u6A21\u578B\u62FF\u4E0D\u51C6\u3001\u5E76\u975E\u300C\u4E2D\u7B49\u76F8\u5173\u300D\uFF0C\u6B64\u65F6\u4FDD\u7559\u66F4\u7A33\u59A5\uFF1B\u8C03\u4F4E\u66F4\u4FDD\u5B88\uFF08\u5C11\u6458\u3001\u5B81\u53EF\u591A\u7559\uFF09\uFF0C\u8C03\u9AD8\u66F4\u6FC0\u8FDB\uFF08\u591A\u6458\uFF09\u3002\u53D6\u503C 0\u20131\u3002",
|
|
117
|
+
features: "\u51B3\u7B56\u70B9\u5F00\u5173",
|
|
118
|
+
basicFeatures: "\u57FA\u7840\u529F\u80FD",
|
|
119
|
+
advancedConfig: "\u9AD8\u7EA7\u914D\u7F6E",
|
|
120
|
+
featureGate: "\u5371\u9669\u95E8\u63A7",
|
|
121
|
+
featureGateHint: "\u5173\u95ED\u540E\u4E0D\u518D\u5BF9\u7834\u574F\u6027\u5DE5\u5177\u8C03\u7528\u505A\u62E6\u622A\u8BC4\u4F30\uFF0C\u8C03\u7528\u53EA\u53D7\u5BBF\u4E3B\u539F\u751F\u6743\u9650\u7EA6\u675F\u3002",
|
|
122
|
+
featureCheck: "\u4EA7\u51FA\u81EA\u68C0",
|
|
123
|
+
featureCheckHint: "\u5173\u95ED\u540E\u4E0D\u518D\u5728\u56DE\u5408\u7ED3\u675F\u65F6\u7ED9\u6700\u7EC8\u56DE\u590D\u6253\u5206\u3002",
|
|
124
|
+
featureNarrow: "\u5DE5\u5177\u6536\u7A84",
|
|
125
|
+
featureNarrowHint: "\u5173\u95ED\u540E\u4E0D\u518D\u5728\u56DE\u5408\u5F00\u59CB\u65F6\u8BC4\u4F30\u5DE5\u5177\u76F8\u5173\u6027\u3002\u9632\u5FAA\u73AF\u4E3A\u786E\u5B9A\u6027\u672C\u5730\u4FDD\u62A4\uFF0C\u59CB\u7EC8\u751F\u6548\uFF0C\u4E0D\u5728\u6B64\u5F00\u5173\u8303\u56F4\u3002",
|
|
126
|
+
backend: "\u88C1\u51B3\u540E\u7AEF",
|
|
127
|
+
url: "\u670D\u52A1\u5730\u5740",
|
|
128
|
+
model: "\u6A21\u578B",
|
|
129
|
+
key: "API Key",
|
|
130
|
+
keyHintSaved: "\u5DF2\u4FDD\u5B58\u4E00\u4E2A Key\u3002\u7559\u7A7A\u5E76\u4FDD\u5B58\uFF1D\u6CBF\u7528\u5B83\uFF08\u4E0D\u6539\u52A8\uFF09\uFF1B\u586B\u65B0\u503C\u5E76\u4FDD\u5B58\uFF1D\u8986\u76D6\u5B83\u3002",
|
|
131
|
+
keyHintEmpty: "\u5C1A\u672A\u4FDD\u5B58 Key\u3002\u7559\u7A7A\u5219\u4F7F\u7528\u73AF\u5883\u53D8\u91CF\u91CC\u7684 Key\uFF1B\u586B\u5165\u5219\u4FDD\u5B58\u5230\u672C\u673A\u3002",
|
|
132
|
+
removeKey: "\u5220\u9664\u5DF2\u4FDD\u5B58\u7684 Key",
|
|
133
|
+
removeKeyHint: "\u628A\u672C\u63D2\u4EF6\u4FDD\u5B58\u5728\u672C\u673A\u7684 Key \u6C38\u4E45\u5220\u9664\uFF0C\u4E4B\u540E\u81EA\u52A8\u56DE\u843D\u5230\u73AF\u5883\u53D8\u91CF\u91CC\u7684 Key\uFF1B\u4E0D\u5F71\u54CD\u4F60\u5728\u522B\u5904\u914D\u7F6E\u7684\u51ED\u636E\u3002",
|
|
134
|
+
removeKeyButton: "\u5220\u9664",
|
|
135
|
+
removeKeyConfirm: "\u786E\u5B9A\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 API Key\uFF1F\u5220\u9664\u540E\u5C06\u56DE\u843D\u5230\u73AF\u5883\u53D8\u91CF\u7684 Key\u3002",
|
|
136
|
+
removeKeyDone: "\u5DF2\u5220\u9664\u4FDD\u5B58\u7684 Key",
|
|
137
|
+
save: "\u4FDD\u5B58\u914D\u7F6E",
|
|
138
|
+
saveAdvanced: "\u4FDD\u5B58\u9AD8\u7EA7\u914D\u7F6E",
|
|
139
|
+
probe: "\u6D4B\u8BD5\u8FDE\u63A5",
|
|
140
|
+
saved: "\u914D\u7F6E\u5DF2\u4FDD\u5B58",
|
|
141
|
+
connected: "\u8FDE\u63A5\u6210\u529F",
|
|
142
|
+
unavailable: "\u8FDE\u63A5\u4E0D\u53EF\u7528",
|
|
143
|
+
error: "\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
144
|
+
loading: "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u72B6\u6001",
|
|
145
|
+
capacity: "\u4F1A\u8BDD\u72B6\u6001\u5BB9\u91CF\u5DF2\u6EE1\uFF1A\u6B64\u4F1A\u8BDD\u81EA\u52A8\u4ECB\u5165\u5DF2\u6682\u505C\uFF1B\u64CD\u4F5C\u4ECD\u53D7\u5BBF\u4E3B\u6743\u9650\u7B56\u7565\u7EA6\u675F\u3002",
|
|
146
|
+
destination: "\u88C1\u51B3\u65F6\u4F1A\u5411\u4EE5\u4E0B\u540E\u7AEF\u53D1\u9001\u5FC5\u8981\u7684\u8BC4\u4F30\u4E0A\u4E0B\u6587\uFF1A",
|
|
147
|
+
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"
|
|
148
|
+
},
|
|
149
|
+
en: {
|
|
150
|
+
summary: "A danger-call gate, output self-check, and loop guard driven by a pluggable adjudication model.",
|
|
151
|
+
button: "Decision layer",
|
|
152
|
+
title: "Decision layer",
|
|
153
|
+
close: "Close",
|
|
154
|
+
metrics: "Automatic decisions",
|
|
155
|
+
triggerDecisions: "decisions",
|
|
156
|
+
empty: "No automatic decisions yet. Manual verdicts are not counted here.",
|
|
157
|
+
attempts: "Evaluations",
|
|
158
|
+
failures: "Fallback failures",
|
|
159
|
+
suggestions: "Model suggestions (allow / ask / deny)",
|
|
160
|
+
actual: "Actual host outcomes (allow / deny)",
|
|
161
|
+
checkAttempts: "Self-check evaluations",
|
|
162
|
+
checkLow: "Low",
|
|
163
|
+
checkOk: "Passed",
|
|
164
|
+
settings: "Session settings",
|
|
165
|
+
cardGate: "Danger gate",
|
|
166
|
+
cardCheck: "Output self-check",
|
|
167
|
+
cardNarrow: "Tool narrowing",
|
|
168
|
+
cardTimes: "",
|
|
169
|
+
allow: "Allow",
|
|
170
|
+
ask: "Ask",
|
|
171
|
+
deny: "Deny",
|
|
172
|
+
actualShort: "Actual",
|
|
173
|
+
narrowAppliedLabel: "Narrowed",
|
|
174
|
+
narrowDroppedLabel: "Tools dropped",
|
|
175
|
+
narrowDropped: "dropped",
|
|
176
|
+
narrowKept: "kept all",
|
|
177
|
+
narrowKeptCount: "kept",
|
|
178
|
+
narrowMore: " and {count} in total",
|
|
179
|
+
narrowObserve: "observe",
|
|
180
|
+
narrowEnforce: "enforced",
|
|
181
|
+
checkPassRate: "Pass rate",
|
|
182
|
+
narrowApplyRate: "Narrow rate",
|
|
183
|
+
rateNa: "\u2014",
|
|
184
|
+
enabled: "Enable automatic interventions",
|
|
185
|
+
backendStatus: "Backend",
|
|
186
|
+
statusChecking: "Checking\u2026",
|
|
187
|
+
statusIdle: "Not checked",
|
|
188
|
+
statusOk: "Connected",
|
|
189
|
+
statusDown: "Unavailable",
|
|
190
|
+
recheck: "Recheck",
|
|
191
|
+
log: "Decision log",
|
|
192
|
+
logEmpty: "No decisions recorded for this session yet.",
|
|
193
|
+
logGate: "Gate",
|
|
194
|
+
logCheck: "Self-check",
|
|
195
|
+
logNarrow: "Narrow",
|
|
196
|
+
logSuggested: "model suggested",
|
|
197
|
+
logEvalFailed: "evaluation failed",
|
|
198
|
+
logScore: "score",
|
|
199
|
+
logConnection: "connection",
|
|
200
|
+
logConfidence: "confidence",
|
|
201
|
+
logScoreHint: "The score is a probability-weighted mean across the levels, so it can be fractional (e.g. 1.4); the top score is the highest level number, 2.",
|
|
202
|
+
logCheckHint: "After each turn, the AI\u2019s final reply for that turn is sent to the adjudication model, which grades its quality on three levels (severe omission/contradiction \u2192 minor gaps \u2192 complete and accurate) as a 0\u20132 score, to catch omissions or contradictions.",
|
|
203
|
+
logNarrowHint: "At the start of each turn, the current task and each available tool are sent to the adjudication model (a noul per tool) to judge relevance, dropping tools clearly not needed. It only intersects the host-allowed set and never expands it; observe merely logs the suggestion, enforced actually restricts the tools for this turn.",
|
|
204
|
+
actionDeny: "denied",
|
|
205
|
+
actionAsk: "sent to approval",
|
|
206
|
+
checkResultLow: "low score",
|
|
207
|
+
checkResultOk: "passed",
|
|
208
|
+
reasonUnavailable: "backend unreachable",
|
|
209
|
+
reasonHttpError: "backend returned an error",
|
|
210
|
+
reasonInvalidResponse: "unexpected response shape",
|
|
211
|
+
reasonLowConfidence: "low confidence",
|
|
212
|
+
reasonCapacity: "session state full",
|
|
213
|
+
reasonConfig: "invalid configuration",
|
|
214
|
+
reasonTooMany: "too many candidates",
|
|
215
|
+
reasonTooManyCount: "{count} candidates is too many",
|
|
216
|
+
reasonLowKeep: "too few kept, not enforced",
|
|
217
|
+
selfCheck: "Output self-check",
|
|
218
|
+
advancedSwitches: "Intervention switches",
|
|
219
|
+
advancedParams: "Narrowing parameters",
|
|
220
|
+
selfCheckSteer: "Auto re-prompt on a low score",
|
|
221
|
+
selfCheckHint: "Each turn ends by scoring the final reply (0\u20132, a probability-weighted mean across the levels, so it can be fractional like 1.4). Off: low scores are only logged, the conversation is not interrupted. On: when the score is low (\u22641) and the model is confident enough, one prompt is appended on your behalf asking the AI to review for gaps or contradictions and finish the work; low-confidence scores are only logged, never interrupt, and at most one prompt per turn.",
|
|
222
|
+
narrow: "Tool narrowing",
|
|
223
|
+
narrowObserveLabel: "Observe only (do not restrict tools)",
|
|
224
|
+
narrowHint: "At the start of each turn, the adjudication model judges how relevant each optional tool is to the task and drops the ones not needed; core tools (read, write, edit, shell, search, todos) are always kept and never judged. Enforced by default: only the relevant tools are kept for this turn, intersected with the host-allowed set and never expanded. Turn on Observe only to just log the tools that could be dropped, without changing the tool set. Three safeguards: core tools always kept; more than 20 optional tools falls back to observe only; fewer than 5 tools remaining is treated as untrustworthy and skipped.",
|
|
225
|
+
narrowKeepLabel: "Always-kept tool prefixes",
|
|
226
|
+
narrowKeepHint: "Tools whose names start with any of these prefixes are always kept and never judged for relevance \u2014 good for resident, on-demand tools like memory/retrieval (defaults to mcp__openviking and team_task_). Separate prefixes with commas or newlines; leave empty to keep nothing extra.",
|
|
227
|
+
narrowMaxLabel: "Candidate tool cap",
|
|
228
|
+
narrowMaxHint: "When more than this many optional tools are judged in one turn (default 20), narrowing downgrades to observe only instead of actually restricting, so a large surface is never mass-pruned. Range 1\u2013200; a higher value leans toward actually narrowing. Core tools and keep-prefix matches do not count.",
|
|
229
|
+
narrowThresholdLabel: "Drop threshold",
|
|
230
|
+
narrowThresholdHint: 'A tool is dropped only when its relevance probability is below this value (default 0.3). A probability near 0.5 means the model is unsure, not "moderately relevant", so keeping is safer there; lower is more conservative (drops fewer), higher is more aggressive. Range 0\u20131.',
|
|
231
|
+
features: "Decision points",
|
|
232
|
+
basicFeatures: "Basic features",
|
|
233
|
+
advancedConfig: "Advanced settings",
|
|
234
|
+
featureGate: "Danger gate",
|
|
235
|
+
featureGateHint: "When off, destructive tool calls are no longer evaluated for interception and are only bound by the host permission rules.",
|
|
236
|
+
featureCheck: "Output self-check",
|
|
237
|
+
featureCheckHint: "When off, the final reply is no longer scored at the end of a turn.",
|
|
238
|
+
featureNarrow: "Tool narrowing",
|
|
239
|
+
featureNarrowHint: "When off, tool relevance is no longer evaluated at the start of a turn. The loop guard is a deterministic local safeguard that is always on and not covered by this switch.",
|
|
240
|
+
backend: "Decision backend",
|
|
241
|
+
url: "Server URL",
|
|
242
|
+
model: "Model",
|
|
243
|
+
key: "API key",
|
|
244
|
+
keyHintSaved: "A key is saved. Leave blank and save to keep it; enter a new value and save to overwrite it.",
|
|
245
|
+
keyHintEmpty: "No key saved yet. Leave blank to use an environment credential, or enter one to save it locally.",
|
|
246
|
+
removeKey: "Delete saved API key",
|
|
247
|
+
removeKeyHint: "Permanently deletes the key this plugin stored locally, then falls back to the environment credential; credentials configured elsewhere are untouched.",
|
|
248
|
+
removeKeyButton: "Delete",
|
|
249
|
+
removeKeyConfirm: "Delete the locally saved API key? It will fall back to the environment credential.",
|
|
250
|
+
removeKeyDone: "Saved key deleted",
|
|
251
|
+
save: "Save configuration",
|
|
252
|
+
saveAdvanced: "Save advanced settings",
|
|
253
|
+
probe: "Test connection",
|
|
254
|
+
saved: "Configuration saved",
|
|
255
|
+
connected: "Connected",
|
|
256
|
+
unavailable: "Connection unavailable",
|
|
257
|
+
error: "Request failed. Please retry.",
|
|
258
|
+
loading: "Loading session settings",
|
|
259
|
+
capacity: "Session capacity reached: automatic intervention is paused here; host permission rules still apply.",
|
|
260
|
+
destination: "Decisions send the necessary evaluation context to this backend:",
|
|
261
|
+
httpWarning: "This address uses unencrypted HTTP. Your API key and evaluation context will be sent in plaintext to this address."
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/client/panel.tsx
|
|
266
|
+
var import_react = require("react");
|
|
267
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
268
|
+
var api = "/plugins/dsh-decision-layer/api";
|
|
269
|
+
async function request(path, init) {
|
|
270
|
+
const response = await fetch(`${api}/${path}`, init);
|
|
271
|
+
const body = await response.json();
|
|
272
|
+
if (!response.ok || !body.ok || body.value === void 0) throw new Error(body.error || "Request failed");
|
|
273
|
+
return body.value;
|
|
274
|
+
}
|
|
275
|
+
function DecisionPanel(props) {
|
|
276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionPanel, { ...props }, props.sessionId);
|
|
277
|
+
}
|
|
278
|
+
function Bar({ allow, ask, deny }) {
|
|
279
|
+
const total = allow + ask + deny;
|
|
280
|
+
if (total === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "decision-bar decision-bar-empty", "aria-hidden": "true" });
|
|
281
|
+
const pct = (n) => `${n / total * 100}%`;
|
|
282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-bar", "aria-hidden": "true", children: [
|
|
283
|
+
allow > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-bar-allow", style: { width: pct(allow) } }),
|
|
284
|
+
ask > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-bar-ask", style: { width: pct(ask) } }),
|
|
285
|
+
deny > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-bar-deny", style: { width: pct(deny) } })
|
|
286
|
+
] });
|
|
287
|
+
}
|
|
288
|
+
function SessionPanel({ sessionId, t }) {
|
|
289
|
+
const dialog = (0, import_react.useRef)(null);
|
|
290
|
+
const trigger = (0, import_react.useRef)(null);
|
|
291
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
292
|
+
const [enabled, setEnabled] = (0, import_react.useState)(null);
|
|
293
|
+
const [capacityExceeded, setCapacityExceeded] = (0, import_react.useState)(false);
|
|
294
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
295
|
+
const [metrics, setMetrics] = (0, import_react.useState)(null);
|
|
296
|
+
const [log, setLog] = (0, import_react.useState)([]);
|
|
297
|
+
const [status, setStatus] = (0, import_react.useState)("idle");
|
|
298
|
+
const [message, setMessage] = (0, import_react.useState)("");
|
|
299
|
+
(0, import_react.useEffect)(() => {
|
|
300
|
+
let live = true;
|
|
301
|
+
void request(`session?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
302
|
+
if (live) {
|
|
303
|
+
setEnabled(value.enabled);
|
|
304
|
+
setCapacityExceeded(Boolean(value.capacityExceeded));
|
|
305
|
+
}
|
|
306
|
+
}).catch(() => {
|
|
307
|
+
if (live) setMessage(t("error"));
|
|
308
|
+
});
|
|
309
|
+
void request(`metrics?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
310
|
+
if (live) setMetrics(value);
|
|
311
|
+
}).catch(() => {
|
|
312
|
+
});
|
|
313
|
+
return () => {
|
|
314
|
+
live = false;
|
|
315
|
+
};
|
|
316
|
+
}, [sessionId, t]);
|
|
317
|
+
const checkStatus = (live) => {
|
|
318
|
+
setStatus("checking");
|
|
319
|
+
void request("probe", { method: "POST" }).then((value) => {
|
|
320
|
+
if (!live()) return;
|
|
321
|
+
setStatus(value.connected ? "ok" : "down");
|
|
322
|
+
}).catch(() => {
|
|
323
|
+
if (live()) setStatus("down");
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
(0, import_react.useEffect)(() => {
|
|
327
|
+
if (!open) return;
|
|
328
|
+
const element = dialog.current;
|
|
329
|
+
if (!element) return;
|
|
330
|
+
if (!element.open) element.showModal();
|
|
331
|
+
let alive = true;
|
|
332
|
+
setMessage("");
|
|
333
|
+
void request(`metrics?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
334
|
+
if (alive) setMetrics(value);
|
|
335
|
+
}).catch(() => {
|
|
336
|
+
});
|
|
337
|
+
void request(`log?sessionId=${encodeURIComponent(sessionId)}`).then((value) => {
|
|
338
|
+
if (alive) setLog(value.entries);
|
|
339
|
+
}).catch(() => {
|
|
340
|
+
});
|
|
341
|
+
return () => {
|
|
342
|
+
alive = false;
|
|
343
|
+
element.close();
|
|
344
|
+
};
|
|
345
|
+
}, [open, t, sessionId]);
|
|
346
|
+
const updateEnabled = async (next) => {
|
|
347
|
+
setBusy(true);
|
|
348
|
+
try {
|
|
349
|
+
const value = await request("session", {
|
|
350
|
+
method: "PUT",
|
|
351
|
+
headers: { "content-type": "application/json" },
|
|
352
|
+
body: JSON.stringify({ sessionId, enabled: next })
|
|
353
|
+
});
|
|
354
|
+
setEnabled(value.enabled);
|
|
355
|
+
setCapacityExceeded(Boolean(value.capacityExceeded));
|
|
356
|
+
} catch {
|
|
357
|
+
setMessage(t("error"));
|
|
358
|
+
} finally {
|
|
359
|
+
setBusy(false);
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
const time = (at) => new Date(at).toLocaleTimeString();
|
|
363
|
+
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 === "capacity" ? t("reasonCapacity") : reason === "too-many-candidates" ? t("reasonTooMany") : reason === "low-keep" ? t("reasonLowKeep") : reason === "config" ? t("reasonConfig") : reason;
|
|
364
|
+
const actionText = (action) => action === "deny" ? t("actionDeny") : action === "ask" ? t("actionAsk") : action;
|
|
365
|
+
const failDetail = (entry) => {
|
|
366
|
+
const reason = reasonText(entry.reason);
|
|
367
|
+
if (entry.reason === "low-confidence" && typeof entry.confidence === "number") return `${reason}\uFF08${t("logConfidence")} ${entry.confidence}\uFF09`;
|
|
368
|
+
return reason;
|
|
369
|
+
};
|
|
370
|
+
const outcomeTag = (entry) => entry.outcome === "deny" ? "deny" : entry.outcome === "error" ? "error" : entry.outcome === "low" ? "warn" : "ok";
|
|
371
|
+
const renderGate = (entry) => {
|
|
372
|
+
const tool = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: "decision-log-tool", children: entry.tool ?? "\u2014" });
|
|
373
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
374
|
+
t("logGate"),
|
|
375
|
+
" \xB7 ",
|
|
376
|
+
tool,
|
|
377
|
+
" ",
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
379
|
+
t("logEvalFailed"),
|
|
380
|
+
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
381
|
+
] })
|
|
382
|
+
] });
|
|
383
|
+
const verdict = entry.outcome === "deny" ? t("actionDeny") : actionText(entry.action) ?? entry.outcome;
|
|
384
|
+
const suggestion = entry.suggestion && entry.suggestion !== entry.action ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
385
|
+
" \xB7 ",
|
|
386
|
+
t("logSuggested"),
|
|
387
|
+
" ",
|
|
388
|
+
actionText(entry.suggestion)
|
|
389
|
+
] }) : null;
|
|
390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
391
|
+
t("logGate"),
|
|
392
|
+
" \xB7 ",
|
|
393
|
+
tool,
|
|
394
|
+
" ",
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
396
|
+
"\u2192 ",
|
|
397
|
+
verdict
|
|
398
|
+
] }),
|
|
399
|
+
suggestion
|
|
400
|
+
] });
|
|
401
|
+
};
|
|
402
|
+
const renderCheck = (entry) => {
|
|
403
|
+
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logCheckHint"), children: t("logCheck") });
|
|
404
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
405
|
+
label,
|
|
406
|
+
" ",
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
408
|
+
t("logEvalFailed"),
|
|
409
|
+
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
410
|
+
] })
|
|
411
|
+
] });
|
|
412
|
+
const result = entry.outcome === "low" ? t("checkResultLow") : t("checkResultOk");
|
|
413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
414
|
+
label,
|
|
415
|
+
" \xB7 ",
|
|
416
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: result }),
|
|
417
|
+
entry.score !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", title: t("logScoreHint"), children: [
|
|
418
|
+
" \xB7 ",
|
|
419
|
+
t("logScore"),
|
|
420
|
+
" ",
|
|
421
|
+
entry.score,
|
|
422
|
+
"/2"
|
|
423
|
+
] }) : null,
|
|
424
|
+
typeof entry.confidence === "number" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
425
|
+
" \xB7 ",
|
|
426
|
+
t("logConfidence"),
|
|
427
|
+
" ",
|
|
428
|
+
entry.confidence
|
|
429
|
+
] }) : null
|
|
430
|
+
] });
|
|
431
|
+
};
|
|
432
|
+
const renderNarrow = (entry) => {
|
|
433
|
+
const label = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: t("logNarrowHint"), children: t("logNarrow") });
|
|
434
|
+
if (entry.outcome === "error") return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
435
|
+
label,
|
|
436
|
+
" ",
|
|
437
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
438
|
+
t("logEvalFailed"),
|
|
439
|
+
entry.reason ? ` \xB7 ${failDetail(entry)}` : ""
|
|
440
|
+
] })
|
|
441
|
+
] });
|
|
442
|
+
const dropped = entry.dropped ?? 0;
|
|
443
|
+
const kept = typeof entry.kept === "number" ? entry.kept : void 0;
|
|
444
|
+
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;
|
|
445
|
+
const guard = guardText ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
446
|
+
" \xB7 ",
|
|
447
|
+
guardText
|
|
448
|
+
] }) : null;
|
|
449
|
+
const modeTag = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
450
|
+
" \xB7 ",
|
|
451
|
+
entry.mode === "enforce" ? t("narrowEnforce") : t("narrowObserve")
|
|
452
|
+
] });
|
|
453
|
+
if (dropped === 0) {
|
|
454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
455
|
+
label,
|
|
456
|
+
" \xB7 ",
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-verdict", children: t("narrowKept") }),
|
|
458
|
+
kept !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
459
|
+
" \xB7 ",
|
|
460
|
+
t("narrowKeptCount"),
|
|
461
|
+
" ",
|
|
462
|
+
kept
|
|
463
|
+
] }) : null,
|
|
464
|
+
guard,
|
|
465
|
+
modeTag
|
|
466
|
+
] });
|
|
467
|
+
}
|
|
468
|
+
const names = Array.isArray(entry.tools) && entry.tools.length > 0 ? entry.tools.join("\u3001") : void 0;
|
|
469
|
+
const overflow = names && Array.isArray(entry.tools) && entry.tools.length < dropped ? t("narrowMore", { count: dropped }) : "";
|
|
470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
471
|
+
label,
|
|
472
|
+
" \xB7 ",
|
|
473
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-verdict", children: [
|
|
474
|
+
t("narrowDropped"),
|
|
475
|
+
" ",
|
|
476
|
+
dropped,
|
|
477
|
+
kept !== void 0 ? ` / ${t("narrowKeptCount")} ${kept}` : ""
|
|
478
|
+
] }),
|
|
479
|
+
names ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-log-detail", children: [
|
|
480
|
+
" \xB7 ",
|
|
481
|
+
names,
|
|
482
|
+
overflow
|
|
483
|
+
] }) : null,
|
|
484
|
+
guard,
|
|
485
|
+
modeTag
|
|
486
|
+
] });
|
|
487
|
+
};
|
|
488
|
+
const outcomeTagOf = (entry) => entry.kind === "narrow" ? entry.outcome === "error" ? "error" : entry.outcome === "applied" ? "ok" : "ok" : outcomeTag(entry);
|
|
489
|
+
const statusLabel = status === "ok" ? t("statusOk") : status === "down" ? t("statusDown") : status === "checking" ? t("statusChecking") : t("statusIdle");
|
|
490
|
+
const attempts = metrics?.attempts ?? 0;
|
|
491
|
+
const checkValid = metrics?.check ? metrics.check.attempts - metrics.check.failures : 0;
|
|
492
|
+
const checkPassRate = metrics?.check && checkValid > 0 ? Math.round((checkValid - metrics.check.low) / checkValid * 100) : null;
|
|
493
|
+
const narrowValid = metrics?.narrow ? metrics.narrow.attempts - metrics.narrow.failures : 0;
|
|
494
|
+
const narrowApplyRate = metrics?.narrow && narrowValid > 0 ? Math.round(metrics.narrow.applied / narrowValid * 100) : null;
|
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
496
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { ref: trigger, className: "decision-trigger", type: "button", "aria-haspopup": "dialog", "aria-expanded": open, "aria-busy": enabled === null, "aria-label": t("button"), onClick: () => setOpen(true), children: [
|
|
497
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "decision-trigger-icon", width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
|
|
498
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 1.5 2 4.2v3.6c0 3.3 2.3 5.6 6 6.7 3.7-1.1 6-3.4 6-6.7V4.2L8 1.5Z", stroke: "currentColor", "stroke-width": "1.3", "stroke-linejoin": "round" }),
|
|
499
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m5.6 8 1.7 1.8L10.6 6.3", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round", "stroke-linejoin": "round" })
|
|
500
|
+
] }),
|
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-trigger-text", children: [
|
|
502
|
+
t("triggerDecisions"),
|
|
503
|
+
" ",
|
|
504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: attempts })
|
|
505
|
+
] })
|
|
506
|
+
] }),
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
508
|
+
"dialog",
|
|
509
|
+
{
|
|
510
|
+
ref: dialog,
|
|
511
|
+
className: "decision-dialog",
|
|
512
|
+
"aria-labelledby": "decision-panel-title",
|
|
513
|
+
onKeyDown: (event) => {
|
|
514
|
+
if (event.key === "Escape") {
|
|
515
|
+
event.stopPropagation();
|
|
516
|
+
event.preventDefault();
|
|
517
|
+
dialog.current?.close();
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
onCancel: (event) => {
|
|
521
|
+
event.preventDefault();
|
|
522
|
+
dialog.current?.close();
|
|
523
|
+
},
|
|
524
|
+
onClick: (event) => {
|
|
525
|
+
if (event.target === dialog.current) dialog.current?.close();
|
|
526
|
+
},
|
|
527
|
+
onClose: () => {
|
|
528
|
+
setOpen(false);
|
|
529
|
+
trigger.current?.focus();
|
|
530
|
+
},
|
|
531
|
+
children: [
|
|
532
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-head", children: [
|
|
533
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "decision-panel-title", children: t("title") }),
|
|
534
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => {
|
|
535
|
+
dialog.current?.close();
|
|
536
|
+
}, "aria-label": t("close"), children: "\xD7" })
|
|
537
|
+
] }),
|
|
538
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-body", children: [
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
540
|
+
enabled === null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: t("loading") }),
|
|
541
|
+
capacityExceeded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", children: t("capacity") }),
|
|
542
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "decision-toggle", children: [
|
|
543
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-toggle-text", children: t("enabled") }),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
545
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
546
|
+
"input",
|
|
547
|
+
{
|
|
548
|
+
className: "decision-toggle-input",
|
|
549
|
+
type: "checkbox",
|
|
550
|
+
checked: enabled === true,
|
|
551
|
+
disabled: busy || enabled === null || capacityExceeded,
|
|
552
|
+
onChange: (event) => void updateEnabled(event.target.checked)
|
|
553
|
+
}
|
|
554
|
+
),
|
|
555
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
556
|
+
] })
|
|
557
|
+
] }),
|
|
558
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-status", children: [
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `decision-status-dot decision-status-${status}`, "aria-hidden": "true" }),
|
|
560
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-status-label", children: [
|
|
561
|
+
t("backendStatus"),
|
|
562
|
+
"\uFF1A",
|
|
563
|
+
statusLabel
|
|
564
|
+
] }),
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "decision-status-recheck", disabled: status === "checking", onClick: () => checkStatus(() => true), children: t("recheck") })
|
|
566
|
+
] })
|
|
567
|
+
] }),
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: t("metrics") }),
|
|
570
|
+
!metrics?.gate && !metrics?.check && !metrics?.narrow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "decision-empty", role: "status", children: t("empty") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-cards", children: [
|
|
571
|
+
metrics.gate && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { className: "decision-card decision-card-wide", children: [
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "decision-card-head", children: [
|
|
573
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-card-title", children: t("cardGate") }),
|
|
574
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-card-total", children: [
|
|
575
|
+
metrics.gate.attempts,
|
|
576
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: t("cardTimes") })
|
|
577
|
+
] })
|
|
578
|
+
] }),
|
|
579
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bar, { allow: metrics.gate.allow, ask: metrics.gate.ask, deny: metrics.gate.deny }),
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { className: "decision-legend", children: [
|
|
581
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-legend-dot decision-dot-allow", "aria-hidden": "true" }),
|
|
583
|
+
t("allow"),
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: metrics.gate.allow })
|
|
585
|
+
] }),
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-legend-dot decision-dot-ask", "aria-hidden": "true" }),
|
|
588
|
+
t("ask"),
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: metrics.gate.ask })
|
|
590
|
+
] }),
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-legend-dot decision-dot-deny", "aria-hidden": "true" }),
|
|
593
|
+
t("deny"),
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: metrics.gate.deny })
|
|
595
|
+
] })
|
|
596
|
+
] }),
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", { className: "decision-card-foot", children: [
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
599
|
+
t("actualShort"),
|
|
600
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("b", { children: [
|
|
601
|
+
metrics.gate.actual.allow,
|
|
602
|
+
" / ",
|
|
603
|
+
metrics.gate.actual.deny
|
|
604
|
+
] })
|
|
605
|
+
] }),
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
607
|
+
t("failures"),
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: metrics.gate.failures })
|
|
609
|
+
] })
|
|
610
|
+
] })
|
|
611
|
+
] }),
|
|
612
|
+
metrics.check && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { className: "decision-card", children: [
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "decision-card-head", children: [
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-card-title", children: t("cardCheck") }),
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-card-total", children: [
|
|
616
|
+
metrics.check.attempts,
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: t("cardTimes") })
|
|
618
|
+
] })
|
|
619
|
+
] }),
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-card-stats", children: [
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num decision-stat-warn", children: metrics.check.low }),
|
|
623
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("checkLow") })
|
|
624
|
+
] }),
|
|
625
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num", children: metrics.check.attempts - metrics.check.low - metrics.check.failures }),
|
|
627
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("checkOk") })
|
|
628
|
+
] }),
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
630
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.check.failures }),
|
|
631
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
632
|
+
] })
|
|
633
|
+
] }),
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { className: "decision-card-foot decision-card-rate", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
635
|
+
t("checkPassRate"),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: checkPassRate === null ? t("rateNa") : `${checkPassRate}%` })
|
|
637
|
+
] }) })
|
|
638
|
+
] }),
|
|
639
|
+
metrics.narrow && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { className: "decision-card", children: [
|
|
640
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "decision-card-head", children: [
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-card-title", children: t("cardNarrow") }),
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "decision-card-total", children: [
|
|
643
|
+
metrics.narrow.attempts,
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: t("cardTimes") })
|
|
645
|
+
] })
|
|
646
|
+
] }),
|
|
647
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-card-stats", children: [
|
|
648
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
649
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.applied }),
|
|
650
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("narrowAppliedLabel") })
|
|
651
|
+
] }),
|
|
652
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
653
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num", children: metrics.narrow.dropped }),
|
|
654
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("narrowDroppedLabel") })
|
|
655
|
+
] }),
|
|
656
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "decision-stat", children: [
|
|
657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-num decision-stat-muted", children: metrics.narrow.failures }),
|
|
658
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-stat-label", children: t("failures") })
|
|
659
|
+
] })
|
|
660
|
+
] }),
|
|
661
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { className: "decision-card-foot decision-card-rate", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
662
|
+
t("narrowApplyRate"),
|
|
663
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: narrowApplyRate === null ? t("rateNa") : `${narrowApplyRate}%` })
|
|
664
|
+
] }) })
|
|
665
|
+
] })
|
|
666
|
+
] })
|
|
667
|
+
] }),
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: t("log") }),
|
|
670
|
+
log.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "decision-empty", role: "status", children: t("logEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "decision-log", children: log.slice().reverse().map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: `decision-log-item decision-log-${outcomeTagOf(entry)}`, children: [
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-time", children: time(entry.at) }),
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "decision-log-body", children: entry.kind === "gate" ? renderGate(entry) : entry.kind === "narrow" ? renderNarrow(entry) : renderCheck(entry) })
|
|
673
|
+
] }, `${entry.at}-${index}`)) })
|
|
674
|
+
] }),
|
|
675
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: "decision-message decision-message-warn", children: message })
|
|
676
|
+
] })
|
|
677
|
+
]
|
|
678
|
+
}
|
|
679
|
+
)
|
|
680
|
+
] });
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// src/client/config-form.tsx
|
|
684
|
+
var import_react2 = require("react");
|
|
685
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
686
|
+
var api2 = "/plugins/dsh-decision-layer/api";
|
|
687
|
+
async function request2(path, fetchFn, init) {
|
|
688
|
+
const response = await fetchFn(`${api2}/${path}`, init);
|
|
689
|
+
const body = await response.json();
|
|
690
|
+
if (!response.ok || !body.ok || body.value === void 0) throw new Error(body.error || "Request failed");
|
|
691
|
+
return body.value;
|
|
692
|
+
}
|
|
693
|
+
var DEFAULT_KEEP_PREFIXES = ["mcp__openviking", "team_task_"];
|
|
694
|
+
var DEFAULT_MAX_CANDIDATES = 20;
|
|
695
|
+
var DEFAULT_THRESHOLD = 0.3;
|
|
696
|
+
var parsePrefixes = (text) => Array.from(new Set(text.split(/[,\r\n]+/).map((line) => line.trim()).filter(Boolean)));
|
|
697
|
+
var prefixesText = (settings) => (settings?.keepPrefixes ?? DEFAULT_KEEP_PREFIXES).join("\n");
|
|
698
|
+
var maxCandidatesOf = (settings) => settings?.maxCandidates ?? DEFAULT_MAX_CANDIDATES;
|
|
699
|
+
var thresholdOf = (settings) => settings?.threshold ?? DEFAULT_THRESHOLD;
|
|
700
|
+
function HeadIcon({ name }) {
|
|
701
|
+
const glyphs = {
|
|
702
|
+
features: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2", y: "3", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "11.9", cy: "5.1", r: "1.25", fill: "currentColor" }),
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2", y: "8.8", width: "12", height: "4.2", rx: "2.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "4.1", cy: "10.9", r: "1.25", fill: "currentColor" })
|
|
707
|
+
] }),
|
|
708
|
+
advanced: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2.5 5h11M2.5 11h11", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round" }),
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "10.5", cy: "5", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
711
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5.5", cy: "11", r: "1.9", fill: "var(--dsw-alias-bg-layer-2,#fff)", stroke: "currentColor", "stroke-width": "1.3" })
|
|
712
|
+
] }),
|
|
713
|
+
backend: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
714
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2.3", y: "2.6", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
715
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2.3", y: "8.8", width: "11.4", height: "4.6", rx: "1.1", stroke: "currentColor", "stroke-width": "1.3" }),
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "4.9", r: ".7", fill: "currentColor" }),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "11.1", r: ".7", fill: "currentColor" })
|
|
718
|
+
] })
|
|
719
|
+
};
|
|
720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `decision-head-icon decision-head-icon-${name}`, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", children: glyphs[name] }) });
|
|
721
|
+
}
|
|
722
|
+
function Toggle({ label, checked, disabled, onChange }) {
|
|
723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-toggle", children: [
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-toggle-text", children: label }),
|
|
725
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "decision-toggle-box", children: [
|
|
726
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
727
|
+
"input",
|
|
728
|
+
{
|
|
729
|
+
className: "decision-toggle-input",
|
|
730
|
+
type: "checkbox",
|
|
731
|
+
checked,
|
|
732
|
+
disabled,
|
|
733
|
+
onChange: (event) => onChange(event.target.checked)
|
|
734
|
+
}
|
|
735
|
+
),
|
|
736
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-toggle-track", "aria-hidden": "true" })
|
|
737
|
+
] })
|
|
738
|
+
] });
|
|
739
|
+
}
|
|
740
|
+
function ConfigForm({ t, fetchFn = fetch }) {
|
|
741
|
+
const [config, setConfig] = (0, import_react2.useState)({ url: "", model: "", apiKeySet: false, httpApprovedUrl: "", effectiveUrl: "https://api.typesafe.ai" });
|
|
742
|
+
const [checkMode, setCheckMode] = (0, import_react2.useState)("observe");
|
|
743
|
+
const [narrowMode, setNarrowMode] = (0, import_react2.useState)("enforce");
|
|
744
|
+
const [keepPrefixes, setKeepPrefixes] = (0, import_react2.useState)(DEFAULT_KEEP_PREFIXES.join("\n"));
|
|
745
|
+
const [maxCandidates, setMaxCandidates] = (0, import_react2.useState)(String(DEFAULT_MAX_CANDIDATES));
|
|
746
|
+
const [threshold, setThreshold] = (0, import_react2.useState)(String(DEFAULT_THRESHOLD));
|
|
747
|
+
const [gateOn, setGateOn] = (0, import_react2.useState)(true);
|
|
748
|
+
const [checkOn, setCheckOn] = (0, import_react2.useState)(true);
|
|
749
|
+
const [narrowOn, setNarrowOn] = (0, import_react2.useState)(true);
|
|
750
|
+
const [key, setKey] = (0, import_react2.useState)("");
|
|
751
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
752
|
+
const [advancedDirty, setAdvancedDirty] = (0, import_react2.useState)(false);
|
|
753
|
+
const [backendDirty, setBackendDirty] = (0, import_react2.useState)(false);
|
|
754
|
+
const [ready, setReady] = (0, import_react2.useState)(false);
|
|
755
|
+
const [message, setMessage] = (0, import_react2.useState)(null);
|
|
756
|
+
const [probeResult, setProbeResult] = (0, import_react2.useState)(null);
|
|
757
|
+
const applyFeatures = (features) => {
|
|
758
|
+
setGateOn(features?.gate !== false);
|
|
759
|
+
setCheckOn(features?.check !== false);
|
|
760
|
+
setNarrowOn(features?.narrow !== false);
|
|
761
|
+
};
|
|
762
|
+
const applyConfig = (value) => {
|
|
763
|
+
setConfig(value);
|
|
764
|
+
setCheckMode(value.checkSettings?.mode ?? "observe");
|
|
765
|
+
setNarrowMode(value.narrowSettings?.mode ?? "enforce");
|
|
766
|
+
setKeepPrefixes(prefixesText(value.narrowSettings));
|
|
767
|
+
setMaxCandidates(String(maxCandidatesOf(value.narrowSettings)));
|
|
768
|
+
setThreshold(String(thresholdOf(value.narrowSettings)));
|
|
769
|
+
applyFeatures(value.features);
|
|
770
|
+
};
|
|
771
|
+
(0, import_react2.useEffect)(() => {
|
|
772
|
+
let live = true;
|
|
773
|
+
setMessage(null);
|
|
774
|
+
setReady(false);
|
|
775
|
+
void request2("config", fetchFn).then((value) => {
|
|
776
|
+
if (live) {
|
|
777
|
+
applyConfig(value);
|
|
778
|
+
setAdvancedDirty(false);
|
|
779
|
+
setBackendDirty(false);
|
|
780
|
+
setReady(true);
|
|
781
|
+
}
|
|
782
|
+
}).catch(() => {
|
|
783
|
+
if (live) setMessage({ text: t("error"), ok: false });
|
|
784
|
+
});
|
|
785
|
+
return () => {
|
|
786
|
+
live = false;
|
|
787
|
+
};
|
|
788
|
+
}, [t, fetchFn]);
|
|
789
|
+
const saveAdvanced = async (event) => {
|
|
790
|
+
event.preventDefault();
|
|
791
|
+
const parsedCap = Number.parseInt(maxCandidates, 10);
|
|
792
|
+
const cap = Number.isFinite(parsedCap) ? Math.min(200, Math.max(1, parsedCap)) : DEFAULT_MAX_CANDIDATES;
|
|
793
|
+
const parsedThreshold = Number.parseFloat(threshold);
|
|
794
|
+
const thresh = Number.isFinite(parsedThreshold) ? Math.min(1, Math.max(0, parsedThreshold)) : DEFAULT_THRESHOLD;
|
|
795
|
+
setBusy(true);
|
|
796
|
+
try {
|
|
797
|
+
const value = await request2("config", fetchFn, {
|
|
798
|
+
method: "PUT",
|
|
799
|
+
headers: { "content-type": "application/json" },
|
|
800
|
+
body: JSON.stringify({
|
|
801
|
+
checkSettings: { mode: checkMode },
|
|
802
|
+
narrowSettings: { mode: narrowMode, keepPrefixes: parsePrefixes(keepPrefixes), maxCandidates: cap, threshold: thresh },
|
|
803
|
+
features: { gate: gateOn, check: checkOn, narrow: narrowOn }
|
|
804
|
+
})
|
|
805
|
+
});
|
|
806
|
+
applyConfig(value);
|
|
807
|
+
setAdvancedDirty(false);
|
|
808
|
+
setMessage({ text: t("saved"), ok: true });
|
|
809
|
+
} catch {
|
|
810
|
+
setMessage({ text: t("error"), ok: false });
|
|
811
|
+
} finally {
|
|
812
|
+
setBusy(false);
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
const saveBackend = async (event) => {
|
|
816
|
+
event.preventDefault();
|
|
817
|
+
const url = config.url.trim();
|
|
818
|
+
const needsHttpConsent = url.startsWith("http://") && url !== config.httpApprovedUrl;
|
|
819
|
+
if (needsHttpConsent && !window.confirm(`${t("httpWarning")}
|
|
820
|
+
${url}`)) return;
|
|
821
|
+
setBusy(true);
|
|
822
|
+
try {
|
|
823
|
+
const value = await request2("config", fetchFn, {
|
|
824
|
+
method: "PUT",
|
|
825
|
+
headers: { "content-type": "application/json" },
|
|
826
|
+
body: JSON.stringify({
|
|
827
|
+
url,
|
|
828
|
+
model: config.model,
|
|
829
|
+
...key ? { apiKey: key } : {},
|
|
830
|
+
...needsHttpConsent ? { confirmHttpUrl: url } : {}
|
|
831
|
+
})
|
|
832
|
+
});
|
|
833
|
+
applyConfig(value);
|
|
834
|
+
setKey("");
|
|
835
|
+
setBackendDirty(false);
|
|
836
|
+
setMessage({ text: t("saved"), ok: true });
|
|
837
|
+
} catch {
|
|
838
|
+
setMessage({ text: t("error"), ok: false });
|
|
839
|
+
} finally {
|
|
840
|
+
setBusy(false);
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
const probe = async () => {
|
|
844
|
+
setBusy(true);
|
|
845
|
+
setProbeResult(null);
|
|
846
|
+
try {
|
|
847
|
+
const value = await request2("probe", fetchFn, { method: "POST" });
|
|
848
|
+
setProbeResult({ text: t(value.connected ? "connected" : "unavailable"), ok: value.connected });
|
|
849
|
+
} catch {
|
|
850
|
+
setProbeResult({ text: t("error"), ok: false });
|
|
851
|
+
} finally {
|
|
852
|
+
setBusy(false);
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
const removeSavedKey = async () => {
|
|
856
|
+
if (!window.confirm(t("removeKeyConfirm"))) return;
|
|
857
|
+
setBusy(true);
|
|
858
|
+
try {
|
|
859
|
+
const value = await request2("config", fetchFn, {
|
|
860
|
+
method: "PUT",
|
|
861
|
+
headers: { "content-type": "application/json" },
|
|
862
|
+
body: JSON.stringify({ apiKey: "" })
|
|
863
|
+
});
|
|
864
|
+
setConfig(value);
|
|
865
|
+
setKey("");
|
|
866
|
+
setMessage({ text: t("removeKeyDone"), ok: true });
|
|
867
|
+
} catch {
|
|
868
|
+
setMessage({ text: t("error"), ok: false });
|
|
869
|
+
} finally {
|
|
870
|
+
setBusy(false);
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-config", children: [
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: "decision-collapse", open: true, children: [
|
|
875
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
876
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { children: [
|
|
877
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(HeadIcon, { name: "features" }),
|
|
878
|
+
t("basicFeatures")
|
|
879
|
+
] }),
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
881
|
+
] }),
|
|
882
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-collapse-body", children: [
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
884
|
+
Toggle,
|
|
885
|
+
{
|
|
886
|
+
label: t("featureGate"),
|
|
887
|
+
checked: gateOn,
|
|
888
|
+
disabled: !ready,
|
|
889
|
+
onChange: (next) => {
|
|
890
|
+
setGateOn(next);
|
|
891
|
+
setAdvancedDirty(true);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
),
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted", children: t("featureGateHint") }),
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
897
|
+
Toggle,
|
|
898
|
+
{
|
|
899
|
+
label: t("featureCheck"),
|
|
900
|
+
checked: checkOn,
|
|
901
|
+
disabled: !ready,
|
|
902
|
+
onChange: (next) => {
|
|
903
|
+
setCheckOn(next);
|
|
904
|
+
setAdvancedDirty(true);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
),
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted", children: t("featureCheckHint") }),
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
910
|
+
Toggle,
|
|
911
|
+
{
|
|
912
|
+
label: t("featureNarrow"),
|
|
913
|
+
checked: narrowOn,
|
|
914
|
+
disabled: !ready,
|
|
915
|
+
onChange: (next) => {
|
|
916
|
+
setNarrowOn(next);
|
|
917
|
+
setAdvancedDirty(true);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
),
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted", children: t("featureNarrowHint") })
|
|
922
|
+
] })
|
|
923
|
+
] }),
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: "decision-collapse", children: [
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("summary", { className: "decision-collapse-head", children: [
|
|
926
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { children: [
|
|
927
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(HeadIcon, { name: "advanced" }),
|
|
928
|
+
t("advancedConfig")
|
|
929
|
+
] }),
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-collapse-icon", "aria-hidden": "true" })
|
|
931
|
+
] }),
|
|
932
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { className: "decision-collapse-body", onSubmit: (event) => void saveAdvanced(event), children: [
|
|
933
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-advanced-grid", children: [
|
|
934
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-field-block", children: [
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-subhead", children: t("advancedSwitches") }),
|
|
936
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
937
|
+
Toggle,
|
|
938
|
+
{
|
|
939
|
+
label: t("selfCheckSteer"),
|
|
940
|
+
checked: checkMode === "steer",
|
|
941
|
+
disabled: !ready || !checkOn,
|
|
942
|
+
onChange: (next) => {
|
|
943
|
+
setCheckMode(next ? "steer" : "observe");
|
|
944
|
+
setAdvancedDirty(true);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
),
|
|
948
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted", children: t("selfCheckHint") }),
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
950
|
+
Toggle,
|
|
951
|
+
{
|
|
952
|
+
label: t("narrowObserveLabel"),
|
|
953
|
+
checked: narrowMode === "observe",
|
|
954
|
+
disabled: !ready || !narrowOn,
|
|
955
|
+
onChange: (next) => {
|
|
956
|
+
setNarrowMode(next ? "observe" : "enforce");
|
|
957
|
+
setAdvancedDirty(true);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "decision-muted", children: t("narrowHint") })
|
|
962
|
+
] }),
|
|
963
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-field-block", children: [
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-subhead", children: t("advancedParams") }),
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field", children: [
|
|
966
|
+
t("narrowKeepLabel"),
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
968
|
+
"textarea",
|
|
969
|
+
{
|
|
970
|
+
className: "decision-prefixes",
|
|
971
|
+
rows: 3,
|
|
972
|
+
value: keepPrefixes,
|
|
973
|
+
disabled: !ready || !narrowOn,
|
|
974
|
+
placeholder: "mcp__openviking",
|
|
975
|
+
onChange: (event) => {
|
|
976
|
+
setKeepPrefixes(event.target.value);
|
|
977
|
+
setAdvancedDirty(true);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
),
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { className: "decision-muted", children: t("narrowKeepHint") })
|
|
982
|
+
] }),
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
984
|
+
t("narrowMaxLabel"),
|
|
985
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
986
|
+
"input",
|
|
987
|
+
{
|
|
988
|
+
className: "decision-narrow-cap",
|
|
989
|
+
type: "number",
|
|
990
|
+
min: 1,
|
|
991
|
+
max: 200,
|
|
992
|
+
step: 1,
|
|
993
|
+
value: maxCandidates,
|
|
994
|
+
disabled: !ready || !narrowOn,
|
|
995
|
+
placeholder: "20",
|
|
996
|
+
onChange: (event) => {
|
|
997
|
+
setMaxCandidates(event.target.value);
|
|
998
|
+
setAdvancedDirty(true);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
),
|
|
1002
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { className: "decision-muted", children: t("narrowMaxHint") })
|
|
1003
|
+
] }),
|
|
1004
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field decision-field-inline", children: [
|
|
1005
|
+
t("narrowThresholdLabel"),
|
|
1006
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1007
|
+
"input",
|
|
1008
|
+
{
|
|
1009
|
+
className: "decision-narrow-cap",
|
|
1010
|
+
type: "number",
|
|
1011
|
+
min: 0,
|
|
1012
|
+
max: 1,
|
|
1013
|
+
step: 0.05,
|
|
1014
|
+
value: threshold,
|
|
1015
|
+
disabled: !ready || !narrowOn,
|
|
1016
|
+
placeholder: "0.3",
|
|
1017
|
+
onChange: (event) => {
|
|
1018
|
+
setThreshold(event.target.value);
|
|
1019
|
+
setAdvancedDirty(true);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
),
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { className: "decision-muted", children: t("narrowThresholdHint") })
|
|
1024
|
+
] })
|
|
1025
|
+
] })
|
|
1026
|
+
] }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "decision-actions", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { disabled: busy || !ready || !advancedDirty, type: "submit", children: t("saveAdvanced") }) })
|
|
1028
|
+
] })
|
|
1029
|
+
] }),
|
|
1030
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
|
|
1031
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { children: [
|
|
1032
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(HeadIcon, { name: "backend" }),
|
|
1033
|
+
t("backend")
|
|
1034
|
+
] }),
|
|
1035
|
+
ready && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "decision-muted decision-destination", children: [
|
|
1036
|
+
t("destination"),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: config.effectiveUrl })
|
|
1038
|
+
] }),
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { onSubmit: (event) => void saveBackend(event), children: [
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field", children: [
|
|
1041
|
+
t("url"),
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1043
|
+
"input",
|
|
1044
|
+
{
|
|
1045
|
+
type: "url",
|
|
1046
|
+
value: config.url,
|
|
1047
|
+
disabled: !ready,
|
|
1048
|
+
placeholder: "https://api.typesafe.ai",
|
|
1049
|
+
onChange: (event) => {
|
|
1050
|
+
setConfig({ ...config, url: event.target.value });
|
|
1051
|
+
setBackendDirty(true);
|
|
1052
|
+
setProbeResult(null);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
)
|
|
1056
|
+
] }),
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field", children: [
|
|
1058
|
+
t("model"),
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1060
|
+
"input",
|
|
1061
|
+
{
|
|
1062
|
+
value: config.model,
|
|
1063
|
+
disabled: !ready,
|
|
1064
|
+
placeholder: "jev-latest",
|
|
1065
|
+
onChange: (event) => {
|
|
1066
|
+
setConfig({ ...config, model: event.target.value });
|
|
1067
|
+
setBackendDirty(true);
|
|
1068
|
+
setProbeResult(null);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
)
|
|
1072
|
+
] }),
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "decision-field", children: [
|
|
1074
|
+
t("key"),
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1076
|
+
"input",
|
|
1077
|
+
{
|
|
1078
|
+
type: "password",
|
|
1079
|
+
autoComplete: "off",
|
|
1080
|
+
value: key,
|
|
1081
|
+
disabled: !ready,
|
|
1082
|
+
placeholder: config.apiKeySet ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : "",
|
|
1083
|
+
onChange: (event) => {
|
|
1084
|
+
setKey(event.target.value);
|
|
1085
|
+
setBackendDirty(true);
|
|
1086
|
+
setProbeResult(null);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
),
|
|
1090
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { className: "decision-muted", children: config.apiKeySet ? t("keyHintSaved") : t("keyHintEmpty") })
|
|
1091
|
+
] }),
|
|
1092
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-actions", children: [
|
|
1093
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { disabled: busy || !ready, type: "submit", children: t("save") }),
|
|
1094
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "decision-secondary", disabled: busy || !ready || backendDirty, type: "button", onClick: () => void probe(), children: t("probe") }),
|
|
1095
|
+
probeResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { role: "status", className: `decision-probe-result${probeResult.ok ? " decision-message-ok" : " decision-message-warn"}`, children: probeResult.text })
|
|
1096
|
+
] })
|
|
1097
|
+
] }),
|
|
1098
|
+
config.apiKeySet && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-danger-row", children: [
|
|
1099
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "decision-danger-text", children: [
|
|
1100
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "decision-danger-title", children: t("removeKey") }),
|
|
1101
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { className: "decision-muted", children: t("removeKeyHint") })
|
|
1102
|
+
] }),
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "decision-danger-button", disabled: busy || !ready, onClick: () => void removeSavedKey(), children: t("removeKeyButton") })
|
|
1104
|
+
] })
|
|
1105
|
+
] }),
|
|
1106
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { role: "status", className: `decision-message${message.ok ? " decision-message-ok" : " decision-message-warn"}`, children: message.text })
|
|
1107
|
+
] });
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// src/client/styles.ts
|
|
1111
|
+
var css = `
|
|
1112
|
+
.decision-trigger{position:relative;display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:14rem;border:none;border-radius:var(--dsw-radius-sm,6px);background:0 0;color:var(--dsw-alias-label-tertiary,#77818b);padding:1px 8px;font:inherit;font-size:calc(var(--dsh-content-font-size-secondary,13px) - 1px);font-weight:400;line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));font-variant-numeric:tabular-nums;white-space:nowrap;cursor:pointer}
|
|
1113
|
+
.decision-trigger:hover,.decision-trigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover,#eef1f3);color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1114
|
+
.decision-trigger-icon{flex:none;color:inherit}
|
|
1115
|
+
.decision-trigger-text{min-width:0;flex:0 1 auto;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
|
|
1116
|
+
.decision-trigger-text b{color:inherit;font-weight:500;font-variant-numeric:tabular-nums}
|
|
1117
|
+
.decision-trigger:focus-visible,.decision-dialog button:focus-visible,.decision-dialog input:focus-visible,.decision-config input:focus-visible,.decision-config button:focus-visible{outline:2px solid #1f5d50;outline-offset:2px}
|
|
1118
|
+
.decision-dialog{box-sizing:border-box;flex-direction:column;width:min(46rem,calc(100vw - 2rem));max-height:min(74vh,40rem);border:1px solid var(--dsw-alias-border-l2,#dce1e6);border-radius:14px;padding:0;overflow:hidden;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#202124);box-shadow:0 1rem 3rem rgba(0,0,0,.18);font:inherit}
|
|
1119
|
+
.decision-dialog[open]{display:flex}
|
|
1120
|
+
.decision-dialog::backdrop{background:rgba(0,0,0,.45)}
|
|
1121
|
+
.decision-head{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.7rem 1.1rem;border-bottom:1px solid var(--dsw-alias-border-l2,#eceff1)}
|
|
1122
|
+
.decision-head h2{font-size:1.05rem;margin:0}
|
|
1123
|
+
.decision-head button{border:0;background:transparent;color:inherit;font:inherit;font-size:1.5rem;cursor:pointer;border-radius:8px;width:2rem;height:2rem}
|
|
1124
|
+
.decision-body{flex:1 1 auto;overflow:auto;padding:0 1.1rem .8rem}
|
|
1125
|
+
.decision-dialog section{border-top:1px solid var(--dsw-alias-border-l2,#eceff1);margin-top:.8rem;padding-top:.8rem}
|
|
1126
|
+
.decision-body>section:first-child{border-top:0;margin-top:0;padding-top:.8rem}
|
|
1127
|
+
.decision-dialog h3{font-size:.9rem;margin:0 0 .55rem}
|
|
1128
|
+
.decision-dialog p{font-size:.84rem;line-height:1.5;margin:.35rem 0}
|
|
1129
|
+
.decision-muted{color:var(--dsw-alias-label-secondary,#59636e);font-size:.76rem;line-height:1.5}
|
|
1130
|
+
.decision-empty{color:var(--dsw-alias-label-secondary,#59636e);font-size:.82rem;padding:.6rem .8rem;border:1px dashed var(--dsw-alias-border-l2,#dce1e6);border-radius:10px}
|
|
1131
|
+
.decision-cards{display:grid;grid-template-columns:1fr 1fr;gap:.75rem}
|
|
1132
|
+
.decision-card{border:1px solid var(--dsw-alias-border-l2,#e6eaee);border-radius:12px;padding:.85rem .95rem;background:linear-gradient(180deg,var(--dsw-alias-bg-layer-2,#fff),var(--dsw-alias-bg-layer-1,#fafbfc))}
|
|
1133
|
+
.decision-card-wide{grid-column:1 / -1}
|
|
1134
|
+
.decision-card-head{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem;margin-bottom:.6rem}
|
|
1135
|
+
.decision-card-title{font-size:.8rem;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e);letter-spacing:.02em}
|
|
1136
|
+
.decision-card-total{font-size:1.5rem;font-weight:700;line-height:1;color:var(--dsw-alias-label-primary,#202124);font-variant-numeric:tabular-nums}
|
|
1137
|
+
.decision-card-total small{font-size:.7rem;font-weight:500;color:var(--dsw-alias-label-tertiary,#77818b);margin-left:.15rem}
|
|
1138
|
+
.decision-bar{display:flex;height:8px;border-radius:999px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,#eef1f3)}
|
|
1139
|
+
.decision-bar-empty{background:var(--dsw-alias-bg-layer-1,#eef1f3)}
|
|
1140
|
+
.decision-bar-allow{background:#1f8a70}
|
|
1141
|
+
.decision-bar-ask{background:#c98a1e}
|
|
1142
|
+
.decision-bar-deny{background:#c0392b}
|
|
1143
|
+
.decision-legend{list-style:none;display:flex;flex-wrap:wrap;gap:.4rem 1rem;margin:.6rem 0 0;padding:0}
|
|
1144
|
+
.decision-legend li{display:flex;align-items:center;gap:.35rem;font-size:.78rem;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1145
|
+
.decision-legend b{color:var(--dsw-alias-label-primary,#202124);font-variant-numeric:tabular-nums}
|
|
1146
|
+
.decision-legend-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
|
|
1147
|
+
.decision-dot-allow{background:#1f8a70}
|
|
1148
|
+
.decision-dot-ask{background:#c98a1e}
|
|
1149
|
+
.decision-dot-deny{background:#c0392b}
|
|
1150
|
+
.decision-card-foot{display:flex;justify-content:space-between;gap:1rem;margin-top:.7rem;padding-top:.6rem;border-top:1px solid var(--dsw-alias-border-l2,#eef1f3);font-size:.76rem;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1151
|
+
.decision-card-foot b{color:var(--dsw-alias-label-primary,#202124);font-variant-numeric:tabular-nums;margin-left:.3rem}
|
|
1152
|
+
.decision-card-rate{justify-content:center}
|
|
1153
|
+
.decision-card-stats{display:flex;gap:.6rem}
|
|
1154
|
+
.decision-stat{flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:.2rem;padding:.5rem .3rem;border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f6f8fa)}
|
|
1155
|
+
.decision-stat-num{font-size:1.35rem;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#202124)}
|
|
1156
|
+
.decision-stat-warn{color:#c98a1e}
|
|
1157
|
+
.decision-stat-muted{color:var(--dsw-alias-label-tertiary,#9aa5b1)}
|
|
1158
|
+
.decision-stat-label{font-size:.72rem;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1159
|
+
.decision-log{list-style:none;margin:0;padding:0;display:grid;gap:.5rem;max-height:13rem;overflow:auto}
|
|
1160
|
+
.decision-log-item{display:flex;align-items:baseline;gap:.6rem;font-size:.8rem;padding-left:.6rem;border-left:2px solid var(--dsw-alias-border-l2,#dce1e6);line-height:1.5}
|
|
1161
|
+
.decision-log-item.decision-log-deny{border-left-color:#c0392b}
|
|
1162
|
+
.decision-log-item.decision-log-error,.decision-log-item.decision-log-warn{border-left-color:#c98a1e}
|
|
1163
|
+
.decision-log-item.decision-log-ok{border-left-color:#1f8a70}
|
|
1164
|
+
.decision-log-time{color:var(--dsw-alias-label-tertiary,#77818b);font-variant-numeric:tabular-nums;flex:0 0 auto}
|
|
1165
|
+
.decision-log-body{color:var(--dsw-alias-label-primary,#202124);flex:1 1 auto;min-width:0}
|
|
1166
|
+
.decision-log-tool{font-size:.76rem;padding:.05rem .35rem;border-radius:5px;background:var(--dsw-alias-bg-layer-1,#f2f4f6);color:var(--dsw-alias-label-primary,#202124)}
|
|
1167
|
+
.decision-log-verdict{font-weight:600}
|
|
1168
|
+
.decision-log-deny .decision-log-verdict{color:#c0392b}
|
|
1169
|
+
.decision-log-ok .decision-log-verdict{color:#1f8a70}
|
|
1170
|
+
.decision-log-warn .decision-log-verdict{color:#c98a1e}
|
|
1171
|
+
.decision-log-detail{color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1172
|
+
|
|
1173
|
+
.decision-status{display:flex;align-items:center;gap:.5rem;margin-top:.7rem;font-size:.82rem}
|
|
1174
|
+
.decision-status-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:#9aa5b1}
|
|
1175
|
+
.decision-status-ok{background:#1f8a70}
|
|
1176
|
+
.decision-status-down{background:#c0392b}
|
|
1177
|
+
.decision-status-checking{background:#c98a1e}
|
|
1178
|
+
.decision-status-idle{background:#9aa5b1}
|
|
1179
|
+
.decision-status-label{color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1180
|
+
.decision-status-recheck{margin-left:auto;border:1px solid var(--dsw-alias-border-l2,#ccd3da);border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);padding:.15rem .55rem;font:inherit;font-size:.76rem;cursor:pointer}
|
|
1181
|
+
.decision-status-recheck:hover:not(:disabled){background:var(--dsw-alias-bg-layer-1,#f2f4f6);color:var(--dsw-alias-label-primary,#202124)}
|
|
1182
|
+
.decision-status-recheck:disabled{opacity:.5;cursor:default}
|
|
1183
|
+
|
|
1184
|
+
.decision-config{display:grid;gap:0;color:var(--dsw-alias-label-primary,#202124);container-type:inline-size}
|
|
1185
|
+
.decision-config section{margin-top:1.25rem;padding-top:1.25rem;border-top:1px solid var(--dsw-alias-border-l2,#eceff1)}
|
|
1186
|
+
.decision-config section:first-child{margin-top:0;padding-top:0;border-top:0}
|
|
1187
|
+
.decision-config h3{font-size:1rem;font-weight:600;margin:0 0 .7rem;display:flex;align-items:center;gap:.55rem}
|
|
1188
|
+
.decision-head-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.7rem;height:1.7rem;border-radius:8px}
|
|
1189
|
+
.decision-head-icon-features{color:#1f8a70;background:rgba(31,138,112,.14)}
|
|
1190
|
+
.decision-head-icon-advanced{color:#c98a1e;background:rgba(201,138,30,.16)}
|
|
1191
|
+
.decision-head-icon-backend{color:#5b6ee1;background:rgba(91,110,225,.15)}
|
|
1192
|
+
.decision-collapse{margin-top:1.25rem;padding-top:1.25rem;border-top:1px solid var(--dsw-alias-border-l2,#eceff1)}
|
|
1193
|
+
.decision-collapse-head{display:flex;align-items:center;justify-content:space-between;gap:.75rem;list-style:none;cursor:pointer;border-radius:8px}
|
|
1194
|
+
.decision-collapse-head::-webkit-details-marker{display:none}
|
|
1195
|
+
.decision-collapse-head h3{margin:0}
|
|
1196
|
+
.decision-collapse-head:hover h3{color:var(--dsw-alias-label-primary,#202124)}
|
|
1197
|
+
.decision-collapse-head:focus-visible{outline:2px solid #1f5d50;outline-offset:2px}
|
|
1198
|
+
.decision-collapse-icon{flex:0 0 auto;position:relative;width:1.6rem;height:1.6rem;border:1px solid var(--dsw-alias-border-l2,#ccd3da);border-radius:8px}
|
|
1199
|
+
.decision-collapse-icon::before,.decision-collapse-icon::after{content:"";position:absolute;top:50%;left:50%;background:var(--dsw-alias-label-secondary,#59636e);transform:translate(-50%,-50%)}
|
|
1200
|
+
.decision-collapse-icon::before{width:.7rem;height:1.5px}
|
|
1201
|
+
.decision-collapse-icon::after{width:1.5px;height:.7rem;transition:transform .15s ease,opacity .15s ease}
|
|
1202
|
+
.decision-collapse[open] .decision-collapse-icon::after{transform:translate(-50%,-50%) scaleY(0);opacity:0}
|
|
1203
|
+
.decision-collapse-body{margin-top:.7rem}
|
|
1204
|
+
.decision-config p{font-size:.84rem;line-height:1.6;margin:.45rem 0}
|
|
1205
|
+
.decision-destination{display:flex;flex-direction:column;gap:.25rem;align-items:flex-start}
|
|
1206
|
+
.decision-destination code{font-size:.78rem;padding:.15rem .4rem;border-radius:6px;background:var(--dsw-alias-bg-layer-1,#f2f4f6);color:var(--dsw-alias-label-primary,#202124);word-break:break-all}
|
|
1207
|
+
.decision-config form{display:grid;gap:1rem;margin-top:.8rem}
|
|
1208
|
+
.decision-field{display:grid;gap:.4rem;font-size:.82rem;font-weight:600}
|
|
1209
|
+
.decision-field .decision-muted{font-weight:400;margin:.1rem 0 0}
|
|
1210
|
+
.decision-config input:not([type=checkbox]){box-sizing:border-box;width:100%;min-height:2.4rem;border:1px solid var(--dsw-alias-border-l2,#ccd3da);border-radius:8px;padding:.4rem .7rem;background:var(--dsw-alias-bg-layer-2,#fff);color:inherit;font:inherit;font-weight:400}
|
|
1211
|
+
.decision-config input:not([type=checkbox]):disabled{background:var(--dsw-alias-bg-layer-1,#f6f8fa);opacity:.7}
|
|
1212
|
+
.decision-config textarea{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-l2,#ccd3da);border-radius:8px;padding:.4rem .7rem;background:var(--dsw-alias-bg-layer-2,#fff);color:inherit;font:inherit;font-weight:400;resize:vertical;min-height:3.4rem}
|
|
1213
|
+
.decision-config textarea:disabled{background:var(--dsw-alias-bg-layer-1,#f6f8fa);opacity:.7}
|
|
1214
|
+
.decision-field-textarea{margin-top:.7rem}
|
|
1215
|
+
.decision-field-inline{margin-top:.7rem}
|
|
1216
|
+
.decision-narrow-cap{width:6rem!important}
|
|
1217
|
+
.decision-prefixes{font-family:var(--dsw-alias-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace)!important;line-height:1.5}
|
|
1218
|
+
|
|
1219
|
+
.decision-field-block{display:grid;gap:.35rem}
|
|
1220
|
+
.decision-field-block+.decision-field-block{margin-top:1.1rem}
|
|
1221
|
+
.decision-field-block .decision-muted{font-weight:400;margin:0}
|
|
1222
|
+
.decision-advanced-grid{display:grid;grid-template-columns:1fr;gap:1.1rem;align-items:start;justify-content:start}
|
|
1223
|
+
.decision-advanced-grid .decision-field-block+.decision-field-block{margin-top:0}
|
|
1224
|
+
@container (min-width:34rem){.decision-advanced-grid{grid-template-columns:repeat(2,minmax(0,28rem));column-gap:2rem}}
|
|
1225
|
+
.decision-subhead{font-size:.86rem;font-weight:600;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
1226
|
+
.decision-toggle{display:flex;align-items:center;justify-content:space-between;gap:1rem;font-size:.86rem;font-weight:600;cursor:pointer}
|
|
1227
|
+
.decision-toggle-text{flex:1 1 auto}
|
|
1228
|
+
.decision-toggle-box{position:relative;display:inline-flex;flex:0 0 auto;width:38px;height:22px}
|
|
1229
|
+
.decision-toggle-input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
|
|
1230
|
+
.decision-toggle-input:disabled{cursor:default}
|
|
1231
|
+
.decision-toggle-track{box-sizing:border-box;position:absolute;inset:0;width:38px;height:22px;border:1px solid var(--dsw-alias-border-l2,#ccd3da);border-radius:999px;background:var(--dsw-alias-bg-layer-1,#f2f4f6);transition:background .15s ease,border-color .15s ease;pointer-events:none}
|
|
1232
|
+
.decision-toggle-track::after{content:"";position:absolute;top:50%;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.3);transform:translateY(-50%);transition:transform .15s ease}
|
|
1233
|
+
.decision-toggle-input:checked+.decision-toggle-track{background:#1f5d50;border-color:#1f5d50}
|
|
1234
|
+
.decision-toggle-input:checked+.decision-toggle-track::after{transform:translate(16px,-50%)}
|
|
1235
|
+
.decision-toggle-input:disabled+.decision-toggle-track{opacity:.5}
|
|
1236
|
+
.decision-toggle-input:focus-visible+.decision-toggle-track{outline:2px solid #1f5d50;outline-offset:2px}
|
|
1237
|
+
|
|
1238
|
+
.decision-actions{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;margin-top:.2rem}
|
|
1239
|
+
.decision-actions button{border:1px solid #1f4038;border-radius:8px;background:#1f4038;color:#fff;padding:.5rem .9rem;font:inherit;font-size:.83rem;font-weight:500;cursor:pointer}
|
|
1240
|
+
.decision-actions .decision-secondary{background:transparent;color:#1f4038}
|
|
1241
|
+
.decision-actions .decision-secondary:hover:not(:disabled){background:var(--dsw-alias-bg-layer-1,#f2f4f6)}
|
|
1242
|
+
.decision-actions button:disabled{opacity:.5;cursor:not-allowed}
|
|
1243
|
+
.decision-probe-result{font-size:.82rem;font-weight:500}
|
|
1244
|
+
.decision-danger-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-top:1rem;padding-top:1rem;border-top:1px dashed var(--dsw-alias-border-l2,#dce1e6)}
|
|
1245
|
+
.decision-danger-text{display:grid;gap:.25rem;min-width:0}
|
|
1246
|
+
.decision-danger-title{font-size:.84rem;font-weight:600;color:var(--dsw-alias-label-primary,#202124)}
|
|
1247
|
+
.decision-danger-text .decision-muted{font-weight:400}
|
|
1248
|
+
.decision-danger-button{flex:0 0 auto;border:1px solid #c0392b;border-radius:8px;background:transparent;color:#c0392b;padding:.4rem .9rem;font:inherit;font-size:.82rem;font-weight:500;cursor:pointer}
|
|
1249
|
+
.decision-danger-button:hover:not(:disabled){background:#fdecea}
|
|
1250
|
+
.decision-danger-button:disabled{opacity:.5;cursor:not-allowed}
|
|
1251
|
+
.decision-danger-button:focus-visible{outline:2px solid #c0392b;outline-offset:2px}
|
|
1252
|
+
.decision-message{font-size:.82rem;margin:.2rem 0 0}
|
|
1253
|
+
.decision-message-ok{color:#1f6f57}
|
|
1254
|
+
.decision-message-warn{color:#9d4b1f}
|
|
1255
|
+
`;
|
|
1256
|
+
function installStyles() {
|
|
1257
|
+
if (typeof document === "undefined" || document.querySelector('style[data-plugin="dsh-decision-layer"]')) return () => {
|
|
1258
|
+
};
|
|
1259
|
+
const element = document.createElement("style");
|
|
1260
|
+
element.dataset.plugin = "dsh-decision-layer";
|
|
1261
|
+
element.textContent = css;
|
|
1262
|
+
document.head.appendChild(element);
|
|
1263
|
+
return () => element.remove();
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/client/index.tsx
|
|
1267
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1268
|
+
var inject = ["slots", "locale"];
|
|
1269
|
+
function apply(ctx) {
|
|
1270
|
+
ctx.effect(installStyles);
|
|
1271
|
+
ctx.effect(() => ctx.locale.register("dsh-decision-layer", dictionaries));
|
|
1272
|
+
ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
|
|
1273
|
+
name: "conversation.composer.dock",
|
|
1274
|
+
id: "decision-layer-panel",
|
|
1275
|
+
order: 20,
|
|
1276
|
+
locale: "dsh-decision-layer",
|
|
1277
|
+
registrant: "dsh-decision-layer",
|
|
1278
|
+
inject: (sessionId) => ({ sessionId })
|
|
1279
|
+
}, DecisionPanel));
|
|
1280
|
+
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register(
|
|
1281
|
+
{ name: "plugins.bundle.config", key: "dsh-decision-layer", locale: "dsh-decision-layer" },
|
|
1282
|
+
(props) => props.view === "summary" ? props.t("summary") : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ConfigForm, { t: props.t })
|
|
1283
|
+
));
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
return module.exports;
|
|
1287
|
+
}
|
|
1288
|
+
});
|