dsh-oauth-login 0.2.4 → 0.2.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/INSTALL.md CHANGED
@@ -2,21 +2,34 @@
2
2
 
3
3
  [中文](INSTALL.zh.md). Product pages: [README.md](README.md) (中文), [README.en.md](README.en.md).
4
4
 
5
- Stock DeepSeek Harness **0.1.5-rc.3** users install with official `dsh` and **pnpm**:
5
+ ## DSH Studio desktop app (recommended)
6
+
7
+ Open **Settings → Plugins → Add plugin** and enter this in “Package name or address”:
8
+
9
+ ```text
10
+ github:aa2246740/dsh-oauth-login#v0.2.7
11
+ ```
12
+
13
+ The in-app plugin manager owns the Desktop profile and bundled package manager. This release includes built `lib/`; normal use needs no clone, build, or DSHX installation. Follow the app if it asks you to reload or reopen.
14
+
15
+ ## Web CLI
16
+
17
+ Stock DeepSeek Harness **0.2.0-rc.2** users install to the Web profile with the official CLI:
6
18
 
7
19
  ```sh
8
- dsh plugin --profile web add github:aa2246740/dsh-oauth-login
20
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
9
21
  ```
10
22
 
11
23
  If `dsh` is not on PATH:
12
24
 
13
25
  ```sh
14
- npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
26
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
15
27
  ```
16
28
 
17
29
  That `github:` spec works because the package declares `dsh.bundle.patch` and
18
30
  commits built `lib/`. Official add runs pnpm in `$DSH_HOME/profiles/web` and
19
- appends the package to `dsh.profile.bundles`. Then restart that Host and reload
31
+ appends the package to `dsh.profile.bundles`. This command writes only `web`,
32
+ not the Desktop App profile. Reopen an already-running Web Host once and reload
20
33
  the page. You do not need Creator Mode or a second toolchain.
21
34
 
22
35
  Use `file:` only when editing a local clone. Keep the prefix. A bare
package/INSTALL.zh.md CHANGED
@@ -2,19 +2,31 @@
2
2
 
3
3
  [English](INSTALL.md)。说明和截图在 [README.md](README.md),英文在 [README.en.md](README.en.md)。
4
4
 
5
- 官方 DeepSeek Harness **0.1.5-rc.3** 用户用官方 `dsh` 和 **pnpm** 安装:
5
+ ## DSH Studio 桌面 App(推荐)
6
+
7
+ 打开 **设置 → 插件 → 添加插件**,在“包名或地址”中输入:
8
+
9
+ ```text
10
+ github:aa2246740/dsh-oauth-login#v0.2.7
11
+ ```
12
+
13
+ 应用内插件管理器负责 Desktop profile 和内置包管理器。本发布已包含编译好的 `lib/`;普通使用不需要 clone、构建或安装 DSHX。若应用提示刷新或重新打开,请按提示完成。
14
+
15
+ ## Web CLI
16
+
17
+ 官方 DeepSeek Harness **0.2.0-rc.2** 用户用官方 CLI 安装到 Web profile:
6
18
 
7
19
  ```sh
8
- dsh plugin --profile web add github:aa2246740/dsh-oauth-login
20
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
9
21
  ```
10
22
 
11
23
  没有 `dsh` 时:
12
24
 
13
25
  ```sh
14
- npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
26
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
15
27
  ```
16
28
 
17
- 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。官方 add 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。装完重启这个 Host,刷新页面。不需要 Creator Mode,也不需要另装一套工具。
29
+ 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。官方 add 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。这条命令只写 `web` profile,不能修改 Desktop App 的 profile;已运行的 Web Host 需要重新打开一次,再刷新网页。不需要 Creator Mode,也不需要另装一套工具。
18
30
 
19
31
  本机改源码时再用 `file:`,并且必须保留前缀。直接写 `./dsh-oauth-login` 会变成符号链接;本插件有意从 profile 复用 DSH 运行时的 peer dependency,因此必须使用 `file:` 副本,才能正确解析依赖。
20
32
 
package/README.en.md CHANGED
@@ -2,11 +2,25 @@
2
2
 
3
3
  [中文](README.md) | English
4
4
 
