@klarkxy/dsh-magpie 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -440,16 +440,27 @@ const inject = [
440
440
  "locale"
441
441
  ];
442
442
  const styles = `${officialUiCss(".mgp-root")}
443
+ .mgp-root .mgp-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; min-width: 0; }
443
444
  .mgp-root .mgp-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
444
- .mgp-root .mgp-row > .mgp-grow { flex: 1 1 220px; }
445
+ .mgp-root .mgp-grow { flex: 1 1 220px; min-width: 0; }
445
446
  .mgp-root .mgp-danger { color: var(--dsw-alias-state-error-primary); }
447
+ /* The advanced disclosure: a plain details/summary, so it opens without any
448
+ * script and keeps the keyboard behaviour the platform gives it. */
449
+ .mgp-root .mgp-advanced { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 8px; min-width: 0; }
450
+ .mgp-root .mgp-advanced > summary { display: inline-flex; align-items: center; gap: 6px; width: fit-content; cursor: pointer; list-style: none; font-size: 12px; line-height: 18px; font-weight: 500; color: var(--dsw-alias-label-secondary); }
451
+ .mgp-root .mgp-advanced > summary::-webkit-details-marker { display: none; }
452
+ .mgp-root .mgp-advanced > summary::before { content: ''; width: 5px; height: 5px; border-right: 1.5px solid currentcolor; border-bottom: 1.5px solid currentcolor; transform: rotate(-45deg) translate(-1px, -1px); transition: transform 120ms ease; }
453
+ .mgp-root .mgp-advanced[open] > summary::before { transform: rotate(45deg) translate(-1px, -1px); }
454
+ .mgp-root .mgp-advanced > summary:hover { color: var(--dsw-alias-label-primary); }
455
+ .mgp-root .mgp-advanced-body { display: flex; flex-direction: column; gap: 12px; padding-top: 12px; min-width: 0; }
446
456
  `;
447
457
  const copy = {
448
458
  zh: {
449
459
  loading: "正在读取状态…",
450
460
  failed: "操作失败:",
451
461
  retry: "重试",
452
- connection: "连接",
462
+ title: "Magpie",
463
+ intro: "连接本机、局域网或远程的 magpie 网关,把它的模型加入本 profile 的模型列表。",
453
464
  address: "网关地址",
454
465
  addressHelp: "本机、局域网或远程的 magpie 网关,例如 http://127.0.0.1:3425。",
455
466
  key: "网关 Key",
@@ -460,7 +471,6 @@ const copy = {
460
471
  test: "测试",
461
472
  save: "保存",
462
473
  saved: "已保存。",
463
- sync: "同步",
464
474
  syncNow: "立即同步",
465
475
  syncing: "正在同步…",
466
476
  syncOnStart: "启动时同步",
@@ -480,13 +490,15 @@ const copy = {
480
490
  confirmDisconnect: "确认断开?",
481
491
  disconnectHelp: "移除三条 magpie 供应商路由并还原默认模型与网络搜索;已保存的 Key 保留。",
482
492
  testOk: (n) => `连接正常,网关返回 ${n} 个模型。`,
483
- notConnected: "尚未连接。"
493
+ notConnected: "尚未连接。",
494
+ advanced: "高级设置"
484
495
  },
485
496
  en: {
486
497
  loading: "Loading status…",
487
498
  failed: "Action failed: ",
488
499
  retry: "Retry",
489
- connection: "Connection",
500
+ title: "Magpie",
501
+ intro: "Point DSH at a magpie gateway on this computer, your LAN, or elsewhere, and its models join this profile.",
490
502
  address: "Gateway address",
491
503
  addressHelp: "A magpie gateway on this computer, your LAN, or elsewhere, e.g. http://127.0.0.1:3425.",
492
504
  key: "Gateway key",
@@ -497,7 +509,6 @@ const copy = {
497
509
  test: "Test",
498
510
  save: "Save",
499
511
  saved: "Saved.",
500
- sync: "Sync",
501
512
  syncNow: "Sync now",
502
513
  syncing: "Syncing…",
503
514
  syncOnStart: "Sync at startup",
@@ -517,7 +528,8 @@ const copy = {
517
528
  confirmDisconnect: "Confirm disconnect?",
518
529
  disconnectHelp: "Removes the three magpie provider routes and reverts the default model and web search; the saved key is kept.",
519
530
  testOk: (n) => `Connection OK: the gateway returned ${n} models.`,
520
- notConnected: "Not connected yet."
531
+ notConnected: "Not connected yet.",
532
+ advanced: "Advanced"
521
533
  }
522
534
  };
523
535
  var RpcError = class extends Error {
@@ -619,23 +631,33 @@ function MagpieSettingsPage({ client }) {
619
631
  setAddress((current) => addressDirty ? current : next.address);
620
632
  };
621
633
  if (!status) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
622
- className: "mgp-root dsh-ui-page dsh-ui-form",
634
+ className: "mgp-root dsh-ui-card",
623
635
  "data-testid": "magpie-settings",
624
- children: [error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
625
- role: "alert",
626
- className: "dsh-ui-error",
627
- children: [text.failed, error]
628
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
629
- role: "status",
630
- className: "dsh-ui-hint",
631
- children: text.loading
632
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
633
- variant: "ghost",
634
- size: "sm",
635
- disabled: Boolean(busy),
636
- onClick: () => void load(),
637
- children: text.retry
638
- })]
636
+ children: [
637
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
638
+ className: "dsh-ui-heading",
639
+ children: text.title
640
+ }),
641
+ error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
642
+ role: "alert",
643
+ className: "dsh-ui-error",
644
+ children: [text.failed, error]
645
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
646
+ role: "status",
647
+ className: "dsh-ui-hint",
648
+ children: text.loading
649
+ }),
650
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
651
+ className: "dsh-ui-actions",
652
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
653
+ variant: "ghost",
654
+ size: "sm",
655
+ disabled: Boolean(busy),
656
+ onClick: () => void load(),
657
+ children: text.retry
658
+ })
659
+ })
660
+ ]
639
661
  });
