@mofeng2223/dsh-claude-provider 0.5.8 → 0.5.9

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.
Files changed (2) hide show
  1. package/lib/client.js +54 -10
  2. package/package.json +3 -3
package/lib/client.js CHANGED
@@ -993,6 +993,8 @@ window.__ModuleLoader__.load({
993
993
  });
994
994
  /** Latest load wins; an older response never overwrites a newer one. */
995
995
  generation = 0;
996
+ /** Callers follow the current refresh's outcome, including callers whose read was superseded. */
997
+ pendingLoads = /* @__PURE__ */ new Set();
996
998
  /**
997
999
  * @param ctx - the page plugin's context, whose `remote.llm` and
998
1000
  * `remote.credentials` namespaces carry the directory and credential reads.
@@ -1009,11 +1011,28 @@ window.__ModuleLoader__.load({
1009
1011
  * settings answer in parallel, then one batched credential describe over
1010
1012
  * every referenced ref. Provider failure or absence of an initial settings
1011
1013
  * answer keeps the last good rows and surfaces an error; a failed settings
1012
- * refresh reuses the mirror's held view.
1013
- * @returns nothing; the snapshot carries the outcome.
1014
+ * refresh reuses the mirror's held view. Concurrent callers resolve only
1015
+ * after the current refresh publishes its ready or error snapshot.
1016
+ * @returns resolution after the current snapshot is published.
1017
+ * @throws the current read's unexpected rejection; superseded rejections are ignored.
1014
1018
  */
1015
- async load() {
1019
+ load() {
1020
+ const pending = Promise.withResolvers();
1021
+ this.pendingLoads.add(pending);
1016
1022
  const generation = ++this.generation;
1023
+ this.read(generation).then(() => {
1024
+ this.settleLoads(generation, (load) => {
1025
+ load.resolve();
1026
+ });
1027
+ }, (error) => {
1028
+ this.settleLoads(generation, (load) => {
1029
+ load.reject(error);
1030
+ });
1031
+ });
1032
+ return pending.promise;
1033
+ }
1034
+ /** Publish one joined answer; stale answers leave the current refresh in charge. */
1035
+ async read(generation) {
1017
1036
  this.store.update((s) => {
1018
1037
  s.status = "loading";
1019
1038
  s.error = null;
@@ -1023,17 +1042,18 @@ window.__ModuleLoader__.load({
1023
1042
  this.ctx.remote.llm.listConfigurableProviders(),
1024
1043
  this.describeFace.ensure()
1025
1044
  ]);
1045
+ if (generation !== this.generation) return;
1026
1046
  if (!registered.ok) {
1027
- this.failLoad(generation, registered.error.message);
1047
+ this.failLoad(registered.error.message);
1028
1048
  return;
1029
1049
  }
1030
1050
  if (!declared.ok) {
1031
- this.failLoad(generation, declared.error.message);
1051
+ this.failLoad(declared.error.message);
1032
1052
  return;
1033
1053
  }
1034
1054
  const mirrored = this.describeFace.getSnapshot();
1035
1055
  if (mirrored.view === void 0) {
1036
- this.failLoad(generation, mirrored.error ?? "settings are unavailable in this browser");
1056
+ this.failLoad(mirrored.error ?? "settings are unavailable in this browser");
1037
1057
  return;
1038
1058
  }
1039
1059
  const providers = joinProviderDirectory(registered.value, declared.value);
@@ -1081,9 +1101,15 @@ window.__ModuleLoader__.load({
1081
1101
  s.namespaces = namespaces;
1082
1102
  });
1083
1103
  }
1084
- /** Publish one load's failure text, unless a newer load already took over. */
1085
- failLoad(generation, message) {
1104
+ /** Settle callers only while this read still owns the current refresh. */
1105
+ settleLoads(generation, settle) {
1086
1106
  if (generation !== this.generation) return;
1107
+ const pending = [...this.pendingLoads];
1108
+ this.pendingLoads.clear();
1109
+ for (const load of pending) settle(load);
1110
+ }
1111
+ /** Publish the current joined read's failure text. */
1112
+ failLoad(message) {
1087
1113
  this.store.update((s) => {
1088
1114
  s.status = "error";
1089
1115
  s.error = message;
@@ -2135,6 +2161,10 @@ window.__ModuleLoader__.load({
2135
2161
  }
2136
2162
  } : row)
2137
2163
  };
2164
+ /** A new or failed surface waits for a current snapshot; background refreshes preserve its drafts. */
2165
+ const [hasReadySnapshot, setHasReadySnapshot] = (0, react.useState)(state.status === "ready");
2166
+ if (state.status === "ready" && !hasReadySnapshot) setHasReadySnapshot(true);
2167
+ if (state.status === "error" && hasReadySnapshot) setHasReadySnapshot(false);
2138
2168
  const [editing, setEditing] = (0, react.useState)(void 0);
2139
2169
  const [addOpen, setAddOpen] = (0, react.useState)(false);
2140
2170
  const [addMode, setAddMode] = (0, react.useState)("catalog");
@@ -2224,6 +2254,16 @@ window.__ModuleLoader__.load({
2224
2254
  })]
2225
2255
  });
2226
2256
  }
2257
+ if (!hasReadySnapshot && state.status !== "ready") return (0, react_jsx_runtime.jsxs)("div", {
2258
+ className: ModelsSection_module_css_default["section"],
2259
+ children: [(0, react_jsx_runtime.jsx)("h2", {
2260
+ className: ModelsSection_module_css_default["title"],
2261
+ children: t("title")
2262
+ }), (0, react_jsx_runtime.jsx)("p", {
2263
+ className: ModelsSection_module_css_default["intro"],
2264
+ children: t("intro")
2265
+ })]
2266
+ });
2227
2267
  const savedRow = savedTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === savedTarget.provider);