5
+ ## Install
6
+
7
+ ### DSH Studio desktop app (recommended)
8
+
9
+ Open **Settings → Plugins → Add plugin** and enter this in “Package name or address”:
10
+
11
+ ```text
12
+ github:aa2246740/dsh-oauth-login#v0.2.7
13
+ ```
14
+
15
+ The desktop plugin manager owns the Desktop profile and bundled package manager. This release includes built `lib/`; normal use needs no clone, build, or DSHX installation. Follow the app if it asks you to reload or reopen after installation.
16
+
17
+ ### Web CLI
18
+
5
19
  ```sh
6
- dsh plugin --profile web add github:aa2246740/dsh-oauth-login
20
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
7
21
  ```
8
22
 
9
- You need official `dsh` on PATH (or `npx @deepseek-ai/dsh`) and **pnpm**. Then restart that Host and reload the page. `dsh plugin add` writes the profile. It does not hot-load a running Host.
23
+ This official CLI command writes only the `web` profile; it cannot modify the Desktop App profile. For an already-running Web Host, reopen that Host once and reload the page.
10
24
 
11
25
  OAuth login for ChatGPT, Claude, Grok, Copilot, OpenRouter, and Kimi on [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), plus Zhipu GLM Coding Plan via its official plan API key. Credentials go only to `$DSH_HOME/.dsh-oauth-auth.json`.
12
26
 
@@ -26,17 +40,17 @@ The UI is **Settings → 订阅登录**.
26
40
 
27
41
  ## Install
28
42
 
29
- Node 22.19+ and official DeepSeek Harness **0.1.5-rc.3** (`@deepseek-ai/dsh@0.1.5-rc.3`, tag `dsh-v0.1.5-rc.3`).
43
+ Node 22.19+ and official DeepSeek Harness **0.2.0-rc.2** (`@deepseek-ai/dsh@0.2.0-rc.2`, tag `dsh-v0.2.0-rc.2`, SHA `639ed015397290b3745d163aafe02ffee4aa3f84`). The `@deepseek-ai/dsh` peer is `>=0.2.0-rc.1 <0.2.1`: it accepts `0.2.0-rc.2` and stable `0.2.0`, and rejects `0.2.0` alphas and `0.1.7-rc.2`.
30
44
 
31
- That `github:` command works because this package declares `dsh.bundle.patch` and commits built `lib/`. Official `dsh plugin add` runs pnpm in `$DSH_HOME/profiles/web` and appends this package to `dsh.profile.bundles`. You do not need Creator Mode or a second toolchain.
45
+ That `github:` command works because this package declares `dsh.bundle.patch` and commits built `lib/`. You do not need Creator Mode or a second toolchain.
32
46
 
33
47
  If `dsh` is not on PATH:
34
48
 
35
49
  ```sh
36
- npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
50
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
37
51
  ```
38
52
 
39
- Use `file:` only when you are editing a local clone (do not drop the prefix):
53
+ Use `file:` only when you are editing a local clone (development/local testing; do not drop the prefix):
40
54
 
41
55
  ```sh
42
56
  git clone https://github.com/aa2246740/dsh-oauth-login.git
package/README.md CHANGED
@@ -2,11 +2,25 @@
2
2
 
3
3
  中文 | [English](README.en.md)
4
4
 
5
+ ## 安装
6
+
7
+ ### DSH Studio 桌面 App(推荐)
8
+
9
+ 打开 **设置 → 插件 → 添加插件**,在“包名或地址”中输入:
10
+
11
+ ```text
12
+ github:aa2246740/dsh-oauth-login#v0.2.7
13
+ ```
14
+
15
+ 桌面端插件管理器负责 Desktop profile 和内置包管理器。本发布已包含编译好的 `lib/`;普通使用不需要 clone、构建或安装 DSHX。若应用提示刷新或重新打开,请按提示完成。
16
+
17
+ ### Web CLI
18
+
5
19
  ```sh