640
662
  const models = status.models;
641
663
  const defaultChoices = models.map((model) => model.id);
@@ -644,10 +666,25 @@ function MagpieSettingsPage({ client }) {
644
666
  const found = models.find((model) => model.id === id);
645
667
  return found ? `${found.name ?? id} · ${found.route}` : id;
646
668
  };
669
+ const gatewaySummary = status.gateway ? `${status.gateway.name}${status.gateway.version ? ` ${status.gateway.version}` : ""} · ${text.models(models.length)}` : text.notConnected;
647
670
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
648
- className: "mgp-root dsh-ui-page dsh-ui-form",
671
+ className: "mgp-root dsh-ui-card",
649
672
  "data-testid": "magpie-settings",
650
673
  children: [
674
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
675
+ className: "mgp-head",
676
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
677
+ className: "dsh-ui-heading",
678
+ children: text.title
679
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
680
+ className: "dsh-ui-meta",
681
+ children: gatewaySummary
682
+ })]
683
+ }),
684
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
685
+ className: "dsh-ui-help",
686
+ children: text.intro
687
+ }),
651
688
  status.writable === false ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
652
689
  role: "status",
653
690
  className: "dsh-ui-hint",
@@ -663,282 +700,257 @@ function MagpieSettingsPage({ client }) {
663
700
  className: "dsh-ui-notice",
664
701
  children: note
665
702
  }) : null,