2228
2268
  const savedIdentity = savedRow === void 0 ? savedTarget : {
2229
2269
  provider: savedRow.entry.provider,
@@ -2362,7 +2402,9 @@ window.__ModuleLoader__.load({
2362
2402
  type: "button",
2363
2403
  className: ModelsSection_module_css_default["secondaryButton"],
2364
2404
  "aria-label": providerCopy(t("editProvider"), target),
2405
+ disabled: !open && state.status !== "ready",
2365
2406
  onClick: () => {
2407
+ if (!open && controller.store.getSnapshot().status !== "ready") return;
2366
2408
  setSavedTarget(void 0);
2367
2409
  setAddOpen(false);
2368
2410
  setEditing(open ? void 0 : target);
@@ -2372,8 +2414,9 @@ window.__ModuleLoader__.load({
2372
2414
  type: "button",
2373
2415
  className: ModelsSection_module_css_default["dangerButton"],
2374
2416
  "aria-label": providerCopy(t("removeProvider"), target),
2375
- disabled: !state.writable,
2417
+ disabled: !state.writable || state.status !== "ready",
2376
2418
  onClick: () => {
2419
+ if (controller.store.getSnapshot().status !== "ready") return;
2377
2420
  setSavedTarget(void 0);
2378
2421
  setDeleteFailure(void 0);
2379
2422
  setDeleteTarget(target);
@@ -2547,8 +2590,9 @@ window.__ModuleLoader__.load({
2547
2590
  children: (0, react_jsx_runtime.jsxs)("button", {
2548
2591
  type: "button",
2549
2592
  className: ModelsSection_module_css_default["addButton"],
2550
- disabled: !state.writable || !catalogEnabled && !customEnabled,
2593
+ disabled: !state.writable || state.status !== "ready" || !catalogEnabled && !customEnabled,
2551
2594
  onClick: () => {
2595
+ if (controller.store.getSnapshot().status !== "ready") return;
2552
2596
  const first = addable[0];
2553
2597
  const initial = catalogEnabled ? "catalog" : "custom";
2554
2598
  setSavedTarget(void 0);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mofeng2223/dsh-claude-provider",
3
- "version": "0.5.8",
4
- "description": "Custom Claude provider support for DeepSeek Harness 0.2.1-alpha.1",
3
+ "version": "0.5.9",
4
+ "description": "Custom Claude provider support for DeepSeek Harness 0.2.1-alpha.2",
5
5
  "author": "mofeng2223",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -62,6 +62,6 @@
62
62
  }
63
63
  },
64
64
  "devDependencies": {
65
- "@deepseek-ai/dsh-client-ui-settings-models": "0.2.1-alpha.1"
65
+ "@deepseek-ai/dsh-client-ui-settings-models": "0.2.1-alpha.2"
66
66
  }
67
67
  }