opencode-navigator 0.27.1 → 0.27.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/HOST_API.md +22 -3
- package/README.md +23 -2
- package/dist/gui-experimental.cjs +1574 -1029
- package/dist/navigator-updates.js +85 -29
- package/dist/provider-limits.js +2 -4
- package/dist/tui.js +155 -76
- package/package.json +1 -1
- package/scripts/update-local-snapshot.mjs +13 -1
|
@@ -1913,7 +1913,7 @@ function providerQuotaCapability(id, canonical) {
|
|
|
1913
1913
|
function quotaStatusMessage(input) {
|
|
1914
1914
|
const { model, snapshot, state } = input;
|
|
1915
1915
|
if (state.status === "error") return snapshot ? "Stale · refresh failed" : "Quota read failed · refresh to retry";
|
|
1916
|
-
if (
|
|
1916
|
+
if (snapshot?.availability === "ready" && (snapshot.windows.length > 0 || snapshot.balances?.length)) return input.showUpdatedAt ? `Updated ${new Date(snapshot.fetchedAt).toLocaleTimeString()}` : void 0;
|
|
1917
1917
|
if (snapshot?.message) {
|
|
1918
1918
|
if (snapshot.availability === "stale") return `Stale · ${snapshot.message}`;
|
|
1919
1919
|
return snapshot.availability === "ready" ? `Updated ${new Date(snapshot.fetchedAt).toLocaleTimeString()} · ${snapshot.message}` : snapshot.message;
|
|
@@ -1930,7 +1930,6 @@ function quotaStatusMessage(input) {
|
|
|
1930
1930
|
if (snapshot.availability === "unsupported") return "No documented quota bucket for this model";
|
|
1931
1931
|
if (snapshot.availability === "rate_limited") return "Provider rate-limited this read · try again later";
|
|
1932
1932
|
if (snapshot.availability === "stale") return "Stale provider data · refresh to update";
|
|
1933
|
-
if (snapshot.availability === "ready" && input.showReadyMessage && (snapshot.windows.length > 0 || snapshot.balances?.length)) return;
|
|
1934
1933
|
return `Updated ${new Date(snapshot.fetchedAt).toLocaleTimeString()}`;
|
|
1935
1934
|
}
|
|
1936
1935
|
// src/entities/preferences/model/codex-account-bindings.ts
|
|
@@ -2718,6 +2717,16 @@ function targetForLegacyScope(scope) {
|
|
|
2718
2717
|
key: scope
|
|
2719
2718
|
};
|
|
2720
2719
|
}
|
|
2720
|
+
// src/shared/lib/reorder.ts
|
|
2721
|
+
function reorderItems(items, from, to, key) {
|
|
2722
|
+
const source = items.findIndex((item) => key(item) === from);
|
|
2723
|
+
const target = items.findIndex((item) => key(item) === to);
|
|
2724
|
+
const next = [...items];
|
|
2725
|
+
if (source === -1 || target === -1 || source === target) return next;
|
|
2726
|
+
const [item] = next.splice(source, 1);
|
|
2727
|
+
next.splice(target, 0, item);
|
|
2728
|
+
return next;
|
|
2729
|
+
}
|
|
2721
2730
|
// src/entities/preferences/model/built-ins.ts
|
|
2722
2731
|
function builtInPreferences(defaults) {
|
|
2723
2732
|
return {
|
|
@@ -3354,6 +3363,14 @@ function createPreferencesModel(ports, defaults, store, configuredInput = {}) {
|
|
|
3354
3363
|
behavior: { quickActionOrder: order }
|
|
3355
3364
|
});
|
|
3356
3365
|
},
|
|
3366
|
+
reorderQuickAction(from, to, scope) {
|
|
3367
|
+
if (scope !== targetKey(selectedTarget())) return;
|
|
3368
|
+
const order = reorderItems(selectedResolved().behavior.quickActionOrder, from, to, (id) => id);
|
|
3369
|
+
update({
|
|
3370
|
+
target: selectedTarget(),
|
|
3371
|
+
behavior: { quickActionOrder: order }
|
|
3372
|
+
});
|
|
3373
|
+
},
|
|
3357
3374
|
sectionItemLimit: (section) => resolved().behavior.sectionItemLimits[section] ?? 0,
|
|
3358
3375
|
selectedSectionItemLimit: (section) => selectedResolved().behavior.sectionItemLimits[section] ?? 0,
|
|
3359
3376
|
setSectionItemLimit(section, value) {
|
|
@@ -3579,6 +3596,11 @@ function createPreferencesModel(ports, defaults, store, configuredInput = {}) {
|
|
|
3579
3596
|
swap(order, index, destination);
|
|
3580
3597
|
setSelectedSessionLayout({ order });
|
|
3581
3598
|
},
|
|
3599
|
+
reorderSelectedSection(from, to, scope) {
|
|
3600
|
+
if (scope !== targetKey(selectedTarget())) return;
|
|
3601
|
+
const layout = resolveTarget(selectedTarget()).layout;
|
|
3602
|
+
setSelectedSessionLayout({ order: reorderItems(layout.order, from, to, (id) => id) });
|
|
3603
|
+
},
|
|
3582
3604
|
previewLayoutPreset(preset) {
|
|
3583
3605
|
return layoutPresetPreview(selectedLayoutResolved().layout, preset);
|
|
3584
3606
|
},
|
|
@@ -3876,10 +3898,16 @@ function sourceIdentity(item) {
|
|
|
3876
3898
|
version: item.source.version
|
|
3877
3899
|
} : item?.source);
|
|
3878
3900
|
}
|
|
3879
|
-
function createMainPluginUpdate(context) {
|
|
3901
|
+
function createMainPluginUpdate(context, changed = () => {}) {
|
|
3880
3902
|
let prepared;
|
|
3881
3903
|
let busy = false;
|
|
3904
|
+
let phase = "idle";
|
|
3905
|
+
const report = (next) => {
|
|
3906
|
+
phase = next;
|
|
3907
|
+
changed();
|
|
3908
|
+
};
|
|
3882
3909
|
return {
|
|
3910
|
+
state: () => ({ phase }),
|
|
3883
3911
|
async check(_input, caller) {
|
|
3884
3912
|
if (busy) throw new Error("Navigator installation is already in progress");
|
|
3885
3913
|
prepared = void 0;
|
|
@@ -3921,6 +3949,7 @@ function createMainPluginUpdate(context) {
|
|
|
3921
3949
|
async install(input, caller) {
|
|
3922
3950
|
if (busy || !prepared || input.token !== prepared.token) throw new Error("Update confirmation expired. Check again.");
|
|
3923
3951
|
busy = true;
|
|
3952
|
+
report("preparing");
|
|
3924
3953
|
const expected = prepared;
|
|
3925
3954
|
prepared = void 0;
|
|
3926
3955
|
try {
|
|
@@ -3933,12 +3962,14 @@ function createMainPluginUpdate(context) {
|
|
|
3933
3962
|
const response = await client.plugin.list({}, { signal });
|
|
3934
3963
|
const item = response.data.find((entry) => entry.id === context.id);
|
|
3935
3964
|
if (context.client !== client || sourceIdentity(item) !== expected.source || packageTarget(item) !== expected.target) throw new Error("Navigator installation changed. Check again before installing.");
|
|
3965
|
+
report("installing");
|
|
3936
3966
|
await client.plugin.update({
|
|
3937
3967
|
location: response.location,
|
|
3938
3968
|
targets: [expected.target]
|
|
3939
3969
|
}, { signal });
|
|
3940
3970
|
} finally {
|
|
3941
3971
|
busy = false;
|
|
3972
|
+
report("idle");
|
|
3942
3973
|
}
|
|
3943
3974
|
}
|
|
3944
3975
|
};
|
|
@@ -4646,6 +4677,13 @@ function localCodexIpc(pluginID) {
|
|
|
4646
4677
|
function pluginUpdateIpc(pluginID) {
|
|
4647
4678
|
return _opencode_plugin_gui.Ipc.define({
|
|
4648
4679
|
id: `${pluginID}.package-update`,
|
|
4680
|
+
state: effect.Schema.Struct({ phase: effect.Schema.Literals([
|
|
4681
|
+
"idle",
|
|
4682
|
+
"preparing",
|
|
4683
|
+
"downloading",
|
|
4684
|
+
"installing",
|
|
4685
|
+
"verifying"
|
|
4686
|
+
]) }),
|
|
4649
4687
|
methods: {
|
|
4650
4688
|
check: { output: effect.Schema.Struct({
|
|
4651
4689
|
status: effect.Schema.Literals([
|
|
@@ -4675,14 +4713,15 @@ function preferencesIpc(pluginID) {
|
|
|
4675
4713
|
var main = (context) => {
|
|
4676
4714
|
const store = desktopPreferencesStore();
|
|
4677
4715
|
const readAccount = createMainAccountReader(context);
|
|
4678
|
-
const codex = createNodeCodexClient({ version: "0.27.
|
|
4716
|
+
const codex = createNodeCodexClient({ version: "0.27.3" });
|
|
4679
4717
|
context.onCleanup(codex.dispose);
|
|
4680
4718
|
context.provide(preferencesIpc(context.id), createMainPreferencesHandlers(store));
|
|
4681
4719
|
context.provide(localAccountIpc(context.id), { read: readAccount });
|
|
4682
4720
|
context.provide(localCodexIpc(context.id), createMainCodexHandlers(context, store, codex));
|
|
4683
|
-
|
|
4721
|
+
const updateImpl = createMainPluginUpdate(context, () => updateProvider.changed());
|
|
4722
|
+
const updateProvider = context.provide(pluginUpdateIpc(context.id), updateImpl);
|
|
4684
4723
|
context.provide(bugReportIpc(context.id), createMainBugReport(context.signal));
|
|
4685
|
-
context.log.write("info", `Navigator 0.27.
|
|
4724
|
+
context.log.write("info", `Navigator 0.27.3 Desktop main ready`);
|
|
4686
4725
|
};
|
|
4687
4726
|
// src/pages/navigator/ui/gui/context.tsx
|
|
4688
4727
|
var NavigatorGuiContext = (0, solid_js.createContext)();
|
|
@@ -4692,11 +4731,11 @@ function useNavigatorGui() {
|
|
|
4692
4731
|
return services;
|
|
4693
4732
|
}
|
|
4694
4733
|
// src/pages/navigator/ui/gui/bookmark.tsx
|
|
4695
|
-
var _tmpl$$
|
|
4734
|
+
var _tmpl$$60 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=width:24px;flex-shrink:0><button type=button style=width:24px;height:24px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:4px;color:inherit><svg width=12 height=16 viewBox="0 0 14 18"aria-hidden=true><path d="M3 2H11V15L7 12L3 15Z"stroke=currentColor stroke-width=1.5>`);
|
|
4696
4735
|
function SidebarBookmark(props) {
|
|
4697
4736
|
const label = () => `${props.selected ? "Unbookmark" : "Bookmark"} ${props.title}`;
|
|
4698
4737
|
return (() => {
|
|
4699
|
-
var _el$ = _tmpl$$
|
|
4738
|
+
var _el$ = _tmpl$$60(), _el$2 = _el$.firstChild, _el$4 = _el$2.firstChild.firstChild;
|
|
4700
4739
|
_el$2.$$click = (event) => {
|
|
4701
4740
|
event.stopPropagation();
|
|
4702
4741
|
props.toggle();
|
|
@@ -4725,7 +4764,7 @@ function SidebarBookmark(props) {
|
|
|
4725
4764
|
}
|
|
4726
4765
|
(0, solid_js_web.delegateEvents)(["click"]);
|
|
4727
4766
|
// src/pages/navigator/ui/gui/catalog-row.tsx
|
|
4728
|
-
var _tmpl$$
|
|
4767
|
+
var _tmpl$$59 = /*#__PURE__*/ (0, solid_js_web.template)(`<li style="display:flex;gap:4px;align-items:center;min-width:0;padding:3px 0"><button type=button style=flex:1;min-width:0;display:flex;gap:6px;align-items:center;text-align:left;padding:4px;color:inherit;border:0;border-radius:6px><span style=min-width:0;flex:1><span style=display:block;overflow-wrap:anywhere></span><span style=display:block;opacity:0.65;font-size:12px;overflow-wrap:anywhere>`);
|
|
4729
4768
|
function navigate$1(event) {
|
|
4730
4769
|
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
4731
4770
|
const buttons = [...event.currentTarget.querySelectorAll("button:not(:disabled)")];
|
|
@@ -4740,7 +4779,7 @@ function CatalogRow(props) {
|
|
|
4740
4779
|
const [hovered, setHovered] = (0, solid_js.createSignal)(false);
|
|
4741
4780
|
const [focused, setFocused] = (0, solid_js.createSignal)(false);
|
|
4742
4781
|
return (() => {
|
|
4743
|
-
var _el$ = _tmpl$$
|
|
4782
|
+
var _el$ = _tmpl$$59(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling;
|
|
4744
4783
|
_el$.$$keydown = navigate$1;
|
|
4745
4784
|
_el$.$$focusout = (event) => {
|
|
4746
4785
|
if (!event.currentTarget.contains(event.relatedTarget)) setFocused(false);
|
|
@@ -4842,15 +4881,19 @@ function GuiActionRow(props) {
|
|
|
4842
4881
|
});
|
|
4843
4882
|
}
|
|
4844
4883
|
// src/pages/navigator/ui/gui/section.tsx
|
|
4845
|
-
var _tmpl$$
|
|
4884
|
+
var _tmpl$$58 = /*#__PURE__*/ (0, solid_js_web.template)(`<section style=min-width:0><div style=display:flex;gap:8px;align-items:center;min-width:0><h2 style=flex:1;min-width:0;font-size:13px;font-weight:600;margin:0><button type=button style="display:flex;gap:6px;align-items:center;width:100%;padding:3px 0;color:inherit;background:transparent;border:0;text-align:left"><span aria-hidden=true data-navigator-disclosure style=display:inline-flex;width:16px;height:16px;flex-shrink:0;align-items:center;justify-content:center></span><span style=overflow:hidden;text-overflow:ellipsis;white-space:nowrap></span><span style=opacity:0.55;font-weight:400>`);
|
|
4846
4885
|
function MonitoringSection(props) {
|
|
4847
4886
|
const services = useNavigatorGui();
|
|
4848
4887
|
const preferences = () => services.runtime.catalogs?.preferences;
|
|
4849
4888
|
const expanded = () => preferences()?.expanded()[props.id] ?? true;
|
|
4889
|
+
const Icon = services.ui.Icon;
|
|
4850
4890
|
return (() => {
|
|
4851
|
-
var _el$ = _tmpl$$
|
|
4891
|
+
var _el$ = _tmpl$$58(), _el$2 = _el$.firstChild, _el$4 = _el$2.firstChild.firstChild, _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling, _el$7 = _el$6.nextSibling;
|
|
4852
4892
|
_el$4.$$click = () => preferences()?.toggleSectionExpanded(props.id);
|
|
4853
|
-
(0, solid_js_web.insert)(_el$5, ()
|
|
4893
|
+
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(Icon, {
|
|
4894
|
+
name: "chevron-down",
|
|
4895
|
+
size: "small"
|
|
4896
|
+
}));
|
|
4854
4897
|
(0, solid_js_web.insert)(_el$6, () => props.title);
|
|
4855
4898
|
(0, solid_js_web.insert)(_el$7, () => props.count);
|
|
4856
4899
|
(0, solid_js_web.insert)(_el$2, () => props.actions, null);
|
|
@@ -4863,24 +4906,26 @@ function MonitoringSection(props) {
|
|
|
4863
4906
|
}
|
|
4864
4907
|
}), null);
|
|
4865
4908
|
(0, solid_js_web.effect)((_p$) => {
|
|
4866
|
-
var _v$ = props.title, _v$2 = expanded();
|
|
4909
|
+
var _v$ = props.title, _v$2 = expanded(), _v$3 = expanded() ? "rotate(0deg)" : "rotate(-90deg)";
|
|
4867
4910
|
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "aria-label", _p$.e = _v$);
|
|
4868
4911
|
_v$2 !== _p$.t && (0, solid_js_web.setAttribute)(_el$4, "aria-expanded", _p$.t = _v$2);
|
|
4912
|
+
_v$3 !== _p$.a && (0, solid_js_web.setStyleProperty)(_el$5, "transform", _p$.a = _v$3);
|
|
4869
4913
|
return _p$;
|
|
4870
4914
|
}, {
|
|
4871
4915
|
e: void 0,
|
|
4872
|
-
t: void 0
|
|
4916
|
+
t: void 0,
|
|
4917
|
+
a: void 0
|
|
4873
4918
|
});
|
|
4874
4919
|
return _el$;
|
|
4875
4920
|
})();
|
|
4876
4921
|
}
|
|
4877
4922
|
(0, solid_js_web.delegateEvents)(["click"]);
|
|
4878
4923
|
// src/pages/navigator/ui/gui/section-filter.tsx
|
|
4879
|
-
var _tmpl$$
|
|
4924
|
+
var _tmpl$$57 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style="margin:8px 0">`);
|
|
4880
4925
|
function SectionFilter(props) {
|
|
4881
4926
|
const TextInput = useNavigatorGui().ui.TextInput;
|
|
4882
4927
|
return (() => {
|
|
4883
|
-
var _el$ = _tmpl$$
|
|
4928
|
+
var _el$ = _tmpl$$57();
|
|
4884
4929
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(TextInput, {
|
|
4885
4930
|
get label() {
|
|
4886
4931
|
return props.label;
|
|
@@ -4900,9 +4945,9 @@ function SectionFilter(props) {
|
|
|
4900
4945
|
})();
|
|
4901
4946
|
}
|
|
4902
4947
|
// src/pages/navigator/ui/gui/actions-section.tsx
|
|
4903
|
-
var _tmpl$$
|
|
4904
|
-
var _tmpl$2$
|
|
4905
|
-
var _tmpl$3$
|
|
4948
|
+
var _tmpl$$56 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>No matching actions.`);
|
|
4949
|
+
var _tmpl$2$38 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;flex-direction:column;gap:12px>`);
|
|
4950
|
+
var _tmpl$3$24 = /*#__PURE__*/ (0, solid_js_web.template)(`<ul style=margin:0;padding:0;list-style:none>`);
|
|
4906
4951
|
function ActionsSection() {
|
|
4907
4952
|
const services = useNavigatorGui();
|
|
4908
4953
|
const catalogs = () => services.runtime.catalogs;
|
|
@@ -4927,13 +4972,13 @@ function ActionsSection() {
|
|
|
4927
4972
|
}
|
|
4928
4973
|
}),
|
|
4929
4974
|
(() => {
|
|
4930
|
-
var _el$ = _tmpl$2$
|
|
4975
|
+
var _el$ = _tmpl$2$38();
|
|
4931
4976
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
4932
4977
|
get each() {
|
|
4933
4978
|
return [true, false].filter((selected) => view().visibility.visible().some((id) => catalogs().preferences.favoriteQuickActions().has(id) === selected));
|
|
4934
4979
|
},
|
|
4935
4980
|
children: (selected) => (() => {
|
|
4936
|
-
var _el$3 = _tmpl$3$
|
|
4981
|
+
var _el$3 = _tmpl$3$24();
|
|
4937
4982
|
(0, solid_js_web.insert)(_el$3, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
4938
4983
|
get each() {
|
|
4939
4984
|
return view().visibility.visible().filter((id) => catalogs().preferences.favoriteQuickActions().has(id) === selected);
|
|
@@ -4948,7 +4993,7 @@ function ActionsSection() {
|
|
|
4948
4993
|
return view().filtered().length === 0;
|
|
4949
4994
|
},
|
|
4950
4995
|
get children() {
|
|
4951
|
-
return _tmpl$$
|
|
4996
|
+
return _tmpl$$56();
|
|
4952
4997
|
}
|
|
4953
4998
|
}), null);
|
|
4954
4999
|
return _el$;
|
|
@@ -4972,52 +5017,690 @@ function ActionsSection() {
|
|
|
4972
5017
|
}
|
|
4973
5018
|
});
|
|
4974
5019
|
}
|
|
4975
|
-
// src/
|
|
4976
|
-
var _tmpl$$
|
|
4977
|
-
|
|
4978
|
-
|
|
5020
|
+
// src/shared/ui/gui/tabs.tsx
|
|
5021
|
+
var _tmpl$$55 = /*#__PURE__*/ (0, solid_js_web.template)(`<nav style=display:flex;gap:4px;flex-wrap:wrap>`);
|
|
5022
|
+
var _tmpl$2$37 = /*#__PURE__*/ (0, solid_js_web.template)(`<span>`);
|
|
5023
|
+
var _tmpl$3$23 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=opacity:0.6;font-weight:400>`);
|
|
5024
|
+
function GuiTabs(props) {
|
|
5025
|
+
const Button = props.ui.Button;
|
|
5026
|
+
function navigate(event) {
|
|
5027
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
5028
|
+
const enabled = props.options.filter((option) => !option.disabled);
|
|
5029
|
+
if (enabled.length === 0) return;
|
|
5030
|
+
event.preventDefault();
|
|
5031
|
+
event.stopPropagation();
|
|
5032
|
+
const next = (enabled.findIndex((option) => option.id === props.selected) + (event.key === "ArrowRight" ? 1 : -1) + enabled.length) % enabled.length;
|
|
5033
|
+
props.onSelect(enabled[next].id);
|
|
5034
|
+
event.currentTarget.querySelectorAll("button:not(:disabled)")[next]?.focus();
|
|
5035
|
+
}
|
|
4979
5036
|
return (() => {
|
|
4980
|
-
var _el$ = _tmpl$$
|
|
4981
|
-
|
|
4982
|
-
(0, solid_js_web.insert)(_el
|
|
5037
|
+
var _el$ = _tmpl$$55();
|
|
5038
|
+
_el$.$$keydown = navigate;
|
|
5039
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5040
|
+
get each() {
|
|
5041
|
+
return props.options.map((option) => option.id);
|
|
5042
|
+
},
|
|
5043
|
+
children: (id) => {
|
|
5044
|
+
const option = () => props.options.find((item) => item.id === id);
|
|
5045
|
+
return (0, solid_js_web.createComponent)(Button, {
|
|
5046
|
+
size: "small",
|
|
5047
|
+
get disabled() {
|
|
5048
|
+
return option().disabled;
|
|
5049
|
+
},
|
|
5050
|
+
get variant() {
|
|
5051
|
+
return props.selected === id ? "neutral" : "ghost-muted";
|
|
5052
|
+
},
|
|
5053
|
+
onClick: () => props.onSelect(id),
|
|
5054
|
+
get children() {
|
|
5055
|
+
return [(() => {
|
|
5056
|
+
var _el$2 = _tmpl$2$37();
|
|
5057
|
+
(0, solid_js_web.insert)(_el$2, () => option().label);
|
|
5058
|
+
(0, solid_js_web.effect)((_$p) => (0, solid_js_web.setStyleProperty)(_el$2, "font-weight", props.selected === id ? "600" : "400"));
|
|
5059
|
+
return _el$2;
|
|
5060
|
+
})(), (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5061
|
+
get when() {
|
|
5062
|
+
return option().count !== void 0;
|
|
5063
|
+
},
|
|
5064
|
+
get children() {
|
|
5065
|
+
var _el$3 = _tmpl$3$23();
|
|
5066
|
+
(0, solid_js_web.insert)(_el$3, () => option().count);
|
|
5067
|
+
return _el$3;
|
|
5068
|
+
}
|
|
5069
|
+
})];
|
|
5070
|
+
}
|
|
5071
|
+
});
|
|
5072
|
+
}
|
|
5073
|
+
}));
|
|
5074
|
+
(0, solid_js_web.effect)(() => (0, solid_js_web.setAttribute)(_el$, "aria-label", props.label));
|
|
5075
|
+
return _el$;
|
|
5076
|
+
})();
|
|
5077
|
+
}
|
|
5078
|
+
(0, solid_js_web.delegateEvents)(["keydown"]);
|
|
5079
|
+
// src/shared/lib/icon-choices/index.ts
|
|
5080
|
+
var ICON_CHOICE_IDS = [
|
|
5081
|
+
"plus",
|
|
5082
|
+
"check",
|
|
5083
|
+
"circle",
|
|
5084
|
+
"star",
|
|
5085
|
+
"pin",
|
|
5086
|
+
"bolt",
|
|
5087
|
+
"book",
|
|
5088
|
+
"search",
|
|
5089
|
+
"code",
|
|
5090
|
+
"terminal",
|
|
5091
|
+
"gear",
|
|
5092
|
+
"shield",
|
|
5093
|
+
"lock",
|
|
5094
|
+
"unlock",
|
|
5095
|
+
"eye",
|
|
5096
|
+
"clock",
|
|
5097
|
+
"refresh",
|
|
5098
|
+
"history",
|
|
5099
|
+
"copy",
|
|
5100
|
+
"export",
|
|
5101
|
+
"edit",
|
|
5102
|
+
"fork",
|
|
5103
|
+
"list",
|
|
5104
|
+
"play",
|
|
5105
|
+
"pause",
|
|
5106
|
+
"stop",
|
|
5107
|
+
"rocket",
|
|
5108
|
+
"bug",
|
|
5109
|
+
"beaker",
|
|
5110
|
+
"wand",
|
|
5111
|
+
"cloud",
|
|
5112
|
+
"server",
|
|
5113
|
+
"folder",
|
|
5114
|
+
"file",
|
|
5115
|
+
"heart",
|
|
5116
|
+
"lightbulb",
|
|
5117
|
+
"arrow-up",
|
|
5118
|
+
"arrow-down",
|
|
5119
|
+
"warning",
|
|
5120
|
+
"close"
|
|
5121
|
+
];
|
|
5122
|
+
var choices = new Set(ICON_CHOICE_IDS);
|
|
5123
|
+
function isIconChoiceId(value) {
|
|
5124
|
+
return choices.has(value);
|
|
5125
|
+
}
|
|
5126
|
+
function iconChoiceLabel(id) {
|
|
5127
|
+
return id.replaceAll("-", " ");
|
|
5128
|
+
}
|
|
5129
|
+
// src/shared/ui/gui/icon.tsx
|
|
5130
|
+
var _tmpl$$54 = /*#__PURE__*/ (0, solid_js_web.template)(`<span aria-hidden=true style=display:inline-flex;width:18px;height:18px;flex-shrink:0;align-items:center;justify-content:center>`);
|
|
5131
|
+
var _tmpl$2$36 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg width=16 height=16 viewBox="0 0 24 26"fill=none stroke=currentColor stroke-width=1.7 stroke-linecap=round stroke-linejoin=round>`);
|
|
5132
|
+
var _tmpl$3$22 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg><path></svg>`, false, true, false);
|
|
5133
|
+
var native = {
|
|
5134
|
+
plus: "plus",
|
|
5135
|
+
check: "check",
|
|
5136
|
+
search: "magnifying-glass",
|
|
5137
|
+
code: "code",
|
|
5138
|
+
terminal: "terminal",
|
|
5139
|
+
gear: "settings-gear",
|
|
5140
|
+
shield: "shield",
|
|
5141
|
+
lock: "lock",
|
|
5142
|
+
eye: "eye",
|
|
5143
|
+
refresh: "refresh",
|
|
5144
|
+
copy: "copy",
|
|
5145
|
+
export: "share",
|
|
5146
|
+
edit: "edit",
|
|
5147
|
+
fork: "fork",
|
|
5148
|
+
list: "bullet-list",
|
|
5149
|
+
stop: "stop",
|
|
5150
|
+
beaker: "flask",
|
|
5151
|
+
server: "server",
|
|
5152
|
+
folder: "folder",
|
|
5153
|
+
file: "file-document",
|
|
5154
|
+
"arrow-up": "arrow-up",
|
|
5155
|
+
warning: "warning",
|
|
5156
|
+
close: "close"
|
|
5157
|
+
};
|
|
5158
|
+
var paths = {
|
|
5159
|
+
circle: ["M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0Z"],
|
|
5160
|
+
star: ["m12 3 2.7 5.5 6.1.9-4.4 4.3 1 6.1-5.4-2.9-5.4 2.9 1-6.1-4.4-4.3 6.1-.9Z"],
|
|
5161
|
+
pin: ["m9 3 6 0-1 6 4 4H6l4-4Z", "M12 13v8"],
|
|
5162
|
+
bolt: ["m13 2-8 12h6l-1 8 9-13h-7Z"],
|
|
5163
|
+
book: ["M3 4h7l2 2 2-2h7v15h-7l-2 2-2-2H3Z", "M12 6v15"],
|
|
5164
|
+
unlock: [
|
|
5165
|
+
"M7 10V7a5 5 0 0 1 9-3",
|
|
5166
|
+
"M5 10h14v11H5Z",
|
|
5167
|
+
"M12 14v3"
|
|
5168
|
+
],
|
|
5169
|
+
clock: ["M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0Z", "M12 7v5l3 2"],
|
|
5170
|
+
history: [
|
|
5171
|
+
"M4 8a9 9 0 1 1-1 7",
|
|
5172
|
+
"M4 3v5h5",
|
|
5173
|
+
"M12 7v5l3 2"
|
|
5174
|
+
],
|
|
5175
|
+
play: ["m7 4 13 8-13 8Z"],
|
|
5176
|
+
pause: ["M8 4v16", "M16 4v16"],
|
|
5177
|
+
rocket: [
|
|
5178
|
+
"M9 16c0-8 6-13 12-13 0 6-5 12-13 12Z",
|
|
5179
|
+
"m9 8-5 1-2 6 6-1",
|
|
5180
|
+
"m16 15-1 5-6 2 1-6",
|
|
5181
|
+
"m5 17-3 5 5-3"
|
|
5182
|
+
],
|
|
5183
|
+
bug: [
|
|
5184
|
+
"M8 10h8v6a4 4 0 0 1-8 0Z",
|
|
5185
|
+
"M9 10V8a3 3 0 0 1 6 0v2",
|
|
5186
|
+
"M5 7l3 4M19 7l-3 4M3 14h5m8 0h5M5 21l4-3m6 0 4 3M12 11v9"
|
|
5187
|
+
],
|
|
5188
|
+
wand: ["m4 20 13-13 3 3L7 23Z", "M5 3v6M2 6h6M18 1v4M16 3h4"],
|
|
5189
|
+
cloud: ["M7 19a5 5 0 1 1 0-10 6 6 0 0 1 11-1 5.5 5.5 0 0 1 0 11Z"],
|
|
5190
|
+
heart: ["M12 21 3.5 12.5a5.5 5.5 0 0 1 8.5-7 5.5 5.5 0 0 1 8.5 7Z"],
|
|
5191
|
+
lightbulb: ["M9 18v-2a7 7 0 1 1 6 0v2Z", "M9 21h6M10 24h4"],
|
|
5192
|
+
"arrow-down": ["M12 3v18", "m5 14 7 7 7-7"]
|
|
5193
|
+
};
|
|
5194
|
+
function GuiIcon(props) {
|
|
5195
|
+
const Icon = props.ui.Icon;
|
|
5196
|
+
const id = () => isIconChoiceId(props.id) ? props.id : "bolt";
|
|
5197
|
+
return (() => {
|
|
5198
|
+
var _el$ = _tmpl$$54();
|
|
5199
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5200
|
+
get when() {
|
|
5201
|
+
return native[id()];
|
|
5202
|
+
},
|
|
5203
|
+
get fallback() {
|
|
5204
|
+
return (() => {
|
|
5205
|
+
var _el$2 = _tmpl$2$36();
|
|
5206
|
+
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5207
|
+
get each() {
|
|
5208
|
+
return paths[id()] ?? paths.bolt;
|
|
5209
|
+
},
|
|
5210
|
+
children: (path) => (() => {
|
|
5211
|
+
var _el$3 = _tmpl$3$22();
|
|
5212
|
+
(0, solid_js_web.setAttribute)(_el$3, "d", path);
|
|
5213
|
+
return _el$3;
|
|
5214
|
+
})()
|
|
5215
|
+
}));
|
|
5216
|
+
return _el$2;
|
|
5217
|
+
})();
|
|
5218
|
+
},
|
|
5219
|
+
children: (name) => (0, solid_js_web.createComponent)(Icon, {
|
|
5220
|
+
get name() {
|
|
5221
|
+
return name();
|
|
5222
|
+
},
|
|
5223
|
+
size: "small"
|
|
5224
|
+
})
|
|
5225
|
+
}));
|
|
5226
|
+
return _el$;
|
|
5227
|
+
})();
|
|
5228
|
+
}
|
|
5229
|
+
// src/shared/ui/gui/multiline-field.tsx
|
|
5230
|
+
var _tmpl$$53 = /*#__PURE__*/ (0, solid_js_web.template)(`<label style=display:grid;gap:8px><span></span><textarea style="width:100%;box-sizing:border-box;min-height:160px;max-height:40vh;resize:vertical;color:var(--v2-text-text-base, inherit);background:var(--v2-background-bg-base, transparent);border:0;caret-color:var(--v2-text-text-base, auto);border-radius:6px;padding:8px;font:inherit">`);
|
|
5231
|
+
function GuiMultilineField(props) {
|
|
5232
|
+
const id = (0, solid_js.createUniqueId)();
|
|
5233
|
+
const [focused, setFocused] = (0, solid_js.createSignal)(false);
|
|
5234
|
+
return (() => {
|
|
5235
|
+
var _el$ = _tmpl$$53(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
5236
|
+
(0, solid_js_web.setAttribute)(_el$, "for", id);
|
|
5237
|
+
(0, solid_js_web.insert)(_el$2, () => props.label);
|
|
5238
|
+
_el$3.$$input = (event) => props.onInput(event.currentTarget.value);
|
|
5239
|
+
_el$3.addEventListener("blur", () => setFocused(false));
|
|
5240
|
+
_el$3.addEventListener("focus", () => setFocused(true));
|
|
5241
|
+
(0, solid_js_web.setAttribute)(_el$3, "id", id);
|
|
4983
5242
|
(0, solid_js_web.effect)((_p$) => {
|
|
4984
|
-
var _v$ = props.
|
|
4985
|
-
_v$ !== _p$.e && (
|
|
4986
|
-
_v$2 !== _p$.t && (0, solid_js_web.
|
|
4987
|
-
_v$3 !== _p$.a && (0, solid_js_web.
|
|
4988
|
-
_v$4 !== _p$.o && (0, solid_js_web.
|
|
4989
|
-
_v$5 !== _p$.i && (0, solid_js_web.setStyleProperty)(_el$3, "width", _p$.i = _v$5);
|
|
5243
|
+
var _v$ = props.disabled, _v$2 = focused() ? "1px solid var(--v2-border-border-focus)" : "1px solid transparent", _v$3 = focused() ? "none" : "var(--v2-elevation-input)", _v$4 = props.disabled ? "0.5" : "1";
|
|
5244
|
+
_v$ !== _p$.e && (_el$3.disabled = _p$.e = _v$);
|
|
5245
|
+
_v$2 !== _p$.t && (0, solid_js_web.setStyleProperty)(_el$3, "outline", _p$.t = _v$2);
|
|
5246
|
+
_v$3 !== _p$.a && (0, solid_js_web.setStyleProperty)(_el$3, "box-shadow", _p$.a = _v$3);
|
|
5247
|
+
_v$4 !== _p$.o && (0, solid_js_web.setStyleProperty)(_el$3, "opacity", _p$.o = _v$4);
|
|
4990
5248
|
return _p$;
|
|
4991
5249
|
}, {
|
|
4992
5250
|
e: void 0,
|
|
4993
5251
|
t: void 0,
|
|
4994
5252
|
a: void 0,
|
|
4995
|
-
o: void 0
|
|
4996
|
-
i: void 0
|
|
5253
|
+
o: void 0
|
|
4997
5254
|
});
|
|
5255
|
+
(0, solid_js_web.effect)(() => _el$3.value = props.value);
|
|
4998
5256
|
return _el$;
|
|
4999
5257
|
})();
|
|
5000
5258
|
}
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
var _tmpl
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
const
|
|
5008
|
-
const
|
|
5009
|
-
const
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5259
|
+
(0, solid_js_web.delegateEvents)(["input"]);
|
|
5260
|
+
// src/shared/ui/gui/group-control.tsx
|
|
5261
|
+
var _tmpl$$52 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=group style=display:flex;gap:8px;flex-wrap:wrap>`);
|
|
5262
|
+
function GuiGroupControl(props) {
|
|
5263
|
+
const Select = props.ui.Select;
|
|
5264
|
+
const TextInput = props.ui.TextInput;
|
|
5265
|
+
const Button = props.ui.Button;
|
|
5266
|
+
const [draft, setDraft] = (0, solid_js.createSignal)("");
|
|
5267
|
+
const [creating, setCreating] = (0, solid_js.createSignal)(false);
|
|
5268
|
+
(0, solid_js.createEffect)(() => setDraft(props.value ?? ""));
|
|
5269
|
+
return (() => {
|
|
5270
|
+
var _el$ = _tmpl$$52();
|
|
5271
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Select, {
|
|
5272
|
+
get label() {
|
|
5273
|
+
return `${props.label} existing group`;
|
|
5274
|
+
},
|
|
5275
|
+
get value() {
|
|
5276
|
+
return (0, solid_js_web.memo)(() => !!props.groups.includes(draft()))() ? draft() : "";
|
|
5277
|
+
},
|
|
5278
|
+
get options() {
|
|
5279
|
+
return [{
|
|
5280
|
+
value: "",
|
|
5281
|
+
label: "Ungrouped"
|
|
5282
|
+
}, ...props.groups.map((value) => ({
|
|
5283
|
+
value,
|
|
5284
|
+
label: value
|
|
5285
|
+
}))];
|
|
5286
|
+
},
|
|
5287
|
+
onChange: (value) => {
|
|
5288
|
+
setDraft(value);
|
|
5289
|
+
setCreating(false);
|
|
5290
|
+
},
|
|
5291
|
+
get disabled() {
|
|
5292
|
+
return props.disabled;
|
|
5293
|
+
}
|
|
5294
|
+
}), null);
|
|
5295
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
5296
|
+
size: "small",
|
|
5297
|
+
variant: "ghost",
|
|
5298
|
+
get disabled() {
|
|
5299
|
+
return props.disabled;
|
|
5300
|
+
},
|
|
5301
|
+
onClick: () => {
|
|
5302
|
+
setCreating(true);
|
|
5303
|
+
setDraft("");
|
|
5304
|
+
},
|
|
5305
|
+
children: "New group"
|
|
5306
|
+
}), null);
|
|
5307
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5308
|
+
get when() {
|
|
5309
|
+
return creating();
|
|
5310
|
+
},
|
|
5311
|
+
get children() {
|
|
5312
|
+
return (0, solid_js_web.createComponent)(TextInput, {
|
|
5313
|
+
get label() {
|
|
5314
|
+
return `${props.label} new group`;
|
|
5315
|
+
},
|
|
5316
|
+
get value() {
|
|
5317
|
+
return draft();
|
|
5318
|
+
},
|
|
5319
|
+
onInput: setDraft,
|
|
5320
|
+
get disabled() {
|
|
5321
|
+
return props.disabled;
|
|
5322
|
+
},
|
|
5323
|
+
get invalid() {
|
|
5324
|
+
return draft().length > 64;
|
|
5325
|
+
}
|
|
5326
|
+
});
|
|
5327
|
+
}
|
|
5328
|
+
}), null);
|
|
5329
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5330
|
+
get when() {
|
|
5331
|
+
return creating() || draft() !== (props.value ?? "");
|
|
5332
|
+
},
|
|
5333
|
+
get children() {
|
|
5334
|
+
return [(0, solid_js_web.createComponent)(Button, {
|
|
5335
|
+
size: "small",
|
|
5336
|
+
get disabled() {
|
|
5337
|
+
return props.disabled || draft().length > 64 || creating() && !draft().trim();
|
|
5338
|
+
},
|
|
5339
|
+
onClick: () => {
|
|
5340
|
+
props.save(draft().trim() || void 0);
|
|
5341
|
+
setCreating(false);
|
|
5342
|
+
},
|
|
5343
|
+
children: "Save group"
|
|
5344
|
+
}), (0, solid_js_web.createComponent)(Button, {
|
|
5345
|
+
size: "small",
|
|
5346
|
+
variant: "ghost",
|
|
5347
|
+
onClick: () => {
|
|
5348
|
+
setDraft(props.value ?? "");
|
|
5349
|
+
setCreating(false);
|
|
5350
|
+
},
|
|
5351
|
+
children: "Cancel"
|
|
5352
|
+
})];
|
|
5353
|
+
}
|
|
5354
|
+
}), null);
|
|
5355
|
+
(0, solid_js_web.effect)(() => (0, solid_js_web.setAttribute)(_el$, "aria-label", `${props.label} grouping`));
|
|
5356
|
+
return _el$;
|
|
5357
|
+
})();
|
|
5358
|
+
}
|
|
5359
|
+
// src/shared/ui/gui/settings-surface.tsx
|
|
5360
|
+
var _tmpl$$51 = /*#__PURE__*/ (0, solid_js_web.template)(`<div data-navigator-settings><style>\n[data-navigator-settings] \{ display: grid; gap: 32px; min-width: 0; container-type: inline-size; }\n[data-navigator-settings] [data-component="settings-row"] \{ display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: 20px; }\n[data-navigator-settings] [data-slot="settings-row-copy"] \{ min-width: 0; overflow-wrap: anywhere; }\n[data-navigator-settings] :is(button, input, textarea, [role="switch"]) \{ scroll-margin-block: 96px; }\n[data-navigator-settings] [data-slot="settings-row-control"] \{ min-width: 0; max-width: 100%; width: 100%; flex-wrap: wrap; gap: 8px; }\n[data-navigator-settings] [data-slot="settings-row-control"] > * \{ min-width: 0; max-width: 100%; }\n[data-navigator-settings] [data-slot="settings-row-control"] > div:not([data-component]) \{ width: 100%; flex-wrap: wrap; }\n[data-navigator-settings] [data-component="button-v2"] \{ white-space: normal; height: auto; min-height: 24px; overflow-wrap: anywhere; }\n[data-navigator-settings] [data-component="text-input-v2"] \{ min-width: 0; max-width: 100%; }\n[data-navigator-settings] [data-sortable-item]:not(:last-of-type) > [data-component="settings-row"] \{ border-bottom: 0.5px solid var(--v2-border-border-base); }\n@container (max-width: 640px) \{\n [data-navigator-settings] [data-component="settings-row"] \{ grid-template-columns: minmax(0, 1fr); gap: 12px; }\n [data-navigator-settings] [data-slot="settings-row-control"] \{ justify-content: flex-start; }\n}\n`);
|
|
5361
|
+
function GuiSettingsSurface(props) {
|
|
5362
|
+
return (() => {
|
|
5363
|
+
var _el$ = _tmpl$$51();
|
|
5364
|
+
_el$.firstChild;
|
|
5365
|
+
(0, solid_js_web.insert)(_el$, () => props.children, null);
|
|
5366
|
+
return _el$;
|
|
5367
|
+
})();
|
|
5368
|
+
}
|
|
5369
|
+
// src/shared/ui/gui/sortable-focus.ts
|
|
5370
|
+
function createSortableFocus(props) {
|
|
5371
|
+
let focused;
|
|
5372
|
+
(0, solid_js.createEffect)(() => {
|
|
5373
|
+
const keys = props.keys();
|
|
5374
|
+
const disabled = props.disabled();
|
|
5375
|
+
const key = focused;
|
|
5376
|
+
if (!key || disabled || !keys.includes(key)) return;
|
|
5377
|
+
queueMicrotask(() => {
|
|
5378
|
+
if (focused !== key || props.disabled() || document.activeElement !== document.body) return;
|
|
5379
|
+
[...props.root().querySelectorAll("[data-sortable-item]")].find((node) => node.dataset.sortableItem === key)?.querySelector("button")?.focus({ preventScroll: true });
|
|
5380
|
+
});
|
|
5381
|
+
});
|
|
5382
|
+
return {
|
|
5383
|
+
enter(event) {
|
|
5384
|
+
const target = event.target;
|
|
5385
|
+
focused = target.getAttribute("aria-label")?.startsWith("Reorder ") ? target.closest("[data-sortable-item]")?.dataset.sortableItem : void 0;
|
|
5386
|
+
},
|
|
5387
|
+
leave(event) {
|
|
5388
|
+
if (event.relatedTarget && !props.root().contains(event.relatedTarget)) focused = void 0;
|
|
5389
|
+
}
|
|
5390
|
+
};
|
|
5391
|
+
}
|
|
5392
|
+
// src/shared/ui/gui/sortable-interaction.ts
|
|
5393
|
+
function createSortableInteraction(props) {
|
|
5394
|
+
const [source, setSource] = (0, solid_js.createSignal)();
|
|
5395
|
+
const [target, setTarget] = (0, solid_js.createSignal)();
|
|
5396
|
+
const [announcement, setAnnouncement] = (0, solid_js.createSignal)("");
|
|
5397
|
+
let drag;
|
|
5398
|
+
const signature = () => JSON.stringify(props.keys());
|
|
5399
|
+
function cancel() {
|
|
5400
|
+
const previous = drag;
|
|
5401
|
+
drag = void 0;
|
|
5402
|
+
setSource(void 0);
|
|
5403
|
+
setTarget(void 0);
|
|
5404
|
+
if (previous && previous.pointer >= 0 && props.root().hasPointerCapture(previous.pointer)) props.root().releasePointerCapture(previous.pointer);
|
|
5405
|
+
}
|
|
5406
|
+
(0, solid_js.createEffect)(() => {
|
|
5407
|
+
source();
|
|
5408
|
+
if (drag && (props.disabled() || props.scope() !== drag.scope || signature() !== drag.keys)) cancel();
|
|
5409
|
+
});
|
|
5410
|
+
function escape(event) {
|
|
5411
|
+
if (event.key !== "Escape") return;
|
|
5412
|
+
event.preventDefault();
|
|
5413
|
+
event.stopPropagation();
|
|
5414
|
+
cancel();
|
|
5415
|
+
}
|
|
5416
|
+
(0, solid_js.createEffect)(() => {
|
|
5417
|
+
if (!source()) return;
|
|
5418
|
+
globalThis.window.addEventListener("keydown", escape, { capture: true });
|
|
5419
|
+
(0, solid_js.onCleanup)(() => globalThis.window.removeEventListener("keydown", escape, true));
|
|
5420
|
+
});
|
|
5421
|
+
(0, solid_js.onCleanup)(cancel);
|
|
5422
|
+
function hover(event) {
|
|
5423
|
+
if (!drag || event.pointerId !== drag.pointer) return;
|
|
5424
|
+
const node = document.elementFromPoint(event.clientX, event.clientY)?.closest("[data-sortable-item]");
|
|
5425
|
+
setTarget(node && props.root().contains(node) ? node.dataset.sortableItem : void 0);
|
|
5426
|
+
}
|
|
5427
|
+
function start(event, id) {
|
|
5428
|
+
if (event.button !== 0 || props.disabled() || drag) return;
|
|
5429
|
+
event.preventDefault();
|
|
5430
|
+
event.stopPropagation();
|
|
5431
|
+
drag = {
|
|
5432
|
+
id,
|
|
5433
|
+
pointer: event.pointerId,
|
|
5434
|
+
scope: props.scope(),
|
|
5435
|
+
keys: signature()
|
|
5436
|
+
};
|
|
5437
|
+
props.root().setPointerCapture(event.pointerId);
|
|
5438
|
+
setSource(id);
|
|
5439
|
+
setTarget(id);
|
|
5440
|
+
}
|
|
5441
|
+
function end(event) {
|
|
5442
|
+
if (!drag || event.pointerId !== drag.pointer) return;
|
|
5443
|
+
hover(event);
|
|
5444
|
+
const current = drag;
|
|
5445
|
+
const destination = target();
|
|
5446
|
+
const valid = !props.disabled() && props.scope() === current.scope && signature() === current.keys;
|
|
5447
|
+
cancel();
|
|
5448
|
+
if (valid && destination && current.id !== destination) props.move(current.id, destination);
|
|
5449
|
+
}
|
|
5450
|
+
function key(event, id) {
|
|
5451
|
+
if (event.key === "Escape") {
|
|
5452
|
+
if (drag) {
|
|
5453
|
+
event.preventDefault();
|
|
5454
|
+
event.stopPropagation();
|
|
5455
|
+
cancel();
|
|
5456
|
+
}
|
|
5457
|
+
return;
|
|
5458
|
+
}
|
|
5459
|
+
if (props.disabled()) return;
|
|
5460
|
+
if ([" ", "Enter"].includes(event.key) && !event.repeat) {
|
|
5461
|
+
event.preventDefault();
|
|
5462
|
+
event.stopPropagation();
|
|
5463
|
+
if (!drag) {
|
|
5464
|
+
drag = {
|
|
5465
|
+
id,
|
|
5466
|
+
pointer: -1,
|
|
5467
|
+
scope: props.scope(),
|
|
5468
|
+
keys: signature()
|
|
5469
|
+
};
|
|
5470
|
+
setSource(id);
|
|
5471
|
+
setTarget(id);
|
|
5472
|
+
setAnnouncement("Picked up. Use arrow keys, Space to drop, or Escape to cancel.");
|
|
5473
|
+
} else if (drag.pointer === -1 && drag.id === id) {
|
|
5474
|
+
const destination = target();
|
|
5475
|
+
const valid = props.scope() === drag.scope && signature() === drag.keys;
|
|
5476
|
+
cancel();
|
|
5477
|
+
if (valid && destination && destination !== id) props.move(id, destination);
|
|
5478
|
+
}
|
|
5479
|
+
return;
|
|
5480
|
+
}
|
|
5481
|
+
if (drag?.pointer !== -1 || drag.id !== id || !["ArrowUp", "ArrowDown"].includes(event.key)) return;
|
|
5482
|
+
const keys = props.keys();
|
|
5483
|
+
const index = keys.indexOf(target() ?? id);
|
|
5484
|
+
const destination = keys[index + (event.key === "ArrowUp" ? -1 : 1)];
|
|
5485
|
+
if (!destination || index === -1) return;
|
|
5486
|
+
event.preventDefault();
|
|
5487
|
+
event.stopPropagation();
|
|
5488
|
+
setTarget(destination);
|
|
5489
|
+
setAnnouncement(`Drop at position ${keys.indexOf(destination) + 1} of ${keys.length}`);
|
|
5490
|
+
}
|
|
5491
|
+
return {
|
|
5492
|
+
source,
|
|
5493
|
+
target,
|
|
5494
|
+
announcement,
|
|
5495
|
+
start,
|
|
5496
|
+
hover,
|
|
5497
|
+
end,
|
|
5498
|
+
key,
|
|
5499
|
+
cancel
|
|
5500
|
+
};
|
|
5501
|
+
}
|
|
5502
|
+
// src/shared/ui/gui/sortable-list.tsx
|
|
5503
|
+
var _tmpl$$50 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=list><span role=status aria-live=polite style=position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)>Drag a handle, or press Space, use arrow keys, then Space to drop. Escape cancels. `);
|
|
5504
|
+
var _tmpl$2$35 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=listitem>`);
|
|
5505
|
+
var _tmpl$3$21 = /*#__PURE__*/ (0, solid_js_web.template)(`<span title="Drag to reorder, or Space, arrow keys, Space. Escape cancels."style=display:inline-flex;touch-action:none;cursor:grab>`);
|
|
5506
|
+
function GuiSortableList(props) {
|
|
5507
|
+
let root;
|
|
5508
|
+
const help = (0, solid_js.createUniqueId)();
|
|
5509
|
+
const IconButton = props.ui.IconButton;
|
|
5510
|
+
const keys = () => props.items.map((item) => props.itemKey(item));
|
|
5511
|
+
const focus = createSortableFocus({
|
|
5512
|
+
root: () => root,
|
|
5513
|
+
keys,
|
|
5514
|
+
disabled: () => Boolean(props.disabled)
|
|
5515
|
+
});
|
|
5516
|
+
const interaction = createSortableInteraction({
|
|
5517
|
+
keys,
|
|
5518
|
+
scope: () => props.scope,
|
|
5519
|
+
disabled: () => Boolean(props.disabled),
|
|
5520
|
+
root: () => root,
|
|
5521
|
+
move: (from, to) => props.move(from, to)
|
|
5522
|
+
});
|
|
5523
|
+
return (() => {
|
|
5524
|
+
var _el$ = _tmpl$$50(), _el$2 = _el$.firstChild;
|
|
5525
|
+
_el$2.firstChild;
|
|
5526
|
+
(0, solid_js_web.addEventListener)(_el$, "lostpointercapture", interaction.cancel);
|
|
5527
|
+
(0, solid_js_web.addEventListener)(_el$, "pointercancel", interaction.cancel);
|
|
5528
|
+
(0, solid_js_web.addEventListener)(_el$, "pointerup", interaction.end, true);
|
|
5529
|
+
(0, solid_js_web.addEventListener)(_el$, "pointermove", interaction.hover, true);
|
|
5530
|
+
(0, solid_js_web.addEventListener)(_el$, "focusout", focus.leave, true);
|
|
5531
|
+
(0, solid_js_web.addEventListener)(_el$, "focusin", focus.enter, true);
|
|
5532
|
+
(0, solid_js_web.use)((node) => {
|
|
5533
|
+
root = node;
|
|
5534
|
+
}, _el$);
|
|
5535
|
+
(0, solid_js_web.setAttribute)(_el$, "aria-describedby", help);
|
|
5536
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5537
|
+
get each() {
|
|
5538
|
+
return keys();
|
|
5539
|
+
},
|
|
5540
|
+
children: (key) => {
|
|
5541
|
+
const item = () => props.items.find((value) => props.itemKey(value) === key);
|
|
5542
|
+
return (() => {
|
|
5543
|
+
var _el$4 = _tmpl$2$35();
|
|
5544
|
+
(0, solid_js_web.setAttribute)(_el$4, "data-sortable-item", key);
|
|
5545
|
+
(0, solid_js_web.insert)(_el$4, () => props.children(item, (() => {
|
|
5546
|
+
var _el$5 = _tmpl$3$21();
|
|
5547
|
+
_el$5.$$keydown = (event) => interaction.key(event, key);
|
|
5548
|
+
_el$5.$$pointerdown = (event) => interaction.start(event, key);
|
|
5549
|
+
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(IconButton, {
|
|
5550
|
+
icon: "dot-grid",
|
|
5551
|
+
get label() {
|
|
5552
|
+
return `Reorder ${props.itemLabel(item())}`;
|
|
5553
|
+
},
|
|
5554
|
+
get disabled() {
|
|
5555
|
+
return props.disabled || keys().length < 2;
|
|
5556
|
+
}
|
|
5557
|
+
}));
|
|
5558
|
+
return _el$5;
|
|
5559
|
+
})()));
|
|
5560
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
5561
|
+
var _v$ = keys().indexOf(key) + 1, _v$2 = keys().length, _v$3 = interaction.source() === key ? "0.65" : "1", _v$4 = interaction.target() === key && interaction.source() !== key ? "1px dashed var(--v2-border-border-focus)" : void 0;
|
|
5562
|
+
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$4, "aria-posinset", _p$.e = _v$);
|
|
5563
|
+
_v$2 !== _p$.t && (0, solid_js_web.setAttribute)(_el$4, "aria-setsize", _p$.t = _v$2);
|
|
5564
|
+
_v$3 !== _p$.a && (0, solid_js_web.setStyleProperty)(_el$4, "opacity", _p$.a = _v$3);
|
|
5565
|
+
_v$4 !== _p$.o && (0, solid_js_web.setStyleProperty)(_el$4, "outline", _p$.o = _v$4);
|
|
5566
|
+
return _p$;
|
|
5567
|
+
}, {
|
|
5568
|
+
e: void 0,
|
|
5569
|
+
t: void 0,
|
|
5570
|
+
a: void 0,
|
|
5571
|
+
o: void 0
|
|
5572
|
+
});
|
|
5573
|
+
return _el$4;
|
|
5574
|
+
})();
|
|
5575
|
+
}
|
|
5576
|
+
}), _el$2);
|
|
5577
|
+
(0, solid_js_web.setAttribute)(_el$2, "id", help);
|
|
5578
|
+
(0, solid_js_web.insert)(_el$2, () => interaction.announcement(), null);
|
|
5579
|
+
(0, solid_js_web.effect)(() => (0, solid_js_web.setAttribute)(_el$, "aria-label", props.label));
|
|
5580
|
+
return _el$;
|
|
5581
|
+
})();
|
|
5582
|
+
}
|
|
5583
|
+
(0, solid_js_web.delegateEvents)([
|
|
5584
|
+
"focusin",
|
|
5585
|
+
"focusout",
|
|
5586
|
+
"pointermove",
|
|
5587
|
+
"pointerup",
|
|
5588
|
+
"pointerdown",
|
|
5589
|
+
"keydown"
|
|
5590
|
+
]);
|
|
5591
|
+
// src/shared/ui/gui/progress.tsx
|
|
5592
|
+
var _tmpl$$49 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=progressbar aria-valuemin=0 aria-valuemax=100 style=display:grid;gap:6px;min-width:0><style>@keyframes navigator-install-pulse \{ from \{ transform: translateX(-100%); } to \{ transform: translateX(400%); } }\n@media (prefers-reduced-motion: reduce) \{ [data-navigator-install-pulse] \{ animation: none !important; } }</style><span style=display:flex;gap:6px;align-items:center></span><span style=display:block;height:3px;overflow:hidden;background:var(--v2-border-border-base)><span style=display:block;height:100%;background:var(--v2-text-text-base)>`);
|
|
5593
|
+
function GuiProgress(props) {
|
|
5594
|
+
const Loader = props.ui.Loader;
|
|
5595
|
+
return (() => {
|
|
5596
|
+
var _el$ = _tmpl$$49(), _el$3 = _el$.firstChild.nextSibling, _el$5 = _el$3.nextSibling.firstChild;
|
|
5597
|
+
(0, solid_js_web.insert)(_el$3, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5598
|
+
get when() {
|
|
5599
|
+
return props.value === void 0;
|
|
5600
|
+
},
|
|
5601
|
+
get children() {
|
|
5602
|
+
return (0, solid_js_web.createComponent)(Loader, { size: "small" });
|
|
5603
|
+
}
|
|
5604
|
+
}), null);
|
|
5605
|
+
(0, solid_js_web.insert)(_el$3, () => props.label, null);
|
|
5606
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
5607
|
+
var _v$ = props.label, _v$2 = props.value === void 0 ? void 0 : Math.floor(props.value * 100), _v$3 = props.label, _v$4 = props.value === void 0 ? "" : void 0, _v$5 = props.value === void 0 ? "25%" : `${Math.min(1, Math.max(0, props.value)) * 100}%`, _v$6 = props.value === void 0 ? "navigator-install-pulse 1.2s linear infinite" : void 0;
|
|
5608
|
+
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "aria-label", _p$.e = _v$);
|
|
5609
|
+
_v$2 !== _p$.t && (0, solid_js_web.setAttribute)(_el$, "aria-valuenow", _p$.t = _v$2);
|
|
5610
|
+
_v$3 !== _p$.a && (0, solid_js_web.setAttribute)(_el$, "aria-valuetext", _p$.a = _v$3);
|
|
5611
|
+
_v$4 !== _p$.o && (0, solid_js_web.setAttribute)(_el$5, "data-navigator-install-pulse", _p$.o = _v$4);
|
|
5612
|
+
_v$5 !== _p$.i && (0, solid_js_web.setStyleProperty)(_el$5, "width", _p$.i = _v$5);
|
|
5613
|
+
_v$6 !== _p$.n && (0, solid_js_web.setStyleProperty)(_el$5, "animation", _p$.n = _v$6);
|
|
5614
|
+
return _p$;
|
|
5615
|
+
}, {
|
|
5616
|
+
e: void 0,
|
|
5617
|
+
t: void 0,
|
|
5618
|
+
a: void 0,
|
|
5619
|
+
o: void 0,
|
|
5620
|
+
i: void 0,
|
|
5621
|
+
n: void 0
|
|
5622
|
+
});
|
|
5623
|
+
return _el$;
|
|
5624
|
+
})();
|
|
5625
|
+
}
|
|
5626
|
+
// src/shared/ui/gui/icon-action.tsx
|
|
5627
|
+
function GuiIconAction(props) {
|
|
5628
|
+
const IconButton = props.ui.IconButton;
|
|
5629
|
+
const Tooltip = props.ui.Tooltip;
|
|
5630
|
+
return (0, solid_js_web.createComponent)(Tooltip, {
|
|
5631
|
+
get value() {
|
|
5632
|
+
return props.label;
|
|
5633
|
+
},
|
|
5634
|
+
get children() {
|
|
5635
|
+
return (0, solid_js_web.createComponent)(IconButton, {
|
|
5636
|
+
get icon() {
|
|
5637
|
+
return props.icon;
|
|
5638
|
+
},
|
|
5639
|
+
get label() {
|
|
5640
|
+
return props.label;
|
|
5641
|
+
},
|
|
5642
|
+
size: "small",
|
|
5643
|
+
get variant() {
|
|
5644
|
+
return props.variant ?? "ghost-muted";
|
|
5645
|
+
},
|
|
5646
|
+
get disabled() {
|
|
5647
|
+
return props.disabled;
|
|
5648
|
+
},
|
|
5649
|
+
get busy() {
|
|
5650
|
+
return props.busy;
|
|
5651
|
+
},
|
|
5652
|
+
get onClick() {
|
|
5653
|
+
return props.onClick;
|
|
5654
|
+
}
|
|
5655
|
+
});
|
|
5656
|
+
}
|
|
5657
|
+
});
|
|
5658
|
+
}
|
|
5659
|
+
// src/pages/navigator/ui/gui/quota-window.tsx
|
|
5660
|
+
var _tmpl$$48 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style="min-width:0;margin:12px 0"><div role=meter aria-valuemin=0 aria-valuemax=100 style="height:2px;background:color-mix(in srgb, currentColor 10%, transparent)"><div style=height:100%;background:currentColor;opacity:0.5></div></div><div style=display:flex;gap:8px;font-size:12px;margin-top:5px><span style=opacity:0.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1></span><span style=flex-shrink:0>`);
|
|
5661
|
+
function GuiQuotaWindow(props) {
|
|
5662
|
+
const view = () => quotaPresentation(props.window);
|
|
5663
|
+
return (() => {
|
|
5664
|
+
var _el$ = _tmpl$$48(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$5 = _el$2.nextSibling.firstChild, _el$6 = _el$5.nextSibling;
|
|
5665
|
+
(0, solid_js_web.insert)(_el$5, () => view().reset);
|
|
5666
|
+
(0, solid_js_web.insert)(_el$6, () => view().value);
|
|
5667
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
5668
|
+
var _v$ = props.window.label, _v$2 = props.window.label, _v$3 = view().ratio === void 0 ? void 0 : Math.round(view().ratio * 100), _v$4 = view().value, _v$5 = `${(view().ratio ?? 0) * 100}%`;
|
|
5669
|
+
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "aria-label", _p$.e = _v$);
|
|
5670
|
+
_v$2 !== _p$.t && (0, solid_js_web.setAttribute)(_el$2, "aria-label", _p$.t = _v$2);
|
|
5671
|
+
_v$3 !== _p$.a && (0, solid_js_web.setAttribute)(_el$2, "aria-valuenow", _p$.a = _v$3);
|
|
5672
|
+
_v$4 !== _p$.o && (0, solid_js_web.setAttribute)(_el$2, "aria-valuetext", _p$.o = _v$4);
|
|
5673
|
+
_v$5 !== _p$.i && (0, solid_js_web.setStyleProperty)(_el$3, "width", _p$.i = _v$5);
|
|
5674
|
+
return _p$;
|
|
5675
|
+
}, {
|
|
5676
|
+
e: void 0,
|
|
5677
|
+
t: void 0,
|
|
5678
|
+
a: void 0,
|
|
5679
|
+
o: void 0,
|
|
5680
|
+
i: void 0
|
|
5681
|
+
});
|
|
5682
|
+
return _el$;
|
|
5683
|
+
})();
|
|
5684
|
+
}
|
|
5685
|
+
// src/pages/navigator/ui/gui/limits-section.tsx
|
|
5686
|
+
var _tmpl$$47 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
5687
|
+
var _tmpl$2$34 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>`);
|
|
5688
|
+
var _tmpl$3$20 = /*#__PURE__*/ (0, solid_js_web.template)(`<p>: `);
|
|
5689
|
+
function LimitsSection() {
|
|
5690
|
+
const props = useNavigatorGui();
|
|
5691
|
+
const limits = () => props.runtime.limits;
|
|
5692
|
+
const snapshot = () => limits()?.controller.snapshot();
|
|
5693
|
+
const state = () => limits()?.controller.state();
|
|
5694
|
+
const message = () => limits()?.selected() ? quotaStatusMessage({
|
|
5695
|
+
model: limits()?.selected(),
|
|
5696
|
+
snapshot: snapshot(),
|
|
5697
|
+
state: state() ?? { status: "idle" },
|
|
5698
|
+
hasAdapter: Boolean(limits()?.controller.current().adapter),
|
|
5699
|
+
showUpdatedAt: true
|
|
5700
|
+
}) : "Select a model in chat to view its provider limits.";
|
|
5701
|
+
const canLink = () => {
|
|
5702
|
+
const model = limits()?.selected();
|
|
5703
|
+
return model && props.onLinkAccount && limits()?.codex && model.hostConnection?.status === "ready" && canLinkCodexAccount(model) && (!model.accountID || snapshot()?.availability === "unauthenticated" && model.accountSource === "binding");
|
|
5021
5704
|
};
|
|
5022
5705
|
const Button = props.ui.Button;
|
|
5023
5706
|
return (0, solid_js_web.createComponent)(MonitoringSection, {
|
|
@@ -5038,40 +5721,17 @@ function LimitsSection() {
|
|
|
5038
5721
|
children: "Banked Resets"
|
|
5039
5722
|
});
|
|
5040
5723
|
}
|
|
5041
|
-
}), (0, solid_js_web.createComponent)(
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5724
|
+
}), (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
5725
|
+
get ui() {
|
|
5726
|
+
return props.ui;
|
|
5727
|
+
},
|
|
5728
|
+
icon: "refresh",
|
|
5729
|
+
label: "Refresh",
|
|
5730
|
+
onClick: () => void limits()?.controller.refresh(true)
|
|
5046
5731
|
})];
|
|
5047
5732
|
},
|
|
5048
5733
|
get children() {
|
|
5049
5734
|
return [
|
|
5050
|
-
(() => {
|
|
5051
|
-
var _el$ = _tmpl$$49();
|
|
5052
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
5053
|
-
size: "small",
|
|
5054
|
-
variant: "ghost",
|
|
5055
|
-
onClick: () => limits()?.chooseModel(),
|
|
5056
|
-
get children() {
|
|
5057
|
-
return limits()?.label() ?? "Select model";
|
|
5058
|
-
}
|
|
5059
|
-
}), null);
|
|
5060
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5061
|
-
get when() {
|
|
5062
|
-
return limits()?.selected()?.variant;
|
|
5063
|
-
},
|
|
5064
|
-
children: (variant) => (0, solid_js_web.createComponent)(Button, {
|
|
5065
|
-
size: "small",
|
|
5066
|
-
variant: "ghost-muted",
|
|
5067
|
-
onClick: () => limits()?.chooseVariant(),
|
|
5068
|
-
get children() {
|
|
5069
|
-
return variant();
|
|
5070
|
-
}
|
|
5071
|
-
})
|
|
5072
|
-
}), null);
|
|
5073
|
-
return _el$;
|
|
5074
|
-
})(),
|
|
5075
5735
|
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
5076
5736
|
get when() {
|
|
5077
5737
|
return canLink();
|
|
@@ -5092,9 +5752,9 @@ function LimitsSection() {
|
|
|
5092
5752
|
return state()?.error;
|
|
5093
5753
|
},
|
|
5094
5754
|
get children() {
|
|
5095
|
-
var _el$
|
|
5096
|
-
(0, solid_js_web.insert)(_el
|
|
5097
|
-
return _el
|
|
5755
|
+
var _el$ = _tmpl$$47();
|
|
5756
|
+
(0, solid_js_web.insert)(_el$, () => state()?.error?.message);
|
|
5757
|
+
return _el$;
|
|
5098
5758
|
}
|
|
5099
5759
|
}),
|
|
5100
5760
|
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
@@ -5102,9 +5762,9 @@ function LimitsSection() {
|
|
|
5102
5762
|
return message();
|
|
5103
5763
|
},
|
|
5104
5764
|
get children() {
|
|
5105
|
-
var _el$
|
|
5106
|
-
(0, solid_js_web.insert)(_el$
|
|
5107
|
-
return _el$
|
|
5765
|
+
var _el$2 = _tmpl$2$34();
|
|
5766
|
+
(0, solid_js_web.insert)(_el$2, message);
|
|
5767
|
+
return _el$2;
|
|
5108
5768
|
}
|
|
5109
5769
|
}),
|
|
5110
5770
|
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
@@ -5121,13 +5781,13 @@ function LimitsSection() {
|
|
|
5121
5781
|
return value().balances;
|
|
5122
5782
|
},
|
|
5123
5783
|
children: (balance) => (() => {
|
|
5124
|
-
var _el$
|
|
5125
|
-
(0, solid_js_web.insert)(_el$
|
|
5126
|
-
(0, solid_js_web.insert)(_el$
|
|
5784
|
+
var _el$3 = _tmpl$3$20(), _el$4 = _el$3.firstChild;
|
|
5785
|
+
(0, solid_js_web.insert)(_el$3, () => balance.label, _el$4);
|
|
5786
|
+
(0, solid_js_web.insert)(_el$3, (() => {
|
|
5127
5787
|
var _c$ = (0, solid_js_web.memo)(() => !!balance.unlimited);
|
|
5128
5788
|
return () => _c$() ? "Unlimited" : `${balance.amount} ${balance.unit ?? ""}`;
|
|
5129
5789
|
})(), null);
|
|
5130
|
-
return _el$
|
|
5790
|
+
return _el$3;
|
|
5131
5791
|
})()
|
|
5132
5792
|
})]
|
|
5133
5793
|
})
|
|
@@ -5590,23 +6250,34 @@ function createMcpModel(options, persist, preferences) {
|
|
|
5590
6250
|
};
|
|
5591
6251
|
}
|
|
5592
6252
|
// src/pages/navigator/ui/gui/mcp-indicator.tsx
|
|
5593
|
-
var _tmpl$$
|
|
6253
|
+
var _tmpl$$46 = /*#__PURE__*/ (0, solid_js_web.template)(`<span aria-hidden=true style="display:inline-flex;width:12px;height:12px;flex-shrink:0;border-radius:50%;border:1px solid currentColor">`);
|
|
6254
|
+
var _tmpl$2$33 = /*#__PURE__*/ (0, solid_js_web.template)(`<span role=img style=display:inline-flex;width:16px;height:16px;flex-shrink:0;align-items:center;justify-content:center>`);
|
|
5594
6255
|
function McpIndicator(props) {
|
|
6256
|
+
const Loader = useNavigatorGui().ui.Loader;
|
|
5595
6257
|
return (() => {
|
|
5596
|
-
var _el$ = _tmpl
|
|
5597
|
-
(0, solid_js_web.
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
6258
|
+
var _el$ = _tmpl$2$33();
|
|
6259
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
6260
|
+
get when() {
|
|
6261
|
+
return props.status !== "pending";
|
|
6262
|
+
},
|
|
6263
|
+
get fallback() {
|
|
6264
|
+
return (0, solid_js_web.createComponent)(Loader, { size: "small" });
|
|
6265
|
+
},
|
|
6266
|
+
get children() {
|
|
6267
|
+
var _el$2 = _tmpl$$46();
|
|
6268
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
6269
|
+
var _v$ = props.status === "connected" ? "currentColor" : "transparent", _v$2 = props.status === "failed" ? 1 : .65;
|
|
6270
|
+
_v$ !== _p$.e && (0, solid_js_web.setStyleProperty)(_el$2, "background", _p$.e = _v$);
|
|
6271
|
+
_v$2 !== _p$.t && (0, solid_js_web.setStyleProperty)(_el$2, "opacity", _p$.t = _v$2);
|
|
6272
|
+
return _p$;
|
|
6273
|
+
}, {
|
|
6274
|
+
e: void 0,
|
|
6275
|
+
t: void 0
|
|
6276
|
+
});
|
|
6277
|
+
return _el$2;
|
|
6278
|
+
}
|
|
6279
|
+
}));
|
|
6280
|
+
(0, solid_js_web.effect)(() => (0, solid_js_web.setAttribute)(_el$, "aria-label", props.status));
|
|
5610
6281
|
return _el$;
|
|
5611
6282
|
})();
|
|
5612
6283
|
}
|
|
@@ -5616,7 +6287,6 @@ function GuiMcpRow(props) {
|
|
|
5616
6287
|
const catalogs = () => services.runtime.catalogs;
|
|
5617
6288
|
const state = () => catalogs().mcp.serverState(props.item.name);
|
|
5618
6289
|
const error = () => props.item.error || state().error?.message;
|
|
5619
|
-
const Button = services.ui.Button;
|
|
5620
6290
|
return (0, solid_js_web.createComponent)(CatalogRow, {
|
|
5621
6291
|
get title() {
|
|
5622
6292
|
return props.item.name;
|
|
@@ -5646,14 +6316,18 @@ function GuiMcpRow(props) {
|
|
|
5646
6316
|
return error();
|
|
5647
6317
|
},
|
|
5648
6318
|
get children() {
|
|
5649
|
-
return (0, solid_js_web.createComponent)(
|
|
5650
|
-
|
|
5651
|
-
|
|
6319
|
+
return (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
6320
|
+
get ui() {
|
|
6321
|
+
return services.ui;
|
|
6322
|
+
},
|
|
6323
|
+
icon: "info",
|
|
6324
|
+
get label() {
|
|
6325
|
+
return `Information about ${props.item.name}`;
|
|
6326
|
+
},
|
|
5652
6327
|
onClick: () => services.onMcpInformation({
|
|
5653
6328
|
...props.item,
|
|
5654
6329
|
error: error()
|
|
5655
|
-
})
|
|
5656
|
-
children: "Info"
|
|
6330
|
+
})
|
|
5657
6331
|
});
|
|
5658
6332
|
}
|
|
5659
6333
|
});
|
|
@@ -5661,22 +6335,44 @@ function GuiMcpRow(props) {
|
|
|
5661
6335
|
});
|
|
5662
6336
|
}
|
|
5663
6337
|
// src/pages/navigator/ui/gui/mcp-group.tsx
|
|
5664
|
-
var _tmpl$$
|
|
6338
|
+
var _tmpl$$45 = /*#__PURE__*/ (0, solid_js_web.template)(`<strong style=overflow:hidden;text-overflow:ellipsis;white-space:nowrap>`);
|
|
6339
|
+
var _tmpl$2$32 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=opacity:0.6;font-weight:400>`);
|
|
6340
|
+
var _tmpl$3$19 = /*#__PURE__*/ (0, solid_js_web.template)(`<div><ul style="margin:0;padding:0 0 0 10px;list-style:none">`);
|
|
5665
6341
|
function GuiMcpGroup(props) {
|
|
5666
6342
|
const services = useNavigatorGui();
|
|
5667
6343
|
const catalogs = () => services.runtime.catalogs;
|
|
5668
6344
|
const view = () => catalogs().views.mcp;
|
|
5669
6345
|
const bucket = () => view().bucket(props.group);
|
|
5670
6346
|
const busy = () => catalogs().mcp.bulkState().group === props.group && catalogs().mcp.bulkState().status === "running";
|
|
6347
|
+
const Button = services.ui.Button;
|
|
5671
6348
|
return (() => {
|
|
5672
|
-
var _el$ = _tmpl
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
6349
|
+
var _el$ = _tmpl$3$19(), _el$4 = _el$.firstChild;
|
|
6350
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
6351
|
+
variant: "ghost",
|
|
6352
|
+
size: "small",
|
|
6353
|
+
get disabled() {
|
|
6354
|
+
return catalogs().mcp.mutating();
|
|
6355
|
+
},
|
|
6356
|
+
onClick: () => void catalogs().mcp.toggleGroup(props.group, bucket().map((item) => item.name))?.catch(() => {}),
|
|
6357
|
+
get children() {
|
|
6358
|
+
return [
|
|
6359
|
+
(0, solid_js_web.createComponent)(McpIndicator, { get status() {
|
|
6360
|
+
return mcpGroupStatus(bucket(), busy());
|
|
6361
|
+
} }),
|
|
6362
|
+
(() => {
|
|
6363
|
+
var _el$2 = _tmpl$$45();
|
|
6364
|
+
(0, solid_js_web.insert)(_el$2, () => props.group);
|
|
6365
|
+
return _el$2;
|
|
6366
|
+
})(),
|
|
6367
|
+
(() => {
|
|
6368
|
+
var _el$3 = _tmpl$2$32();
|
|
6369
|
+
(0, solid_js_web.insert)(_el$3, () => bucket().length);
|
|
6370
|
+
return _el$3;
|
|
6371
|
+
})()
|
|
6372
|
+
];
|
|
6373
|
+
}
|
|
6374
|
+
}), _el$4);
|
|
6375
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5680
6376
|
get each() {
|
|
5681
6377
|
return view().visibility.visible().filter((item) => item.bucket === props.group).map((item) => item.name);
|
|
5682
6378
|
},
|
|
@@ -5689,16 +6385,14 @@ function GuiMcpGroup(props) {
|
|
|
5689
6385
|
} })
|
|
5690
6386
|
})
|
|
5691
6387
|
}));
|
|
5692
|
-
(0, solid_js_web.effect)(() => _el$2.disabled = catalogs().mcp.mutating());
|
|
5693
6388
|
return _el$;
|
|
5694
6389
|
})();
|
|
5695
6390
|
}
|
|
5696
|
-
(0, solid_js_web.delegateEvents)(["click"]);
|
|
5697
6391
|
// src/pages/navigator/ui/gui/mcp-section.tsx
|
|
5698
|
-
var _tmpl$$
|
|
5699
|
-
var _tmpl$2$
|
|
5700
|
-
var _tmpl$3$
|
|
5701
|
-
var _tmpl$4$
|
|
6392
|
+
var _tmpl$$44 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
6393
|
+
var _tmpl$2$31 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status>/<!> servers updated`);
|
|
6394
|
+
var _tmpl$3$18 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;flex-direction:column;gap:12px>`);
|
|
6395
|
+
var _tmpl$4$12 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>No matching MCP servers.`);
|
|
5702
6396
|
function McpSection() {
|
|
5703
6397
|
const services = useNavigatorGui();
|
|
5704
6398
|
const catalogs = () => services.runtime.catalogs;
|
|
@@ -5750,13 +6444,16 @@ function McpSection() {
|
|
|
5750
6444
|
},
|
|
5751
6445
|
get children() {
|
|
5752
6446
|
return [(() => {
|
|
5753
|
-
var _el$ = _tmpl$$
|
|
6447
|
+
var _el$ = _tmpl$$44();
|
|
5754
6448
|
(0, solid_js_web.insert)(_el$, () => state().error?.message);
|
|
5755
6449
|
return _el$;
|
|
5756
|
-
})(), (0, solid_js_web.createComponent)(
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
6450
|
+
})(), (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
6451
|
+
get ui() {
|
|
6452
|
+
return services.ui;
|
|
6453
|
+
},
|
|
6454
|
+
icon: "refresh",
|
|
6455
|
+
label: "Retry",
|
|
6456
|
+
onClick: () => void catalogs().mcp.retry().catch(() => {})
|
|
5760
6457
|
})];
|
|
5761
6458
|
}
|
|
5762
6459
|
}),
|
|
@@ -5766,7 +6463,7 @@ function McpSection() {
|
|
|
5766
6463
|
},
|
|
5767
6464
|
get children() {
|
|
5768
6465
|
return [(() => {
|
|
5769
|
-
var _el$2 = _tmpl$2$
|
|
6466
|
+
var _el$2 = _tmpl$2$31(), _el$3 = _el$2.firstChild, _el$5 = _el$3.nextSibling;
|
|
5770
6467
|
_el$5.nextSibling;
|
|
5771
6468
|
(0, solid_js_web.insert)(_el$2, () => bulk().completed, _el$3);
|
|
5772
6469
|
(0, solid_js_web.insert)(_el$2, () => bulk().total, _el$5);
|
|
@@ -5786,13 +6483,13 @@ function McpSection() {
|
|
|
5786
6483
|
}
|
|
5787
6484
|
}),
|
|
5788
6485
|
(() => {
|
|
5789
|
-
var _el$6 = _tmpl$3$
|
|
6486
|
+
var _el$6 = _tmpl$3$18();
|
|
5790
6487
|
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5791
6488
|
get each() {
|
|
5792
6489
|
return view().groups();
|
|
5793
6490
|
},
|
|
5794
6491
|
get fallback() {
|
|
5795
|
-
return _tmpl$4$
|
|
6492
|
+
return _tmpl$4$12();
|
|
5796
6493
|
},
|
|
5797
6494
|
children: (group) => (0, solid_js_web.createComponent)(GuiMcpGroup, { group })
|
|
5798
6495
|
}));
|
|
@@ -5861,10 +6558,10 @@ function GuiSkillRow(props) {
|
|
|
5861
6558
|
});
|
|
5862
6559
|
}
|
|
5863
6560
|
// src/pages/navigator/ui/gui/skills-section.tsx
|
|
5864
|
-
var _tmpl$$
|
|
5865
|
-
var _tmpl$2$
|
|
5866
|
-
var _tmpl$3$
|
|
5867
|
-
var _tmpl$4$
|
|
6561
|
+
var _tmpl$$43 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
6562
|
+
var _tmpl$2$30 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;flex-direction:column;gap:12px>`);
|
|
6563
|
+
var _tmpl$3$17 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>No matching Skills.`);
|
|
6564
|
+
var _tmpl$4$11 = /*#__PURE__*/ (0, solid_js_web.template)(`<div><h3 style="font-size:12px;opacity:0.65;margin:0 0 4px"></h3><ul style="margin:0;padding:0 0 0 10px;list-style:none">`);
|
|
5868
6565
|
function SkillsSection() {
|
|
5869
6566
|
const services = useNavigatorGui();
|
|
5870
6567
|
const catalogs = () => services.runtime.catalogs;
|
|
@@ -5894,27 +6591,30 @@ function SkillsSection() {
|
|
|
5894
6591
|
},
|
|
5895
6592
|
get children() {
|
|
5896
6593
|
return [(() => {
|
|
5897
|
-
var _el$ = _tmpl$$
|
|
6594
|
+
var _el$ = _tmpl$$43();
|
|
5898
6595
|
(0, solid_js_web.insert)(_el$, () => catalogs().skills.error());
|
|
5899
6596
|
return _el$;
|
|
5900
|
-
})(), (0, solid_js_web.createComponent)(
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
6597
|
+
})(), (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
6598
|
+
get ui() {
|
|
6599
|
+
return services.ui;
|
|
6600
|
+
},
|
|
6601
|
+
icon: "refresh",
|
|
6602
|
+
label: "Retry",
|
|
6603
|
+
onClick: () => void catalogs().skills.retry().catch(() => {})
|
|
5904
6604
|
})];
|
|
5905
6605
|
}
|
|
5906
6606
|
}),
|
|
5907
6607
|
(() => {
|
|
5908
|
-
var _el$2 = _tmpl$2$
|
|
6608
|
+
var _el$2 = _tmpl$2$30();
|
|
5909
6609
|
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5910
6610
|
get each() {
|
|
5911
6611
|
return view().groups();
|
|
5912
6612
|
},
|
|
5913
6613
|
get fallback() {
|
|
5914
|
-
return _tmpl$3$
|
|
6614
|
+
return _tmpl$3$17();
|
|
5915
6615
|
},
|
|
5916
6616
|
children: (group) => (() => {
|
|
5917
|
-
var _el$4 = _tmpl$4$
|
|
6617
|
+
var _el$4 = _tmpl$4$11(), _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling;
|
|
5918
6618
|
(0, solid_js_web.insert)(_el$5, group);
|
|
5919
6619
|
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
5920
6620
|
get each() {
|
|
@@ -6227,452 +6927,154 @@ function createSubagentModel(options) {
|
|
|
6227
6927
|
status: currentStatuses[session.id] ?? (unavailable()[current.key]?.[session.id] ? void 0 : source.status(session.id))
|
|
6228
6928
|
})).filter((item) => activeStatus(item.status)).map((item) => ({
|
|
6229
6929
|
...item,
|
|
6230
|
-
run: history.active(current.key, item.session.id),
|
|
6231
|
-
unavailable: unavailable()[current.key]?.[item.session.id]
|
|
6232
|
-
}));
|
|
6233
|
-
}
|
|
6234
|
-
function recent(parentID) {
|
|
6235
|
-
const current = target(parentID);
|
|
6236
|
-
const sessions = new Map((snapshots()[current.key] ?? []).map((session) => [session.id, session]));
|
|
6237
|
-
return history.recent(current.key).flatMap((run) => {
|
|
6238
|
-
const session = sessions.get(run.sessionID);
|
|
6239
|
-
return session ? [{
|
|
6240
|
-
session,
|
|
6241
|
-
status: { type: "idle" },
|
|
6242
|
-
run,
|
|
6243
|
-
unavailable: false
|
|
6244
|
-
}] : [];
|
|
6245
|
-
});
|
|
6246
|
-
}
|
|
6247
|
-
const unsubscribe = options.subscribe((event) => {
|
|
6248
|
-
switch (event.type) {
|
|
6249
|
-
case "upsert":
|
|
6250
|
-
recordSession(event);
|
|
6251
|
-
break;
|
|
6252
|
-
case "remove":
|
|
6253
|
-
recordSession(event);
|
|
6254
|
-
recordStatus({
|
|
6255
|
-
sessionID: event.sessionID,
|
|
6256
|
-
status: { type: "idle" }
|
|
6257
|
-
});
|
|
6258
|
-
break;
|
|
6259
|
-
case "status":
|
|
6260
|
-
recordStatus(event);
|
|
6261
|
-
break;
|
|
6262
|
-
case "error":
|
|
6263
|
-
recordError(event);
|
|
6264
|
-
break;
|
|
6265
|
-
case "reconnect": {
|
|
6266
|
-
const current = activeTarget ? targets.get(activeTarget) : void 0;
|
|
6267
|
-
if (current) retryBackgroundRefresh(() => refreshTarget(current), { signal: options.lifecycle.signal }).catch(() => {});
|
|
6268
|
-
break;
|
|
6269
|
-
}
|
|
6270
|
-
}
|
|
6271
|
-
});
|
|
6272
|
-
options.lifecycle.onDispose(() => {
|
|
6273
|
-
unsubscribe();
|
|
6274
|
-
if (pollTimer) clearTimeout(pollTimer);
|
|
6275
|
-
});
|
|
6276
|
-
return {
|
|
6277
|
-
target,
|
|
6278
|
-
list,
|
|
6279
|
-
recent,
|
|
6280
|
-
refresh,
|
|
6281
|
-
state(parentID) {
|
|
6282
|
-
return requests.state(target(parentID).key);
|
|
6283
|
-
},
|
|
6284
|
-
retry(parentID) {
|
|
6285
|
-
return refresh(parentID, true);
|
|
6286
|
-
},
|
|
6287
|
-
activate(parentID) {
|
|
6288
|
-
const current = target(parentID);
|
|
6289
|
-
targets.set(current.key, current);
|
|
6290
|
-
if (activeTarget !== current.key) {
|
|
6291
|
-
if (pollTimer) clearTimeout(pollTimer);
|
|
6292
|
-
requests.abortAll();
|
|
6293
|
-
refreshing.clear();
|
|
6294
|
-
activeTarget = current.key;
|
|
6295
|
-
leases = /* @__PURE__ */ new Set();
|
|
6296
|
-
const poll = () => {
|
|
6297
|
-
if (activeTarget !== current.key || options.lifecycle.signal.aborted) return;
|
|
6298
|
-
refreshTarget(current).catch(() => {});
|
|
6299
|
-
pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
6300
|
-
};
|
|
6301
|
-
if (options.cache === "model") pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
6302
|
-
}
|
|
6303
|
-
const lease = Symbol(current.key);
|
|
6304
|
-
leases.add(lease);
|
|
6305
|
-
return () => {
|
|
6306
|
-
if (activeTarget !== current.key || !leases.delete(lease) || leases.size > 0) return;
|
|
6307
|
-
activeTarget = void 0;
|
|
6308
|
-
if (pollTimer) clearTimeout(pollTimer);
|
|
6309
|
-
pollTimer = void 0;
|
|
6310
|
-
requests.abortAll();
|
|
6311
|
-
refreshing.clear();
|
|
6312
|
-
};
|
|
6313
|
-
},
|
|
6314
|
-
open(sessionID) {
|
|
6315
|
-
options.open(sessionID);
|
|
6316
|
-
}
|
|
6317
|
-
};
|
|
6318
|
-
}
|
|
6319
|
-
// src/entities/subagent/model/view.ts
|
|
6320
|
-
function filterSubagentView(rows, mode, query) {
|
|
6321
|
-
const needle = query.trim().toLocaleLowerCase();
|
|
6322
|
-
return rows.filter((row) => {
|
|
6323
|
-
if (mode === "active" && row.group !== "Active") return false;
|
|
6324
|
-
if (mode === "recent" && row.group !== "Recent") return false;
|
|
6325
|
-
if (mode === "errors" && row.run?.outcome !== "error" && !row.unavailable) return false;
|
|
6326
|
-
return !needle || [
|
|
6327
|
-
row.session.title,
|
|
6328
|
-
row.session.id,
|
|
6329
|
-
row.run?.errorMessage
|
|
6330
|
-
].some((value) => value?.toLocaleLowerCase().includes(needle));
|
|
6331
|
-
});
|
|
6332
|
-
}
|
|
6333
|
-
function countSubagentView(rows, query) {
|
|
6334
|
-
return {
|
|
6335
|
-
all: filterSubagentView(rows, "all", query).length,
|
|
6336
|
-
active: filterSubagentView(rows, "active", query).length,
|
|
6337
|
-
recent: filterSubagentView(rows, "recent", query).length,
|
|
6338
|
-
errors: filterSubagentView(rows, "errors", query).length
|
|
6339
|
-
};
|
|
6340
|
-
}
|
|
6341
|
-
function buildSubagentView(active, recent) {
|
|
6342
|
-
const priority = (item) => {
|
|
6343
|
-
if (item.run?.errorMessage || item.unavailable) return 0;
|
|
6344
|
-
return item.status.type === "retry" ? 1 : 2;
|
|
6345
|
-
};
|
|
6346
|
-
return [...[...active].sort((a, b) => priority(a) - priority(b)).map((item) => ({
|
|
6347
|
-
...item,
|
|
6348
|
-
group: "Active"
|
|
6349
|
-
})), ...[...recent].sort((a, b) => (b.run?.finishedAt ?? 0) - (a.run?.finishedAt ?? 0) || a.session.id.localeCompare(b.session.id)).map((item) => ({
|
|
6350
|
-
...item,
|
|
6351
|
-
group: "Recent"
|
|
6352
|
-
}))];
|
|
6353
|
-
}
|
|
6354
|
-
function formatSubagentDuration(startedAt, now) {
|
|
6355
|
-
const seconds = Math.max(0, Math.floor((now - startedAt) / 1e3));
|
|
6356
|
-
let value = `${seconds}s`;
|
|
6357
|
-
if (seconds >= 3600) value = `${Math.floor(seconds / 3600)}h ${String(Math.floor(seconds / 60) % 60).padStart(2, "0")}m`;
|
|
6358
|
-
else if (seconds >= 60) value = `${Math.floor(seconds / 60)}m ${String(seconds % 60).padStart(2, "0")}s`;
|
|
6359
|
-
return value;
|
|
6360
|
-
}
|
|
6361
|
-
function createSubagentClock(key) {
|
|
6362
|
-
const [now, setNow] = (0, solid_js.createSignal)(Date.now());
|
|
6363
|
-
(0, solid_js.createEffect)(() => {
|
|
6364
|
-
if (key() === void 0) return;
|
|
6365
|
-
setNow(Date.now());
|
|
6366
|
-
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
6367
|
-
(0, solid_js.onCleanup)(() => clearInterval(timer));
|
|
6368
|
-
});
|
|
6369
|
-
return now;
|
|
6370
|
-
}
|
|
6371
|
-
// src/shared/ui/gui/tabs.tsx
|
|
6372
|
-
var _tmpl$$44 = /*#__PURE__*/ (0, solid_js_web.template)(`<nav style=display:flex;gap:4px;flex-wrap:wrap>`);
|
|
6373
|
-
var _tmpl$2$30 = /*#__PURE__*/ (0, solid_js_web.template)(`<span>`);
|
|
6374
|
-
var _tmpl$3$17 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=opacity:0.6;font-weight:400>`);
|
|
6375
|
-
function GuiTabs(props) {
|
|
6376
|
-
const Button = props.ui.Button;
|
|
6377
|
-
function navigate(event) {
|
|
6378
|
-
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
6379
|
-
const enabled = props.options.filter((option) => !option.disabled);
|
|
6380
|
-
if (enabled.length === 0) return;
|
|
6381
|
-
event.preventDefault();
|
|
6382
|
-
event.stopPropagation();
|
|
6383
|
-
const next = (enabled.findIndex((option) => option.id === props.selected) + (event.key === "ArrowRight" ? 1 : -1) + enabled.length) % enabled.length;
|
|
6384
|
-
props.onSelect(enabled[next].id);
|
|
6385
|
-
event.currentTarget.querySelectorAll("button:not(:disabled)")[next]?.focus();
|
|
6386
|
-
}
|
|
6387
|
-
return (() => {
|
|
6388
|
-
var _el$ = _tmpl$$44();
|
|
6389
|
-
_el$.$$keydown = navigate;
|
|
6390
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
6391
|
-
get each() {
|
|
6392
|
-
return props.options.map((option) => option.id);
|
|
6393
|
-
},
|
|
6394
|
-
children: (id) => {
|
|
6395
|
-
const option = () => props.options.find((item) => item.id === id);
|
|
6396
|
-
return (0, solid_js_web.createComponent)(Button, {
|
|
6397
|
-
size: "small",
|
|
6398
|
-
get disabled() {
|
|
6399
|
-
return option().disabled;
|
|
6400
|
-
},
|
|
6401
|
-
get variant() {
|
|
6402
|
-
return props.selected === id ? "neutral" : "ghost-muted";
|
|
6403
|
-
},
|
|
6404
|
-
onClick: () => props.onSelect(id),
|
|
6405
|
-
get children() {
|
|
6406
|
-
return [(() => {
|
|
6407
|
-
var _el$2 = _tmpl$2$30();
|
|
6408
|
-
(0, solid_js_web.insert)(_el$2, () => option().label);
|
|
6409
|
-
(0, solid_js_web.effect)((_$p) => (0, solid_js_web.setStyleProperty)(_el$2, "font-weight", props.selected === id ? "600" : "400"));
|
|
6410
|
-
return _el$2;
|
|
6411
|
-
})(), (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
6412
|
-
get when() {
|
|
6413
|
-
return option().count !== void 0;
|
|
6414
|
-
},
|
|
6415
|
-
get children() {
|
|
6416
|
-
var _el$3 = _tmpl$3$17();
|
|
6417
|
-
(0, solid_js_web.insert)(_el$3, () => option().count);
|
|
6418
|
-
return _el$3;
|
|
6419
|
-
}
|
|
6420
|
-
})];
|
|
6421
|
-
}
|
|
6422
|
-
});
|
|
6423
|
-
}
|
|
6424
|
-
}));
|
|
6425
|
-
(0, solid_js_web.effect)(() => (0, solid_js_web.setAttribute)(_el$, "aria-label", props.label));
|
|
6426
|
-
return _el$;
|
|
6427
|
-
})();
|
|
6428
|
-
}
|
|
6429
|
-
(0, solid_js_web.delegateEvents)(["keydown"]);
|
|
6430
|
-
// src/shared/lib/icon-choices/index.ts
|
|
6431
|
-
var ICON_CHOICE_IDS = [
|
|
6432
|
-
"plus",
|
|
6433
|
-
"check",
|
|
6434
|
-
"circle",
|
|
6435
|
-
"star",
|
|
6436
|
-
"pin",
|
|
6437
|
-
"bolt",
|
|
6438
|
-
"book",
|
|
6439
|
-
"search",
|
|
6440
|
-
"code",
|
|
6441
|
-
"terminal",
|
|
6442
|
-
"gear",
|
|
6443
|
-
"shield",
|
|
6444
|
-
"lock",
|
|
6445
|
-
"unlock",
|
|
6446
|
-
"eye",
|
|
6447
|
-
"clock",
|
|
6448
|
-
"refresh",
|
|
6449
|
-
"history",
|
|
6450
|
-
"copy",
|
|
6451
|
-
"export",
|
|
6452
|
-
"edit",
|
|
6453
|
-
"fork",
|
|
6454
|
-
"list",
|
|
6455
|
-
"play",
|
|
6456
|
-
"pause",
|
|
6457
|
-
"stop",
|
|
6458
|
-
"rocket",
|
|
6459
|
-
"bug",
|
|
6460
|
-
"beaker",
|
|
6461
|
-
"wand",
|
|
6462
|
-
"cloud",
|
|
6463
|
-
"server",
|
|
6464
|
-
"folder",
|
|
6465
|
-
"file",
|
|
6466
|
-
"heart",
|
|
6467
|
-
"lightbulb",
|
|
6468
|
-
"arrow-up",
|
|
6469
|
-
"arrow-down",
|
|
6470
|
-
"warning",
|
|
6471
|
-
"close"
|
|
6472
|
-
];
|
|
6473
|
-
var choices = new Set(ICON_CHOICE_IDS);
|
|
6474
|
-
function isIconChoiceId(value) {
|
|
6475
|
-
return choices.has(value);
|
|
6476
|
-
}
|
|
6477
|
-
function iconChoiceLabel(id) {
|
|
6478
|
-
return id.replaceAll("-", " ");
|
|
6479
|
-
}
|
|
6480
|
-
// src/shared/ui/gui/icon.tsx
|
|
6481
|
-
var _tmpl$$43 = /*#__PURE__*/ (0, solid_js_web.template)(`<span aria-hidden=true style=display:inline-flex;width:18px;height:18px;flex-shrink:0;align-items:center;justify-content:center>`);
|
|
6482
|
-
var _tmpl$2$29 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg width=16 height=16 viewBox="0 0 24 26"fill=none stroke=currentColor stroke-width=1.7 stroke-linecap=round stroke-linejoin=round>`);
|
|
6483
|
-
var _tmpl$3$16 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg><path></svg>`, false, true, false);
|
|
6484
|
-
var native = {
|
|
6485
|
-
plus: "plus",
|
|
6486
|
-
check: "check",
|
|
6487
|
-
search: "magnifying-glass",
|
|
6488
|
-
code: "code",
|
|
6489
|
-
terminal: "terminal",
|
|
6490
|
-
gear: "settings-gear",
|
|
6491
|
-
shield: "shield",
|
|
6492
|
-
lock: "lock",
|
|
6493
|
-
eye: "eye",
|
|
6494
|
-
refresh: "refresh",
|
|
6495
|
-
copy: "copy",
|
|
6496
|
-
export: "share",
|
|
6497
|
-
edit: "edit",
|
|
6498
|
-
fork: "fork",
|
|
6499
|
-
list: "bullet-list",
|
|
6500
|
-
stop: "stop",
|
|
6501
|
-
beaker: "flask",
|
|
6502
|
-
server: "server",
|
|
6503
|
-
folder: "folder",
|
|
6504
|
-
file: "file-document",
|
|
6505
|
-
"arrow-up": "arrow-up",
|
|
6506
|
-
warning: "warning",
|
|
6507
|
-
close: "close"
|
|
6508
|
-
};
|
|
6509
|
-
var paths = {
|
|
6510
|
-
circle: ["M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0Z"],
|
|
6511
|
-
star: ["m12 3 2.7 5.5 6.1.9-4.4 4.3 1 6.1-5.4-2.9-5.4 2.9 1-6.1-4.4-4.3 6.1-.9Z"],
|
|
6512
|
-
pin: ["m9 3 6 0-1 6 4 4H6l4-4Z", "M12 13v8"],
|
|
6513
|
-
bolt: ["m13 2-8 12h6l-1 8 9-13h-7Z"],
|
|
6514
|
-
book: ["M3 4h7l2 2 2-2h7v15h-7l-2 2-2-2H3Z", "M12 6v15"],
|
|
6515
|
-
unlock: [
|
|
6516
|
-
"M7 10V7a5 5 0 0 1 9-3",
|
|
6517
|
-
"M5 10h14v11H5Z",
|
|
6518
|
-
"M12 14v3"
|
|
6519
|
-
],
|
|
6520
|
-
clock: ["M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0Z", "M12 7v5l3 2"],
|
|
6521
|
-
history: [
|
|
6522
|
-
"M4 8a9 9 0 1 1-1 7",
|
|
6523
|
-
"M4 3v5h5",
|
|
6524
|
-
"M12 7v5l3 2"
|
|
6525
|
-
],
|
|
6526
|
-
play: ["m7 4 13 8-13 8Z"],
|
|
6527
|
-
pause: ["M8 4v16", "M16 4v16"],
|
|
6528
|
-
rocket: [
|
|
6529
|
-
"M9 16c0-8 6-13 12-13 0 6-5 12-13 12Z",
|
|
6530
|
-
"m9 8-5 1-2 6 6-1",
|
|
6531
|
-
"m16 15-1 5-6 2 1-6",
|
|
6532
|
-
"m5 17-3 5 5-3"
|
|
6533
|
-
],
|
|
6534
|
-
bug: [
|
|
6535
|
-
"M8 10h8v6a4 4 0 0 1-8 0Z",
|
|
6536
|
-
"M9 10V8a3 3 0 0 1 6 0v2",
|
|
6537
|
-
"M5 7l3 4M19 7l-3 4M3 14h5m8 0h5M5 21l4-3m6 0 4 3M12 11v9"
|
|
6538
|
-
],
|
|
6539
|
-
wand: ["m4 20 13-13 3 3L7 23Z", "M5 3v6M2 6h6M18 1v4M16 3h4"],
|
|
6540
|
-
cloud: ["M7 19a5 5 0 1 1 0-10 6 6 0 0 1 11-1 5.5 5.5 0 0 1 0 11Z"],
|
|
6541
|
-
heart: ["M12 21 3.5 12.5a5.5 5.5 0 0 1 8.5-7 5.5 5.5 0 0 1 8.5 7Z"],
|
|
6542
|
-
lightbulb: ["M9 18v-2a7 7 0 1 1 6 0v2Z", "M9 21h6M10 24h4"],
|
|
6543
|
-
"arrow-down": ["M12 3v18", "m5 14 7 7 7-7"]
|
|
6544
|
-
};
|
|
6545
|
-
function GuiIcon(props) {
|
|
6546
|
-
const Icon = props.ui.Icon;
|
|
6547
|
-
const id = () => isIconChoiceId(props.id) ? props.id : "bolt";
|
|
6548
|
-
return (() => {
|
|
6549
|
-
var _el$ = _tmpl$$43();
|
|
6550
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
6551
|
-
get when() {
|
|
6552
|
-
return native[id()];
|
|
6553
|
-
},
|
|
6554
|
-
get fallback() {
|
|
6555
|
-
return (() => {
|
|
6556
|
-
var _el$2 = _tmpl$2$29();
|
|
6557
|
-
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
6558
|
-
get each() {
|
|
6559
|
-
return paths[id()] ?? paths.bolt;
|
|
6560
|
-
},
|
|
6561
|
-
children: (path) => (() => {
|
|
6562
|
-
var _el$3 = _tmpl$3$16();
|
|
6563
|
-
(0, solid_js_web.setAttribute)(_el$3, "d", path);
|
|
6564
|
-
return _el$3;
|
|
6565
|
-
})()
|
|
6566
|
-
}));
|
|
6567
|
-
return _el$2;
|
|
6568
|
-
})();
|
|
6569
|
-
},
|
|
6570
|
-
children: (name) => (0, solid_js_web.createComponent)(Icon, {
|
|
6571
|
-
get name() {
|
|
6572
|
-
return name();
|
|
6573
|
-
},
|
|
6574
|
-
size: "small"
|
|
6575
|
-
})
|
|
6576
|
-
}));
|
|
6577
|
-
return _el$;
|
|
6578
|
-
})();
|
|
6579
|
-
}
|
|
6580
|
-
// src/shared/ui/gui/multiline-field.tsx
|
|
6581
|
-
var _tmpl$$42 = /*#__PURE__*/ (0, solid_js_web.template)(`<label style=display:grid;gap:8px><span></span><textarea style="width:100%;box-sizing:border-box;min-height:160px;max-height:40vh;resize:vertical;color:var(--v2-text-text-base, inherit);background:var(--v2-background-bg-base, transparent);border:0;caret-color:var(--v2-text-text-base, auto);border-radius:6px;padding:8px;font:inherit">`);
|
|
6582
|
-
function GuiMultilineField(props) {
|
|
6583
|
-
const id = (0, solid_js.createUniqueId)();
|
|
6584
|
-
const [focused, setFocused] = (0, solid_js.createSignal)(false);
|
|
6585
|
-
return (() => {
|
|
6586
|
-
var _el$ = _tmpl$$42(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
6587
|
-
(0, solid_js_web.setAttribute)(_el$, "for", id);
|
|
6588
|
-
(0, solid_js_web.insert)(_el$2, () => props.label);
|
|
6589
|
-
_el$3.$$input = (event) => props.onInput(event.currentTarget.value);
|
|
6590
|
-
_el$3.addEventListener("blur", () => setFocused(false));
|
|
6591
|
-
_el$3.addEventListener("focus", () => setFocused(true));
|
|
6592
|
-
(0, solid_js_web.setAttribute)(_el$3, "id", id);
|
|
6593
|
-
(0, solid_js_web.effect)((_p$) => {
|
|
6594
|
-
var _v$ = props.disabled, _v$2 = focused() ? "1px solid var(--v2-border-border-focus)" : "1px solid transparent", _v$3 = focused() ? "none" : "var(--v2-elevation-input)", _v$4 = props.disabled ? "0.5" : "1";
|
|
6595
|
-
_v$ !== _p$.e && (_el$3.disabled = _p$.e = _v$);
|
|
6596
|
-
_v$2 !== _p$.t && (0, solid_js_web.setStyleProperty)(_el$3, "outline", _p$.t = _v$2);
|
|
6597
|
-
_v$3 !== _p$.a && (0, solid_js_web.setStyleProperty)(_el$3, "box-shadow", _p$.a = _v$3);
|
|
6598
|
-
_v$4 !== _p$.o && (0, solid_js_web.setStyleProperty)(_el$3, "opacity", _p$.o = _v$4);
|
|
6599
|
-
return _p$;
|
|
6600
|
-
}, {
|
|
6601
|
-
e: void 0,
|
|
6602
|
-
t: void 0,
|
|
6603
|
-
a: void 0,
|
|
6604
|
-
o: void 0
|
|
6605
|
-
});
|
|
6606
|
-
(0, solid_js_web.effect)(() => _el$3.value = props.value);
|
|
6607
|
-
return _el$;
|
|
6608
|
-
})();
|
|
6609
|
-
}
|
|
6610
|
-
(0, solid_js_web.delegateEvents)(["input"]);
|
|
6611
|
-
// src/shared/ui/gui/group-control.tsx
|
|
6612
|
-
var _tmpl$$41 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=group style=display:flex;gap:8px;flex-wrap:wrap>`);
|
|
6613
|
-
function GuiGroupControl(props) {
|
|
6614
|
-
const Select = props.ui.Select;
|
|
6615
|
-
const TextInput = props.ui.TextInput;
|
|
6616
|
-
const Button = props.ui.Button;
|
|
6617
|
-
const [draft, setDraft] = (0, solid_js.createSignal)("");
|
|
6618
|
-
(0, solid_js.createEffect)(() => setDraft(props.value ?? ""));
|
|
6619
|
-
return (() => {
|
|
6620
|
-
var _el$ = _tmpl$$41();
|
|
6621
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Select, {
|
|
6622
|
-
get label() {
|
|
6623
|
-
return `${props.label} existing group`;
|
|
6624
|
-
},
|
|
6625
|
-
get value() {
|
|
6626
|
-
return (0, solid_js_web.memo)(() => !!props.groups.includes(draft()))() ? draft() : "";
|
|
6627
|
-
},
|
|
6628
|
-
get options() {
|
|
6629
|
-
return [{
|
|
6630
|
-
value: "",
|
|
6631
|
-
label: "Ungrouped"
|
|
6632
|
-
}, ...props.groups.map((value) => ({
|
|
6633
|
-
value,
|
|
6634
|
-
label: value
|
|
6635
|
-
}))];
|
|
6636
|
-
},
|
|
6637
|
-
onChange: setDraft,
|
|
6638
|
-
get disabled() {
|
|
6639
|
-
return props.disabled;
|
|
6930
|
+
run: history.active(current.key, item.session.id),
|
|
6931
|
+
unavailable: unavailable()[current.key]?.[item.session.id]
|
|
6932
|
+
}));
|
|
6933
|
+
}
|
|
6934
|
+
function recent(parentID) {
|
|
6935
|
+
const current = target(parentID);
|
|
6936
|
+
const sessions = new Map((snapshots()[current.key] ?? []).map((session) => [session.id, session]));
|
|
6937
|
+
return history.recent(current.key).flatMap((run) => {
|
|
6938
|
+
const session = sessions.get(run.sessionID);
|
|
6939
|
+
return session ? [{
|
|
6940
|
+
session,
|
|
6941
|
+
status: { type: "idle" },
|
|
6942
|
+
run,
|
|
6943
|
+
unavailable: false
|
|
6944
|
+
}] : [];
|
|
6945
|
+
});
|
|
6946
|
+
}
|
|
6947
|
+
const unsubscribe = options.subscribe((event) => {
|
|
6948
|
+
switch (event.type) {
|
|
6949
|
+
case "upsert":
|
|
6950
|
+
recordSession(event);
|
|
6951
|
+
break;
|
|
6952
|
+
case "remove":
|
|
6953
|
+
recordSession(event);
|
|
6954
|
+
recordStatus({
|
|
6955
|
+
sessionID: event.sessionID,
|
|
6956
|
+
status: { type: "idle" }
|
|
6957
|
+
});
|
|
6958
|
+
break;
|
|
6959
|
+
case "status":
|
|
6960
|
+
recordStatus(event);
|
|
6961
|
+
break;
|
|
6962
|
+
case "error":
|
|
6963
|
+
recordError(event);
|
|
6964
|
+
break;
|
|
6965
|
+
case "reconnect": {
|
|
6966
|
+
const current = activeTarget ? targets.get(activeTarget) : void 0;
|
|
6967
|
+
if (current) retryBackgroundRefresh(() => refreshTarget(current), { signal: options.lifecycle.signal }).catch(() => {});
|
|
6968
|
+
break;
|
|
6640
6969
|
}
|
|
6641
|
-
}
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6970
|
+
}
|
|
6971
|
+
});
|
|
6972
|
+
options.lifecycle.onDispose(() => {
|
|
6973
|
+
unsubscribe();
|
|
6974
|
+
if (pollTimer) clearTimeout(pollTimer);
|
|
6975
|
+
});
|
|
6976
|
+
return {
|
|
6977
|
+
target,
|
|
6978
|
+
list,
|
|
6979
|
+
recent,
|
|
6980
|
+
refresh,
|
|
6981
|
+
state(parentID) {
|
|
6982
|
+
return requests.state(target(parentID).key);
|
|
6983
|
+
},
|
|
6984
|
+
retry(parentID) {
|
|
6985
|
+
return refresh(parentID, true);
|
|
6986
|
+
},
|
|
6987
|
+
activate(parentID) {
|
|
6988
|
+
const current = target(parentID);
|
|
6989
|
+
targets.set(current.key, current);
|
|
6990
|
+
if (activeTarget !== current.key) {
|
|
6991
|
+
if (pollTimer) clearTimeout(pollTimer);
|
|
6992
|
+
requests.abortAll();
|
|
6993
|
+
refreshing.clear();
|
|
6994
|
+
activeTarget = current.key;
|
|
6995
|
+
leases = /* @__PURE__ */ new Set();
|
|
6996
|
+
const poll = () => {
|
|
6997
|
+
if (activeTarget !== current.key || options.lifecycle.signal.aborted) return;
|
|
6998
|
+
refreshTarget(current).catch(() => {});
|
|
6999
|
+
pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
7000
|
+
};
|
|
7001
|
+
if (options.cache === "model") pollTimer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
6655
7002
|
}
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
7003
|
+
const lease = Symbol(current.key);
|
|
7004
|
+
leases.add(lease);
|
|
7005
|
+
return () => {
|
|
7006
|
+
if (activeTarget !== current.key || !leases.delete(lease) || leases.size > 0) return;
|
|
7007
|
+
activeTarget = void 0;
|
|
7008
|
+
if (pollTimer) clearTimeout(pollTimer);
|
|
7009
|
+
pollTimer = void 0;
|
|
7010
|
+
requests.abortAll();
|
|
7011
|
+
refreshing.clear();
|
|
7012
|
+
};
|
|
7013
|
+
},
|
|
7014
|
+
open(sessionID) {
|
|
7015
|
+
options.open(sessionID);
|
|
7016
|
+
}
|
|
7017
|
+
};
|
|
7018
|
+
}
|
|
7019
|
+
// src/entities/subagent/model/view.ts
|
|
7020
|
+
function filterSubagentView(rows, mode, query) {
|
|
7021
|
+
const needle = query.trim().toLocaleLowerCase();
|
|
7022
|
+
return rows.filter((row) => {
|
|
7023
|
+
if (mode === "active" && row.group !== "Active") return false;
|
|
7024
|
+
if (mode === "recent" && row.group !== "Recent") return false;
|
|
7025
|
+
if (mode === "errors" && row.run?.outcome !== "error" && !row.unavailable) return false;
|
|
7026
|
+
return !needle || [
|
|
7027
|
+
row.session.title,
|
|
7028
|
+
row.session.id,
|
|
7029
|
+
row.run?.errorMessage
|
|
7030
|
+
].some((value) => value?.toLocaleLowerCase().includes(needle));
|
|
7031
|
+
});
|
|
7032
|
+
}
|
|
7033
|
+
function countSubagentView(rows, query) {
|
|
7034
|
+
return {
|
|
7035
|
+
all: filterSubagentView(rows, "all", query).length,
|
|
7036
|
+
active: filterSubagentView(rows, "active", query).length,
|
|
7037
|
+
recent: filterSubagentView(rows, "recent", query).length,
|
|
7038
|
+
errors: filterSubagentView(rows, "errors", query).length
|
|
7039
|
+
};
|
|
7040
|
+
}
|
|
7041
|
+
function buildSubagentView(active, recent) {
|
|
7042
|
+
const priority = (item) => {
|
|
7043
|
+
if (item.run?.errorMessage || item.unavailable) return 0;
|
|
7044
|
+
return item.status.type === "retry" ? 1 : 2;
|
|
7045
|
+
};
|
|
7046
|
+
return [...[...active].sort((a, b) => priority(a) - priority(b)).map((item) => ({
|
|
7047
|
+
...item,
|
|
7048
|
+
group: "Active"
|
|
7049
|
+
})), ...[...recent].sort((a, b) => (b.run?.finishedAt ?? 0) - (a.run?.finishedAt ?? 0) || a.session.id.localeCompare(b.session.id)).map((item) => ({
|
|
7050
|
+
...item,
|
|
7051
|
+
group: "Recent"
|
|
7052
|
+
}))];
|
|
7053
|
+
}
|
|
7054
|
+
function formatSubagentDuration(startedAt, now) {
|
|
7055
|
+
const seconds = Math.max(0, Math.floor((now - startedAt) / 1e3));
|
|
7056
|
+
let value = `${seconds}s`;
|
|
7057
|
+
if (seconds >= 3600) value = `${Math.floor(seconds / 3600)}h ${String(Math.floor(seconds / 60) % 60).padStart(2, "0")}m`;
|
|
7058
|
+
else if (seconds >= 60) value = `${Math.floor(seconds / 60)}m ${String(seconds % 60).padStart(2, "0")}s`;
|
|
7059
|
+
return value;
|
|
7060
|
+
}
|
|
7061
|
+
function createSubagentClock(key) {
|
|
7062
|
+
const [now, setNow] = (0, solid_js.createSignal)(Date.now());
|
|
7063
|
+
(0, solid_js.createEffect)(() => {
|
|
7064
|
+
if (key() === void 0) return;
|
|
7065
|
+
setNow(Date.now());
|
|
7066
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
7067
|
+
(0, solid_js.onCleanup)(() => clearInterval(timer));
|
|
7068
|
+
});
|
|
7069
|
+
return now;
|
|
6668
7070
|
}
|
|
6669
7071
|
// src/pages/navigator/ui/gui/subagent-row.tsx
|
|
6670
|
-
var _tmpl$$
|
|
6671
|
-
var _tmpl$2$
|
|
7072
|
+
var _tmpl$$42 = /*#__PURE__*/ (0, solid_js_web.template)(`<li><p style="font-size:12px;opacity:0.65;margin:0 0 8px;overflow-wrap:anywhere">`);
|
|
7073
|
+
var _tmpl$2$29 = /*#__PURE__*/ (0, solid_js_web.template)(`<span> · `);
|
|
6672
7074
|
function SubagentRow(props) {
|
|
6673
7075
|
const Button = props.ui.Button;
|
|
6674
7076
|
return (() => {
|
|
6675
|
-
var _el$ = _tmpl$$
|
|
7077
|
+
var _el$ = _tmpl$$42(), _el$2 = _el$.firstChild;
|
|
6676
7078
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
6677
7079
|
size: "small",
|
|
6678
7080
|
variant: "ghost",
|
|
@@ -6689,7 +7091,7 @@ function SubagentRow(props) {
|
|
|
6689
7091
|
return props.item.run;
|
|
6690
7092
|
},
|
|
6691
7093
|
children: (run) => (() => {
|
|
6692
|
-
var _el$3 = _tmpl$2$
|
|
7094
|
+
var _el$3 = _tmpl$2$29();
|
|
6693
7095
|
_el$3.firstChild;
|
|
6694
7096
|
(0, solid_js_web.insert)(_el$3, () => run().startedBeforeObservation ? "Observed after start · " : "", null);
|
|
6695
7097
|
(0, solid_js_web.insert)(_el$3, () => formatSubagentDuration(run().startedAt, run().finishedAt ?? props.now), null);
|
|
@@ -6700,9 +7102,9 @@ function SubagentRow(props) {
|
|
|
6700
7102
|
})();
|
|
6701
7103
|
}
|
|
6702
7104
|
// src/pages/navigator/ui/gui/subagent-section.tsx
|
|
6703
|
-
var _tmpl$$
|
|
6704
|
-
var _tmpl$2$
|
|
6705
|
-
var _tmpl$3$
|
|
7105
|
+
var _tmpl$$41 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
7106
|
+
var _tmpl$2$28 = /*#__PURE__*/ (0, solid_js_web.template)(`<ul style="padding:0;margin:8px 0 0;list-style:none">`);
|
|
7107
|
+
var _tmpl$3$16 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>No matching subagents.`);
|
|
6706
7108
|
function SubagentSection() {
|
|
6707
7109
|
const props = useNavigatorGui();
|
|
6708
7110
|
const mode = () => props.runtime.view.subagentMode();
|
|
@@ -6767,7 +7169,7 @@ function SubagentSection() {
|
|
|
6767
7169
|
return state().error;
|
|
6768
7170
|
},
|
|
6769
7171
|
get children() {
|
|
6770
|
-
var _el$ = _tmpl$$
|
|
7172
|
+
var _el$ = _tmpl$$41();
|
|
6771
7173
|
(0, solid_js_web.insert)(_el$, () => state().error?.message);
|
|
6772
7174
|
return _el$;
|
|
6773
7175
|
}
|
|
@@ -6777,10 +7179,10 @@ function SubagentSection() {
|
|
|
6777
7179
|
return rows().length > 0;
|
|
6778
7180
|
},
|
|
6779
7181
|
get fallback() {
|
|
6780
|
-
return _tmpl$3$
|
|
7182
|
+
return _tmpl$3$16();
|
|
6781
7183
|
},
|
|
6782
7184
|
get children() {
|
|
6783
|
-
var _el$2 = _tmpl$2$
|
|
7185
|
+
var _el$2 = _tmpl$2$28();
|
|
6784
7186
|
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
6785
7187
|
get each() {
|
|
6786
7188
|
return keys();
|
|
@@ -6959,26 +7361,95 @@ function buildTodoView(todos, mode) {
|
|
|
6959
7361
|
}
|
|
6960
7362
|
};
|
|
6961
7363
|
}
|
|
7364
|
+
// src/pages/navigator/ui/gui/todo-presentation.ts
|
|
7365
|
+
function todoPresentation(status) {
|
|
7366
|
+
const finished = status === "completed" || status === "cancelled";
|
|
7367
|
+
return {
|
|
7368
|
+
decoration: finished ? "line-through" : "none",
|
|
7369
|
+
text: finished ? "var(--v2-text-text-faint)" : status === "in_progress" ? "var(--v2-text-text-base)" : "var(--v2-text-text-muted)",
|
|
7370
|
+
icon: status === "in_progress" ? "var(--v2-state-fg-warning)" : status === "completed" ? "var(--v2-icon-icon-muted)" : "var(--v2-icon-icon-faint)"
|
|
7371
|
+
};
|
|
7372
|
+
}
|
|
7373
|
+
// src/pages/navigator/ui/gui/todo-status-icon.tsx
|
|
7374
|
+
var _tmpl$$40 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg><path d="M8 4a4 4 0 0 0 0 8V4Z"fill=currentColor></svg>`, false, true, false);
|
|
7375
|
+
var _tmpl$2$27 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg><path d="M5 8 7.5 11 11 5.5"stroke=currentColor stroke-linecap=round stroke-linejoin=round></svg>`, false, true, false);
|
|
7376
|
+
var _tmpl$3$15 = /*#__PURE__*/ (0, solid_js_web.template)(`<svg><path d="M3.5 12.5 12.5 3.5"stroke=currentColor></svg>`, false, true, false);
|
|
7377
|
+
var _tmpl$4$10 = /*#__PURE__*/ (0, solid_js_web.template)(`<span role=img style=display:inline-flex;height:20px;align-items:center;flex-shrink:0><svg width=16 height=16 viewBox="0 0 16 16"fill=none aria-hidden=true><circle cx=8 cy=8 r=6.5 stroke=currentColor>`);
|
|
7378
|
+
function TodoStatusIcon(props) {
|
|
7379
|
+
const color = () => todoPresentation(props.status).icon;
|
|
7380
|
+
return (() => {
|
|
7381
|
+
var _el$ = _tmpl$4$10(), _el$2 = _el$.firstChild;
|
|
7382
|
+
_el$2.firstChild;
|
|
7383
|
+
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.Switch, { get children() {
|
|
7384
|
+
return [
|
|
7385
|
+
(0, solid_js_web.createComponent)(solid_js.Match, {
|
|
7386
|
+
get when() {
|
|
7387
|
+
return props.status === "in_progress";
|
|
7388
|
+
},
|
|
7389
|
+
get children() {
|
|
7390
|
+
return _tmpl$$40();
|
|
7391
|
+
}
|
|
7392
|
+
}),
|
|
7393
|
+
(0, solid_js_web.createComponent)(solid_js.Match, {
|
|
7394
|
+
get when() {
|
|
7395
|
+
return props.status === "completed";
|
|
7396
|
+
},
|
|
7397
|
+
get children() {
|
|
7398
|
+
return _tmpl$2$27();
|
|
7399
|
+
}
|
|
7400
|
+
}),
|
|
7401
|
+
(0, solid_js_web.createComponent)(solid_js.Match, {
|
|
7402
|
+
get when() {
|
|
7403
|
+
return props.status === "cancelled";
|
|
7404
|
+
},
|
|
7405
|
+
get children() {
|
|
7406
|
+
return _tmpl$3$15();
|
|
7407
|
+
}
|
|
7408
|
+
})
|
|
7409
|
+
];
|
|
7410
|
+
} }), null);
|
|
7411
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
7412
|
+
var _v$ = props.status, _v$2 = color();
|
|
7413
|
+
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "aria-label", _p$.e = _v$);
|
|
7414
|
+
_v$2 !== _p$.t && (0, solid_js_web.setStyleProperty)(_el$, "color", _p$.t = _v$2);
|
|
7415
|
+
return _p$;
|
|
7416
|
+
}, {
|
|
7417
|
+
e: void 0,
|
|
7418
|
+
t: void 0
|
|
7419
|
+
});
|
|
7420
|
+
return _el$;
|
|
7421
|
+
})();
|
|
7422
|
+
}
|
|
6962
7423
|
// src/pages/navigator/ui/gui/todo-row.tsx
|
|
6963
|
-
var _tmpl$$
|
|
7424
|
+
var _tmpl$$39 = /*#__PURE__*/ (0, solid_js_web.template)(`<li data-navigator-todo-row style="display:flex;align-items:flex-start;gap:8px;padding:4px 6px;min-width:0"><span dir=auto data-navigator-todo-text style=flex:1;min-width:0;overflow-wrap:anywhere;font-size:13px;line-height:var(--line-height-base);letter-spacing:-0.04px>`);
|
|
6964
7425
|
function TodoRow(props) {
|
|
7426
|
+
const appearance = () => todoPresentation(props.item.status);
|
|
6965
7427
|
return (() => {
|
|
6966
|
-
var _el$ = _tmpl$$
|
|
6967
|
-
(0, solid_js_web.insert)(_el
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
(0, solid_js_web.
|
|
6972
|
-
|
|
7428
|
+
var _el$ = _tmpl$$39(), _el$2 = _el$.firstChild;
|
|
7429
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(TodoStatusIcon, { get status() {
|
|
7430
|
+
return props.item.status;
|
|
7431
|
+
} }), _el$2);
|
|
7432
|
+
(0, solid_js_web.insert)(_el$2, () => props.item.content);
|
|
7433
|
+
(0, solid_js_web.effect)((_p$) => {
|
|
7434
|
+
var _v$ = props.item.status, _v$2 = appearance().text, _v$3 = appearance().decoration;
|
|
7435
|
+
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "data-status", _p$.e = _v$);
|
|
7436
|
+
_v$2 !== _p$.t && (0, solid_js_web.setStyleProperty)(_el$2, "color", _p$.t = _v$2);
|
|
7437
|
+
_v$3 !== _p$.a && (0, solid_js_web.setStyleProperty)(_el$2, "text-decoration", _p$.a = _v$3);
|
|
7438
|
+
return _p$;
|
|
7439
|
+
}, {
|
|
7440
|
+
e: void 0,
|
|
7441
|
+
t: void 0,
|
|
7442
|
+
a: void 0
|
|
7443
|
+
});
|
|
6973
7444
|
return _el$;
|
|
6974
7445
|
})();
|
|
6975
7446
|
}
|
|
6976
7447
|
// src/pages/navigator/ui/gui/todo-section.tsx
|
|
6977
|
-
var _tmpl$$
|
|
7448
|
+
var _tmpl$$38 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
6978
7449
|
var _tmpl$2$26 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65;font-size:12px> completed of `);
|
|
6979
7450
|
var _tmpl$3$14 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status>Reading Todo configuration…`);
|
|
6980
7451
|
var _tmpl$4$9 = /*#__PURE__*/ (0, solid_js_web.template)(`<div><p>`);
|
|
6981
|
-
var _tmpl$5$
|
|
7452
|
+
var _tmpl$5$4 = /*#__PURE__*/ (0, solid_js_web.template)(`<p style=opacity:0.65>No matching tasks. Manage Todo through chat.`);
|
|
6982
7453
|
var _tmpl$6$2 = /*#__PURE__*/ (0, solid_js_web.template)(`<div><h3 style=font-size:12px;opacity:0.65></h3><ul style=padding:0;margin:0;list-style:none>`);
|
|
6983
7454
|
function TodoSection() {
|
|
6984
7455
|
const props = useNavigatorGui();
|
|
@@ -7024,11 +7495,13 @@ function TodoSection() {
|
|
|
7024
7495
|
},
|
|
7025
7496
|
children: "Enable Todo"
|
|
7026
7497
|
}), null);
|
|
7027
|
-
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7498
|
+
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
7499
|
+
get ui() {
|
|
7500
|
+
return props.ui;
|
|
7501
|
+
},
|
|
7502
|
+
icon: "refresh",
|
|
7503
|
+
label: "Retry",
|
|
7504
|
+
onClick: () => void props.runtime.refresh(true)
|
|
7032
7505
|
}), null);
|
|
7033
7506
|
return _el$6;
|
|
7034
7507
|
})();
|
|
@@ -7076,7 +7549,7 @@ function TodoSection() {
|
|
|
7076
7549
|
return state().error;
|
|
7077
7550
|
},
|
|
7078
7551
|
get children() {
|
|
7079
|
-
var _el$ = _tmpl$$
|
|
7552
|
+
var _el$ = _tmpl$$38();
|
|
7080
7553
|
(0, solid_js_web.insert)(_el$, () => state().error?.message);
|
|
7081
7554
|
return _el$;
|
|
7082
7555
|
}
|
|
@@ -7086,7 +7559,7 @@ function TodoSection() {
|
|
|
7086
7559
|
return setup()?.status === "error";
|
|
7087
7560
|
},
|
|
7088
7561
|
get children() {
|
|
7089
|
-
var _el$2 = _tmpl$$
|
|
7562
|
+
var _el$2 = _tmpl$$38();
|
|
7090
7563
|
(0, solid_js_web.insert)(_el$2, () => setup()?.error);
|
|
7091
7564
|
return _el$2;
|
|
7092
7565
|
}
|
|
@@ -7096,7 +7569,7 @@ function TodoSection() {
|
|
|
7096
7569
|
return view().rows.length > 0;
|
|
7097
7570
|
},
|
|
7098
7571
|
get fallback() {
|
|
7099
|
-
return _tmpl$5$
|
|
7572
|
+
return _tmpl$5$4();
|
|
7100
7573
|
},
|
|
7101
7574
|
get children() {
|
|
7102
7575
|
return [(() => {
|
|
@@ -7140,7 +7613,7 @@ function TodoSection() {
|
|
|
7140
7613
|
});
|
|
7141
7614
|
}
|
|
7142
7615
|
// src/pages/navigator/ui/gui/sections.tsx
|
|
7143
|
-
var _tmpl$$
|
|
7616
|
+
var _tmpl$$37 = /*#__PURE__*/ (0, solid_js_web.template)(`<hr style="border:0;border-top:1px solid currentColor;opacity:0.18;margin:14px 0">`);
|
|
7144
7617
|
function NavigatorSections() {
|
|
7145
7618
|
const services = useNavigatorGui();
|
|
7146
7619
|
const preferences = () => services.runtime.catalogs?.preferences;
|
|
@@ -7159,7 +7632,7 @@ function NavigatorSections() {
|
|
|
7159
7632
|
return index() > 0;
|
|
7160
7633
|
},
|
|
7161
7634
|
get children() {
|
|
7162
|
-
return _tmpl$$
|
|
7635
|
+
return _tmpl$$37();
|
|
7163
7636
|
}
|
|
7164
7637
|
}), (0, solid_js_web.createComponent)(solid_js.Switch, { get children() {
|
|
7165
7638
|
return [
|
|
@@ -7204,7 +7677,7 @@ function NavigatorSections() {
|
|
|
7204
7677
|
});
|
|
7205
7678
|
}
|
|
7206
7679
|
// src/features/pinned-toolbar/ui/gui/icon-picker.tsx
|
|
7207
|
-
var _tmpl$$
|
|
7680
|
+
var _tmpl$$36 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(110px, 1fr));gap:4px;margin:8px 0">`);
|
|
7208
7681
|
function GuiIconPicker(props) {
|
|
7209
7682
|
const Dialog = props.ui.Dialog;
|
|
7210
7683
|
const Button = props.ui.Button;
|
|
@@ -7232,7 +7705,7 @@ function GuiIconPicker(props) {
|
|
|
7232
7705
|
autofocus: true,
|
|
7233
7706
|
"class": "w-full"
|
|
7234
7707
|
}), (() => {
|
|
7235
|
-
var _el$ = _tmpl$$
|
|
7708
|
+
var _el$ = _tmpl$$36();
|
|
7236
7709
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
7237
7710
|
get each() {
|
|
7238
7711
|
return choices();
|
|
@@ -7259,13 +7732,24 @@ function GuiIconPicker(props) {
|
|
|
7259
7732
|
});
|
|
7260
7733
|
}
|
|
7261
7734
|
// src/features/pinned-toolbar/ui/gui/icon-group.tsx
|
|
7262
|
-
var _tmpl$$
|
|
7263
|
-
var _tmpl$2$25 = /*#__PURE__*/ (0, solid_js_web.template)(`<li style="display:flex;gap:4px;margin:4px 0">`);
|
|
7735
|
+
var _tmpl$$35 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style="display:flex;gap:4px;margin:4px 0">`);
|
|
7264
7736
|
function GuiIconGroupEditor(props) {
|
|
7265
7737
|
const Dialog = props.ui.Dialog;
|
|
7266
7738
|
const Button = props.ui.Button;
|
|
7267
|
-
|
|
7268
|
-
|
|
7739
|
+
let nextKey = props.initial.length;
|
|
7740
|
+
const [slots, setSlots] = (0, solid_js.createSignal)(props.initial.map((id, key) => ({
|
|
7741
|
+
id,
|
|
7742
|
+
key
|
|
7743
|
+
})));
|
|
7744
|
+
const values = () => slots().map((slot) => slot.id);
|
|
7745
|
+
function choose(key) {
|
|
7746
|
+
const select = (id) => setSlots((previous) => key === void 0 ? [...previous, {
|
|
7747
|
+
id,
|
|
7748
|
+
key: nextKey++
|
|
7749
|
+
}].slice(0, 3) : previous.map((slot) => slot.key === key ? {
|
|
7750
|
+
...slot,
|
|
7751
|
+
id
|
|
7752
|
+
} : slot));
|
|
7269
7753
|
props.dialogs.open((dialog) => (0, solid_js_web.createComponent)(GuiIconPicker, {
|
|
7270
7754
|
get ui() {
|
|
7271
7755
|
return props.ui;
|
|
@@ -7273,11 +7757,7 @@ function GuiIconGroupEditor(props) {
|
|
|
7273
7757
|
get close() {
|
|
7274
7758
|
return dialog.close;
|
|
7275
7759
|
},
|
|
7276
|
-
choose:
|
|
7277
|
-
const next = [...previous];
|
|
7278
|
-
next[index] = id;
|
|
7279
|
-
return next;
|
|
7280
|
-
})
|
|
7760
|
+
choose: select
|
|
7281
7761
|
}));
|
|
7282
7762
|
}
|
|
7283
7763
|
return (0, solid_js_web.createComponent)(Dialog, {
|
|
@@ -7299,59 +7779,64 @@ function GuiIconGroupEditor(props) {
|
|
|
7299
7779
|
})];
|
|
7300
7780
|
},
|
|
7301
7781
|
get children() {
|
|
7302
|
-
return [((
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
})
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7782
|
+
return [(0, solid_js_web.createComponent)(GuiSortableList, {
|
|
7783
|
+
get ui() {
|
|
7784
|
+
return props.ui;
|
|
7785
|
+
},
|
|
7786
|
+
label: "Button icon order",
|
|
7787
|
+
get items() {
|
|
7788
|
+
return slots();
|
|
7789
|
+
},
|
|
7790
|
+
itemKey: (slot) => String(slot.key),
|
|
7791
|
+
itemLabel: (slot) => `Icon ${slots().findIndex((value) => value.key === slot.key) + 1}: ${iconChoiceLabel(slot.id)}`,
|
|
7792
|
+
scope: "icon-draft",
|
|
7793
|
+
move: (from, to) => setSlots((previous) => reorderItems(previous, from, to, (slot) => String(slot.key))),
|
|
7794
|
+
children: (slot, handle) => (() => {
|
|
7795
|
+
var _el$ = _tmpl$$35();
|
|
7796
|
+
(0, solid_js_web.insert)(_el$, handle, null);
|
|
7797
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
7798
|
+
variant: "ghost",
|
|
7799
|
+
onClick: () => choose(slot().key),
|
|
7800
|
+
get children() {
|
|
7801
|
+
return [
|
|
7802
|
+
(0, solid_js_web.createComponent)(GuiIcon, {
|
|
7803
|
+
get ui() {
|
|
7804
|
+
return props.ui;
|
|
7805
|
+
},
|
|
7806
|
+
get id() {
|
|
7807
|
+
return slot().id;
|
|
7808
|
+
}
|
|
7809
|
+
}),
|
|
7810
|
+
"Icon ",
|
|
7811
|
+
(0, solid_js_web.memo)(() => slots().findIndex((value) => value.key === slot().key) + 1),
|
|
7812
|
+
": ",
|
|
7813
|
+
(0, solid_js_web.memo)(() => iconChoiceLabel(slot().id))
|
|
7814
|
+
];
|
|
7815
|
+
}
|
|
7816
|
+
}), null);
|
|
7817
|
+
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
7818
|
+
variant: "ghost-muted",
|
|
7819
|
+
onClick: () => setSlots((previous) => previous.filter((value) => value.key !== slot().key)),
|
|
7820
|
+
children: "Remove"
|
|
7821
|
+
}), null);
|
|
7822
|
+
return _el$;
|
|
7823
|
+
})()
|
|
7824
|
+
}), (0, solid_js_web.createComponent)(Button, {
|
|
7340
7825
|
get disabled() {
|
|
7341
7826
|
return values().length >= 3;
|
|
7342
7827
|
},
|
|
7343
|
-
onClick: () => choose(
|
|
7828
|
+
onClick: () => choose(),
|
|
7344
7829
|
children: "Add icon"
|
|
7345
7830
|
})];
|
|
7346
7831
|
}
|
|
7347
7832
|
});
|
|
7348
7833
|
}
|
|
7349
7834
|
// src/features/pinned-toolbar/ui/gui/pin-editor.tsx
|
|
7350
|
-
var _tmpl$$
|
|
7351
|
-
var _tmpl$2$
|
|
7835
|
+
var _tmpl$$34 = /*#__PURE__*/ (0, solid_js_web.template)(`<p>Base appearance`);
|
|
7836
|
+
var _tmpl$2$25 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;gap:4px;align-items:center><span>`);
|
|
7352
7837
|
var _tmpl$3$13 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>Use a single line of up to 128 characters.`);
|
|
7353
7838
|
var _tmpl$4$8 = /*#__PURE__*/ (0, solid_js_web.template)(`<p>Saved state icons are retained. Desktop uses the base icons unless the action exposes its state publicly.`);
|
|
7354
|
-
var _tmpl$5$
|
|
7839
|
+
var _tmpl$5$3 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
7355
7840
|
function GuiPinEditor(props) {
|
|
7356
7841
|
const initial = toolbarPinAppearance(props.pin);
|
|
7357
7842
|
const [base, setBase] = (0, solid_js.createSignal)([...initial.base]);
|
|
@@ -7438,9 +7923,9 @@ function GuiPinEditor(props) {
|
|
|
7438
7923
|
},
|
|
7439
7924
|
get children() {
|
|
7440
7925
|
return [
|
|
7441
|
-
_tmpl$$
|
|
7926
|
+
_tmpl$$34(),
|
|
7442
7927
|
(() => {
|
|
7443
|
-
var _el$2 = _tmpl$2$
|
|
7928
|
+
var _el$2 = _tmpl$2$25(), _el$3 = _el$2.firstChild;
|
|
7444
7929
|
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
7445
7930
|
get each() {
|
|
7446
7931
|
return base();
|
|
@@ -7507,7 +7992,7 @@ function GuiPinEditor(props) {
|
|
|
7507
7992
|
return error();
|
|
7508
7993
|
},
|
|
7509
7994
|
get children() {
|
|
7510
|
-
var _el$6 = _tmpl$5$
|
|
7995
|
+
var _el$6 = _tmpl$5$3();
|
|
7511
7996
|
(0, solid_js_web.insert)(_el$6, error);
|
|
7512
7997
|
return _el$6;
|
|
7513
7998
|
}
|
|
@@ -7517,11 +8002,10 @@ function GuiPinEditor(props) {
|
|
|
7517
8002
|
});
|
|
7518
8003
|
}
|
|
7519
8004
|
// src/features/pinned-toolbar/ui/gui/manager.tsx
|
|
7520
|
-
var _tmpl$$
|
|
7521
|
-
var _tmpl$2$
|
|
7522
|
-
var _tmpl$3$12 = /*#__PURE__*/ (0, solid_js_web.template)(`<
|
|
7523
|
-
var _tmpl$4$7 = /*#__PURE__*/ (0, solid_js_web.template)(`<
|
|
7524
|
-
var _tmpl$5$3 = /*#__PURE__*/ (0, solid_js_web.template)(`<li style="padding:8px 0;display:flex;gap:4px;align-items:center;min-width:0"><span style=flex:1;min-width:0;overflow-wrap:anywhere><strong>`);
|
|
8005
|
+
var _tmpl$$33 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
8006
|
+
var _tmpl$2$24 = /*#__PURE__*/ (0, solid_js_web.template)(`<p>Pin a Skill or Quick Action from its row menu.`);
|
|
8007
|
+
var _tmpl$3$12 = /*#__PURE__*/ (0, solid_js_web.template)(`<small style=display:block;opacity:0.6>`);
|
|
8008
|
+
var _tmpl$4$7 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style="padding:8px 0;display:flex;gap:4px;align-items:center;min-width:0"><span style=flex:1;min-width:0;overflow-wrap:anywhere><strong>`);
|
|
7525
8009
|
var source = (pin) => pin.kind === "skill" ? pin.location : void 0;
|
|
7526
8010
|
function GuiToolbarManager(props) {
|
|
7527
8011
|
const Dialog = props.ui.Dialog;
|
|
@@ -7557,89 +8041,82 @@ function GuiToolbarManager(props) {
|
|
|
7557
8041
|
get onClick() {
|
|
7558
8042
|
return props.close;
|
|
7559
8043
|
},
|
|
7560
|
-
children: "Close"
|
|
7561
|
-
});
|
|
7562
|
-
},
|
|
7563
|
-
get children() {
|
|
7564
|
-
return [
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
get children() {
|
|
7569
|
-
var _el$ = _tmpl$$32();
|
|
7570
|
-
(0, solid_js_web.insert)(_el$, error);
|
|
7571
|
-
return _el$;
|
|
7572
|
-
}
|
|
7573
|
-
}), (() => {
|
|
7574
|
-
var _el$2 = _tmpl$2$23();
|
|
7575
|
-
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
7576
|
-
get each() {
|
|
7577
|
-
return props.pins.map((pin) => toolbarPinKey(pin));
|
|
8044
|
+
children: "Close"
|
|
8045
|
+
});
|
|
8046
|
+
},
|
|
8047
|
+
get children() {
|
|
8048
|
+
return [
|
|
8049
|
+
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
8050
|
+
get when() {
|
|
8051
|
+
return error();
|
|
7578
8052
|
},
|
|
7579
|
-
get
|
|
7580
|
-
|
|
8053
|
+
get children() {
|
|
8054
|
+
var _el$ = _tmpl$$33();
|
|
8055
|
+
(0, solid_js_web.insert)(_el$, error);
|
|
8056
|
+
return _el$;
|
|
8057
|
+
}
|
|
8058
|
+
}),
|
|
8059
|
+
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
8060
|
+
get when() {
|
|
8061
|
+
return props.pins.length === 0;
|
|
7581
8062
|
},
|
|
7582
|
-
children
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
})
|
|
7640
|
-
}));
|
|
7641
|
-
return _el$2;
|
|
7642
|
-
})()];
|
|
8063
|
+
get children() {
|
|
8064
|
+
return _tmpl$2$24();
|
|
8065
|
+
}
|
|
8066
|
+
}),
|
|
8067
|
+
(0, solid_js_web.createComponent)(GuiSortableList, {
|
|
8068
|
+
get ui() {
|
|
8069
|
+
return props.ui;
|
|
8070
|
+
},
|
|
8071
|
+
label: "Toolbar pin order",
|
|
8072
|
+
get items() {
|
|
8073
|
+
return props.pins;
|
|
8074
|
+
},
|
|
8075
|
+
itemKey: toolbarPinKey,
|
|
8076
|
+
get itemLabel() {
|
|
8077
|
+
return props.label;
|
|
8078
|
+
},
|
|
8079
|
+
scope: "toolbar",
|
|
8080
|
+
get disabled() {
|
|
8081
|
+
return busy() || !props.current();
|
|
8082
|
+
},
|
|
8083
|
+
move: (from, to) => void run(() => props.move(from, to)),
|
|
8084
|
+
children: (pin, handle) => (() => {
|
|
8085
|
+
var _el$3 = _tmpl$4$7(), _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild;
|
|
8086
|
+
(0, solid_js_web.insert)(_el$5, () => props.label(pin()));
|
|
8087
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
8088
|
+
get when() {
|
|
8089
|
+
return source(pin());
|
|
8090
|
+
},
|
|
8091
|
+
get children() {
|
|
8092
|
+
var _el$6 = _tmpl$3$12();
|
|
8093
|
+
(0, solid_js_web.insert)(_el$6, () => source(pin()));
|
|
8094
|
+
return _el$6;
|
|
8095
|
+
}
|
|
8096
|
+
}), null);
|
|
8097
|
+
(0, solid_js_web.insert)(_el$3, handle, null);
|
|
8098
|
+
(0, solid_js_web.insert)(_el$3, (0, solid_js_web.createComponent)(Button, {
|
|
8099
|
+
size: "small",
|
|
8100
|
+
get disabled() {
|
|
8101
|
+
return busy();
|
|
8102
|
+
},
|
|
8103
|
+
onClick: () => props.configure(toolbarPinKey(pin())),
|
|
8104
|
+
children: "Configure"
|
|
8105
|
+
}), null);
|
|
8106
|
+
(0, solid_js_web.insert)(_el$3, (0, solid_js_web.createComponent)(IconButton, {
|
|
8107
|
+
icon: "close",
|
|
8108
|
+
get label() {
|
|
8109
|
+
return `Unpin ${props.label(pin())}`;
|
|
8110
|
+
},
|
|
8111
|
+
get disabled() {
|
|
8112
|
+
return busy();
|
|
8113
|
+
},
|
|
8114
|
+
onClick: () => void run(() => props.remove(toolbarPinKey(pin())))
|
|
8115
|
+
}), null);
|
|
8116
|
+
return _el$3;
|
|
8117
|
+
})()
|
|
8118
|
+
})
|
|
8119
|
+
];
|
|
7643
8120
|
}
|
|
7644
8121
|
});
|
|
7645
8122
|
}
|
|
@@ -7760,8 +8237,8 @@ function createMeasuredToolbar() {
|
|
|
7760
8237
|
};
|
|
7761
8238
|
}
|
|
7762
8239
|
// src/features/pinned-toolbar/ui/gui/toolbar-button.tsx
|
|
7763
|
-
var _tmpl$$
|
|
7764
|
-
var _tmpl$2$
|
|
8240
|
+
var _tmpl$$32 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap>`);
|
|
8241
|
+
var _tmpl$2$23 = /*#__PURE__*/ (0, solid_js_web.template)(`<span aria-hidden=true style=display:inline-flex;gap:4px;align-items:center;min-width:0;max-width:100%><span style=white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0>`);
|
|
7765
8242
|
var _tmpl$3$11 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=display:inline-flex;min-width:0;flex-shrink:0>`);
|
|
7766
8243
|
function GuiToolbarButton(props) {
|
|
7767
8244
|
const Button = props.ui.Button;
|
|
@@ -7783,11 +8260,11 @@ function GuiToolbarButton(props) {
|
|
|
7783
8260
|
},
|
|
7784
8261
|
get children() {
|
|
7785
8262
|
return [(() => {
|
|
7786
|
-
var _el$ = _tmpl$$
|
|
8263
|
+
var _el$ = _tmpl$$32();
|
|
7787
8264
|
(0, solid_js_web.insert)(_el$, label);
|
|
7788
8265
|
return _el$;
|
|
7789
8266
|
})(), (() => {
|
|
7790
|
-
var _el$2 = _tmpl$2$
|
|
8267
|
+
var _el$2 = _tmpl$2$23(), _el$3 = _el$2.firstChild;
|
|
7791
8268
|
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
7792
8269
|
get each() {
|
|
7793
8270
|
return view().icons;
|
|
@@ -7846,8 +8323,8 @@ function GuiToolbarButton(props) {
|
|
|
7846
8323
|
}
|
|
7847
8324
|
(0, solid_js_web.delegateEvents)(["contextmenu", "keydown"]);
|
|
7848
8325
|
// src/features/pinned-toolbar/ui/gui/toolbar.tsx
|
|
7849
|
-
var _tmpl$$
|
|
7850
|
-
var _tmpl$2$
|
|
8326
|
+
var _tmpl$$31 = /*#__PURE__*/ (0, solid_js_web.template)(`<span data-toolbar-visible>`);
|
|
8327
|
+
var _tmpl$2$22 = /*#__PURE__*/ (0, solid_js_web.template)(`<div data-navigator-toolbar role=toolbar tabindex=-1 aria-label="Navigator pins"style="position:relative;display:flex;gap:4px;align-items:center;justify-content:center;padding:0 4px;min-height:28px;margin-bottom:8px"><div aria-hidden=true inert style=position:absolute;left:0;top:0;width:0;height:0;overflow:hidden;visibility:hidden;pointer-events:none><div style=display:flex;gap:4px;width:max-content><span>`);
|
|
7851
8328
|
function navigate(event) {
|
|
7852
8329
|
if (event.defaultPrevented || event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
7853
8330
|
const buttons = [...event.currentTarget.querySelectorAll(":scope [data-toolbar-visible] button")];
|
|
@@ -7871,7 +8348,7 @@ function GuiPinnedToolbar(props) {
|
|
|
7871
8348
|
return keys().length > 0;
|
|
7872
8349
|
},
|
|
7873
8350
|
get children() {
|
|
7874
|
-
var _el$ = _tmpl$2$
|
|
8351
|
+
var _el$ = _tmpl$2$22(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild;
|
|
7875
8352
|
_el$.$$keydown = navigate;
|
|
7876
8353
|
var _ref$ = layout.root;
|
|
7877
8354
|
typeof _ref$ === "function" ? (0, solid_js_web.use)(_ref$, _el$) : layout.root = _el$;
|
|
@@ -7907,7 +8384,7 @@ function GuiPinnedToolbar(props) {
|
|
|
7907
8384
|
return hidden().length > 0;
|
|
7908
8385
|
},
|
|
7909
8386
|
get children() {
|
|
7910
|
-
var _el$2 = _tmpl$$
|
|
8387
|
+
var _el$2 = _tmpl$$31();
|
|
7911
8388
|
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(Menu, {
|
|
7912
8389
|
label: "More toolbar items",
|
|
7913
8390
|
trigger: "icon",
|
|
@@ -7998,7 +8475,7 @@ function NavigatorPinnedToolbar() {
|
|
|
7998
8475
|
});
|
|
7999
8476
|
}
|
|
8000
8477
|
// src/pages/navigator/ui/gui/monitoring-content.tsx
|
|
8001
|
-
var _tmpl$$
|
|
8478
|
+
var _tmpl$$30 = /*#__PURE__*/ (0, solid_js_web.template)(`<div data-navigator-content style=padding:12px;overflow-y:auto;min-height:0;flex:1;font-size:13px>`);
|
|
8002
8479
|
function MonitoringContent(props) {
|
|
8003
8480
|
let body;
|
|
8004
8481
|
(0, solid_js.onMount)(() => {
|
|
@@ -8007,7 +8484,7 @@ function MonitoringContent(props) {
|
|
|
8007
8484
|
return (0, solid_js_web.createComponent)(NavigatorGuiContext.Provider, {
|
|
8008
8485
|
value: props,
|
|
8009
8486
|
get children() {
|
|
8010
|
-
var _el$ = _tmpl$$
|
|
8487
|
+
var _el$ = _tmpl$$30();
|
|
8011
8488
|
_el$.addEventListener("scroll", (event) => props.onScroll?.(event.currentTarget.scrollTop));
|
|
8012
8489
|
(0, solid_js_web.use)((node) => {
|
|
8013
8490
|
body = node;
|
|
@@ -8662,10 +9139,8 @@ function createMiniWindowInteraction(props) {
|
|
|
8662
9139
|
};
|
|
8663
9140
|
}
|
|
8664
9141
|
// src/pages/navigator/ui/gui/mini-window.tsx
|
|
8665
|
-
var _tmpl$$
|
|
9142
|
+
var _tmpl$$29 = /*#__PURE__*/ (0, solid_js_web.template)(`<aside data-navigator-floating style="position:fixed;display:flex;flex-direction:column;z-index:40;background:var(--v2-background-bg-layer-01);color:var(--v2-text-text-base);border:1px solid var(--v2-border-border-base, color-mix(in srgb, currentColor 20%, transparent));border-radius:12px;box-shadow:var(--v2-elevation-overlay, 0 8px 32px #0003);overflow:hidden;font-size:13px"><header style=display:grid;gap:6px;padding:8px;cursor:move;touch-action:none;user-select:none><strong data-navigator-session-title style=min-width:0;overflow:hidden;overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:20px></strong><div role=group aria-label="Mini-window actions"style=display:flex;gap:4px;align-items:center><span data-navigator-move title="Drag or use arrow keys; Shift moves ten pixels"></span></div></header><footer style=display:flex;gap:4px;padding:6px;align-items:center><span title="Drag or use arrow keys; Shift resizes ten pixels"style=margin-left:auto;cursor:nwse-resize;touch-action:none>`);
|
|
8666
9143
|
function NavigatorMiniWindow(props) {
|
|
8667
|
-
const Button = props.ui.Button;
|
|
8668
|
-
const IconButton = props.ui.IconButton;
|
|
8669
9144
|
const interaction = createMiniWindowInteraction(props);
|
|
8670
9145
|
function dragHeader(event) {
|
|
8671
9146
|
const target = event.target;
|
|
@@ -8673,63 +9148,77 @@ function NavigatorMiniWindow(props) {
|
|
|
8673
9148
|
interaction.start(event, "move");
|
|
8674
9149
|
}
|
|
8675
9150
|
return (() => {
|
|
8676
|
-
var _el$ = _tmpl$$
|
|
9151
|
+
var _el$ = _tmpl$$29(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.firstChild, _el$6 = _el$2.nextSibling, _el$7 = _el$6.firstChild;
|
|
8677
9152
|
(0, solid_js_web.addEventListener)(_el$2, "lostpointercapture", interaction.end);
|
|
8678
9153
|
(0, solid_js_web.addEventListener)(_el$2, "pointercancel", interaction.end);
|
|
8679
9154
|
(0, solid_js_web.addEventListener)(_el$2, "pointerup", interaction.end, true);
|
|
8680
9155
|
(0, solid_js_web.addEventListener)(_el$2, "pointermove", interaction.move, true);
|
|
8681
9156
|
_el$2.$$pointerdown = dragHeader;
|
|
8682
|
-
_el$3
|
|
8683
|
-
|
|
9157
|
+
(0, solid_js_web.insert)(_el$3, () => props.title);
|
|
9158
|
+
_el$5.$$keydown = (event) => interaction.key(event, "move");
|
|
9159
|
+
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9160
|
+
get ui() {
|
|
9161
|
+
return props.ui;
|
|
9162
|
+
},
|
|
8684
9163
|
icon: "dot-grid",
|
|
8685
9164
|
label: "Move Navigator mini-window"
|
|
8686
9165
|
}));
|
|
8687
|
-
(0, solid_js_web.insert)(_el$4, (
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
9166
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9167
|
+
get ui() {
|
|
9168
|
+
return props.ui;
|
|
9169
|
+
},
|
|
9170
|
+
icon: "layout-right",
|
|
9171
|
+
label: "Dock",
|
|
8691
9172
|
get onClick() {
|
|
8692
9173
|
return props.redock;
|
|
8693
|
-
}
|
|
8694
|
-
children: "Dock"
|
|
9174
|
+
}
|
|
8695
9175
|
}), null);
|
|
8696
|
-
(0, solid_js_web.insert)(_el$, () => props.children, _el$
|
|
8697
|
-
(0, solid_js_web.insert)(_el$
|
|
8698
|
-
|
|
8699
|
-
|
|
9176
|
+
(0, solid_js_web.insert)(_el$, () => props.children, _el$6);
|
|
9177
|
+
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9178
|
+
get ui() {
|
|
9179
|
+
return props.ui;
|
|
9180
|
+
},
|
|
9181
|
+
icon: "magnifying-glass",
|
|
9182
|
+
label: "Search",
|
|
8700
9183
|
get onClick() {
|
|
8701
9184
|
return props.search;
|
|
9185
|
+
}
|
|
9186
|
+
}), _el$7);
|
|
9187
|
+
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9188
|
+
get ui() {
|
|
9189
|
+
return props.ui;
|
|
8702
9190
|
},
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(Button, {
|
|
8706
|
-
size: "small",
|
|
8707
|
-
variant: "ghost-muted",
|
|
9191
|
+
icon: "refresh",
|
|
9192
|
+
label: "Refresh",
|
|
8708
9193
|
get onClick() {
|
|
8709
9194
|
return props.refresh;
|
|
9195
|
+
}
|
|
9196
|
+
}), _el$7);
|
|
9197
|
+
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9198
|
+
get ui() {
|
|
9199
|
+
return props.ui;
|
|
8710
9200
|
},
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(Button, {
|
|
8714
|
-
size: "small",
|
|
8715
|
-
variant: "ghost-muted",
|
|
9201
|
+
icon: "outline-reset",
|
|
9202
|
+
label: "Reset position",
|
|
8716
9203
|
get onClick() {
|
|
8717
9204
|
return interaction.reset;
|
|
9205
|
+
}
|
|
9206
|
+
}), _el$7);
|
|
9207
|
+
_el$7.$$keydown = (event) => interaction.key(event, "resize");
|
|
9208
|
+
(0, solid_js_web.addEventListener)(_el$7, "lostpointercapture", interaction.end);
|
|
9209
|
+
(0, solid_js_web.addEventListener)(_el$7, "pointercancel", interaction.end);
|
|
9210
|
+
(0, solid_js_web.addEventListener)(_el$7, "pointerup", interaction.end, true);
|
|
9211
|
+
(0, solid_js_web.addEventListener)(_el$7, "pointermove", interaction.move, true);
|
|
9212
|
+
_el$7.$$pointerdown = (event) => interaction.start(event, "resize");
|
|
9213
|
+
(0, solid_js_web.insert)(_el$7, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9214
|
+
get ui() {
|
|
9215
|
+
return props.ui;
|
|
8718
9216
|
},
|
|
8719
|
-
children: "Reset position"
|
|
8720
|
-
}), _el$6);
|
|
8721
|
-
_el$6.$$keydown = (event) => interaction.key(event, "resize");
|
|
8722
|
-
(0, solid_js_web.addEventListener)(_el$6, "lostpointercapture", interaction.end);
|
|
8723
|
-
(0, solid_js_web.addEventListener)(_el$6, "pointercancel", interaction.end);
|
|
8724
|
-
(0, solid_js_web.addEventListener)(_el$6, "pointerup", interaction.end, true);
|
|
8725
|
-
(0, solid_js_web.addEventListener)(_el$6, "pointermove", interaction.move, true);
|
|
8726
|
-
_el$6.$$pointerdown = (event) => interaction.start(event, "resize");
|
|
8727
|
-
(0, solid_js_web.insert)(_el$6, (0, solid_js_web.createComponent)(IconButton, {
|
|
8728
9217
|
icon: "outline-expand",
|
|
8729
9218
|
label: "Resize Navigator mini-window"
|
|
8730
9219
|
}));
|
|
8731
9220
|
(0, solid_js_web.effect)((_p$) => {
|
|
8732
|
-
var _v$ = `Navigator mini-window: ${props.title}`, _v$2 = props.modal, _v$3 = props.modal, _v$4 = `${props.rect.x}px`, _v$5 = `${props.rect.y}px`, _v$6 = `${props.rect.width}px`, _v$7 = `${props.rect.height}px`, _v$8 = props.modal ? "hidden" : "visible", _v$9 = props.mode;
|
|
9221
|
+
var _v$ = `Navigator mini-window: ${props.title}`, _v$2 = props.modal, _v$3 = props.modal, _v$4 = `${props.rect.x}px`, _v$5 = `${props.rect.y}px`, _v$6 = `${props.rect.width}px`, _v$7 = `${props.rect.height}px`, _v$8 = props.modal ? "hidden" : "visible", _v$9 = props.mode, _v$0 = props.title;
|
|
8733
9222
|
_v$ !== _p$.e && (0, solid_js_web.setAttribute)(_el$, "aria-label", _p$.e = _v$);
|
|
8734
9223
|
_v$2 !== _p$.t && (0, solid_js_web.setAttribute)(_el$, "aria-hidden", _p$.t = _v$2);
|
|
8735
9224
|
_v$3 !== _p$.a && (_el$.inert = _p$.a = _v$3);
|
|
@@ -8739,6 +9228,7 @@ function NavigatorMiniWindow(props) {
|
|
|
8739
9228
|
_v$7 !== _p$.s && (0, solid_js_web.setStyleProperty)(_el$, "height", _p$.s = _v$7);
|
|
8740
9229
|
_v$8 !== _p$.h && (0, solid_js_web.setStyleProperty)(_el$, "visibility", _p$.h = _v$8);
|
|
8741
9230
|
_v$9 !== _p$.r && (0, solid_js_web.setStyleProperty)(_el$, "color-scheme", _p$.r = _v$9);
|
|
9231
|
+
_v$0 !== _p$.d && (0, solid_js_web.setAttribute)(_el$3, "title", _p$.d = _v$0);
|
|
8742
9232
|
return _p$;
|
|
8743
9233
|
}, {
|
|
8744
9234
|
e: void 0,
|
|
@@ -8749,7 +9239,8 @@ function NavigatorMiniWindow(props) {
|
|
|
8749
9239
|
n: void 0,
|
|
8750
9240
|
s: void 0,
|
|
8751
9241
|
h: void 0,
|
|
8752
|
-
r: void 0
|
|
9242
|
+
r: void 0,
|
|
9243
|
+
d: void 0
|
|
8753
9244
|
});
|
|
8754
9245
|
return _el$;
|
|
8755
9246
|
})();
|
|
@@ -8761,48 +9252,56 @@ function NavigatorMiniWindow(props) {
|
|
|
8761
9252
|
"keydown"
|
|
8762
9253
|
]);
|
|
8763
9254
|
// src/pages/navigator/ui/gui/monitoring-panel.tsx
|
|
8764
|
-
var _tmpl$$
|
|
8765
|
-
var _tmpl$2$
|
|
8766
|
-
var _tmpl$3$10 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status>Loading Navigator…`);
|
|
9255
|
+
var _tmpl$$28 = /*#__PURE__*/ (0, solid_js_web.template)(`<div data-navigator-panel style=display:flex;flex-direction:column;height:100%;min-height:0><header data-navigator-panel-header style="padding:8px 12px;display:grid;gap:6px;min-width:0"><strong data-navigator-session-title style=min-width:0;overflow:hidden;overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:20px></strong><div role=group aria-label="Navigator actions"style=display:flex;gap:4px;align-items:center;flex-wrap:wrap>`);
|
|
9256
|
+
var _tmpl$2$21 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=padding:12px><p>Navigator is in its mini-window.`);
|
|
9257
|
+
var _tmpl$3$10 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status> Loading Navigator…`);
|
|
8767
9258
|
function MonitoringPanel(props) {
|
|
8768
|
-
const
|
|
9259
|
+
const Loader = props.ui.Loader;
|
|
8769
9260
|
return (() => {
|
|
8770
|
-
var _el$ = _tmpl$$
|
|
9261
|
+
var _el$ = _tmpl$$28(), _el$3 = _el$.firstChild.firstChild, _el$4 = _el$3.nextSibling;
|
|
8771
9262
|
(0, solid_js_web.insert)(_el$3, () => props.title);
|
|
8772
|
-
(0, solid_js_web.insert)(_el$
|
|
8773
|
-
|
|
8774
|
-
|
|
9263
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9264
|
+
get ui() {
|
|
9265
|
+
return props.ui;
|
|
9266
|
+
},
|
|
9267
|
+
icon: "magnifying-glass",
|
|
9268
|
+
label: "Search",
|
|
8775
9269
|
get onClick() {
|
|
8776
9270
|
return props.search;
|
|
8777
|
-
}
|
|
8778
|
-
children: "Search"
|
|
9271
|
+
}
|
|
8779
9272
|
}), null);
|
|
8780
|
-
(0, solid_js_web.insert)(_el$
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
9273
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9274
|
+
get ui() {
|
|
9275
|
+
return props.ui;
|
|
9276
|
+
},
|
|
9277
|
+
icon: "refresh",
|
|
9278
|
+
label: "Refresh",
|
|
9279
|
+
onClick: () => void props.runtime?.refresh(true)
|
|
8785
9280
|
}), null);
|
|
8786
|
-
(0, solid_js_web.insert)(_el$
|
|
8787
|
-
|
|
8788
|
-
|
|
9281
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9282
|
+
get ui() {
|
|
9283
|
+
return props.ui;
|
|
9284
|
+
},
|
|
9285
|
+
icon: "expand",
|
|
9286
|
+
label: "Float",
|
|
8789
9287
|
get onClick() {
|
|
8790
9288
|
return props.float;
|
|
8791
|
-
}
|
|
8792
|
-
children: "Float"
|
|
9289
|
+
}
|
|
8793
9290
|
}), null);
|
|
8794
|
-
(0, solid_js_web.insert)(_el$
|
|
9291
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
8795
9292
|
get when() {
|
|
8796
9293
|
return props.onSettings;
|
|
8797
9294
|
},
|
|
8798
9295
|
get children() {
|
|
8799
|
-
return (0, solid_js_web.createComponent)(
|
|
8800
|
-
|
|
8801
|
-
|
|
9296
|
+
return (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9297
|
+
get ui() {
|
|
9298
|
+
return props.ui;
|
|
9299
|
+
},
|
|
9300
|
+
icon: "settings-gear",
|
|
9301
|
+
label: "Settings",
|
|
8802
9302
|
get onClick() {
|
|
8803
9303
|
return props.onSettings;
|
|
8804
|
-
}
|
|
8805
|
-
children: "Settings"
|
|
9304
|
+
}
|
|
8806
9305
|
});
|
|
8807
9306
|
}
|
|
8808
9307
|
}), null);
|
|
@@ -8812,16 +9311,19 @@ function MonitoringPanel(props) {
|
|
|
8812
9311
|
},
|
|
8813
9312
|
get fallback() {
|
|
8814
9313
|
return (() => {
|
|
8815
|
-
var _el$
|
|
8816
|
-
_el$
|
|
8817
|
-
(0, solid_js_web.insert)(_el$
|
|
8818
|
-
|
|
9314
|
+
var _el$5 = _tmpl$2$21();
|
|
9315
|
+
_el$5.firstChild;
|
|
9316
|
+
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(GuiIconAction, {
|
|
9317
|
+
get ui() {
|
|
9318
|
+
return props.ui;
|
|
9319
|
+
},
|
|
9320
|
+
icon: "layout-right",
|
|
9321
|
+
label: "Dock Navigator",
|
|
8819
9322
|
get onClick() {
|
|
8820
9323
|
return props.dock;
|
|
8821
|
-
}
|
|
8822
|
-
children: "Dock Navigator"
|
|
9324
|
+
}
|
|
8823
9325
|
}), null);
|
|
8824
|
-
return _el$
|
|
9326
|
+
return _el$5;
|
|
8825
9327
|
})();
|
|
8826
9328
|
},
|
|
8827
9329
|
get children() {
|
|
@@ -8830,7 +9332,11 @@ function MonitoringPanel(props) {
|
|
|
8830
9332
|
return props.runtime;
|
|
8831
9333
|
},
|
|
8832
9334
|
get fallback() {
|
|
8833
|
-
return
|
|
9335
|
+
return (() => {
|
|
9336
|
+
var _el$7 = _tmpl$3$10(), _el$8 = _el$7.firstChild;
|
|
9337
|
+
(0, solid_js_web.insert)(_el$7, (0, solid_js_web.createComponent)(Loader, { size: "small" }), _el$8);
|
|
9338
|
+
return _el$7;
|
|
9339
|
+
})();
|
|
8834
9340
|
},
|
|
8835
9341
|
children: (runtime) => (0, solid_js_web.createComponent)(MonitoringContent, (0, solid_js_web.mergeProps)(props, { get runtime() {
|
|
8836
9342
|
return runtime();
|
|
@@ -8877,9 +9383,23 @@ function parseChangelog(source) {
|
|
|
8877
9383
|
function changesSince(source, previous, current) {
|
|
8878
9384
|
return parseChangelog(source).filter((entry) => entry.changes.length > 0 && isNewerVersion(entry.version, previous) && !isNewerVersion(entry.version, current));
|
|
8879
9385
|
}
|
|
9386
|
+
// src/entities/navigator-release/model/update-progress.ts
|
|
9387
|
+
function updateProgressView(progress) {
|
|
9388
|
+
const labels = {
|
|
9389
|
+
preparing: "Preparing",
|
|
9390
|
+
downloading: "Downloading",
|
|
9391
|
+
installing: "Downloading / installing",
|
|
9392
|
+
verifying: "Verifying"
|
|
9393
|
+
};
|
|
9394
|
+
const fraction = progress.total !== void 0 && Number.isFinite(progress.total) && progress.total > 0 && progress.received !== void 0 && Number.isFinite(progress.received) && progress.received >= 0 ? Math.min(1, progress.received / progress.total) : void 0;
|
|
9395
|
+
return {
|
|
9396
|
+
label: fraction === void 0 ? labels[progress.phase] : `${labels[progress.phase]} ${Math.floor(fraction * 100)}%`,
|
|
9397
|
+
fraction
|
|
9398
|
+
};
|
|
9399
|
+
}
|
|
8880
9400
|
// src/features/sidebar-settings/ui/gui/mcp-preset-menu.tsx
|
|
8881
|
-
var _tmpl$$
|
|
8882
|
-
var _tmpl$2$
|
|
9401
|
+
var _tmpl$$27 = /*#__PURE__*/ (0, solid_js_web.template)(`<ul style="margin:8px 0;padding:0;list-style:none">`);
|
|
9402
|
+
var _tmpl$2$20 = /*#__PURE__*/ (0, solid_js_web.template)(`<li>No matching saved presets.`);
|
|
8883
9403
|
var _tmpl$3$9 = /*#__PURE__*/ (0, solid_js_web.template)(`<li>`);
|
|
8884
9404
|
function GuiMcpPresetMenu(props) {
|
|
8885
9405
|
const Dialog = props.ui.Dialog;
|
|
@@ -8912,13 +9432,13 @@ function GuiMcpPresetMenu(props) {
|
|
|
8912
9432
|
autofocus: true,
|
|
8913
9433
|
"class": "w-full"
|
|
8914
9434
|
}), (() => {
|
|
8915
|
-
var _el$ = _tmpl$$
|
|
9435
|
+
var _el$ = _tmpl$$27();
|
|
8916
9436
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
8917
9437
|
get each() {
|
|
8918
9438
|
return names();
|
|
8919
9439
|
},
|
|
8920
9440
|
get fallback() {
|
|
8921
|
-
return _tmpl$2$
|
|
9441
|
+
return _tmpl$2$20();
|
|
8922
9442
|
},
|
|
8923
9443
|
children: (name) => (() => {
|
|
8924
9444
|
var _el$3 = _tmpl$3$9();
|
|
@@ -8936,8 +9456,8 @@ function GuiMcpPresetMenu(props) {
|
|
|
8936
9456
|
});
|
|
8937
9457
|
}
|
|
8938
9458
|
// src/features/sidebar-settings/ui/gui/mcp-preview-rows.tsx
|
|
8939
|
-
var _tmpl$$
|
|
8940
|
-
var _tmpl$2$
|
|
9459
|
+
var _tmpl$$26 = /*#__PURE__*/ (0, solid_js_web.template)(`<section><h3></h3><ul style=padding:0;list-style:none>`);
|
|
9460
|
+
var _tmpl$2$19 = /*#__PURE__*/ (0, solid_js_web.template)(`<li style="padding:6px 0;overflow-wrap:anywhere"><strong></strong><p style="margin:2px 0;opacity:0.65"> · `);
|
|
8941
9461
|
var groups = [
|
|
8942
9462
|
"Changes",
|
|
8943
9463
|
"Skipped",
|
|
@@ -8955,7 +9475,7 @@ function GuiMcpPreviewRows(props) {
|
|
|
8955
9475
|
return props.model.preview().rows.some((row) => group(row.change) === section);
|
|
8956
9476
|
},
|
|
8957
9477
|
get children() {
|
|
8958
|
-
var _el$ = _tmpl$$
|
|
9478
|
+
var _el$ = _tmpl$$26(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
|
|
8959
9479
|
(0, solid_js_web.insert)(_el$2, section);
|
|
8960
9480
|
(0, solid_js_web.insert)(_el$3, (0, solid_js_web.createComponent)(solid_js.For, {
|
|
8961
9481
|
get each() {
|
|
@@ -8964,7 +9484,7 @@ function GuiMcpPreviewRows(props) {
|
|
|
8964
9484
|
children: (name) => {
|
|
8965
9485
|
const row = () => props.model.preview().rows.find((item) => item.name === name);
|
|
8966
9486
|
return (() => {
|
|
8967
|
-
var _el$4 = _tmpl$2$
|
|
9487
|
+
var _el$4 = _tmpl$2$19(), _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling, _el$7 = _el$6.firstChild;
|
|
8968
9488
|
(0, solid_js_web.insert)(_el$5, name);
|
|
8969
9489
|
(0, solid_js_web.insert)(_el$6, () => row().status ?? "Not available", _el$7);
|
|
8970
9490
|
(0, solid_js_web.insert)(_el$6, () => row().change, null);
|
|
@@ -8982,8 +9502,8 @@ function GuiMcpPreviewRows(props) {
|
|
|
8982
9502
|
});
|
|
8983
9503
|
}
|
|
8984
9504
|
// src/features/sidebar-settings/ui/gui/mcp-preset-preview.tsx
|
|
8985
|
-
var _tmpl$$
|
|
8986
|
-
var _tmpl$2$
|
|
9505
|
+
var _tmpl$$25 = /*#__PURE__*/ (0, solid_js_web.template)(`<p>`);
|
|
9506
|
+
var _tmpl$2$18 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=alert>`);
|
|
8987
9507
|
function GuiMcpPresetPreview(props) {
|
|
8988
9508
|
const Dialog = props.ui.Dialog;
|
|
8989
9509
|
const Button = props.ui.Button;
|
|
@@ -9044,7 +9564,7 @@ function GuiMcpPresetPreview(props) {
|
|
|
9044
9564
|
get children() {
|
|
9045
9565
|
return [
|
|
9046
9566
|
(() => {
|
|
9047
|
-
var _el$ = _tmpl$$
|
|
9567
|
+
var _el$ = _tmpl$$25();
|
|
9048
9568
|
(0, solid_js_web.insert)(_el$, () => props.persistent ? "Desired states will be remembered for this scope, including unavailable servers." : "MCP persistence is off; desired states will not be saved.");
|
|
9049
9569
|
return _el$;
|
|
9050
9570
|
})(),
|
|
@@ -9053,7 +9573,7 @@ function GuiMcpPresetPreview(props) {
|
|
|
9053
9573
|
return props.model.blocked() || error();
|
|
9054
9574
|
},
|
|
9055
9575
|
get children() {
|
|
9056
|
-
var _el$2 = _tmpl$2$
|
|
9576
|
+
var _el$2 = _tmpl$2$18();
|
|
9057
9577
|
(0, solid_js_web.insert)(_el$2, () => error() || props.model.blocked());
|
|
9058
9578
|
return _el$2;
|
|
9059
9579
|
}
|
|
@@ -9066,7 +9586,7 @@ function GuiMcpPresetPreview(props) {
|
|
|
9066
9586
|
});
|
|
9067
9587
|
}
|
|
9068
9588
|
// src/features/sidebar-settings/ui/gui/settings-about.tsx
|
|
9069
|
-
var _tmpl$$
|
|
9589
|
+
var _tmpl$$24 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status>`);
|
|
9070
9590
|
function GuiSettingsAbout(props) {
|
|
9071
9591
|
const Section = props.ui.SettingsSection;
|
|
9072
9592
|
const Row = props.ui.SettingsRow;
|
|
@@ -9076,11 +9596,15 @@ function GuiSettingsAbout(props) {
|
|
|
9076
9596
|
const versions = () => props.about.changelog.filter((entry) => entry.changes.length > 0);
|
|
9077
9597
|
const [version, setVersion] = (0, solid_js.createSignal)(versions()[0]?.version);
|
|
9078
9598
|
const changes = () => versions().find((entry) => entry.version === version())?.changes.map((change) => `- ${change}`).join("\n") ?? "No user-facing release notes are bundled.";
|
|
9599
|
+
const progress = () => {
|
|
9600
|
+
const current = props.about.progress?.();
|
|
9601
|
+
return current && updateProgressView(current);
|
|
9602
|
+
};
|
|
9079
9603
|
return [(0, solid_js_web.createComponent)(Section, {
|
|
9080
9604
|
title: "About Navigator",
|
|
9081
9605
|
get footer() {
|
|
9082
9606
|
return (() => {
|
|
9083
|
-
var _el$ = _tmpl$$
|
|
9607
|
+
var _el$ = _tmpl$$24();
|
|
9084
9608
|
(0, solid_js_web.insert)(_el$, () => props.about.status());
|
|
9085
9609
|
return _el$;
|
|
9086
9610
|
})();
|
|
@@ -9089,7 +9613,17 @@ function GuiSettingsAbout(props) {
|
|
|
9089
9613
|
return [
|
|
9090
9614
|
(0, solid_js_web.createComponent)(Row, {
|
|
9091
9615
|
get title() {
|
|
9092
|
-
return
|
|
9616
|
+
return (0, solid_js_web.memo)(() => !!progress())() ? (0, solid_js_web.createComponent)(GuiProgress, {
|
|
9617
|
+
get ui() {
|
|
9618
|
+
return props.ui;
|
|
9619
|
+
},
|
|
9620
|
+
get label() {
|
|
9621
|
+
return `Navigator · ${progress().label}`;
|
|
9622
|
+
},
|
|
9623
|
+
get value() {
|
|
9624
|
+
return progress().fraction;
|
|
9625
|
+
}
|
|
9626
|
+
}) : `Navigator ${props.about.version}`;
|
|
9093
9627
|
},
|
|
9094
9628
|
get description() {
|
|
9095
9629
|
return `OpenCode Desktop ${props.about.hostVersion}. Experimental Desktop GUI.`;
|
|
@@ -9167,7 +9701,7 @@ function GuiSettingsAbout(props) {
|
|
|
9167
9701
|
})];
|
|
9168
9702
|
}
|
|
9169
9703
|
// src/features/sidebar-settings/ui/gui/settings-behavior.tsx
|
|
9170
|
-
var _tmpl$$
|
|
9704
|
+
var _tmpl$$23 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;gap:8px;align-items:center>`);
|
|
9171
9705
|
function GuiSettingsBehavior(props) {
|
|
9172
9706
|
const Section = props.ui.SettingsSection;
|
|
9173
9707
|
const Row = props.ui.SettingsRow;
|
|
@@ -9251,7 +9785,7 @@ function GuiSettingsBehavior(props) {
|
|
|
9251
9785
|
title: "Limits refresh",
|
|
9252
9786
|
description: "Whole minutes, at least one. Manual refresh and model/account switches remain immediate.",
|
|
9253
9787
|
get children() {
|
|
9254
|
-
var _el$ = _tmpl$$
|
|
9788
|
+
var _el$ = _tmpl$$23();
|
|
9255
9789
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(TextInput, {
|
|
9256
9790
|
label: "Limits refresh in minutes",
|
|
9257
9791
|
get value() {
|
|
@@ -9334,6 +9868,7 @@ function GuiSettingsBehavior(props) {
|
|
|
9334
9868
|
];
|
|
9335
9869
|
}
|
|
9336
9870
|
// src/features/sidebar-settings/ui/gui/settings-catalogs.tsx
|
|
9871
|
+
var _tmpl$$22 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=display:flex;gap:8px;align-items:center>`);
|
|
9337
9872
|
function GuiSettingsCatalogs(props) {
|
|
9338
9873
|
const Section = props.ui.SettingsSection;
|
|
9339
9874
|
const Row = props.ui.SettingsRow;
|
|
@@ -9346,42 +9881,40 @@ function GuiSettingsCatalogs(props) {
|
|
|
9346
9881
|
title: "Quick Actions",
|
|
9347
9882
|
footer: "Visibility and order are scoped. Favorites are private and user-wide; usage never reorders actions.",
|
|
9348
9883
|
get children() {
|
|
9349
|
-
return (0, solid_js_web.createComponent)(
|
|
9350
|
-
get
|
|
9884
|
+
return (0, solid_js_web.createComponent)(GuiSortableList, {
|
|
9885
|
+
get ui() {
|
|
9886
|
+
return props.ui;
|
|
9887
|
+
},
|
|
9888
|
+
label: "Quick Action order",
|
|
9889
|
+
get items() {
|
|
9351
9890
|
return props.catalogs.actions();
|
|
9352
9891
|
},
|
|
9353
|
-
|
|
9892
|
+
itemKey: (action) => action.id,
|
|
9893
|
+
itemLabel: (action) => action.label,
|
|
9894
|
+
get scope() {
|
|
9895
|
+
return props.preferences.selectedScopeKey();
|
|
9896
|
+
},
|
|
9897
|
+
move: (from, to) => props.preferences.reorderQuickAction(from, to, props.preferences.selectedScopeKey()),
|
|
9898
|
+
children: (action, handle) => (0, solid_js_web.createComponent)(Row, {
|
|
9354
9899
|
get title() {
|
|
9355
|
-
return
|
|
9900
|
+
return (() => {
|
|
9901
|
+
var _el$ = _tmpl$$22();
|
|
9902
|
+
(0, solid_js_web.insert)(_el$, handle, null);
|
|
9903
|
+
(0, solid_js_web.insert)(_el$, () => action().label, null);
|
|
9904
|
+
return _el$;
|
|
9905
|
+
})();
|
|
9356
9906
|
},
|
|
9357
9907
|
get children() {
|
|
9358
|
-
return
|
|
9359
|
-
(
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
size: "small",
|
|
9369
|
-
get disabled() {
|
|
9370
|
-
return index() === props.catalogs.actions().length - 1;
|
|
9371
|
-
},
|
|
9372
|
-
onClick: () => props.preferences.moveQuickAction(action.id, 1),
|
|
9373
|
-
children: "Move down"
|
|
9374
|
-
}),
|
|
9375
|
-
(0, solid_js_web.createComponent)(Switch, {
|
|
9376
|
-
get label() {
|
|
9377
|
-
return `Show action ${action.label}`;
|
|
9378
|
-
},
|
|
9379
|
-
get checked() {
|
|
9380
|
-
return props.preferences.selectedQuickActionVisible(action.id);
|
|
9381
|
-
},
|
|
9382
|
-
onChange: () => props.preferences.toggleQuickAction(action.id)
|
|
9383
|
-
})
|
|
9384
|
-
];
|
|
9908
|
+
return (0, solid_js_web.createComponent)(Switch, {
|
|
9909
|
+
get label() {
|
|
9910
|
+
return `Show action ${action().label}`;
|
|
9911
|
+
},
|
|
9912
|
+
hideLabel: true,
|
|
9913
|
+
get checked() {
|
|
9914
|
+
return props.preferences.selectedQuickActionVisible(action().id);
|
|
9915
|
+
},
|
|
9916
|
+
onChange: () => props.preferences.toggleQuickAction(action().id)
|
|
9917
|
+
});
|
|
9385
9918
|
}
|
|
9386
9919
|
})
|
|
9387
9920
|
});
|
|
@@ -9546,7 +10079,7 @@ function GuiPresetControls(props) {
|
|
|
9546
10079
|
}
|
|
9547
10080
|
// src/features/sidebar-settings/ui/gui/settings-presets.tsx
|
|
9548
10081
|
var _tmpl$$20 = /*#__PURE__*/ (0, solid_js_web.template)(`<div style=display:flex;gap:8px;flex-wrap:wrap>`);
|
|
9549
|
-
var _tmpl$2$
|
|
10082
|
+
var _tmpl$2$17 = /*#__PURE__*/ (0, solid_js_web.template)(`<p role=status>`);
|
|
9550
10083
|
function GuiSettingsPresets(props) {
|
|
9551
10084
|
const Section = props.ui.SettingsSection;
|
|
9552
10085
|
const Row = props.ui.SettingsRow;
|
|
@@ -9573,7 +10106,7 @@ function GuiSettingsPresets(props) {
|
|
|
9573
10106
|
return message();
|
|
9574
10107
|
},
|
|
9575
10108
|
get children() {
|
|
9576
|
-
var _el$2 = _tmpl$2$
|
|
10109
|
+
var _el$2 = _tmpl$2$17();
|
|
9577
10110
|
(0, solid_js_web.insert)(_el$2, message);
|
|
9578
10111
|
return _el$2;
|
|
9579
10112
|
}
|
|
@@ -9762,7 +10295,8 @@ function GuiSettingsResets(props) {
|
|
|
9762
10295
|
});
|
|
9763
10296
|
}
|
|
9764
10297
|
// src/features/sidebar-settings/ui/gui/section-settings-row.tsx
|
|
9765
|
-
var _tmpl$$19 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=group style=display:flex;gap:8px;align-items:center;flex-wrap:wrap
|
|
10298
|
+
var _tmpl$$19 = /*#__PURE__*/ (0, solid_js_web.template)(`<div role=group style=display:flex;gap:8px;align-items:center;flex-wrap:wrap><span style=display:flex;gap:6px;align-items:center><span>Visible</span></span><span style=display:flex;gap:6px;align-items:center><span>Expanded`);
|
|
10299
|
+
var _tmpl$2$16 = /*#__PURE__*/ (0, solid_js_web.template)(`<span style=display:flex;gap:8px;align-items:center>`);
|
|
9766
10300
|
function GuiSectionSettingsRow(props) {
|
|
9767
10301
|
const Row = props.ui.SettingsRow;
|
|
9768
10302
|
const Switch = props.ui.Switch;
|
|
@@ -9774,7 +10308,12 @@ function GuiSectionSettingsRow(props) {
|
|
|
9774
10308
|
(0, solid_js.createEffect)(() => setLimit(String(props.preferences.selectedSectionItemLimit(props.section))));
|
|
9775
10309
|
return (0, solid_js_web.createComponent)(Row, {
|
|
9776
10310
|
get title() {
|
|
9777
|
-
return
|
|
10311
|
+
return (() => {
|
|
10312
|
+
var _el$6 = _tmpl$2$16();
|
|
10313
|
+
(0, solid_js_web.insert)(_el$6, () => props.handle, null);
|
|
10314
|
+
(0, solid_js_web.insert)(_el$6, label, null);
|
|
10315
|
+
return _el$6;
|
|
10316
|
+
})();
|
|
9778
10317
|
},
|
|
9779
10318
|
get id() {
|
|
9780
10319
|
return `navigator-section-${props.section}`;
|
|
@@ -9783,24 +10322,12 @@ function GuiSectionSettingsRow(props) {
|
|
|
9783
10322
|
return props.section === "lsp" ? "LSP is not exposed by this Desktop API. Its saved layout is retained for supported TUI hosts." : void 0;
|
|
9784
10323
|
},
|
|
9785
10324
|
get children() {
|
|
9786
|
-
var _el$ = _tmpl$$19();
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
onClick: () => props.preferences.moveSelectedSection(props.section, -1),
|
|
9793
|
-
children: "Move up"
|
|
9794
|
-
}), null);
|
|
9795
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Button, {
|
|
9796
|
-
size: "small",
|
|
9797
|
-
get disabled() {
|
|
9798
|
-
return props.index === props.count - 1;
|
|
9799
|
-
},
|
|
9800
|
-
onClick: () => props.preferences.moveSelectedSection(props.section, 1),
|
|
9801
|
-
children: "Move down"
|
|
9802
|
-
}), null);
|
|
9803
|
-
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(Switch, {
|
|
10325
|
+
var _el$ = _tmpl$$19(), _el$2 = _el$.firstChild;
|
|
10326
|
+
_el$2.firstChild;
|
|
10327
|
+
var _el$4 = _el$2.nextSibling;
|
|
10328
|
+
_el$4.firstChild;
|
|
10329
|
+
(0, solid_js_web.insert)(_el$2, (0, solid_js_web.createComponent)(Switch, {
|
|
10330
|
+
hideLabel: true,
|
|
9804
10331
|
get label() {
|
|
9805
10332
|
return `Show ${label()}`;
|
|
9806
10333
|
},
|
|
@@ -9809,7 +10336,8 @@ function GuiSectionSettingsRow(props) {
|
|
|
9809
10336
|
},
|
|
9810
10337
|
onChange: () => props.preferences.toggleSelectedSection(props.section)
|
|
9811
10338
|
}), null);
|
|
9812
|
-
(0, solid_js_web.insert)(_el
|
|
10339
|
+
(0, solid_js_web.insert)(_el$4, (0, solid_js_web.createComponent)(Switch, {
|
|
10340
|
+
hideLabel: true,
|
|
9813
10341
|
get label() {
|
|
9814
10342
|
return `Expand ${label()}`;
|
|
9815
10343
|
},
|
|
@@ -9857,18 +10385,25 @@ function GuiSettingsSections(props) {
|
|
|
9857
10385
|
title: "Sections",
|
|
9858
10386
|
footer: "Visibility changes apply immediately. Save this layout as the scoped default to use it in future sessions.",
|
|
9859
10387
|
get children() {
|
|
9860
|
-
return (0, solid_js_web.createComponent)(
|
|
9861
|
-
get
|
|
10388
|
+
return (0, solid_js_web.createComponent)(GuiSortableList, {
|
|
10389
|
+
get ui() {
|
|
10390
|
+
return props.ui;
|
|
10391
|
+
},
|
|
10392
|
+
label: "Section order",
|
|
10393
|
+
get items() {
|
|
9862
10394
|
return preferences.selectedSectionOrder();
|
|
9863
10395
|
},
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
10396
|
+
itemKey: (section) => section,
|
|
10397
|
+
itemLabel: (section) => SECTION_DEFINITIONS.find((value) => value.name === section)?.label ?? section,
|
|
10398
|
+
get scope() {
|
|
10399
|
+
return preferences.selectedScopeKey();
|
|
10400
|
+
},
|
|
10401
|
+
move: (from, to) => preferences.reorderSelectedSection(from, to, preferences.selectedScopeKey()),
|
|
10402
|
+
children: (section, handle) => (0, solid_js_web.createComponent)(GuiSectionSettingsRow, (0, solid_js_web.mergeProps)(props, {
|
|
10403
|
+
get section() {
|
|
10404
|
+
return section();
|
|
9868
10405
|
},
|
|
9869
|
-
|
|
9870
|
-
return preferences.selectedSectionOrder().length;
|
|
9871
|
-
}
|
|
10406
|
+
handle
|
|
9872
10407
|
}))
|
|
9873
10408
|
});
|
|
9874
10409
|
}
|
|
@@ -9902,103 +10437,105 @@ function GuiNavigatorSettings(props) {
|
|
|
9902
10437
|
title: "Navigator",
|
|
9903
10438
|
description: "Shared sidebar settings for this Desktop and your local TUI instances.",
|
|
9904
10439
|
get children() {
|
|
9905
|
-
return (0, solid_js_web.createComponent)(
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
var _el$2 = _tmpl$2$15();
|
|
9923
|
-
(0, solid_js_web.insert)(_el$2, status);
|
|
9924
|
-
return _el$2;
|
|
9925
|
-
}
|
|
9926
|
-
});
|
|
9927
|
-
},
|
|
9928
|
-
get children() {
|
|
9929
|
-
return [
|
|
9930
|
-
(0, solid_js_web.createComponent)(Row, {
|
|
9931
|
-
title: "Scope",
|
|
9932
|
-
description: "Global applies everywhere. Worktree overrides use the currently selected server and location.",
|
|
9933
|
-
get children() {
|
|
9934
|
-
return (0, solid_js_web.createComponent)(Select, {
|
|
9935
|
-
label: "Navigator preference scope",
|
|
9936
|
-
get value() {
|
|
9937
|
-
return props.preferences.preferenceScope();
|
|
9938
|
-
},
|
|
9939
|
-
get options() {
|
|
9940
|
-
return [{
|
|
9941
|
-
value: "global",
|
|
9942
|
-
label: "Global"
|
|
9943
|
-
}, ...props.preferences.canUseWorktreeScope() ? [{
|
|
9944
|
-
value: "worktree",
|
|
9945
|
-
label: "Worktree"
|
|
9946
|
-
}] : []];
|
|
9947
|
-
},
|
|
9948
|
-
get onChange() {
|
|
9949
|
-
return props.preferences.setPreferenceScope;
|
|
9950
|
-
}
|
|
9951
|
-
});
|
|
9952
|
-
}
|
|
9953
|
-
}),
|
|
9954
|
-
(0, solid_js_web.createComponent)(Row, {
|
|
9955
|
-
title: "Layout default",
|
|
9956
|
-
description: "Changing section visibility or order does not implicitly replace the saved default.",
|
|
9957
|
-
get children() {
|
|
9958
|
-
return (0, solid_js_web.createComponent)(Button, {
|
|
9959
|
-
get busy() {
|
|
9960
|
-
return busy();
|
|
9961
|
-
},
|
|
9962
|
-
onClick: () => void run(props.preferences.saveLayoutAsDefault, "Layout default saved for this scope."),
|
|
9963
|
-
children: "Save layout as default"
|
|
9964
|
-
});
|
|
9965
|
-
}
|
|
9966
|
-
}),
|
|
9967
|
-
(0, solid_js_web.createComponent)(Row, {
|
|
9968
|
-
title: "Reload private preferences",
|
|
9969
|
-
description: "Flush local writes, then load changes from other Navigator instances. Temporary layout overrides are cleared.",
|
|
10440
|
+
return (0, solid_js_web.createComponent)(GuiSettingsSurface, { get children() {
|
|
10441
|
+
return (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
10442
|
+
get when() {
|
|
10443
|
+
return props.preferences.ready();
|
|
10444
|
+
},
|
|
10445
|
+
get fallback() {
|
|
10446
|
+
return _tmpl$$18();
|
|
10447
|
+
},
|
|
10448
|
+
get children() {
|
|
10449
|
+
return [
|
|
10450
|
+
(0, solid_js_web.createComponent)(Section, {
|
|
10451
|
+
title: "Preference scope",
|
|
10452
|
+
get footer() {
|
|
10453
|
+
return (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
10454
|
+
get when() {
|
|
10455
|
+
return status();
|
|
10456
|
+
},
|
|
9970
10457
|
get children() {
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
},
|
|
9975
|
-
onClick: () => void run(props.preferences.reloadFromFile, "Private preferences reloaded."),
|
|
9976
|
-
children: "Reload preferences"
|
|
9977
|
-
});
|
|
10458
|
+
var _el$2 = _tmpl$2$15();
|
|
10459
|
+
(0, solid_js_web.insert)(_el$2, status);
|
|
10460
|
+
return _el$2;
|
|
9978
10461
|
}
|
|
9979
|
-
})
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10462
|
+
});
|
|
10463
|
+
},
|
|
10464
|
+
get children() {
|
|
10465
|
+
return [
|
|
10466
|
+
(0, solid_js_web.createComponent)(Row, {
|
|
10467
|
+
title: "Scope",
|
|
10468
|
+
description: "Global applies everywhere. Worktree overrides use the currently selected server and location.",
|
|
10469
|
+
get children() {
|
|
10470
|
+
return (0, solid_js_web.createComponent)(Select, {
|
|
10471
|
+
label: "Navigator preference scope",
|
|
10472
|
+
get value() {
|
|
10473
|
+
return props.preferences.preferenceScope();
|
|
10474
|
+
},
|
|
10475
|
+
get options() {
|
|
10476
|
+
return [{
|
|
10477
|
+
value: "global",
|
|
10478
|
+
label: "Global"
|
|
10479
|
+
}, ...props.preferences.canUseWorktreeScope() ? [{
|
|
10480
|
+
value: "worktree",
|
|
10481
|
+
label: "Worktree"
|
|
10482
|
+
}] : []];
|
|
10483
|
+
},
|
|
10484
|
+
get onChange() {
|
|
10485
|
+
return props.preferences.setPreferenceScope;
|
|
10486
|
+
}
|
|
10487
|
+
});
|
|
10488
|
+
}
|
|
10489
|
+
}),
|
|
10490
|
+
(0, solid_js_web.createComponent)(Row, {
|
|
10491
|
+
title: "Layout default",
|
|
10492
|
+
description: "Changing section visibility or order does not implicitly replace the saved default.",
|
|
10493
|
+
get children() {
|
|
10494
|
+
return (0, solid_js_web.createComponent)(Button, {
|
|
10495
|
+
get busy() {
|
|
10496
|
+
return busy();
|
|
10497
|
+
},
|
|
10498
|
+
onClick: () => void run(props.preferences.saveLayoutAsDefault, "Layout default saved for this scope."),
|
|
10499
|
+
children: "Save layout as default"
|
|
10500
|
+
});
|
|
10501
|
+
}
|
|
10502
|
+
}),
|
|
10503
|
+
(0, solid_js_web.createComponent)(Row, {
|
|
10504
|
+
title: "Reload private preferences",
|
|
10505
|
+
description: "Flush local writes, then load changes from other Navigator instances. Temporary layout overrides are cleared.",
|
|
10506
|
+
get children() {
|
|
10507
|
+
return (0, solid_js_web.createComponent)(Button, {
|
|
10508
|
+
get busy() {
|
|
10509
|
+
return busy();
|
|
10510
|
+
},
|
|
10511
|
+
onClick: () => void run(props.preferences.reloadFromFile, "Private preferences reloaded."),
|
|
10512
|
+
children: "Reload preferences"
|
|
10513
|
+
});
|
|
10514
|
+
}
|
|
10515
|
+
})
|
|
10516
|
+
];
|
|
10517
|
+
}
|
|
10518
|
+
}),
|
|
10519
|
+
(0, solid_js_web.createComponent)(GuiSettingsSections, props),
|
|
10520
|
+
(0, solid_js_web.createComponent)(GuiSettingsBehavior, props),
|
|
10521
|
+
(0, solid_js_web.createComponent)(GuiSettingsPresets, props),
|
|
10522
|
+
(0, solid_js_web.createComponent)(GuiSettingsCatalogs, props),
|
|
10523
|
+
(0, solid_js_web.createComponent)(GuiSettingsResets, props),
|
|
10524
|
+
(0, solid_js_web.createComponent)(GuiSettingsAbout, {
|
|
10525
|
+
get ui() {
|
|
10526
|
+
return props.ui;
|
|
10527
|
+
},
|
|
10528
|
+
get about() {
|
|
10529
|
+
return props.about;
|
|
10530
|
+
},
|
|
10531
|
+
get showGuide() {
|
|
10532
|
+
return props.showGuide;
|
|
10533
|
+
}
|
|
10534
|
+
})
|
|
10535
|
+
];
|
|
10536
|
+
}
|
|
10537
|
+
});
|
|
10538
|
+
} });
|
|
10002
10539
|
}
|
|
10003
10540
|
});
|
|
10004
10541
|
}
|
|
@@ -10604,7 +11141,7 @@ function createGuiBugReport(context) {
|
|
|
10604
11141
|
let token = "";
|
|
10605
11142
|
(0, solid_js.onCleanup)(() => abort.abort());
|
|
10606
11143
|
const model = createBugReportModel({
|
|
10607
|
-
navigatorVersion: "0.27.
|
|
11144
|
+
navigatorVersion: "0.27.3",
|
|
10608
11145
|
openCodeVersion: context.app.version,
|
|
10609
11146
|
platform: context.app.platform,
|
|
10610
11147
|
runtime: "OpenCode Desktop GUI"
|
|
@@ -10656,8 +11193,8 @@ function createGuiBugReport(context) {
|
|
|
10656
11193
|
}
|
|
10657
11194
|
// src/app/gui/release.ts
|
|
10658
11195
|
var guiRelease = {
|
|
10659
|
-
version: "0.27.
|
|
10660
|
-
changelog: "# Changelog\n\n## [0.27.1] - 2026-11-11\n\n- Drag the Desktop mini-window by its header as well as its move handle, while keeping Dock a separate action. Match its surface and controls to OpenCode's light and dark themes.\n- Use native Desktop switches and selectors for Skill trust and Todo configuration, and align multiline fields with the host theme and focus styles.\n- Show a remaining-lifetime scale and time until expiry for banked reset credits with provider-supplied dates. Keep missing expiry explicit and prevent selecting expired credits for review.\n\n## [0.27.0] - 2026-11-11\n\n- Add an experimental OpenCode Desktop interface with a native panel, narrow-screen drawer, and opt-in in-app mini-window. Move, resize, reset and redock it with the mouse or keyboard while keeping the selected session and filters.\n- Bring Search Everything, Skills, MCP groups and presets, Quick Actions, and customizable toolbar pins to Desktop. Share private favorites, trust decisions and preferences with local TUI instances without duplicating monitoring.\n- Add native Desktop settings with scoped section controls, groups, reviewed presets and project profiles, portable import/export, a seven-slide setup guide, About, browsable release history and editable GitHub Bug reports.\n- Keep superseded Desktop configuration reads from showing a false error after a newer refresh, while preserving genuine failures and retry guidance.\n- Show verified provider/account quotas in Desktop with explicit account linking and separately confirmed banked resets. Keep remote sessions isolated from local accounts and preserve unresolved reset attempts across retries.\n- Support OpenCode 1.19.5 and 2.2.6 while preserving both TUI adapters, existing settings, pinned-source updates and read-only legacy Todo archives.\n\n## [0.26.0] - 2026-11-06\n\n- Prevent background retries from accumulating cancellation listeners and preferences loading from waiting indefinitely on recovery markers.\n- Show exact active Subagent durations from OpenCode 2's native execution start time, preserving the observation fallback when timing is unavailable. Keep interrupted executions marked as cancelled in recent history.\n\n## [0.25.0] - 2026-10-31\n\n- Offer Enable Todo when OpenCode 2's native tool is disabled, with an existing server-config picker, exact change preview and separate confirmation. Preserve unrelated JSONC content and refuse stale targets; distinguish disabled Todo from an enabled empty list.\n- Update the seven-slide setup wizard for native Todo enablement, provider/account limits, multi-icon or text-only toolbar pins, About/changelog and Bug reports. Describe each host's real permissions/LSP capabilities and keep navigation visible while short-terminal content scrolls.\n\n## [0.24.0] - 2026-10-31\n\n- Support the latest stable OpenCode 1.19.5 and 2.2.5 releases, preserving both host adapters and existing sidebar behavior.\n- Preserve Limits scales and reset-credit controls across equivalent quota snapshots and unrelated workspace events, while retaining current-account and credential-change guards.\n- Keep rounded selection backgrounds consistent in nested dialogs and highlighted rows.\n- Configure each toolbar button with zero to three icons and optional custom text, including text-only buttons. Keep legacy/state choices, unsaved drafts, rounded clipping, and width-aware More/wrapping.\n- Keep Quick Action rows and their hover/focus state stable while typing in the main prompt on both supported OpenCode hosts.\n- Show toolbar hover/focus hints without moving Limits or other sections, preserving centered, uniformly sized icon controls and empty-toolbar collapse.\n- Add Settings → About with the running versions, explicit update status/checking, confirmed updates, and a versioned changelog that can be reopened independently of first-launch upgrade notes.\n- Prepare editable Bug reports with confirmed sending through authenticated GitHub CLI and an independent Open in browser action. Retain drafts through errors and cancellation, and require manual review before retrying an uncertain submission.\n\n## [0.23.0] - 2026-10-28\n\n- Support only the latest stable OpenCode 1.x and 2.x releases, currently 1.19.5 and 2.2.0, including the newer terminal renderer.\n- Keep Skills, MCP servers, and Subagents current as OpenCode 2 updates, and launch the intended Skill when multiple sources have the same name.\n- Show OpenCode Console workspace budgets and Go allowance through the public host usage API without a Navigator server plugin. Preserve workspace scope, native units, reset times, and explicit failure/retry states.\n- Preserve Navigator shortcuts and nested-dialog navigation with OpenCode 2.2's keyboard handling.\n- Verify a supported runtime before changing a pinned Navigator snapshot, preserving the installed version when no compatible verifier is available.\n\n## [0.22.0] - 2026-10-23\n\n- Pin Quick Actions and Skills to a compact sidebar toolbar independently of bookmarks. Choose icons in a searchable picker, customize supported state icons, reorder buttons, and select a More menu or wrapping rows. Preserve Skill confirmations, unavailable reasons, keyboard navigation, and Text fallback; hide the toolbar entirely when empty.\n- Use OpenCode 2's built-in Todo history for the sidebar, with native completed-write and revert semantics, existing filters/progress, and manual Refresh. Keep edits in ordinary chat, preserve previous Navigator tasks as a read-only archive, and retain the independent provider-quota server integration.\n- Support OpenCode 2.1's plugin and rendering APIs while retaining the OpenCode 1.x adapter; restore custom dialogs and rounded selections on the newer native renderer.\n- Replace the shortcut toast with an icon-led hint featuring highlighted keys, navigation/update groups, a distinct Escape action, and responsive Text/no-corner-font layouts. Keep prompt focus and share its action list with scrollable keyboard help.\n- Update Subagent status immediately from OpenCode 2's execution lifecycle and keep unresolved external credentials separate from verified provider accounts.\n- Keep OpenCode updates on the current major line and preserve pinned-source Navigator updates when a target release needs newer runtime dependencies.\n\n## [0.21.8] - 2026-10-09\n\n- Make the unfilled part of Limits scales substantially quieter, matching the theme-derived sidebar-divider tone. Keep the filled segment, reset text, and remaining values readable in both icon modes and after theme changes.\n\n## [0.21.7] - 2026-10-09\n\n- Remove the vertical guide and its reserved gutter from Limits in both icon modes. Keep full-width quota scales, reset-left/remaining-right details, and one blank row between quota windows.\n\n## [0.21.6] - 2026-10-09\n\n- Refine Limits with a continuous muted guide, full-width thin-line quota scales, and reset-left/remaining-right details. Keep long reset text from overlapping the remaining value and preserve Text fallback, resize clipping, and existing controls.\n\n## [0.21.5] - 2026-10-07\n\n- Make automatic Limits refresh configurable in scoped Behavior settings and portable configuration, with a five-minute default and one-minute minimum. Keep manual Refresh and supported model/account switches immediate.\n- Avoid extra quota polling from unrelated preference changes and unchanged provider-account metadata observations.\n\n## [0.21.4] - 2026-10-07\n\n- Add `c` to Navigator shortcuts for a manual update check and `u` to check then confirm a Navigator update. Report available, current, or unavailable results, preserve the installation method and scope, and require a restart after updating.\n- Ignore cancelled, outdated, and repeated update confirmations, and recover from stalled update checks without blocking later checks.\n\n## [0.21.3] - 2026-10-06\n\n- Replace block quota meters with full-width adaptive thin-line scales and keep quota rows inside the sidebar's padding after resize. Show only reset time below each meter, removing technical account and window-duration suffixes.\n\n## [0.21.2] - 2026-10-06\n\n- Make Limits compact with clickable provider/model and variant controls, remaining-headroom progress rows, and muted reset times. Move Refresh and Banked Resets into the section header, remove the section counter and Provider sources action, and keep reset consumption behind a separate confirmation.\n\n## [0.21.1] - 2026-10-06\n\n- Fix Codex account quota windows being hidden when the provider omits model metadata. Show ordinary usage as shared account quota, retain banked-reset counts, and keep separate model buckets explicitly associated.\n\n## [0.21.0] - 2026-10-06\n\n- Automatically verify Codex account identity from OpenCode 2's ChatGPT connection. When host identity is unavailable, confirm a private binding once per connection or provider and reuse it across models, projects, and sessions; preserve compatible older confirmations and isolate conflicting ones until relinked.\n- Expand OpenCode 2 Limits with documented native subscription allowances, API rate-limit observations, configured capacities, account balances, and key budgets. Keep provider-native units, currencies, model associations, and active-account boundaries explicit.\n- Add Provider sources to explain each provider's supported measurements, required permissions, and unavailable APIs without guessing remaining quota.\n- Keep available account balances visible when a separate subscription read fails, and show exhausted NanoGPT subscription windows instead of hiding them.\n- Keep stale quota guidance visible after failed refreshes, reject late results after credential changes, and recover from stalled provider reads without blocking model response streams.\n\n## [0.20.0] - 2026-10-05\n\n- Add a default-visible Limits section for the selected model's provider-native quota windows, reset times, account identity, and freshness. Codex CLI support requires an explicit private account binding; unsupported providers show calm guidance.\n- Review Codex banked reset credits and use them only after a separate confirmation and fresh eligibility checks. Preserve the same attempt key when reconciling an uncertain result, including after a restart.\n- Save named, commit-safe project layout and MCP profiles to `.opencode/navigator.json` with the `opencode-navigator-profile` command, an explicit preview, and `--apply`; profile application remains manual.\n\n## [0.19.3] - 2026-10-03\n\n- Indent grouped Todo, Subagent, Skill, and MCP rows and align MCP server status indicators with their group headings.\n- Place Skill, MCP, and Quick Action bookmarks before item names. Reveal unselected bookmarks on hover or keyboard focus, keep favorites visible, and keep labels steady.\n\n## [0.19.2] - 2026-10-02\n\n- Show MCP group connection states with the same radio-style indicators as individual servers, without Connect/Disconnect labels on group headings.\n\n## [0.19.1] - 2026-10-02\n\n- Remember the OpenCode 1.x auto-approve mode as a user-wide default for new sessions, including changes made through the host's permission toggle.\n\n## [0.19.0] - 2026-10-02\n\n- Connect or disconnect all eligible MCP servers in a group from its heading, including filtered-out items, with keyboard access and failed-only retry.\n- Organize Skills into user-wide groups by source location, with Favorites first and group names searchable across the full catalog.\n- Reload saved Navigator settings from disk in another running OpenCode session without restarting it.\n\n## [0.18.2] - 2026-10-02\n\n- Open the host Settings dialog from the OpenCode 2.x Permissions Quick Action, where the user can change between `prompt` and `auto accept`; keep the direct auto-approve toggle on OpenCode 1.x.\n\n## [0.18.1] - 2026-10-01\n\n- Show calm Todo setup guidance in OpenCode 2.x when Navigator's server plugin is absent, without a request error or Retry control. Actual server failures still offer Retry.\n- Keep Quick Action names readable in narrow sidebars by placing unavailable reasons below them and showing shortcuts only when they fit.\n\n## [0.18.0] - 2026-10-01\n\n- Add durable per-session Todo lists to OpenCode 2.x through a separately configured Navigator server plugin and an agent Todo tool.\n- Update Todo in the sidebar as tasks change, and offer an off-by-default per-session switch for model-context Todo instructions.\n- Keep Todo visible with setup guidance when the OpenCode 2.x server plugin is missing.\n\n## [0.17.3] - 2026-09-30\n\n## [0.17.2] - 2026-09-30\n\n- Update a pinned local Navigator installation from its version label while keeping its file or directory source unchanged.\n- Hide the session title and creation date independently with Global/Worktree settings in OpenCode 1.x.\n\n## [0.17.1] - 2026-09-29\n\n- Fix the local Navigator installation changing unexpectedly when rebuilding the repository; it now stays on its pinned version.\n\n## [0.17.0] - 2026-09-29\n\n- Add an opt-in Behavior setting to start a new session directly in chat with the sidebar from Home or New session.\n- Remember the previously installed Navigator version and show the intervening release notes once after an update.\n\n## [0.16.1] - 2026-09-25\n\n- Make the entire OpenCode or Navigator version label open its own update confirmation when an update is available. The separator and the other version remain inactive.\n- Replace the small update arrow with a more prominent filled-circle Nerd Font indicator, retaining an ASCII fallback.\n\n## [0.16.0] - 2026-09-25\n\n- Show both OpenCode and Navigator versions in the OpenCode 2.x footer.\n- Confirm updates from the footer or command palette, preserve the original installation method and scope, and report the outcome with a restart reminder.\n\nEarlier release notes are available on [GitHub Releases](https://github.com/St1ggy/opencode-navigator/releases).\n\n[0.22.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.8...v0.22.0\n[0.21.8]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.7...v0.21.8\n[0.21.7]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.6...v0.21.7\n[0.21.6]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.5...v0.21.6\n[0.21.5]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.4...v0.21.5\n[0.21.4]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.3...v0.21.4\n[0.21.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.2...v0.21.3\n[0.21.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.1...v0.21.2\n[0.21.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.0...v0.21.1\n[0.21.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.20.0...v0.21.0\n[0.20.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.3...v0.20.0\n[0.19.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.2...v0.19.3\n[0.19.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.1...v0.19.2\n[0.19.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.0...v0.19.1\n[0.19.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.2...v0.19.0\n[0.18.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.1...v0.18.2\n[0.18.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.0...v0.18.1\n[0.18.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.3...v0.18.0\n[0.17.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.2...v0.17.3\n[0.17.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.1...v0.17.2\n[0.17.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.0...v0.17.1\n[0.17.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.16.1...v0.17.0\n[0.16.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.16.0...v0.16.1\n[0.16.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.15.0...v0.16.0\n"
|
|
11196
|
+
version: "0.27.3",
|
|
11197
|
+
changelog: "# Changelog\n\n## [0.27.3] - 2026-11-12\n\n- Keep the Desktop session title on its own full-width row in both the panel and floating mini-window, with readable wrapping instead of squeezing it between action labels.\n- Use native icon buttons with tooltips for familiar sidebar actions such as Search, Refresh, Settings, Float, Dock and information. Keep descriptive labels for account linking, Banked Resets, presets and other less obvious operations.\n- Remove the persistent account/model scope explanation from successful Desktop Limits. Keep the short update time, quota data and actionable warnings without changing account scope or reset-credit safeguards.\n\n## [0.27.2] - 2026-11-11\n\n- Keep Desktop Settings fields and actions inside their rows at narrow widths, with readable labels and compact group creation.\n- Reorder Desktop sections, Quick Actions, toolbar pins and button icons by dragging their handles, or use Space and arrow keys to move them with the keyboard. Escape cancels an unfinished move.\n- Show download and installation progress in place of the running version in TUI and inline in Desktop About. Show real percentages only when byte totals are available; otherwise show the active stage.\n- Bring Desktop section arrows, loading indicators and Todo rows closer to native OpenCode. Completed and cancelled tasks use muted, struck-through text with distinct status icons.\n- Remove duplicate model and reasoning-effort selectors from the Desktop sidebar. Select them below chat instead; Limits continue to follow the active model.\n\n## [0.27.1] - 2026-11-11\n\n- Drag the Desktop mini-window by its header as well as its move handle, while keeping Dock a separate action. Match its surface and controls to OpenCode's light and dark themes.\n- Use native Desktop switches and selectors for Skill trust and Todo configuration, and align multiline fields with the host theme and focus styles.\n- Show a remaining-lifetime scale and time until expiry for banked reset credits with provider-supplied dates. Keep missing expiry explicit and prevent selecting expired credits for review.\n\n## [0.27.0] - 2026-11-11\n\n- Add an experimental OpenCode Desktop interface with a native panel, narrow-screen drawer, and opt-in in-app mini-window. Move, resize, reset and redock it with the mouse or keyboard while keeping the selected session and filters.\n- Bring Search Everything, Skills, MCP groups and presets, Quick Actions, and customizable toolbar pins to Desktop. Share private favorites, trust decisions and preferences with local TUI instances without duplicating monitoring.\n- Add native Desktop settings with scoped section controls, groups, reviewed presets and project profiles, portable import/export, a seven-slide setup guide, About, browsable release history and editable GitHub Bug reports.\n- Keep superseded Desktop configuration reads from showing a false error after a newer refresh, while preserving genuine failures and retry guidance.\n- Show verified provider/account quotas in Desktop with explicit account linking and separately confirmed banked resets. Keep remote sessions isolated from local accounts and preserve unresolved reset attempts across retries.\n- Support OpenCode 1.19.5 and 2.2.6 while preserving both TUI adapters, existing settings, pinned-source updates and read-only legacy Todo archives.\n\n## [0.26.0] - 2026-11-06\n\n- Prevent background retries from accumulating cancellation listeners and preferences loading from waiting indefinitely on recovery markers.\n- Show exact active Subagent durations from OpenCode 2's native execution start time, preserving the observation fallback when timing is unavailable. Keep interrupted executions marked as cancelled in recent history.\n\n## [0.25.0] - 2026-10-31\n\n- Offer Enable Todo when OpenCode 2's native tool is disabled, with an existing server-config picker, exact change preview and separate confirmation. Preserve unrelated JSONC content and refuse stale targets; distinguish disabled Todo from an enabled empty list.\n- Update the seven-slide setup wizard for native Todo enablement, provider/account limits, multi-icon or text-only toolbar pins, About/changelog and Bug reports. Describe each host's real permissions/LSP capabilities and keep navigation visible while short-terminal content scrolls.\n\n## [0.24.0] - 2026-10-31\n\n- Support the latest stable OpenCode 1.19.5 and 2.2.5 releases, preserving both host adapters and existing sidebar behavior.\n- Preserve Limits scales and reset-credit controls across equivalent quota snapshots and unrelated workspace events, while retaining current-account and credential-change guards.\n- Keep rounded selection backgrounds consistent in nested dialogs and highlighted rows.\n- Configure each toolbar button with zero to three icons and optional custom text, including text-only buttons. Keep legacy/state choices, unsaved drafts, rounded clipping, and width-aware More/wrapping.\n- Keep Quick Action rows and their hover/focus state stable while typing in the main prompt on both supported OpenCode hosts.\n- Show toolbar hover/focus hints without moving Limits or other sections, preserving centered, uniformly sized icon controls and empty-toolbar collapse.\n- Add Settings → About with the running versions, explicit update status/checking, confirmed updates, and a versioned changelog that can be reopened independently of first-launch upgrade notes.\n- Prepare editable Bug reports with confirmed sending through authenticated GitHub CLI and an independent Open in browser action. Retain drafts through errors and cancellation, and require manual review before retrying an uncertain submission.\n\n## [0.23.0] - 2026-10-28\n\n- Support only the latest stable OpenCode 1.x and 2.x releases, currently 1.19.5 and 2.2.0, including the newer terminal renderer.\n- Keep Skills, MCP servers, and Subagents current as OpenCode 2 updates, and launch the intended Skill when multiple sources have the same name.\n- Show OpenCode Console workspace budgets and Go allowance through the public host usage API without a Navigator server plugin. Preserve workspace scope, native units, reset times, and explicit failure/retry states.\n- Preserve Navigator shortcuts and nested-dialog navigation with OpenCode 2.2's keyboard handling.\n- Verify a supported runtime before changing a pinned Navigator snapshot, preserving the installed version when no compatible verifier is available.\n\n## [0.22.0] - 2026-10-23\n\n- Pin Quick Actions and Skills to a compact sidebar toolbar independently of bookmarks. Choose icons in a searchable picker, customize supported state icons, reorder buttons, and select a More menu or wrapping rows. Preserve Skill confirmations, unavailable reasons, keyboard navigation, and Text fallback; hide the toolbar entirely when empty.\n- Use OpenCode 2's built-in Todo history for the sidebar, with native completed-write and revert semantics, existing filters/progress, and manual Refresh. Keep edits in ordinary chat, preserve previous Navigator tasks as a read-only archive, and retain the independent provider-quota server integration.\n- Support OpenCode 2.1's plugin and rendering APIs while retaining the OpenCode 1.x adapter; restore custom dialogs and rounded selections on the newer native renderer.\n- Replace the shortcut toast with an icon-led hint featuring highlighted keys, navigation/update groups, a distinct Escape action, and responsive Text/no-corner-font layouts. Keep prompt focus and share its action list with scrollable keyboard help.\n- Update Subagent status immediately from OpenCode 2's execution lifecycle and keep unresolved external credentials separate from verified provider accounts.\n- Keep OpenCode updates on the current major line and preserve pinned-source Navigator updates when a target release needs newer runtime dependencies.\n\n## [0.21.8] - 2026-10-09\n\n- Make the unfilled part of Limits scales substantially quieter, matching the theme-derived sidebar-divider tone. Keep the filled segment, reset text, and remaining values readable in both icon modes and after theme changes.\n\n## [0.21.7] - 2026-10-09\n\n- Remove the vertical guide and its reserved gutter from Limits in both icon modes. Keep full-width quota scales, reset-left/remaining-right details, and one blank row between quota windows.\n\n## [0.21.6] - 2026-10-09\n\n- Refine Limits with a continuous muted guide, full-width thin-line quota scales, and reset-left/remaining-right details. Keep long reset text from overlapping the remaining value and preserve Text fallback, resize clipping, and existing controls.\n\n## [0.21.5] - 2026-10-07\n\n- Make automatic Limits refresh configurable in scoped Behavior settings and portable configuration, with a five-minute default and one-minute minimum. Keep manual Refresh and supported model/account switches immediate.\n- Avoid extra quota polling from unrelated preference changes and unchanged provider-account metadata observations.\n\n## [0.21.4] - 2026-10-07\n\n- Add `c` to Navigator shortcuts for a manual update check and `u` to check then confirm a Navigator update. Report available, current, or unavailable results, preserve the installation method and scope, and require a restart after updating.\n- Ignore cancelled, outdated, and repeated update confirmations, and recover from stalled update checks without blocking later checks.\n\n## [0.21.3] - 2026-10-06\n\n- Replace block quota meters with full-width adaptive thin-line scales and keep quota rows inside the sidebar's padding after resize. Show only reset time below each meter, removing technical account and window-duration suffixes.\n\n## [0.21.2] - 2026-10-06\n\n- Make Limits compact with clickable provider/model and variant controls, remaining-headroom progress rows, and muted reset times. Move Refresh and Banked Resets into the section header, remove the section counter and Provider sources action, and keep reset consumption behind a separate confirmation.\n\n## [0.21.1] - 2026-10-06\n\n- Fix Codex account quota windows being hidden when the provider omits model metadata. Show ordinary usage as shared account quota, retain banked-reset counts, and keep separate model buckets explicitly associated.\n\n## [0.21.0] - 2026-10-06\n\n- Automatically verify Codex account identity from OpenCode 2's ChatGPT connection. When host identity is unavailable, confirm a private binding once per connection or provider and reuse it across models, projects, and sessions; preserve compatible older confirmations and isolate conflicting ones until relinked.\n- Expand OpenCode 2 Limits with documented native subscription allowances, API rate-limit observations, configured capacities, account balances, and key budgets. Keep provider-native units, currencies, model associations, and active-account boundaries explicit.\n- Add Provider sources to explain each provider's supported measurements, required permissions, and unavailable APIs without guessing remaining quota.\n- Keep available account balances visible when a separate subscription read fails, and show exhausted NanoGPT subscription windows instead of hiding them.\n- Keep stale quota guidance visible after failed refreshes, reject late results after credential changes, and recover from stalled provider reads without blocking model response streams.\n\n## [0.20.0] - 2026-10-05\n\n- Add a default-visible Limits section for the selected model's provider-native quota windows, reset times, account identity, and freshness. Codex CLI support requires an explicit private account binding; unsupported providers show calm guidance.\n- Review Codex banked reset credits and use them only after a separate confirmation and fresh eligibility checks. Preserve the same attempt key when reconciling an uncertain result, including after a restart.\n- Save named, commit-safe project layout and MCP profiles to `.opencode/navigator.json` with the `opencode-navigator-profile` command, an explicit preview, and `--apply`; profile application remains manual.\n\n## [0.19.3] - 2026-10-03\n\n- Indent grouped Todo, Subagent, Skill, and MCP rows and align MCP server status indicators with their group headings.\n- Place Skill, MCP, and Quick Action bookmarks before item names. Reveal unselected bookmarks on hover or keyboard focus, keep favorites visible, and keep labels steady.\n\n## [0.19.2] - 2026-10-02\n\n- Show MCP group connection states with the same radio-style indicators as individual servers, without Connect/Disconnect labels on group headings.\n\n## [0.19.1] - 2026-10-02\n\n- Remember the OpenCode 1.x auto-approve mode as a user-wide default for new sessions, including changes made through the host's permission toggle.\n\n## [0.19.0] - 2026-10-02\n\n- Connect or disconnect all eligible MCP servers in a group from its heading, including filtered-out items, with keyboard access and failed-only retry.\n- Organize Skills into user-wide groups by source location, with Favorites first and group names searchable across the full catalog.\n- Reload saved Navigator settings from disk in another running OpenCode session without restarting it.\n\n## [0.18.2] - 2026-10-02\n\n- Open the host Settings dialog from the OpenCode 2.x Permissions Quick Action, where the user can change between `prompt` and `auto accept`; keep the direct auto-approve toggle on OpenCode 1.x.\n\n## [0.18.1] - 2026-10-01\n\n- Show calm Todo setup guidance in OpenCode 2.x when Navigator's server plugin is absent, without a request error or Retry control. Actual server failures still offer Retry.\n- Keep Quick Action names readable in narrow sidebars by placing unavailable reasons below them and showing shortcuts only when they fit.\n\n## [0.18.0] - 2026-10-01\n\n- Add durable per-session Todo lists to OpenCode 2.x through a separately configured Navigator server plugin and an agent Todo tool.\n- Update Todo in the sidebar as tasks change, and offer an off-by-default per-session switch for model-context Todo instructions.\n- Keep Todo visible with setup guidance when the OpenCode 2.x server plugin is missing.\n\n## [0.17.3] - 2026-09-30\n\n## [0.17.2] - 2026-09-30\n\n- Update a pinned local Navigator installation from its version label while keeping its file or directory source unchanged.\n- Hide the session title and creation date independently with Global/Worktree settings in OpenCode 1.x.\n\n## [0.17.1] - 2026-09-29\n\n- Fix the local Navigator installation changing unexpectedly when rebuilding the repository; it now stays on its pinned version.\n\n## [0.17.0] - 2026-09-29\n\n- Add an opt-in Behavior setting to start a new session directly in chat with the sidebar from Home or New session.\n- Remember the previously installed Navigator version and show the intervening release notes once after an update.\n\n## [0.16.1] - 2026-09-25\n\n- Make the entire OpenCode or Navigator version label open its own update confirmation when an update is available. The separator and the other version remain inactive.\n- Replace the small update arrow with a more prominent filled-circle Nerd Font indicator, retaining an ASCII fallback.\n\n## [0.16.0] - 2026-09-25\n\n- Show both OpenCode and Navigator versions in the OpenCode 2.x footer.\n- Confirm updates from the footer or command palette, preserve the original installation method and scope, and report the outcome with a restart reminder.\n\nEarlier release notes are available on [GitHub Releases](https://github.com/St1ggy/opencode-navigator/releases).\n\n[0.22.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.8...v0.22.0\n[0.21.8]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.7...v0.21.8\n[0.21.7]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.6...v0.21.7\n[0.21.6]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.5...v0.21.6\n[0.21.5]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.4...v0.21.5\n[0.21.4]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.3...v0.21.4\n[0.21.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.2...v0.21.3\n[0.21.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.1...v0.21.2\n[0.21.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.21.0...v0.21.1\n[0.21.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.20.0...v0.21.0\n[0.20.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.3...v0.20.0\n[0.19.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.2...v0.19.3\n[0.19.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.1...v0.19.2\n[0.19.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.19.0...v0.19.1\n[0.19.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.2...v0.19.0\n[0.18.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.1...v0.18.2\n[0.18.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.18.0...v0.18.1\n[0.18.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.3...v0.18.0\n[0.17.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.2...v0.17.3\n[0.17.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.1...v0.17.2\n[0.17.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.0...v0.17.1\n[0.17.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.16.1...v0.17.0\n[0.16.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.16.0...v0.16.1\n[0.16.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.15.0...v0.16.0\n"
|
|
10661
11198
|
};
|
|
10662
11199
|
// src/app/gui/about.ts
|
|
10663
11200
|
function createGuiAbout(context) {
|
|
@@ -10665,13 +11202,18 @@ function createGuiAbout(context) {
|
|
|
10665
11202
|
const [busy, setBusy] = (0, solid_js.createSignal)(false);
|
|
10666
11203
|
const [status, setStatus] = (0, solid_js.createSignal)("Updates have not been checked.");
|
|
10667
11204
|
const [token, setToken] = (0, solid_js.createSignal)();
|
|
11205
|
+
const progress = () => {
|
|
11206
|
+
const current = ipc.state();
|
|
11207
|
+
return current && current.phase !== "idle" ? { phase: current.phase } : void 0;
|
|
11208
|
+
};
|
|
10668
11209
|
return {
|
|
10669
11210
|
report: createGuiBugReport(context),
|
|
10670
11211
|
version: guiRelease.version,
|
|
10671
11212
|
hostVersion: context.app?.version ?? "unknown",
|
|
10672
11213
|
changelog: parseChangelog(guiRelease.changelog),
|
|
10673
11214
|
status,
|
|
10674
|
-
busy,
|
|
11215
|
+
busy: () => busy() || Boolean(progress()),
|
|
11216
|
+
progress,
|
|
10675
11217
|
available: () => Boolean(token()),
|
|
10676
11218
|
async check() {
|
|
10677
11219
|
if (busy()) return;
|
|
@@ -14063,10 +14605,11 @@ function createGuiPresetDialogs(context, preferences, registry, mcp) {
|
|
|
14063
14605
|
};
|
|
14064
14606
|
}
|
|
14065
14607
|
// src/features/search-everything/ui/gui/result-row.tsx
|
|
14066
|
-
var _tmpl$$7 = /*#__PURE__*/ (0, solid_js_web.template)(`<span role=status>Working…`);
|
|
14608
|
+
var _tmpl$$7 = /*#__PURE__*/ (0, solid_js_web.template)(`<span role=status style=display:inline-flex;gap:6px;align-items:center>Working…`);
|
|
14067
14609
|
var _tmpl$2$6 = /*#__PURE__*/ (0, solid_js_web.template)(`<li style="display:flex;gap:4px;align-items:center;min-width:0;padding:3px 0"><button type=button style=flex:1;min-width:0;text-align:left;padding:8px;color:inherit;border:0;border-radius:6px><strong style=display:block;overflow-wrap:anywhere></strong><span style=display:block;opacity:0.65;font-size:12px;overflow-wrap:anywhere>`);
|
|
14068
14610
|
function GuiSearchResultRow(props) {
|
|
14069
14611
|
const Button = props.ui.Button;
|
|
14612
|
+
const Loader = props.ui.Loader;
|
|
14070
14613
|
return (() => {
|
|
14071
14614
|
var _el$ = _tmpl$2$6(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling;
|
|
14072
14615
|
_el$2.$$click = (event) => {
|
|
@@ -14081,7 +14624,9 @@ function GuiSearchResultRow(props) {
|
|
|
14081
14624
|
return props.busy;
|
|
14082
14625
|
},
|
|
14083
14626
|
get children() {
|
|
14084
|
-
|
|
14627
|
+
var _el$5 = _tmpl$$7(), _el$6 = _el$5.firstChild;
|
|
14628
|
+
(0, solid_js_web.insert)(_el$5, (0, solid_js_web.createComponent)(Loader, { size: "small" }), _el$6);
|
|
14629
|
+
return _el$5;
|
|
14085
14630
|
}
|
|
14086
14631
|
}), null);
|
|
14087
14632
|
(0, solid_js_web.insert)(_el$, (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
@@ -15287,12 +15832,12 @@ function createGuiToolbarDialogs(context, registry, preferences) {
|
|
|
15287
15832
|
if (!current()) throw new DOMException("Toolbar target changed", "AbortError");
|
|
15288
15833
|
await save(update);
|
|
15289
15834
|
}
|
|
15290
|
-
async function move(key,
|
|
15835
|
+
async function move(key, target) {
|
|
15291
15836
|
const pins = preferences.toolbarPins();
|
|
15292
15837
|
const index = pins.findIndex((pin) => toolbarPinKey(pin) === key);
|
|
15293
|
-
const destination =
|
|
15294
|
-
if (index === -1 || destination
|
|
15295
|
-
const before = pins[destination + (
|
|
15838
|
+
const destination = pins.findIndex((pin) => toolbarPinKey(pin) === target);
|
|
15839
|
+
if (index === -1 || destination === -1 || destination >= pins.length) return;
|
|
15840
|
+
const before = pins[destination + (destination > index ? 1 : 0)];
|
|
15296
15841
|
await change({
|
|
15297
15842
|
operation: "move",
|
|
15298
15843
|
key,
|
|
@@ -15633,7 +16178,7 @@ var setup = (context) => {
|
|
|
15633
16178
|
try {
|
|
15634
16179
|
await preferences.flush();
|
|
15635
16180
|
context.toast.show({
|
|
15636
|
-
title: `Navigator 0.27.
|
|
16181
|
+
title: `Navigator 0.27.3`,
|
|
15637
16182
|
variant: "default"
|
|
15638
16183
|
});
|
|
15639
16184
|
} catch {
|