666
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
667
- className: "dsh-ui-card",
703
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
704
+ className: "dsh-ui-fields-grid",
705
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
706
+ className: "dsh-ui-field",
707
+ children: [
708
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
709
+ className: "dsh-ui-label",
710
+ children: text.address
711
+ }),
712
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
713
+ value: addressDirty ? address : status.address,
714
+ placeholder: "http://127.0.0.1:3425",
715
+ onChange: (event) => {
716
+ setAddress(event.target.value);
717
+ setAddressDirty(true);
718
+ }
719
+ }),
720
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
721
+ className: "dsh-ui-help",
722
+ children: text.addressHelp
723
+ })
724
+ ]
725
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
726
+ className: "dsh-ui-field",
727
+ children: [
728
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
729
+ className: "dsh-ui-label",
730
+ children: [
731
+ text.key,
732
+ " ",
733
+ status.keyConfigured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
734
+ tone: "success",
735
+ children: text.keyConfigured
736
+ }) : null
737
+ ]
738
+ }),
739
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
740
+ className: "mgp-row",
741
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
742
+ className: "mgp-grow",
743
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
744
+ type: "password",
745
+ value: keyDraft,
746
+ placeholder: text.keyPlaceholder,
747
+ onChange: (event) => setKeyDraft(event.target.value)
748
+ })
749
+ }), status.keyConfigured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
750
+ variant: "ghost",
751
+ size: "sm",
752
+ disabled: Boolean(busy),
753
+ onClick: () => void action("clear-key", async () => {
754
+ refresh(await call(RPC_ENDPOINTS.saveConnection, { clearKey: true }));
755
+ setNote(text.saved);
756
+ }),
757
+ children: text.keyClear
758
+ }) : null]
759
+ }),
760
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
761
+ className: "dsh-ui-help",
762
+ children: text.keyHelp
763
+ })
764
+ ]
765
+ })]
766
+ }),
767
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
768
+ className: "dsh-ui-actions",
668
769
  children: [
669
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
670
- className: "dsh-ui-label",
671
- children: text.connection
672
- }),
673
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
674
- className: "dsh-ui-field",
675
- children: [
676
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
677
- className: "dsh-ui-label",
678
- children: text.address
679
- }),
680
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
681
- value: addressDirty ? address : status.address,
682
- placeholder: "http://127.0.0.1:3425",
683
- onChange: (event) => {
684
- setAddress(event.target.value);
685
- setAddressDirty(true);
686
- }
687
- }),
688
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
689
- className: "dsh-ui-help",
690
- children: text.addressHelp
691
- })
692
- ]
693
- }),
694
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
695
- className: "dsh-ui-field",
696
- children: [
697
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
698
- className: "dsh-ui-label",
699
- children: [
700
- text.key,
701
- " ",
702
- status.keyConfigured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
703
- tone: "success",
704
- children: text.keyConfigured
705
- }) : null
706
- ]
707
- }),
708
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
709
- className: "mgp-row",
710
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
711
- className: "mgp-grow",
712
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
713
- type: "password",
714
- value: keyDraft,
715
- placeholder: text.keyPlaceholder,
716
- onChange: (event) => setKeyDraft(event.target.value)
717
- })
718
- }), status.keyConfigured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
719
- variant: "ghost",
720
- size: "sm",
721
- disabled: Boolean(busy),
722
- onClick: () => void action("clear-key", async () => {
723
- refresh(await call(RPC_ENDPOINTS.saveConnection, { clearKey: true }));
724
- setNote(text.saved);
725
- }),
726
- children: text.keyClear
727
- }) : null]
728
- }),
729
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
730
- className: "dsh-ui-help",
731
- children: text.keyHelp
732
- })
733
- ]
734
- }),
735
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
736
- className: "dsh-ui-form-footer mgp-row",
737
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
738
- variant: "outline",
739
- size: "md",
740
- disabled: Boolean(busy),
741
- onClick: () => void action("test", async () => {
742
- if (addressDirty || keyDraft) {
743
- refresh(await call(RPC_ENDPOINTS.saveConnection, {
744
- address,
745
- apiKey: keyDraft || void 0
746
- }));
747
- setKeyDraft("");
748
- setAddressDirty(false);
749
- }
750
- const result = await call(RPC_ENDPOINTS.test);
751
- setNote(text.testOk(result.models));
752
- await load();
753
- }),
754
- children: text.test
755
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
756
- variant: "primary",
757
- size: "md",
758
- disabled: Boolean(busy) || !addressDirty && !keyDraft,
759
- onClick: () => void action("save", async () => {
770
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
771
+ variant: "outline",
772
+ size: "sm",
773
+ disabled: Boolean(busy),
774
+ onClick: () => void action("test", async () => {
775
+ if (addressDirty || keyDraft) {
760
776
  refresh(await call(RPC_ENDPOINTS.saveConnection, {
761
777
  address,
762
778
  apiKey: keyDraft || void 0
763
779
  }));
764
780
  setKeyDraft("");
765
781
  setAddressDirty(false);
766
- setNote(text.saved);
767
- }),
768
- children: text.save
769
- })]
782
+ }
783
+ const result = await call(RPC_ENDPOINTS.test);
784
+ setNote(text.testOk(result.models));
785
+ await load();
786
+ }),
787
+ children: text.test
788
+ }),
789
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
790
+ variant: "primary",
791
+ size: "sm",
792
+ disabled: Boolean(busy) || !addressDirty && !keyDraft,
793
+ onClick: () => void action("save", async () => {
794
+ refresh(await call(RPC_ENDPOINTS.saveConnection, {
795
+ address,
796
+ apiKey: keyDraft || void 0
797
+ }));
798
+ setKeyDraft("");
799
+ setAddressDirty(false);
800
+ setNote(text.saved);
801
+ }),
802
+ children: text.save
803
+ }),
804
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
805
+ variant: "outline",
806
+ size: "sm",
807
+ disabled: Boolean(busy) || status.syncing,
808
+ onClick: () => void action("sync", async () => {
809
+ refresh(await call(RPC_ENDPOINTS.sync));
810
+ setNote(text.saved);
811
+ }),
812
+ children: status.syncing ? text.syncing : text.syncNow
770
813
  })