6
- dsh plugin --profile web add github:aa2246740/dsh-oauth-login
20
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
7
21
  ```
8
22
 
9
- PATH 上需要官方 `dsh`(没有的话用 `npx @deepseek-ai/dsh`)和 **pnpm**。装完重启这个 Host,刷新页面。`dsh plugin add` 只写 profile,不会热挂正在跑的 Host。
23
+ 这条官方 CLI 命令只写入 `web` profile,不能修改 Desktop App 的 profile。对于已经运行的 Web Host,请重新打开该 Host 一次,再刷新网页。
10
24
 
11
25
  把 ChatGPT、Claude、Grok、Copilot、OpenRouter、Kimi 的 OAuth 登录和智谱 GLM Coding Plan 接到 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)。凭据只写 `$DSH_HOME/.dsh-oauth-auth.json`。
12
26
 
@@ -26,17 +40,17 @@ PATH 上需要官方 `dsh`(没有的话用 `npx @deepseek-ai/dsh`)和 **pnpm
26
40
 
27
41
  ## 安装
28
42
 
29
- 需要 Node 22.19+,以及能跑起来的官方 DeepSeek Harness **0.1.5-rc.3**(`@deepseek-ai/dsh@0.1.5-rc.3`,tag `dsh-v0.1.5-rc.3`)。
43
+ 需要 Node 22.19+,以及能跑起来的官方 DeepSeek Harness **0.2.0-rc.2**(`@deepseek-ai/dsh@0.2.0-rc.2`,tag `dsh-v0.2.0-rc.2`,SHA `639ed015397290b3745d163aafe02ffee4aa3f84`)。`@deepseek-ai/dsh` peer 为 `>=0.2.0-rc.1 <0.2.1`:接受 `0.2.0-rc.2` 和稳定版 `0.2.0`,拒绝 `0.2.0` alpha,也拒绝 `0.1.7-rc.2`。
30
44
 
31
- 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。官方 `dsh plugin add` 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。不需要 Creator Mode,也不需要另装一套工具。
45
+ 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。不需要 Creator Mode,也不需要另装一套工具。
32
46
 
33
47
  没有 `dsh` 时:
34
48
 
35
49
  ```sh
36
- npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
50
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
37
51
  ```
38
52
 
39
- 本机改源码时再用 `file:`(不要写成裸的 `./`):
53
+ 本机改源码时再用 `file:`(开发/本地测试;不要写成裸的 `./`):
40
54
 
41
55
  ```sh
42
56
  git clone https://github.com/aa2246740/dsh-oauth-login.git
package/lib/bin.js CHANGED
@@ -4,7 +4,7 @@ import { realpathSync } from "node:fs";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { LlmError, RetryPolicySchema } from "@deepseek-ai/dsh-llm";
7
- import { createModels } from "@earendil-works/pi-ai";
7
+ import { createModels, getCurrentTools, normalizeContext } from "@earendil-works/pi-ai";
8
8
  import "@deepseek-ai/dsh-llm-pi-ai";
9
9
  import { AsyncLocalStorage } from "node:async_hooks";
10
10
  import { basename, dirname, join, resolve } from "node:path";
@@ -543,6 +543,10 @@ const OPENROUTER_REFRESH_MS = 9e5;
543
543
  const OPENROUTER_COOLDOWN_MS = 6e4;
544
544
  //#endregion
545
545
  //#region src/native-tools.ts
546
+ /**
547
+ * OAuth routes that already have provider-hosted search / image tools.
548
+ * DSH's web_search function tool would hide those and bill a second key.
549
+ */
546
550
  /** DSH model-facing tools that steal traffic from a subscribed provider. */
547
551
  const DSH_WEB_TOOL_NAMES = ["web_search", "web_fetch"];
548
552
  /** Matching tool-web prompt sections. */
@@ -665,10 +669,15 @@ function wrapOnPayload(existing, providerId, api, policy = DEFAULT_NATIVE_TOOL_P
665
669
  };
666
670
  }
667
671
  function filterPiContext(context, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
668
- if (nativePlan(providerId, api, policy) === void 0 || context.tools === void 0) return context;
672
+ if (nativePlan(providerId, api, policy) === void 0) return context;
669
673
  return {
670
674
  ...context,
671
- tools: context.tools.filter((tool) => !isDshWebToolName(tool.name))
675
+ ...context.tools === void 0 ? {} : { tools: context.tools.filter((tool) => !isDshWebToolName(tool.name)) },
676
+ messages: context.messages.map((message) => message.role !== "system" ? message : {
677
+ ...message,
678
+ ...message.toolsAdded === void 0 ? {} : { toolsAdded: message.toolsAdded.filter((tool) => !isDshWebToolName(tool.name)) },
679
+ ...message.toolsRemoved === void 0 ? {} : { toolsRemoved: message.toolsRemoved.filter((tool) => !isDshWebToolName(tool.name)) }
680
+ })
672
681
  };
673
682
  }
