@spotpatch/runtime 1.14.0 → 1.15.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/dist/{chunk-2WA6XVA4.js → chunk-DCN6OMLH.js} +13 -3
- package/dist/{chunk-2WA6XVA4.js.map → chunk-DCN6OMLH.js.map} +1 -1
- package/dist/{chunk-KIDHJQRG.js → chunk-PXJKFEUJ.js} +1 -1
- package/dist/chunk-PXJKFEUJ.js.map +1 -0
- package/dist/contextual-ask-panel.cjs +217 -127
- package/dist/contextual-ask-panel.cjs.map +1 -1
- package/dist/contextual-ask-panel.d.cts +2 -0
- package/dist/contextual-ask-panel.d.ts +2 -0
- package/dist/contextual-ask-panel.js +219 -128
- package/dist/contextual-ask-panel.js.map +1 -1
- package/dist/data-flow-panel.cjs +12 -2
- package/dist/data-flow-panel.cjs.map +1 -1
- package/dist/data-flow-panel.d.cts +1 -1
- package/dist/data-flow-panel.d.ts +1 -1
- package/dist/data-flow-panel.js +7 -1
- package/dist/data-flow-panel.js.map +1 -1
- package/dist/{data-flow-runtime-DMmV0d3E.d.cts → data-flow-runtime-CacBbxN0.d.cts} +2 -1
- package/dist/{data-flow-runtime-DMmV0d3E.d.ts → data-flow-runtime-CacBbxN0.d.ts} +2 -1
- package/dist/data-flow.cjs +13 -2
- package/dist/data-flow.cjs.map +1 -1
- package/dist/data-flow.d.cts +1 -1
- package/dist/data-flow.d.ts +1 -1
- package/dist/data-flow.js +3 -1
- package/dist/external-handoff-panel.cjs +22 -6
- package/dist/external-handoff-panel.cjs.map +1 -1
- package/dist/external-handoff-panel.d.cts +5 -2
- package/dist/external-handoff-panel.d.ts +5 -2
- package/dist/external-handoff-panel.js +21 -6
- package/dist/external-handoff-panel.js.map +1 -1
- package/dist/index.cjs +15 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-KIDHJQRG.js.map +0 -1
|
@@ -81,8 +81,10 @@ function isExecutorCapability(value) {
|
|
|
81
81
|
"providerDataConsentRequired",
|
|
82
82
|
"readOnlyProven"
|
|
83
83
|
],
|
|
84
|
-
["errorCode"]
|
|
85
|
-
) || !isOpaqueId(value.executorId) || !isEnum(value.kind, import_contextual_ask_browser.CONTEXTUAL_ASK_EXECUTOR_KINDS) || !isNonEmptyString(value.label) || !isNonEmptyString(value.requestedModelLabel) || !isNonEmptyString(value.effectiveModelLabel) ||
|
|
84
|
+
["errorCode", "models"]
|
|
85
|
+
) || !isOpaqueId(value.executorId) || !isEnum(value.kind, import_contextual_ask_browser.CONTEXTUAL_ASK_EXECUTOR_KINDS) || !isNonEmptyString(value.label) || !isNonEmptyString(value.requestedModelLabel) || !isNonEmptyString(value.effectiveModelLabel) || value.models !== void 0 && (!Array.isArray(value.models) || value.models.length === 0 || value.models.length > import_contextual_ask_browser.CONTEXTUAL_ASK_LIMITS.maximumModels || !value.models.every(
|
|
86
|
+
(model) => isNonEmptyString(model) && model.length <= import_contextual_ask_browser.CONTEXTUAL_ASK_LIMITS.maximumLabelCharacters
|
|
87
|
+
) || !unique(value.models)) || !isEnum(value.state, import_contextual_ask_browser.CONTEXTUAL_ASK_EXECUTOR_STATES) || typeof value.providerDataConsentRequired !== "boolean" || typeof value.readOnlyProven !== "boolean" || value.errorCode !== void 0 && !isAskDomainError(value.errorCode)) {
|
|
86
88
|
return false;
|
|
87
89
|
}
|
|
88
90
|
return value.state === "ready" ? value.readOnlyProven && value.errorCode === void 0 : value.errorCode !== void 0;
|
|
@@ -556,6 +558,7 @@ function createContextualAskWorkflow(input) {
|
|
|
556
558
|
return;
|
|
557
559
|
}
|
|
558
560
|
const requestRevision = ++revision;
|
|
561
|
+
const model = input.panel.readModel();
|
|
559
562
|
currentQuestion = question;
|
|
560
563
|
busy = true;
|
|
561
564
|
input.onBusyChange(true);
|
|
@@ -568,6 +571,7 @@ function createContextualAskWorkflow(input) {
|
|
|
568
571
|
requestId: input.createId(),
|
|
569
572
|
envelope,
|
|
570
573
|
executorId,
|
|
574
|
+
...model === void 0 ? {} : { model },
|
|
571
575
|
providerDataConsent: true
|
|
572
576
|
});
|
|
573
577
|
if (!isCurrent(requestRevision)) return;
|
|
@@ -801,6 +805,158 @@ function createButton(document, label, className = "") {
|
|
|
801
805
|
return button;
|
|
802
806
|
}
|
|
803
807
|
|
|
808
|
+
// src/ui/ask-picker.ts
|
|
809
|
+
function createAskPicker(document, onViewChange) {
|
|
810
|
+
const root = createMarkedElement(document, "div");
|
|
811
|
+
root.className = "spotpatch-ask-executor-picker";
|
|
812
|
+
const trigger = createButton(document, "", "spotpatch-ask-executor");
|
|
813
|
+
trigger.id = `spotpatch-ask-picker-${Math.random().toString(36).slice(2)}`;
|
|
814
|
+
trigger.setAttribute("role", "combobox");
|
|
815
|
+
trigger.setAttribute("aria-haspopup", "listbox");
|
|
816
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
817
|
+
const text = createMarkedElement(document, "span");
|
|
818
|
+
trigger.append(text);
|
|
819
|
+
const menu = createMarkedElement(document, "div");
|
|
820
|
+
menu.id = `${trigger.id}-menu`;
|
|
821
|
+
menu.className = "spotpatch-ask-executor-menu";
|
|
822
|
+
menu.setAttribute("role", "listbox");
|
|
823
|
+
menu.hidden = true;
|
|
824
|
+
trigger.setAttribute("aria-controls", menu.id);
|
|
825
|
+
const select = createMarkedElement(document, "select");
|
|
826
|
+
select.className = "spotpatch-ask-executor-native";
|
|
827
|
+
select.tabIndex = -1;
|
|
828
|
+
select.setAttribute("aria-hidden", "true");
|
|
829
|
+
root.append(trigger, menu, select);
|
|
830
|
+
function close(focus = false) {
|
|
831
|
+
if (menu.hidden) return;
|
|
832
|
+
menu.hidden = true;
|
|
833
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
834
|
+
trigger.removeAttribute("aria-activedescendant");
|
|
835
|
+
if (focus) trigger.focus({ preventScroll: true });
|
|
836
|
+
onViewChange();
|
|
837
|
+
}
|
|
838
|
+
function activate(index) {
|
|
839
|
+
const options = [...menu.children];
|
|
840
|
+
const active = options[index];
|
|
841
|
+
if (active === void 0) return;
|
|
842
|
+
for (const option of options) option.dataset.active = String(option === active);
|
|
843
|
+
trigger.setAttribute("aria-activedescendant", active.id);
|
|
844
|
+
const itemRect = active.getBoundingClientRect();
|
|
845
|
+
const menuRect = menu.getBoundingClientRect();
|
|
846
|
+
if (itemRect.top < menuRect.top) menu.scrollTop -= menuRect.top - itemRect.top;
|
|
847
|
+
else if (itemRect.bottom > menuRect.bottom)
|
|
848
|
+
menu.scrollTop += itemRect.bottom - menuRect.bottom;
|
|
849
|
+
}
|
|
850
|
+
function open() {
|
|
851
|
+
if (trigger.disabled || !menu.hidden) return;
|
|
852
|
+
menu.hidden = false;
|
|
853
|
+
trigger.setAttribute("aria-expanded", "true");
|
|
854
|
+
activate(Math.max(0, select.selectedIndex));
|
|
855
|
+
onViewChange();
|
|
856
|
+
}
|
|
857
|
+
function sync() {
|
|
858
|
+
text.textContent = select.selectedOptions[0]?.textContent ?? "";
|
|
859
|
+
trigger.title = text.textContent;
|
|
860
|
+
trigger.dataset.empty = String(select.value.length === 0);
|
|
861
|
+
for (const option of [...menu.children]) {
|
|
862
|
+
option.setAttribute(
|
|
863
|
+
"aria-selected",
|
|
864
|
+
String(option.dataset.value === select.value)
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
function choose(value) {
|
|
869
|
+
if (trigger.disabled) return;
|
|
870
|
+
select.value = value;
|
|
871
|
+
sync();
|
|
872
|
+
close(true);
|
|
873
|
+
select.dispatchEvent(new Event("change", { bubbles: true }));
|
|
874
|
+
}
|
|
875
|
+
function rebuild() {
|
|
876
|
+
close();
|
|
877
|
+
menu.replaceChildren();
|
|
878
|
+
for (const [index, option] of [...select.options].entries()) {
|
|
879
|
+
const item = createMarkedElement(document, "div");
|
|
880
|
+
item.id = `${menu.id}-${String(index)}`;
|
|
881
|
+
item.className = "spotpatch-ask-executor-option";
|
|
882
|
+
item.setAttribute("role", "option");
|
|
883
|
+
item.dataset.value = option.value;
|
|
884
|
+
item.textContent = option.textContent;
|
|
885
|
+
item.title = option.textContent;
|
|
886
|
+
item.addEventListener("pointerdown", (event) => {
|
|
887
|
+
event.preventDefault();
|
|
888
|
+
});
|
|
889
|
+
item.addEventListener("click", () => {
|
|
890
|
+
choose(option.value);
|
|
891
|
+
});
|
|
892
|
+
menu.append(item);
|
|
893
|
+
}
|
|
894
|
+
sync();
|
|
895
|
+
}
|
|
896
|
+
trigger.addEventListener("click", () => {
|
|
897
|
+
if (menu.hidden) open();
|
|
898
|
+
else close();
|
|
899
|
+
});
|
|
900
|
+
trigger.addEventListener("keydown", (event) => {
|
|
901
|
+
if (event.key === "Escape" && !menu.hidden) {
|
|
902
|
+
event.preventDefault();
|
|
903
|
+
event.stopPropagation();
|
|
904
|
+
close();
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
if (event.key === "Tab") {
|
|
908
|
+
close();
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
if (["Enter", " "].includes(event.key) && !menu.hidden) {
|
|
912
|
+
event.preventDefault();
|
|
913
|
+
const active = [...menu.children].find(
|
|
914
|
+
(item) => item.id === trigger.getAttribute("aria-activedescendant")
|
|
915
|
+
);
|
|
916
|
+
if (active?.dataset.value !== void 0) choose(active.dataset.value);
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
920
|
+
event.preventDefault();
|
|
921
|
+
if (menu.hidden) {
|
|
922
|
+
open();
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const options = [...menu.children];
|
|
926
|
+
const index = options.findIndex(
|
|
927
|
+
(item) => item.id === trigger.getAttribute("aria-activedescendant")
|
|
928
|
+
);
|
|
929
|
+
activate(
|
|
930
|
+
event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : (index + (event.key === "ArrowDown" ? 1 : -1) + options.length) % options.length
|
|
931
|
+
);
|
|
932
|
+
});
|
|
933
|
+
root.addEventListener("focusout", (event) => {
|
|
934
|
+
if (!(event.relatedTarget instanceof Node) || !root.contains(event.relatedTarget))
|
|
935
|
+
close();
|
|
936
|
+
});
|
|
937
|
+
const outside = (event) => {
|
|
938
|
+
if (!event.composedPath().includes(root)) close();
|
|
939
|
+
};
|
|
940
|
+
document.addEventListener("pointerdown", outside);
|
|
941
|
+
select.addEventListener("change", sync);
|
|
942
|
+
return {
|
|
943
|
+
root,
|
|
944
|
+
trigger,
|
|
945
|
+
select,
|
|
946
|
+
rebuild,
|
|
947
|
+
close,
|
|
948
|
+
setDisabled(disabled) {
|
|
949
|
+
select.disabled = disabled;
|
|
950
|
+
trigger.disabled = disabled || select.options.length < 2;
|
|
951
|
+
trigger.dataset.expandable = String(!trigger.disabled);
|
|
952
|
+
if (trigger.disabled) close();
|
|
953
|
+
},
|
|
954
|
+
dispose() {
|
|
955
|
+
document.removeEventListener("pointerdown", outside);
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
|
|
804
960
|
// src/ui/contextual-ask-localization.ts
|
|
805
961
|
var EN = Object.freeze({
|
|
806
962
|
mode: Object.freeze({ ask: "Ask", change: "Change", label: "Task mode" }),
|
|
@@ -815,6 +971,7 @@ var EN = Object.freeze({
|
|
|
815
971
|
"Why is it implemented this way?"
|
|
816
972
|
]),
|
|
817
973
|
executorLabel: "Read-only executor",
|
|
974
|
+
modelLabel: "Model",
|
|
818
975
|
loadingExecutors: "Checking available executors\u2026",
|
|
819
976
|
noExecutor: "No verified read-only executor is available.",
|
|
820
977
|
unavailable: "unavailable",
|
|
@@ -884,6 +1041,7 @@ var ZH = Object.freeze({
|
|
|
884
1041
|
"\u4E3A\u4EC0\u4E48\u8981\u8FD9\u6837\u5B9E\u73B0\uFF1F"
|
|
885
1042
|
]),
|
|
886
1043
|
executorLabel: "\u53EA\u8BFB\u6267\u884C\u5668",
|
|
1044
|
+
modelLabel: "\u6A21\u578B",
|
|
887
1045
|
loadingExecutors: "\u6B63\u5728\u68C0\u67E5\u53EF\u7528\u6267\u884C\u5668\u2026",
|
|
888
1046
|
noExecutor: "\u76EE\u524D\u6CA1\u6709\u901A\u8FC7\u53EA\u8BFB\u9A8C\u8BC1\u7684\u6267\u884C\u5668\u3002",
|
|
889
1047
|
unavailable: "\u4E0D\u53EF\u7528",
|
|
@@ -952,7 +1110,8 @@ function createStyles(document) {
|
|
|
952
1110
|
.spotpatch-ask-mode button { min-height: 34px; border: 0; border-radius: 7px; color: var(--spotpatch-text-secondary); background: transparent; cursor: pointer; font-size: 12px; font-weight: 700; }
|
|
953
1111
|
.spotpatch-ask-mode button[aria-selected="true"] { color: #f7f7ff; background: linear-gradient(135deg, rgb(139 123 255 / 25%), rgb(82 168 255 / 14%)); box-shadow: inset 0 0 0 1px rgb(139 123 255 / 24%); }
|
|
954
1112
|
.spotpatch-ask-panel { display: grid; gap: 14px; }
|
|
955
|
-
.spotpatch-ask-field { display: grid; gap: 7px; }
|
|
1113
|
+
.spotpatch-ask-field { display: grid; gap: 7px; min-width: 0; }
|
|
1114
|
+
.spotpatch-ask-field[hidden] { display: none; }
|
|
956
1115
|
.spotpatch-ask-field > label, .spotpatch-ask-label { color: #c9cad2; font-size: 11px; font-weight: 680; }
|
|
957
1116
|
.spotpatch-ask-question { box-sizing: border-box; width: 100%; min-height: 92px; resize: vertical; border: 1px solid var(--spotpatch-border); border-radius: 10px; padding: 11px 12px; outline: none; color: var(--spotpatch-text); background: var(--spotpatch-bg-input); line-height: 1.55; }
|
|
958
1117
|
.spotpatch-ask-question:focus { border-color: rgb(139 123 255 / 68%); box-shadow: 0 0 0 3px rgb(139 123 255 / 12%); }
|
|
@@ -967,10 +1126,10 @@ function createStyles(document) {
|
|
|
967
1126
|
.spotpatch-ask-executor:focus-visible { border-color: rgb(139 123 255 / 68%); box-shadow: 0 0 0 3px rgb(139 123 255 / 12%); }
|
|
968
1127
|
.spotpatch-ask-executor:disabled { color: var(--spotpatch-text); background: rgb(255 255 255 / 3%); cursor: default; opacity: 1; }
|
|
969
1128
|
.spotpatch-ask-executor[data-empty="true"]:disabled { color: var(--spotpatch-text-muted); }
|
|
970
|
-
.spotpatch-ask-executor-menu { display: grid; gap: 3px; border: 1px solid var(--spotpatch-border); border-radius: 9px; padding: 4px; background:
|
|
1129
|
+
.spotpatch-ask-executor-menu { display: grid; gap: 3px; border: 1px solid var(--spotpatch-border); border-radius: 9px; padding: 4px; background: var(--spotpatch-bg-input); max-height: 224px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; box-shadow: 0 10px 28px rgb(0 0 0 / 28%); }
|
|
971
1130
|
.spotpatch-ask-executor-menu[hidden] { display: none; }
|
|
972
|
-
.spotpatch-ask-executor-option { box-sizing: border-box; min-height: 34px; border: 0; border-radius: 6px; padding: 7px 9px; color: var(--spotpatch-text-secondary); background: transparent; cursor: pointer; font: inherit; text-align: left; }
|
|
973
|
-
.spotpatch-ask-executor-option
|
|
1131
|
+
.spotpatch-ask-executor-option { box-sizing: border-box; min-height: 34px; border: 0; border-radius: 6px; padding: 7px 9px; color: var(--spotpatch-text-secondary); background: transparent; cursor: pointer; font: inherit; text-align: left; overflow-wrap: anywhere; }
|
|
1132
|
+
.spotpatch-ask-executor-option[data-active="true"], .spotpatch-ask-executor-option:hover { color: #fff; background: rgb(139 123 255 / 13%); outline: none; }
|
|
974
1133
|
.spotpatch-ask-executor-option[aria-selected="true"] { color: #f4f1ff; background: rgb(139 123 255 / 20%); }
|
|
975
1134
|
.spotpatch-ask-executor-native { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; border: 0; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
976
1135
|
.spotpatch-ask-executor-status { margin: 0; border-left: 2px solid var(--spotpatch-warning); padding-left: 8px; color: #d8b66c; font-size: 10.5px; line-height: 1.45; }
|
|
@@ -1071,33 +1230,21 @@ function createContextualAskPanel(input) {
|
|
|
1071
1230
|
const executorField = createMarkedElement(document, "div");
|
|
1072
1231
|
executorField.className = "spotpatch-ask-field";
|
|
1073
1232
|
const executorLabel = createMarkedElement(document, "label");
|
|
1074
|
-
const executorPicker =
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
const executorText = createMarkedElement(document, "span");
|
|
1085
|
-
executorTrigger.append(executorText);
|
|
1086
|
-
const executorMenu = createMarkedElement(document, "div");
|
|
1087
|
-
executorMenu.id = executorMenuId;
|
|
1088
|
-
executorMenu.className = "spotpatch-ask-executor-menu";
|
|
1089
|
-
executorMenu.setAttribute("role", "listbox");
|
|
1090
|
-
executorMenu.hidden = true;
|
|
1091
|
-
executorSelect.className = "spotpatch-ask-executor-native";
|
|
1092
|
-
executorSelect.tabIndex = -1;
|
|
1093
|
-
executorSelect.setAttribute("aria-hidden", "true");
|
|
1094
|
-
executorLabel.htmlFor = executorId;
|
|
1233
|
+
const executorPicker = createAskPicker(document, input.onViewChange);
|
|
1234
|
+
const executorSelect = executorPicker.select;
|
|
1235
|
+
executorLabel.htmlFor = executorPicker.trigger.id;
|
|
1236
|
+
const modelField = createMarkedElement(document, "div");
|
|
1237
|
+
modelField.className = "spotpatch-ask-field";
|
|
1238
|
+
const modelLabel = createMarkedElement(document, "label");
|
|
1239
|
+
const modelPicker = createAskPicker(document, input.onViewChange);
|
|
1240
|
+
modelLabel.htmlFor = modelPicker.trigger.id;
|
|
1241
|
+
modelField.append(modelLabel, modelPicker.root);
|
|
1242
|
+
let modelExecutorId;
|
|
1095
1243
|
const executorStatus = createMarkedElement(document, "p");
|
|
1096
1244
|
executorStatus.className = "spotpatch-ask-executor-status";
|
|
1097
1245
|
executorStatus.setAttribute("role", "status");
|
|
1098
1246
|
executorStatus.hidden = true;
|
|
1099
|
-
|
|
1100
|
-
executorField.append(executorLabel, executorPicker, executorStatus);
|
|
1247
|
+
executorField.append(executorLabel, executorPicker.root, executorStatus);
|
|
1101
1248
|
const safety = createMarkedElement(document, "div");
|
|
1102
1249
|
safety.className = "spotpatch-ask-safety";
|
|
1103
1250
|
const dataSummary = createMarkedElement(document, "div");
|
|
@@ -1154,7 +1301,16 @@ function createContextualAskPanel(input) {
|
|
|
1154
1301
|
const convertButton = createButton(document, "", "spotpatch-primary");
|
|
1155
1302
|
answerActions.append(copyButton, convertButton);
|
|
1156
1303
|
answer.append(stale, answerTitle, warnings, blocks, sourcesSection, answerActions);
|
|
1157
|
-
askPanel.append(
|
|
1304
|
+
askPanel.append(
|
|
1305
|
+
questionField,
|
|
1306
|
+
executorField,
|
|
1307
|
+
modelField,
|
|
1308
|
+
safety,
|
|
1309
|
+
status,
|
|
1310
|
+
error,
|
|
1311
|
+
actions,
|
|
1312
|
+
answer
|
|
1313
|
+
);
|
|
1158
1314
|
root.append(modeSwitch, origin, askPanel);
|
|
1159
1315
|
function hasReadyExecutor() {
|
|
1160
1316
|
const selected = currentCapability?.executors.find(
|
|
@@ -1167,57 +1323,31 @@ function createContextualAskPanel(input) {
|
|
|
1167
1323
|
(candidate) => candidate.state === "ready" && candidate.readOnlyProven
|
|
1168
1324
|
) === true;
|
|
1169
1325
|
}
|
|
1170
|
-
function
|
|
1171
|
-
|
|
1172
|
-
(
|
|
1173
|
-
).length ?? 0;
|
|
1174
|
-
}
|
|
1175
|
-
function closeExecutorMenu(focusTrigger = false) {
|
|
1176
|
-
if (executorMenu.hidden) return;
|
|
1177
|
-
executorMenu.hidden = true;
|
|
1178
|
-
executorTrigger.setAttribute("aria-expanded", "false");
|
|
1179
|
-
if (focusTrigger) executorTrigger.focus({ preventScroll: true });
|
|
1180
|
-
input.onViewChange();
|
|
1181
|
-
}
|
|
1182
|
-
function openExecutorMenu(focusSelected = false) {
|
|
1183
|
-
if (executorTrigger.disabled || !executorMenu.hidden) return;
|
|
1184
|
-
executorMenu.hidden = false;
|
|
1185
|
-
executorTrigger.setAttribute("aria-expanded", "true");
|
|
1186
|
-
if (focusSelected) {
|
|
1187
|
-
const selected = executorMenu.querySelector(
|
|
1188
|
-
'.spotpatch-ask-executor-option[aria-selected="true"]'
|
|
1189
|
-
);
|
|
1190
|
-
const first = executorMenu.firstElementChild;
|
|
1191
|
-
const focusTarget = selected ?? (first instanceof HTMLElement ? first : null);
|
|
1192
|
-
focusTarget?.focus({ preventScroll: true });
|
|
1193
|
-
}
|
|
1194
|
-
input.onViewChange();
|
|
1195
|
-
}
|
|
1196
|
-
function syncExecutorControl() {
|
|
1197
|
-
const selectedOption = [...executorSelect.options].find(
|
|
1198
|
-
(option) => option.value === executorSelect.value
|
|
1326
|
+
function renderModels() {
|
|
1327
|
+
const executor = currentCapability?.executors.find(
|
|
1328
|
+
(item) => item.executorId === executorSelect.value
|
|
1199
1329
|
);
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
)
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1330
|
+
const previous = modelExecutorId === executor?.executorId ? modelPicker.select.value : void 0;
|
|
1331
|
+
modelExecutorId = executor?.executorId;
|
|
1332
|
+
const models = executor?.models;
|
|
1333
|
+
modelField.hidden = models === void 0;
|
|
1334
|
+
modelPicker.select.replaceChildren();
|
|
1335
|
+
for (const model of models ?? []) {
|
|
1336
|
+
const option = document.createElement("option");
|
|
1337
|
+
option.value = model;
|
|
1338
|
+
option.textContent = model;
|
|
1339
|
+
modelPicker.select.append(option);
|
|
1209
1340
|
}
|
|
1341
|
+
modelPicker.select.value = models?.find((model) => model === previous) ?? models?.find((model) => model === executor?.requestedModelLabel) ?? models?.[0] ?? "";
|
|
1342
|
+
modelPicker.rebuild();
|
|
1210
1343
|
}
|
|
1211
1344
|
function refreshSubmitState() {
|
|
1212
1345
|
submitButton.disabled = busy || questionInput.value.trim().length === 0 || !hasReadyExecutor() || !consentCheckbox.checked || currentPreview.targetCount === 0;
|
|
1213
1346
|
if (!currentPreview.contextReady) submitButton.disabled = true;
|
|
1214
1347
|
questionInput.disabled = busy;
|
|
1215
|
-
const readyCount = readyExecutorCount();
|
|
1216
1348
|
const executorUnavailable = busy || currentCapability === void 0 || !hasAnyReadyExecutor();
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
executorTrigger.dataset.expandable = String(!executorUnavailable && readyCount > 1);
|
|
1220
|
-
if (executorTrigger.disabled) closeExecutorMenu();
|
|
1349
|
+
executorPicker.setDisabled(executorUnavailable);
|
|
1350
|
+
modelPicker.setDisabled(busy || !hasReadyExecutor());
|
|
1221
1351
|
consentCheckbox.disabled = busy || !hasReadyExecutor();
|
|
1222
1352
|
newQuestionButton.hidden = busy || currentResult === void 0;
|
|
1223
1353
|
cancelButton.hidden = !busy;
|
|
@@ -1260,6 +1390,9 @@ function createContextualAskPanel(input) {
|
|
|
1260
1390
|
questionInput.placeholder = messages.questionPlaceholder;
|
|
1261
1391
|
suggestions.setAttribute("aria-label", messages.suggestionsLabel);
|
|
1262
1392
|
executorLabel.textContent = messages.executorLabel;
|
|
1393
|
+
modelLabel.textContent = messages.modelLabel;
|
|
1394
|
+
executorPicker.root.querySelector("[role=listbox]")?.setAttribute("aria-label", messages.executorLabel);
|
|
1395
|
+
modelPicker.root.querySelector("[role=listbox]")?.setAttribute("aria-label", messages.modelLabel);
|
|
1263
1396
|
consentText.textContent = messages.consent;
|
|
1264
1397
|
safetyText.textContent = messages.safety;
|
|
1265
1398
|
submitButton.textContent = messages.submit;
|
|
@@ -1284,8 +1417,7 @@ function createContextualAskPanel(input) {
|
|
|
1284
1417
|
currentCapability = capability;
|
|
1285
1418
|
const previous = executorSelect.value;
|
|
1286
1419
|
executorSelect.replaceChildren();
|
|
1287
|
-
|
|
1288
|
-
closeExecutorMenu();
|
|
1420
|
+
executorPicker.close();
|
|
1289
1421
|
executorStatus.hidden = true;
|
|
1290
1422
|
executorStatus.textContent = "";
|
|
1291
1423
|
if (capability === void 0) {
|
|
@@ -1308,22 +1440,8 @@ function createContextualAskPanel(input) {
|
|
|
1308
1440
|
for (const executor of readyExecutors) {
|
|
1309
1441
|
const option = document.createElement("option");
|
|
1310
1442
|
option.value = executor.executorId;
|
|
1311
|
-
option.textContent = `${executor.label} \xB7 ${executor.effectiveModelLabel}
|
|
1443
|
+
option.textContent = executor.models === void 0 ? `${executor.label} \xB7 ${executor.effectiveModelLabel}` : executor.label;
|
|
1312
1444
|
executorSelect.append(option);
|
|
1313
|
-
const menuOption = createButton(
|
|
1314
|
-
document,
|
|
1315
|
-
option.textContent,
|
|
1316
|
-
"spotpatch-ask-executor-option"
|
|
1317
|
-
);
|
|
1318
|
-
menuOption.dataset.executorId = executor.executorId;
|
|
1319
|
-
menuOption.setAttribute("role", "option");
|
|
1320
|
-
menuOption.addEventListener("click", () => {
|
|
1321
|
-
executorSelect.value = executor.executorId;
|
|
1322
|
-
syncExecutorControl();
|
|
1323
|
-
closeExecutorMenu(true);
|
|
1324
|
-
executorSelect.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1325
|
-
});
|
|
1326
|
-
executorMenu.append(menuOption);
|
|
1327
1445
|
}
|
|
1328
1446
|
if (readyExecutors.length === 0) {
|
|
1329
1447
|
const option = document.createElement("option");
|
|
@@ -1339,7 +1457,8 @@ function createContextualAskPanel(input) {
|
|
|
1339
1457
|
executorStatus.hidden = false;
|
|
1340
1458
|
}
|
|
1341
1459
|
}
|
|
1342
|
-
|
|
1460
|
+
executorPicker.rebuild();
|
|
1461
|
+
renderModels();
|
|
1343
1462
|
refreshSubmitState();
|
|
1344
1463
|
}
|
|
1345
1464
|
function renderJob(snapshot) {
|
|
@@ -1494,42 +1613,11 @@ ${sourceText}`;
|
|
|
1494
1613
|
applyMode();
|
|
1495
1614
|
});
|
|
1496
1615
|
questionInput.addEventListener("input", refreshSubmitState);
|
|
1497
|
-
executorSelect.addEventListener("change",
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
});
|
|
1502
|
-
executorTrigger.addEventListener("keydown", (event) => {
|
|
1503
|
-
if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
|
|
1504
|
-
event.preventDefault();
|
|
1505
|
-
openExecutorMenu(true);
|
|
1506
|
-
});
|
|
1507
|
-
executorMenu.addEventListener("keydown", (event) => {
|
|
1508
|
-
const options = [
|
|
1509
|
-
...executorMenu.querySelectorAll(
|
|
1510
|
-
".spotpatch-ask-executor-option"
|
|
1511
|
-
)
|
|
1512
|
-
];
|
|
1513
|
-
if (event.key === "Escape") {
|
|
1514
|
-
event.preventDefault();
|
|
1515
|
-
closeExecutorMenu(true);
|
|
1516
|
-
return;
|
|
1517
|
-
}
|
|
1518
|
-
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
1519
|
-
event.preventDefault();
|
|
1520
|
-
const currentIndex = options.indexOf(document.activeElement);
|
|
1521
|
-
const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : event.key === "ArrowDown" ? (currentIndex + 1 + options.length) % options.length : (currentIndex - 1 + options.length) % options.length;
|
|
1522
|
-
options[nextIndex]?.focus({ preventScroll: true });
|
|
1523
|
-
});
|
|
1524
|
-
executorPicker.addEventListener("focusout", (event) => {
|
|
1525
|
-
if (!(event.relatedTarget instanceof Node) || !executorPicker.contains(event.relatedTarget)) {
|
|
1526
|
-
closeExecutorMenu();
|
|
1527
|
-
}
|
|
1616
|
+
executorSelect.addEventListener("change", () => {
|
|
1617
|
+
renderModels();
|
|
1618
|
+
refreshSubmitState();
|
|
1619
|
+
input.onViewChange();
|
|
1528
1620
|
});
|
|
1529
|
-
const closeExecutorMenuOutside = (event) => {
|
|
1530
|
-
if (!event.composedPath().includes(executorPicker)) closeExecutorMenu();
|
|
1531
|
-
};
|
|
1532
|
-
document.addEventListener("pointerdown", closeExecutorMenuOutside);
|
|
1533
1621
|
consentCheckbox.addEventListener("change", refreshSubmitState);
|
|
1534
1622
|
const unsubscribeLocale = input.subscribeLocale(applyMessages);
|
|
1535
1623
|
applyMessages();
|
|
@@ -1548,7 +1636,8 @@ ${sourceText}`;
|
|
|
1548
1636
|
clear,
|
|
1549
1637
|
dispose: () => {
|
|
1550
1638
|
unsubscribeLocale();
|
|
1551
|
-
|
|
1639
|
+
executorPicker.dispose();
|
|
1640
|
+
modelPicker.dispose();
|
|
1552
1641
|
},
|
|
1553
1642
|
focusQuestion: () => {
|
|
1554
1643
|
questionInput.focus({ preventScroll: true });
|
|
@@ -1560,6 +1649,7 @@ ${sourceText}`;
|
|
|
1560
1649
|
},
|
|
1561
1650
|
readConsent: () => consentCheckbox.checked,
|
|
1562
1651
|
readExecutorId: () => executorSelect.value || void 0,
|
|
1652
|
+
readModel: () => modelPicker.select.value || void 0,
|
|
1563
1653
|
readQuestion: () => questionInput.value.trim(),
|
|
1564
1654
|
renderAnswer,
|
|
1565
1655
|
renderCapability,
|