771
814
  ]
772
815
  }),
773
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
774
- className: "dsh-ui-card",
775
- children: [
776
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
777
- className: "mgp-row",
778
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
779
- className: "dsh-ui-label mgp-grow",
780
- children: text.sync
781
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
782
- variant: "outline",
783
- size: "md",
784
- disabled: Boolean(busy) || status.syncing,
785
- onClick: () => void action("sync", async () => {
786
- refresh(await call(RPC_ENDPOINTS.sync));
787
- setNote(text.saved);
788
- }),
789
- children: status.syncing ? text.syncing : text.syncNow
790
- })]
791
- }),
792
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
793
- className: "dsh-ui-field",
794
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
795
- className: "mgp-row",
796
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
816
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
817
+ className: "mgp-advanced",
818
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: text.advanced }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
819
+ className: "mgp-advanced-body",
820
+ children: [
821
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
822
+ className: "dsh-ui-field",
823
+ children: [
824
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
825
+ className: "dsh-ui-label",
826
+ children: text.defaultModel
827
+ }),
828
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
829
+ className: "dsh-ui-select",
830
+ value: status.options.defaultModel ?? "",
831
+ disabled: Boolean(busy),
832
+ onChange: (event) => void action("options", async () => {
833
+ refresh(await call(RPC_ENDPOINTS.setOptions, { defaultModel: event.target.value || null }));
834
+ }),
835
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
836
+ value: "",
837
+ children: text.keepCurrent
838
+ }), defaultChoices.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
839
+ value: id,
840
+ children: modelLabel(id)
841
+ }, id))]
842
+ }),
843
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
844
+ className: "dsh-ui-help",
845
+ children: text.defaultModelHelp
846
+ })
847
+ ]
848
+ }),
849
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
850
+ className: "dsh-ui-toggle-row",
851
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
852
+ className: "dsh-ui-toggle-text",
853
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
854
+ className: "dsh-ui-toggle-label",
855
+ children: text.webSearch
856
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
857
+ className: "dsh-ui-help",
858
+ children: text.webSearchHelp
859
+ })]
860
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
861
+ checked: status.options.webSearch,
862
+ disabled: Boolean(busy),
863
+ label: text.webSearch,
864
+ onChange: (next) => void action("options", async () => {
865
+ refresh(await call(RPC_ENDPOINTS.setOptions, { webSearch: next }));
866
+ })
867
+ })]
868
+ }),
869
+ status.options.webSearch ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
870
+ className: "dsh-ui-field",
871
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
872
+ className: "dsh-ui-select",
873
+ value: status.options.webSearchModel ?? "",
874
+ disabled: Boolean(busy),
875
+ onChange: (event) => void action("options", async () => {
876
+ refresh(await call(RPC_ENDPOINTS.setOptions, { webSearchModel: event.target.value || null }));
877
+ }),
878
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
879
+ value: "",
880
+ children: text.sameAsDefault
881
+ }), models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
882
+ value: model.id,
883
+ children: model.name ?? model.id
884
+ }, model.id))]
885
+ })
886
+ }) : null,
887
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
888
+ className: "dsh-ui-toggle-row",
889
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
890
+ className: "dsh-ui-toggle-text",
891
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
892
+ className: "dsh-ui-toggle-label",
893
+ children: text.syncOnStart
894
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
895
+ className: "dsh-ui-help",
896
+ children: text.syncOnStartHelp
897
+ })]
898
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
797
899
  checked: status.options.syncOnStart,
