dsh-codex-subscription 0.3.6 → 0.3.7

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/AGENTS.md CHANGED
@@ -6,7 +6,7 @@ Use this guide when a user asks an Agent to install, update, verify, or remove
6
6
  ## Safety
7
7
 
8
8
  - Confirm the target DSH profile; use `web` only when it is the user's target.
9
- - Use the pinned `v0.3.6` release assets for a first install, never a moving branch.
9
+ - Use the pinned `v0.3.7` release assets for a first install, never a moving branch.
10
10
  - Never print OAuth credentials, account IDs, authorization callbacks, or the
11
11
  credential store.
12
12
  - Do not start, stop, or restart DSH without explicit permission.
@@ -51,7 +51,7 @@ the user which installation is the target.
51
51
  Download the fixed release asset to a visible file, then invoke the requested action:
52
52
 
53
53
  ```powershell
54
- curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.6/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
54
+ curl.exe -fL https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.7/dsh-codex.ps1 -o "$env:TEMP\dsh-codex.ps1"
55
55
  powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
56
56
  ```
57
57
 
@@ -59,7 +59,7 @@ If `curl.exe` is unavailable, download the same pinned asset without executing
59
59
  remote text in memory:
60
60
 
61
61
  ```powershell
62
- Invoke-WebRequest -UseBasicParsing -Uri 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.6/dsh-codex.ps1' -OutFile "$env:TEMP\dsh-codex.ps1"
62
+ Invoke-WebRequest -UseBasicParsing -Uri 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.7/dsh-codex.ps1' -OutFile "$env:TEMP\dsh-codex.ps1"
63
63
  powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\dsh-codex.ps1" Install
64
64
  ```
65
65
 
@@ -93,7 +93,7 @@ When `dsh`, Node.js, and pnpm are already available, install the pinned npm
93
93
  package directly:
94
94
 
95
95
  ```sh
96
- dsh plugin --profile web add dsh-codex-subscription@0.3.6
96
+ dsh plugin --profile web add dsh-codex-subscription@0.3.7
97
97
  ```
98
98
 
99
99
  Update with `dsh plugin --profile web update dsh-codex-subscription`. When