674
683
  /**
@@ -680,7 +689,7 @@ function filterPiContext(context, providerId, api, policy = DEFAULT_NATIVE_TOOL_
680
689
  * when the provider serializer later emits `tools: []`.
681
690
  */
682
691
  function prepareNativeToolRequest(context, options, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
683
- if (context.tools === void 0 || nativePlan(providerId, api, policy) === void 0) return {
692
+ if (context.tools === void 0 && getCurrentTools(context.messages).length === 0 || nativePlan(providerId, api, policy) === void 0) return {
684
693
  context,
685
694
  options
686
695
  };
@@ -1382,12 +1391,12 @@ function harnessProvider(spec, native = DEFAULT_NATIVE_TOOL_POLICY, catalog) {
1382
1391
  stream: (model, context, options) => {
1383
1392
  const request = prepareNativeToolRequest(context, options ?? {}, spec.id, model.api, native);
1384
1393
  const guarded = spec.id === "openrouter" ? prepareOpenRouterOptions(model, request.options, catalog) : request.options;
1385
- return base.stream(model, request.context, guarded);
1394
+ return base.stream(model, normalizeContext(request.context), guarded);
1386
1395
  },
1387
1396
  streamSimple: (model, context, options) => {
1388
1397
  const request = prepareNativeToolRequest(context, options ?? {}, spec.id, model.api, native);
1389
1398
  const guarded = spec.id === "openrouter" ? prepareOpenRouterOptions(model, request.options, catalog) : request.options;
1390
- return base.streamSimple(model, request.context, guarded);
1399
+ return base.streamSimple(model, normalizeContext(request.context), guarded);
1391
1400
  }
1392
1401
  };
1393
1402
  }
package/lib/client.js CHANGED
@@ -1168,23 +1168,22 @@ window.__ModuleLoader__.load({
1168
1168
  if (event.relatedTarget instanceof Node && rootRef.current?.contains(event.relatedTarget)) return;
1169
1169
  close();
1170
1170
  };
1171
- const settleSelection = (accepted) => {
1172
- if (accepted) {
1171
+ const settleSelection = (result) => {
1172
+ if (result === void 0) return;
1173
+ if (result.ok) {
1173
1174
  if (rootRef.current !== null) close(true);
1174
1175
  return;
1175
1176
  }
1176
- const message = directory.getSnapshot().error;
1177
- if (message !== null) {
1178
- noticeSeq.current += 1;
1179
- window.clearTimeout(noticeTimer.current);
1180
- setNotice({
1181
- seq: noticeSeq.current,
1182
- text: t("error.action", { message })
1183
- });
1184
- noticeTimer.current = window.setTimeout(() => {
1185
- setNotice(null);
1186
- }, 4e3);
1187
- }
1177
+ const { error } = result;
1178
+ noticeSeq.current += 1;
1179
+ window.clearTimeout(noticeTimer.current);
1180
+ setNotice({
1181
+ seq: noticeSeq.current,
1182
+ text: error.code === "session/writer-held" ? t("error.sessionInUse") : t("error.action", { message: `${error.code}: ${error.message}` })
1183
+ });
1184
+ noticeTimer.current = window.setTimeout(() => {
1185
+ setNotice(null);
1186
+ }, 4e3);
1188
1187
  };
1189
1188
  const choose = (selection) => {
1190
1189
  const info = selection.provider === "pi-openrouter" ? metadata.get(selection.model) : void 0;
@@ -1898,7 +1897,7 @@ window.__ModuleLoader__.load({
1898
1897
  load: () => {
1899
1898
  if (available) directory.load().catch(() => {});
1900
1899
  },
1901
- select: (selection) => available ? directory.select(selection).then(() => true, () => false) : Promise.resolve(false),
1900
+ select: (selection) => available ? directory.select(selection) : Promise.resolve(void 0),
1902
1901
  ts
1903
1902
  };
1904
1903
  }