798
900
  disabled: Boolean(busy),
799
901
  label: text.syncOnStart,
800
902
  onChange: (next) => void action("options", async () => {
801
903
  refresh(await call(RPC_ENDPOINTS.setOptions, { syncOnStart: next }));
802
904
  })
803
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
804
- className: "dsh-ui-label",
805
- children: text.syncOnStart
806
905
  })]
807
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
808
- className: "dsh-ui-help",
809
- children: text.syncOnStartHelp
810
- })]
811
- }),
812
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
813
- className: "dsh-ui-meta",
814
- children: [
815
- text.lastSync,
816
- ": ",
817
- status.lastSync ? `${new Date(status.lastSync.at).toLocaleString()} · ${Object.entries(status.lastSync.routes).map(([route, count]) => `${route}: ${count}`).join(" · ")}` : text.never
818
- ]
819
- }),
820
- status.lastSync?.warnings.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
821
- className: "dsh-ui-label",
822
- children: text.warnings
823
- }), status.lastSync.warnings.map((warning, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
824
- className: "dsh-ui-hint",
825
- children: warning
826
- }, index))] }) : null,
827
- status.lastError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
828
- role: "alert",
829
- className: "dsh-ui-error",
830
- children: [
831
- new Date(status.lastError.at).toLocaleString(),
832
- " · ",
833
- status.lastError.message
834
- ]
835
- }) : null,
836
- status.gateway ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
837
- className: "dsh-ui-hint",
838
- children: [
839
- status.gateway.name,
840
- status.gateway.version ? ` ${status.gateway.version}` : "",
841
- " · ",
842
- text.models(models.length)
843
- ]
844
- }) : null
845
- ]
846
- }),
847
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("article", {
848
- className: "dsh-ui-card",
849
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
850
- className: "dsh-ui-field",
851
- children: [
852
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
853
- className: "dsh-ui-label",
854
- children: text.defaultModel
855
906
  }),
856
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
857
- className: "dsh-ui-select",
858
- value: status.options.defaultModel ?? "",
859
- disabled: Boolean(busy),
860
- onChange: (event) => void action("options", async () => {
861
- refresh(await call(RPC_ENDPOINTS.setOptions, { defaultModel: event.target.value || null }));
862
- }),
863
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
864
- value: "",
865
- children: text.keepCurrent
866
- }), defaultChoices.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
867
- value: id,
868
- children: modelLabel(id)
869
- }, id))]
907
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
908
+ className: "dsh-ui-meta",
909
+ children: [
910
+ text.lastSync,
911
+ ": ",
912
+ status.lastSync ? `${new Date(status.lastSync.at).toLocaleString()} · ${Object.entries(status.lastSync.routes).map(([route, count]) => `${route}: ${count}`).join(" · ")}` : text.never
913
+ ]
870
914
  }),