package/README.en.md CHANGED
@@ -33,7 +33,7 @@ If this helps, open the [GitHub repository](https://github.com/WSL043/dsh-codex-
33
33
 
34
34
  ## Prepare DSH
35
35
 
36
- This plugin supports DeepSeek Harness `0.1.0-rc.6` and requires a ChatGPT account
36
+ This plugin supports DeepSeek Harness `0.1.0-rc.6` and `0.1.0-rc.7`, and requires a ChatGPT account
37
37
  that currently has Codex access.
38
38
 
39
39
  - Do not want to configure Node.js? Use the [community DSH-Portable package](https://github.com/WSL043/DSH-Portable).
package/README.md CHANGED
@@ -29,7 +29,7 @@
29
29
 
30
30
  ## 准备 DSH
31
31
 
32
- 本插件适配 DeepSeek Harness `0.1.0-rc.6`,还需要一个当前具有 Codex 使用资格的
32
+ 本插件适配 DeepSeek Harness `0.1.0-rc.6` 与 `0.1.0-rc.7`,还需要一个当前具有 Codex 使用资格的
33
33
  ChatGPT 账户。
34
34
 
35
35
  - 不想配置 Node.js:使用 [DSH-Portable(社区便携包)](https://github.com/WSL043/DSH-Portable);
package/dsh-codex.ps1 CHANGED
@@ -32,8 +32,8 @@ if ($Managed -and -not $PSBoundParameters.ContainsKey('Action')) {
32
32
 
33
33
  $PackageName = 'dsh-codex-subscription'
34
34
  $LegacyPackageName = '@wsl043/dsh-codex-subscription'
35
- $PackageVersion = '0.3.6'
36
- $PackageSpec = 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.6/dsh-codex-subscription.tgz'
35
+ $PackageVersion = '0.3.7'
36
+ $PackageSpec = 'https://github.com/WSL043/dsh-codex-subscription/releases/download/v0.3.7/dsh-codex-subscription.tgz'
37
37
  $PnpmVersion = '11.19.0'
38
38
  $PnpmUrl = 'https://registry.npmjs.org/pnpm/-/pnpm-11.19.0.tgz'
39
39
  $PnpmSha512 = '7881F3ED590D472C4A955E2B88B2121791116066DCC88CBCA3849EC9B60F1BBAA6D2CCB221FA91DA4E1C65BEF2BCBE379365AEA7AC539C7BF86DEDC3A1B22DCE'
package/lib/client.js CHANGED
@@ -9,6 +9,7 @@ window.__ModuleLoader__.load({
9
9
  let _deepseek_ai_dsh_client_ui_attachment = require("@deepseek-ai/dsh-client-ui-attachment");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
11
  //#region src/settings-contract.js
12
+ const SETTINGS_NAMESPACE = "codex-subscription";
12
13
  const QUICK_QUOTA_FIELD = "quickQuotaVisible";
13
14
  const SEARCH_PROVIDER_FIELD = "searchProvider";
14
15
  const SEARCH_PROVIDER_CODEX = "codex";
@@ -37,6 +38,8 @@ window.__ModuleLoader__.load({
37
38
  "slots",
38
39
  "locale",
39
40
  "connection",
41
+ "remote",
42
+ "settingsScope",
40
43
  "modelDirectories",
41
44
  "conversation"
42
45
  ];
@@ -280,61 +283,92 @@ window.__ModuleLoader__.load({
280
283
  ]
281
284
  });
282
285
  }
283
- function createPreferenceController(rpc) {
284
- let snapshot = Object.freeze({
285
- status: "loading",
286
- visible: false,
287
- searchProvider: "dsh",
288
- writable: false,
289
- error: false
290
- });
286
+ function createPreferenceController(scope, rpc) {
287
+ let updating = false;
288
+ let error = false;
289
+ let fallbackStatus = "loading";
290
+ let fallback;
291
291
  let generation = 0;
292
+ const nativeSnapshot = () => scope.getSnapshot();
293
+ const read = () => {
294
+ const native = nativeSnapshot();
295
+ const current = native.status === "ready" ? native : fallbackStatus === "ready" ? fallback : native;
296
+ return Object.freeze({
297
+ status: updating ? "updating" : current.status,
298
+ visible: current.value?.[QUICK_QUOTA_FIELD] === true,
299
+ searchProvider: normalizeSearchProvider(current.value?.[SEARCH_PROVIDER_FIELD]),
300
+ writable: !updating && current.status === "ready" && current.writable === true,
301
+ error
302
+ });
303
+ };
304
+ let snapshot = read();
292
305
  const listeners = /* @__PURE__ */ new Set();
293
- const publish = (next) => {
294
- snapshot = Object.freeze(next);
306
+ const publish = () => {
307
+ snapshot = read();
295
308
  for (const listener of listeners) listener();
296
309
  };
297
- const accept = (value) => publish({
298
- status: "ready",
299
- visible: value?.[QUICK_QUOTA_FIELD] === true,
300
- searchProvider: normalizeSearchProvider(value?.[SEARCH_PROVIDER_FIELD]),
301
- writable: value?.writable === true,
302
- error: false
310
+ const disposeScope = scope.subscribe(() => {
311
+ error = false;
312
+ publish();
303
313
  });
314
+ const acceptFallback = (value) => {
315
+ fallbackStatus = "ready";
316
+ fallback = {
317
+ status: "ready",
318
+ value: {
319
+ [QUICK_QUOTA_FIELD]: value?.[QUICK_QUOTA_FIELD] === true,
320
+ [SEARCH_PROVIDER_FIELD]: normalizeSearchProvider(value?.[SEARCH_PROVIDER_FIELD])
321
+ },
322
+ writable: value?.writable === true
323
+ };
324
+ };
304
325
  const load = async () => {
305
326
  const current = ++generation;
327
+ updating = false;
328
+ fallbackStatus = "loading";
329
+ fallback = void 0;
330
+ error = false;
331
+ publish();
332
+ if (nativeSnapshot().status === "ready") return;
306
333
  try {
307
334
  const value = unwrap(await rpc.call(CHANNEL, "preferences/status", {}));
308
- if (current === generation) accept(value);
335
+ if (current !== generation || nativeSnapshot().status === "ready") return;
336
+ acceptFallback(value);
337
+ publish();
309
338
  } catch {
310
- if (current === generation) publish({
311
- status: "unavailable",
312
- visible: false,
313
- searchProvider: "dsh",
314
- writable: false,
315
- error: false
316
- });
339
+ if (current !== generation || nativeSnapshot().status === "ready") return;
340
+ fallbackStatus = "unavailable";
341
+ publish();
317
342
  }
318
343
  };
319
344
  const set = async (patch) => {
320
345
  if (snapshot.status !== "ready" || snapshot.writable !== true) return;
321
- const previous = snapshot;
322
346
  const current = ++generation;
323
- publish({
324
- status: "updating",
325
- visible: patch["quickQuotaVisible"] ?? snapshot.visible,
326
- searchProvider: patch["searchProvider"] ?? snapshot.searchProvider,
327
- writable: false,
328
- error: false
329
- });
347
+ const entries = Object.entries(patch);
348
+ updating = true;
349
+ error = false;
350
+ publish();
330
351
  try {
331
- const value = unwrap(await rpc.call(CHANNEL, "preferences/update", patch));
332
- if (current === generation) accept(value);
352
+ if (nativeSnapshot().status === "ready") {
353
+ for (const [field, value] of entries) {
354
+ if (current !== generation) return;
355
+ await scope.set(field, value);
356
+ }
357
+ if (current !== generation) return;
358
+ const accepted = nativeSnapshot().value;
359
+ error = entries.some(([field, value]) => accepted?.[field] !== value);
360
+ } else {
361
+ const value = unwrap(await rpc.call(CHANNEL, "preferences/update", patch));
362
+ if (current !== generation) return;
363
+ acceptFallback(value);
364
+ }
333
365
  } catch {
334
- if (current === generation) publish({
335
- ...previous,
336
- error: true
337
- });
366
+ if (current === generation) error = true;
367
+ } finally {
368
+ if (current === generation) {
369
+ updating = false;
370
+ publish();
371
+ }
338
372
  }
339
373
  };
340
374
  return {
@@ -344,7 +378,8 @@ window.__ModuleLoader__.load({
344
378
  return () => listeners.delete(listener);
345
379
  },
346
380
  load,
347
- set
381
+ set,
382
+ dispose: disposeScope
348
383
  };
349
384
  }
350
385
  const usePreferenceSnapshot = (preference) => (0, react.useSyncExternalStore)(preference.subscribe, preference.getSnapshot);
@@ -902,12 +937,16 @@ window.__ModuleLoader__.load({
902
937
  return () => tag.remove();
903
938
  }, "codex-subscription: style");
904
939
  const connection = ctx.get("connection");
905
- const preference = createPreferenceController(connection.rpc);
940
+ const preference = createPreferenceController(ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE }), connection.rpc);
906
941
  ctx.effect(() => {
907
942
  preference.load();
908
- return ctx.on("connection/reset", () => {
943
+ const disposeReset = ctx.on("connection/reset", () => {
909
944
  preference.load();
910
945
  });
946
+ return () => {
947
+ disposeReset?.();
948
+ preference.dispose();
949
+ };
911
950
  }, "codex-subscription: preferences");
912
951
  const t = ctx.locale.bind(NS);
913
952
  ctx.slots.inject("settings.section", () => ctx.slots.register({
package/lib/index.js CHANGED
@@ -540,7 +540,7 @@ function createCodexSearchProvider(options) {
540
540
  accept: "application/json",
541
541
  "content-type": "application/json",
542
542
  originator: "pi",
543
- "user-agent": "dsh-codex-subscription/0.3.6"
543
+ "user-agent": "dsh-codex-subscription/0.3.7"
544
544
  },
545
545
  body: JSON.stringify({
546
546
  id,
@@ -929,7 +929,7 @@ function createCodexUsageReader(options) {
929
929
  "chatgpt-account-id": accountId,
930
930
  accept: "application/json",
931
931
  "cache-control": "no-store",
932
- "user-agent": "dsh-codex-subscription/0.3.6"
932
+ "user-agent": "dsh-codex-subscription/0.3.7"
933
933
  },
934
934
  signal: requestSignal(signal, timeoutMs)
935
935
  });
@@ -1064,17 +1064,7 @@ function apply(ctx) {
1064
1064
  [SEARCH_PROVIDER_FIELD]: settings.get()[SEARCH_PROVIDER_FIELD],
1065
1065
  writable: ctx.settings.writable
1066
1066
  }),
1067
- update: async (patch) => {
1068
- const previousSearchProvider = settings.get()[SEARCH_PROVIDER_FIELD];
1069
- await settings.update(patch);
1070
- if (patch["searchProvider"] === void 0) return;
1071
- try {
1072
- await searchProvider.select(patch[SEARCH_PROVIDER_FIELD]);
1073
- } catch (error) {
1074
- await settings.update({ [SEARCH_PROVIDER_FIELD]: previousSearchProvider });
1075
- throw error;
1076
- }
1077
- }
1067
+ update: (patch) => settings.update(patch)
1078
1068
  };
1079
1069
  const store = new DshOAuthCredentialStore(ctx.credentials, CREDENTIAL_REF, [LEGACY_CREDENTIAL_REF]);
1080
1070
  const provider = openaiCodexSubscriptionProvider();
@@ -1122,9 +1112,15 @@ function apply(ctx) {
1122
1112
  resolveSessionId: () => currentAgent()?.session.id
1123
1113
  }));
1124
1114
  ctx.effect(() => {
1125
- searchProvider.select(settings.get()[SEARCH_PROVIDER_FIELD]).catch((error) => {
1126
- ctx.logger?.warn?.("could not select the configured web search provider: %s", error.message);
1127
- });
1115
+ const select = async (value) => {
1116
+ try {
1117
+ await searchProvider.select(value[SEARCH_PROVIDER_FIELD]);
1118
+ } catch (error) {
1119
+ ctx.logger?.warn?.("could not select the configured web search provider: %s", error.message);
1120
+ }
1121
+ };
1122
+ select(settings.get());
1123
+ return settings.watch(select);
1128
1124
  }, "codex-subscription: search provider selection");
1129
1125
  const coordinator = new CodexLoginCoordinator(createCodexAuthService(authModels, store));
1130
1126
  const usageReader = createCodexUsageReader({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "packageManager": "pnpm@11.19.0",
5
5
  "description": "ChatGPT and Codex subscriptions for DeepSeek Harness with OAuth login, image generation, quota, and subscription web search",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "client": {
31
31
  "inject": [
32
+ "@deepseek-ai/dsh-api-remotes",
32
33
  "@deepseek-ai/dsh-client-connection",
33
34
  "@deepseek-ai/dsh-client-locale",
34
35
  "@deepseek-ai/dsh-client-runtime",
@@ -79,44 +80,46 @@
79
80
  },
80
81
  "peerDependencies": {
81
82
  "@deepseek-ai/cordis": "4.0.1",
82
- "@deepseek-ai/dsh-client-connection": "0.1.0-rc.6",
83
- "@deepseek-ai/dsh-client-locale": "0.1.0-rc.6",
84
- "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6",
85
- "@deepseek-ai/dsh-client-ui-attachment": "0.1.0-rc.6",
86
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6",
87
- "@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6",
88
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6",
89
- "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6",
90
- "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6",
91
- "@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6",
92
- "@deepseek-ai/dsh-credentials": "0.1.0-rc.6",
93
- "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
94
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6",
95
- "@deepseek-ai/dsh-settings": "0.1.0-rc.6",
96
- "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
97
- "@deepseek-ai/dsh-web": "0.1.0-rc.6",
83
+ "@deepseek-ai/dsh-api-remotes": "0.1.0-rc.6 || 0.1.0-rc.7",
84
+ "@deepseek-ai/dsh-client-connection": "0.1.0-rc.6 || 0.1.0-rc.7",
85
+ "@deepseek-ai/dsh-client-locale": "0.1.0-rc.6 || 0.1.0-rc.7",
86
+ "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6 || 0.1.0-rc.7",
87
+ "@deepseek-ai/dsh-client-ui-attachment": "0.1.0-rc.6 || 0.1.0-rc.7",
88
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6 || 0.1.0-rc.7",
89
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6 || 0.1.0-rc.7",
90
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6 || 0.1.0-rc.7",
91
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6 || 0.1.0-rc.7",
92
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6 || 0.1.0-rc.7",
93
+ "@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6 || 0.1.0-rc.7",
94
+ "@deepseek-ai/dsh-credentials": "0.1.0-rc.6 || 0.1.0-rc.7",
95
+ "@deepseek-ai/dsh-llm": "0.1.0-rc.6 || 0.1.0-rc.7",
96
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6 || 0.1.0-rc.7",
97
+ "@deepseek-ai/dsh-settings": "0.1.0-rc.6 || 0.1.0-rc.7",
98
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.6 || 0.1.0-rc.7",
99
+ "@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7",
98
100
  "@deepseek-ai/schemastery": "3.18.1",
99
101
  "@earendil-works/pi-ai": "0.82.1",
100
102
  "react": "^18.2.0"
101
103
  },
102
104
  "devDependencies": {
103
105
  "@deepseek-ai/cordis": "4.0.1",
104
- "@deepseek-ai/dsh-client-connection": "0.1.0-rc.6",
105
- "@deepseek-ai/dsh-client-locale": "0.1.0-rc.6",
106
- "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6",
107
- "@deepseek-ai/dsh-client-ui-attachment": "0.1.0-rc.6",
108
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6",
109
- "@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6",
110
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6",
111
- "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6",
112
- "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6",
113
- "@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6",
114
- "@deepseek-ai/dsh-credentials": "0.1.0-rc.6",
115
- "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
116
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6",
117
- "@deepseek-ai/dsh-settings": "0.1.0-rc.6",
118
- "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
119
- "@deepseek-ai/dsh-web": "0.1.0-rc.6",
106
+ "@deepseek-ai/dsh-api-remotes": "0.1.0-rc.7",
107
+ "@deepseek-ai/dsh-client-connection": "0.1.0-rc.7",
108
+ "@deepseek-ai/dsh-client-locale": "0.1.0-rc.7",
109
+ "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.7",
110
+ "@deepseek-ai/dsh-client-ui-attachment": "0.1.0-rc.7",
111
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.7",
112
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.7",
113
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.7",
114
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.7",
115
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.7",
116
+ "@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.7",
117
+ "@deepseek-ai/dsh-credentials": "0.1.0-rc.7",
118
+ "@deepseek-ai/dsh-llm": "0.1.0-rc.7",
119
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.7",
120
+ "@deepseek-ai/dsh-settings": "0.1.0-rc.7",
121
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.7",
122
+ "@deepseek-ai/dsh-web": "0.1.0-rc.7",
120
123
  "@deepseek-ai/schemastery": "3.18.1",
121
124
  "@earendil-works/pi-ai": "0.82.1",
122
125
  "react": "18.3.1",