871
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
872
- className: "dsh-ui-help",
873
- children: text.defaultModelHelp
874
- })
875
- ]
876
- })
877
- }),
878
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
879
- className: "dsh-ui-card",
880
- children: [
881
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
882
- className: "mgp-row",
883
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
884
- className: "dsh-ui-label mgp-grow",
885
- children: text.webSearch
886
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
887
- checked: status.options.webSearch,
888
- disabled: Boolean(busy),
889
- label: text.webSearch,
890
- onChange: (next) => void action("options", async () => {
891
- refresh(await call(RPC_ENDPOINTS.setOptions, { webSearch: next }));
892
- })
893
- })]
894
- }),
895
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
896
- className: "dsh-ui-help",
897
- children: text.webSearchHelp
898
- }),
899
- status.options.webSearch ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
900
- className: "dsh-ui-field",
901
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
902
- className: "dsh-ui-select",
903
- value: status.options.webSearchModel ?? "",
904
- disabled: Boolean(busy),
905
- onChange: (event) => void action("options", async () => {
906
- refresh(await call(RPC_ENDPOINTS.setOptions, { webSearchModel: event.target.value || null }));
907
- }),
908
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
909
- value: "",
910
- children: text.sameAsDefault
911
- }), models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
912
- value: model.id,
913
- children: model.name ?? model.id
914
- }, model.id))]
915
- })
916
- }) : null
917
- ]
918
- }),
919
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("article", {
920
- className: "dsh-ui-card",
921
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
922
- className: "mgp-row",
923
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
924
- className: "mgp-grow",
925
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
915
+ status.lastSync?.warnings.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
926
916
  className: "dsh-ui-label",
927
- children: text.disconnect
928
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
929
- className: "dsh-ui-help",
930
- children: text.disconnectHelp
931
- })]
932
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmButton, {
933
- label: text.disconnect,
934
- confirmLabel: text.confirmDisconnect,
935
- disabled: Boolean(busy),
936
- onConfirm: () => void action("disconnect", async () => {
937
- refresh(await call(RPC_ENDPOINTS.disconnect));
938
- setNote(text.saved);
917
+ children: text.warnings
918
+ }), status.lastSync.warnings.map((warning, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
919
+ className: "dsh-ui-hint",
920
+ children: warning
921
+ }, index))] }) : null,
922
+ status.lastError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
923
+ role: "alert",
924
+ className: "dsh-ui-error",
925
+ children: [
926
+ new Date(status.lastError.at).toLocaleString(),
927
+ " · ",
928
+ status.lastError.message
929
+ ]
930
+ }) : null,
931
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
932
+ className: "mgp-row",
933
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
934
+ className: "mgp-grow",
935
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
936
+ className: "dsh-ui-label",
937
+ children: text.disconnect
938
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
939
+ className: "dsh-ui-help",
940
+ children: text.disconnectHelp
941
+ })]
942
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmButton, {
943
+ label: text.disconnect,
944
+ confirmLabel: text.confirmDisconnect,
945
+ disabled: Boolean(busy),
946
+ onConfirm: () => void action("disconnect", async () => {
947
+ refresh(await call(RPC_ENDPOINTS.disconnect));
948
+ setNote(text.saved);
949
+ })
950
+ })]
939
951
  })
940
- })]
941
- })
952
+ ]
953
+ })]
942
954
  })
943
955
  ]
944
956
  });
@@ -953,9 +965,10 @@ function apply(ctx) {
953
965
  document.head.appendChild(style);
954
966
  return () => style.remove();
955
967
  }, "magpie.styles");
956
- ctx.effect(() => client.slots.inject("plugins.bundle.config", () => client.slots.register({
957
- name: "plugins.bundle.config",
958
- key: PLUGIN_NAME
968
+ ctx.effect(() => client.slots.inject("settings.models.footer", () => client.slots.register({
969
+ name: "settings.models.footer",
970
+ id: "magpie",
971
+ order: 100
959
972
  }, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MagpieSettingsPage, { client }))), "magpie.settings");
960
973
  }
961
974
  //#endregion