dsh-oauth-login 0.2.7 → 0.2.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.
- package/INSTALL.md +9 -8
- package/INSTALL.zh.md +5 -5
- package/README.en.md +7 -5
- package/README.md +7 -5
- package/lib/bin.js +31 -17
- package/lib/index.d.ts +5 -1
- package/lib/index.js +32 -17
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/native-tools.ts +24 -16
- package/src/plugin-config.ts +4 -1
package/INSTALL.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Open **Settings → Plugins → Add plugin** and enter this in “Package name or address”:
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
|
|
10
|
+
dsh-oauth-login@0.2.9
|
|
11
11
|
```
|
|
12
12
|
|
|
13
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.
|
|
@@ -17,20 +17,21 @@ The in-app plugin manager owns the Desktop profile and bundled package manager.
|
|
|
17
17
|
Stock DeepSeek Harness **0.2.0-rc.2** users install to the Web profile with the official CLI:
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
dsh plugin --profile web add
|
|
20
|
+
dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
If `dsh` is not on PATH:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
npx @deepseek-ai/dsh plugin --profile web add
|
|
26
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
The package declares `dsh.bundle.patch` and includes built `lib/`.
|
|
30
|
+
Official add runs pnpm in `$DSH_HOME/profiles/web` and
|
|
31
31
|
appends the package to `dsh.profile.bundles`. This command writes only `web`,
|
|
32
|
-
not the Desktop App profile.
|
|
33
|
-
the
|
|
32
|
+
not the Desktop App profile. Follow the installer's activation result; reopen
|
|
33
|
+
the original launcher only when it reports that a restart is required.
|
|
34
|
+
You do not need Creator Mode or a second toolchain.
|
|
34
35
|
|
|
35
36
|
Use `file:` only when editing a local clone. Keep the prefix. A bare
|
|
36
37
|
`./dsh-oauth-login` becomes a symlink, while this plugin intentionally resolves
|
|
@@ -54,7 +55,7 @@ dsh plugin --profile web exec dsh-oauth-login logout openai-codex
|
|
|
54
55
|
For Zhipu GLM Coding Plan, the command opens the official Plan page and asks
|
|
55
56
|
for its API key locally. The plugin never reads your browser session.
|
|
56
57
|
|
|
57
|
-
After upgrading
|
|
58
|
+
After upgrading and following the installer's activation result, open Settings →
|
|
58
59
|
Subscription Login → Network proxy. Configure HTTP and WebSocket independently.
|
|
59
60
|
The address defaults to `http://127.0.0.1`, with the port left empty. An enabled
|
|
60
61
|
channel with an explicit address and port overrides automatic discovery; an
|
package/INSTALL.zh.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
打开 **设置 → 插件 → 添加插件**,在“包名或地址”中输入:
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
|
|
10
|
+
dsh-oauth-login@0.2.9
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
应用内插件管理器负责 Desktop profile 和内置包管理器。本发布已包含编译好的 `lib/`;普通使用不需要 clone、构建或安装 DSHX。若应用提示刷新或重新打开,请按提示完成。
|
|
@@ -17,16 +17,16 @@ github:aa2246740/dsh-oauth-login#v0.2.7
|
|
|
17
17
|
官方 DeepSeek Harness **0.2.0-rc.2** 用户用官方 CLI 安装到 Web profile:
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
dsh plugin --profile web add
|
|
20
|
+
dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
没有 `dsh` 时:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
npx @deepseek-ai/dsh plugin --profile web add
|
|
26
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
包中声明了 `dsh.bundle.patch`,并包含编好的 `lib/`。官方 add 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。这条命令只写 `web` profile,不能修改 Desktop App 的 profile;按安装器的生效结果继续,只有提示需要重启时才用原启动方式重新打开。不需要 Creator Mode,也不需要另装一套工具。
|
|
30
30
|
|
|
31
31
|
本机改源码时再用 `file:`,并且必须保留前缀。直接写 `./dsh-oauth-login` 会变成符号链接;本插件有意从 profile 复用 DSH 运行时的 peer dependency,因此必须使用 `file:` 副本,才能正确解析依赖。
|
|
32
32
|
|
|
@@ -47,7 +47,7 @@ dsh plugin --profile web exec dsh-oauth-login logout openai-codex
|
|
|
47
47
|
智谱 GLM Coding Plan 会打开官方套餐页,再在本机提示你输入 API Key;
|
|
48
48
|
插件不会读取你的浏览器登录状态。
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
升级服务端插件并按安装器提示完成生效后,进入「设置 → 订阅登录 → 网络代理」。HTTP 与 WebSocket 可以独立配置,地址默认填入 `http://127.0.0.1`,端口留空。开启并填写端口时优先使用该代理;默认地址且端口留空时沿用自动发现,不会默认使用 80 端口;关闭时直接连接。请使用 HTTP(S) CONNECT / 混合代理端口,不能填纯 SOCKS 端口。页面保存后用于新请求,不需要再次重启;改变启动时继承的环境变量则需要重启。详见[网络代理与恢复机制](docs/network-proxy.md)。
|
|
51
51
|
|
|
52
52
|
卸载:
|
|
53
53
|
|
package/README.en.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Open **Settings → Plugins → Add plugin** and enter this in “Package name or address”:
|
|
10
10
|
|
|
11
11
|
```text
|
|
12
|
-
|
|
12
|
+
dsh-oauth-login@0.2.9
|
|
13
13
|
```
|
|
14
14
|
|
|
15
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.
|
|
@@ -17,10 +17,10 @@ The desktop plugin manager owns the Desktop profile and bundled package manager.
|
|
|
17
17
|
### Web CLI
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
dsh plugin --profile web add
|
|
20
|
+
dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
This official CLI command writes only the `web` profile; it cannot modify the Desktop App profile.
|
|
23
|
+
This official CLI command writes only the `web` profile; it cannot modify the Desktop App profile. Follow the installer's activation result and reopen the original launcher only when a restart is required.
|
|
24
24
|
|
|
25
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`.
|
|
26
26
|
|
|
@@ -47,7 +47,7 @@ That `github:` command works because this package declares `dsh.bundle.patch` an
|
|
|
47
47
|
If `dsh` is not on PATH:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
npx @deepseek-ai/dsh plugin --profile web add
|
|
50
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Use `file:` only when you are editing a local clone (development/local testing; do not drop the prefix):
|
|
@@ -97,7 +97,7 @@ On these routes the plugin removes DSH `web_search` / `web_fetch` and attaches t
|
|
|
97
97
|
| Route | Hosted tools |
|
|
98
98
|
|---|---|
|
|
99
99
|
| `pi-xai` | `web_search`, `x_search`, `image_generation` |
|
|
100
|
-
| `pi-openai-codex` | `web_search
|
|
100
|
+
| `pi-openai-codex` | `web_search` (cached by default) |
|
|
101
101
|
| `pi-anthropic` | `web_search_20250305` |
|
|
102
102
|
|
|
103
103
|
Copilot, OpenRouter, Kimi, and Zhipu do not get hosted tools. To keep DSH search:
|
|
@@ -111,6 +111,8 @@ Copilot, OpenRouter, Kimi, and Zhipu do not get hosted tools. To keep DSH search
|
|
|
111
111
|
|
|
112
112
|
`nativeImage: false` keeps search and drops image generation.
|
|
113
113
|
|
|
114
|
+
Codex uses its own tool declaration. `codexSearch: cached` sends `external_web_access: false`; `live` explicitly enables external access; `off` leaves the DSH client web tools available. Cached results may be stale. Account or backend rejections remain visible, and the plugin never silently changes model or search mode. Codex does not inherit generic Responses image-generation tools. Grok and Anthropic retain their own protocols.
|
|
115
|
+
|
|
114
116
|
Chat retries use official `dsh-llm-retry`. HTTP 429 is not the same as quota exhaustion. **Settings → 订阅登录 → 网络代理** affects only this plugin.
|
|
115
117
|
|
|
116
118
|
## License
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
打开 **设置 → 插件 → 添加插件**,在“包名或地址”中输入:
|
|
10
10
|
|
|
11
11
|
```text
|
|
12
|
-
|
|
12
|
+
dsh-oauth-login@0.2.9
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
桌面端插件管理器负责 Desktop profile 和内置包管理器。本发布已包含编译好的 `lib/`;普通使用不需要 clone、构建或安装 DSHX。若应用提示刷新或重新打开,请按提示完成。
|
|
@@ -17,10 +17,10 @@ github:aa2246740/dsh-oauth-login#v0.2.7
|
|
|
17
17
|
### Web CLI
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
dsh plugin --profile web add
|
|
20
|
+
dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
这条官方 CLI 命令只写入 `web` profile,不能修改 Desktop App 的 profile
|
|
23
|
+
这条官方 CLI 命令只写入 `web` profile,不能修改 Desktop App 的 profile。按安装器的生效结果继续;只有提示需要重启时才用原启动方式重新打开 Host。
|
|
24
24
|
|
|
25
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`。
|
|
26
26
|
|
|
@@ -47,7 +47,7 @@ dsh plugin --profile web add github:aa2246740/dsh-oauth-login#v0.2.7
|
|
|
47
47
|
没有 `dsh` 时:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
npx @deepseek-ai/dsh plugin --profile web add
|
|
50
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-oauth-login@0.2.9
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
本机改源码时再用 `file:`(开发/本地测试;不要写成裸的 `./`):
|
|
@@ -109,7 +109,9 @@ Copilot、OpenRouter、Kimi、智谱不挂 hosted tool。要继续用 DSH 自己
|
|
|
109
109
|
nativeTools: false
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
`nativeImage: false`
|
|
112
|
+
`nativeImage: false` 关闭受支持路由的托管出图。
|
|
113
|
+
|
|
114
|
+
Codex 订阅路由使用独立的工具声明:`codexSearch: cached` 默认发送 `external_web_access: false`;`live` 显式请求实时外部访问,`off` 不注入托管搜索并保留 DSH 的客户端搜索工具。缓存搜索不保证结果实时性;账户和后端仍可能拒绝工具请求,插件不会自动换模型或在失败后静默重试另一种搜索模式。Codex 不再继承通用 Responses 的托管图片生成声明。Grok、Anthropic 保持各自协议。
|
|
113
115
|
|
|
114
116
|
Chat 失败重试走官方 `dsh-llm-retry`。429 不等于额度耗尽。设置 → 订阅登录 → 网络代理只影响本插件。
|
|
115
117
|
|
package/lib/bin.js
CHANGED
|
@@ -577,10 +577,12 @@ const HOSTED_CLIENT_LEAK_NAMES = [
|
|
|
577
577
|
new Set(HOSTED_CLIENT_LEAK_NAMES);
|
|
578
578
|
const DEFAULT_NATIVE_TOOL_POLICY = {
|
|
579
579
|
enabled: true,
|
|
580
|
-
image: true
|
|
580
|
+
image: true,
|
|
581
|
+
codexSearch: "cached"
|
|
581
582
|
};
|
|
582
583
|
const SEARCH_GUIDANCE = "This turn already includes this account's native hosted search. Do not call web_search or web_fetch — those DSH tools are not available on this route.";
|
|
583
584
|
const SEARCH_AND_IMAGE_GUIDANCE = "This turn already includes this account's native hosted search and image generation. Do not call web_search or web_fetch — those DSH tools are not available on this route.";
|
|
585
|
+
const CACHED_SEARCH_GUIDANCE = "This turn includes native cached web search. Cached results may not reflect current pages. Do not call web_search or web_fetch as client functions — those DSH tools are not available on this route.";
|
|
584
586
|
function responsesSearch() {
|
|
585
587
|
return { type: "web_search" };
|
|
586
588
|
}
|
|
@@ -609,12 +611,17 @@ function nativePlan(providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
|
609
611
|
],
|
|
610
612
|
guidance: policy.image ? SEARCH_AND_IMAGE_GUIDANCE : SEARCH_GUIDANCE
|
|
611
613
|
};
|
|
612
|
-
case "openai-codex:openai-codex-responses":
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
614
|
+
case "openai-codex:openai-codex-responses":
|
|
615
|
+
if (policy.codexSearch === "off") return void 0;
|
|
616
|
+
return {
|
|
617
|
+
providerId,
|
|
618
|
+
api: "openai-codex-responses",
|
|
619
|
+
hosted: [{
|
|
620
|
+
type: "web_search",
|
|
621
|
+
external_web_access: policy.codexSearch === "live"
|
|
622
|
+
}],
|
|
623
|
+
guidance: policy.codexSearch === "live" ? SEARCH_GUIDANCE : CACHED_SEARCH_GUIDANCE
|
|
624
|
+
};
|
|
618
625
|
case "anthropic:anthropic-messages": return {
|
|
619
626
|
providerId,
|
|
620
627
|
api: "anthropic-messages",
|
|
@@ -644,13 +651,15 @@ function hostedToolKey(tool) {
|
|
|
644
651
|
function applyNativeToolsToPayload(payload, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
645
652
|
const plan = nativePlan(providerId, api, policy);
|
|
646
653
|
if (plan === void 0 || !isRecord(payload) || !Array.isArray(payload.tools)) return payload;
|
|
647
|
-
const
|
|
648
|
-
const
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
+
const current = payload.tools;
|
|
655
|
+
const managed = new Set(plan.hosted.map(hostedToolKey));
|
|
656
|
+
const kept = current.filter((tool) => !isDshWebFunctionTool(tool) && (!isRecord(tool) || !managed.has(hostedToolKey(tool))) && !(providerId === "openai-codex" && isRecord(tool) && tool.type === "image_generation"));
|
|
657
|
+
const hosted = plan.hosted.map((tool) => {
|
|
658
|
+
const previous = current.find((candidate) => isRecord(candidate) && hostedToolKey(candidate) === hostedToolKey(tool));
|
|
659
|
+
return {
|
|
660
|
+
...isRecord(previous) ? previous : {},
|
|
661
|
+
...tool
|
|
662
|
+
};
|
|
654
663
|
});
|
|
655
664
|
return {
|
|
656
665
|
...payload,
|
|
@@ -664,8 +673,8 @@ function wrapOnPayload(existing, providerId, api, policy = DEFAULT_NATIVE_TOOL_P
|
|
|
664
673
|
...payload,
|
|
665
674
|
tools: []
|
|
666
675
|
} : payload, providerId, api, policy);
|
|
667
|
-
|
|
668
|
-
return
|
|
676
|
+
const customized = existing === void 0 ? void 0 : await existing(injected, model);
|
|
677
|
+
return applyNativeToolsToPayload(customized === void 0 ? injected : customized, providerId, api, policy);
|
|
669
678
|
};
|
|
670
679
|
}
|
|
671
680
|
function filterPiContext(context, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
@@ -1981,7 +1990,12 @@ z.object({
|
|
|
1981
1990
|
streamIdleTimeoutMs: z.number().min(1).default(PI_LOGIN_STREAM_IDLE_TIMEOUT_MS),
|
|
1982
1991
|
retryPolicy: RetryPolicySchema,
|
|
1983
1992
|
nativeTools: z.boolean().default(true),
|
|
1984
|
-
nativeImage: z.boolean().default(true)
|
|
1993
|
+
nativeImage: z.boolean().default(true),
|
|
1994
|
+
codexSearch: z.union([
|
|
1995
|
+
"cached",
|
|
1996
|
+
"live",
|
|
1997
|
+
"off"
|
|
1998
|
+
]).default("cached")
|
|
1985
1999
|
});
|
|
1986
2000
|
//#endregion
|
|
1987
2001
|
//#region src/bin.ts
|
package/lib/index.d.ts
CHANGED
|
@@ -20,8 +20,10 @@ interface Config {
|
|
|
20
20
|
* search, and attach those hosted tools to the provider request.
|
|
21
21
|
*/
|
|
22
22
|
nativeTools?: boolean;
|
|
23
|
-
/** Also attach hosted image generation on
|
|
23
|
+
/** Also attach hosted image generation on transports that support it (Grok). */
|
|
24
24
|
nativeImage?: boolean;
|
|
25
|
+
/** Codex defaults to cached search; live external access is explicit. */
|
|
26
|
+
codexSearch?: 'cached' | 'live' | 'off';
|
|
25
27
|
}
|
|
26
28
|
declare const Config: z<Config>;
|
|
27
29
|
//#endregion
|
|
@@ -117,6 +119,8 @@ interface NativeToolPolicy {
|
|
|
117
119
|
enabled: boolean;
|
|
118
120
|
/** Also attach hosted image generation where the provider documents it. Default true. */
|
|
119
121
|
image: boolean;
|
|
122
|
+
/** Codex search distinguishes cached content from live external access. */
|
|
123
|
+
codexSearch?: 'cached' | 'live' | 'off';
|
|
120
124
|
}
|
|
121
125
|
declare const DEFAULT_NATIVE_TOOL_POLICY: NativeToolPolicy;
|
|
122
126
|
interface NativeToolPlan {
|
package/lib/index.js
CHANGED
|
@@ -796,10 +796,12 @@ const HOSTED_CLIENT_LEAK_NAMES = [
|
|
|
796
796
|
const HOSTED_CLIENT_LEAK_NAME_SET = new Set(HOSTED_CLIENT_LEAK_NAMES);
|
|
797
797
|
const DEFAULT_NATIVE_TOOL_POLICY = {
|
|
798
798
|
enabled: true,
|
|
799
|
-
image: true
|
|
799
|
+
image: true,
|
|
800
|
+
codexSearch: "cached"
|
|
800
801
|
};
|
|
801
802
|
const SEARCH_GUIDANCE = "This turn already includes this account's native hosted search. Do not call web_search or web_fetch — those DSH tools are not available on this route.";
|
|
802
803
|
const SEARCH_AND_IMAGE_GUIDANCE = "This turn already includes this account's native hosted search and image generation. Do not call web_search or web_fetch — those DSH tools are not available on this route.";
|
|
804
|
+
const CACHED_SEARCH_GUIDANCE = "This turn includes native cached web search. Cached results may not reflect current pages. Do not call web_search or web_fetch as client functions — those DSH tools are not available on this route.";
|
|
803
805
|
function responsesSearch() {
|
|
804
806
|
return { type: "web_search" };
|
|
805
807
|
}
|
|
@@ -828,12 +830,17 @@ function nativePlan(providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
|
828
830
|
],
|
|
829
831
|
guidance: policy.image ? SEARCH_AND_IMAGE_GUIDANCE : SEARCH_GUIDANCE
|
|
830
832
|
};
|
|
831
|
-
case "openai-codex:openai-codex-responses":
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
833
|
+
case "openai-codex:openai-codex-responses":
|
|
834
|
+
if (policy.codexSearch === "off") return void 0;
|
|
835
|
+
return {
|
|
836
|
+
providerId,
|
|
837
|
+
api: "openai-codex-responses",
|
|
838
|
+
hosted: [{
|
|
839
|
+
type: "web_search",
|
|
840
|
+
external_web_access: policy.codexSearch === "live"
|
|
841
|
+
}],
|
|
842
|
+
guidance: policy.codexSearch === "live" ? SEARCH_GUIDANCE : CACHED_SEARCH_GUIDANCE
|
|
843
|
+
};
|
|
837
844
|
case "anthropic:anthropic-messages": return {
|
|
838
845
|
providerId,
|
|
839
846
|
api: "anthropic-messages",
|
|
@@ -1020,13 +1027,15 @@ function hostedToolKey(tool) {
|
|
|
1020
1027
|
function applyNativeToolsToPayload(payload, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
1021
1028
|
const plan = nativePlan(providerId, api, policy);
|
|
1022
1029
|
if (plan === void 0 || !isRecord(payload) || !Array.isArray(payload.tools)) return payload;
|
|
1023
|
-
const
|
|
1024
|
-
const
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
+
const current = payload.tools;
|
|
1031
|
+
const managed = new Set(plan.hosted.map(hostedToolKey));
|
|
1032
|
+
const kept = current.filter((tool) => !isDshWebFunctionTool(tool) && (!isRecord(tool) || !managed.has(hostedToolKey(tool))) && !(providerId === "openai-codex" && isRecord(tool) && tool.type === "image_generation"));
|
|
1033
|
+
const hosted = plan.hosted.map((tool) => {
|
|
1034
|
+
const previous = current.find((candidate) => isRecord(candidate) && hostedToolKey(candidate) === hostedToolKey(tool));
|
|
1035
|
+
return {
|
|
1036
|
+
...isRecord(previous) ? previous : {},
|
|
1037
|
+
...tool
|
|
1038
|
+
};
|
|
1030
1039
|
});
|
|
1031
1040
|
return {
|
|
1032
1041
|
...payload,
|
|
@@ -1040,8 +1049,8 @@ function wrapOnPayload(existing, providerId, api, policy = DEFAULT_NATIVE_TOOL_P
|
|
|
1040
1049
|
...payload,
|
|
1041
1050
|
tools: []
|
|
1042
1051
|
} : payload, providerId, api, policy);
|
|
1043
|
-
|
|
1044
|
-
return
|
|
1052
|
+
const customized = existing === void 0 ? void 0 : await existing(injected, model);
|
|
1053
|
+
return applyNativeToolsToPayload(customized === void 0 ? injected : customized, providerId, api, policy);
|
|
1045
1054
|
};
|
|
1046
1055
|
}
|
|
1047
1056
|
function filterPiContext(context, providerId, api, policy = DEFAULT_NATIVE_TOOL_POLICY) {
|
|
@@ -3050,7 +3059,12 @@ const Config = z.object({
|
|
|
3050
3059
|
streamIdleTimeoutMs: z.number().min(1).default(PI_LOGIN_STREAM_IDLE_TIMEOUT_MS),
|
|
3051
3060
|
retryPolicy: RetryPolicySchema,
|
|
3052
3061
|
nativeTools: z.boolean().default(true),
|
|
3053
|
-
nativeImage: z.boolean().default(true)
|
|
3062
|
+
nativeImage: z.boolean().default(true),
|
|
3063
|
+
codexSearch: z.union([
|
|
3064
|
+
"cached",
|
|
3065
|
+
"live",
|
|
3066
|
+
"off"
|
|
3067
|
+
]).default("cached")
|
|
3054
3068
|
});
|
|
3055
3069
|
//#endregion
|
|
3056
3070
|
//#region src/index.ts
|
|
@@ -3067,6 +3081,7 @@ function apply(ctx, config) {
|
|
|
3067
3081
|
console.log("[my-plugins/dsh-oauth-login] loaded");
|
|
3068
3082
|
const native = {
|
|
3069
3083
|
enabled: config.nativeTools !== false,
|
|
3084
|
+
codexSearch: config.codexSearch ?? "cached",
|
|
3070
3085
|
image: config.nativeImage !== false
|
|
3071
3086
|
};
|
|
3072
3087
|
const session = new PiLoginSession(new PiLoginCredentialStore(), native);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-oauth-login",
|
|
3
3
|
"description": "DSH-owned subscription login powered by Pi AI adapters: OAuth plus official Plan API keys, with an independent credential store.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.9",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
package/src/index.ts
CHANGED
|
@@ -131,6 +131,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
131
131
|
console.log('[my-plugins/dsh-oauth-login] loaded')
|
|
132
132
|
const native = {
|
|
133
133
|
enabled: config.nativeTools !== false,
|
|
134
|
+
codexSearch: config.codexSearch ?? 'cached',
|
|
134
135
|
image: config.nativeImage !== false,
|
|
135
136
|
}
|
|
136
137
|
const session = new PiLoginSession(new PiLoginCredentialStore(), native)
|
package/src/native-tools.ts
CHANGED
|
@@ -48,11 +48,14 @@ export interface NativeToolPolicy {
|
|
|
48
48
|
enabled: boolean
|
|
49
49
|
/** Also attach hosted image generation where the provider documents it. Default true. */
|
|
50
50
|
image: boolean
|
|
51
|
+
/** Codex search distinguishes cached content from live external access. */
|
|
52
|
+
codexSearch?: 'cached' | 'live' | 'off'
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
export const DEFAULT_NATIVE_TOOL_POLICY: NativeToolPolicy = {
|
|
54
56
|
enabled: true,
|
|
55
57
|
image: true,
|
|
58
|
+
codexSearch: 'cached',
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
export interface NativeToolPlan {
|
|
@@ -68,6 +71,9 @@ const SEARCH_GUIDANCE =
|
|
|
68
71
|
const SEARCH_AND_IMAGE_GUIDANCE =
|
|
69
72
|
'This turn already includes this account\'s native hosted search and image generation. Do not call web_search or web_fetch — those DSH tools are not available on this route.'
|
|
70
73
|
|
|
74
|
+
const CACHED_SEARCH_GUIDANCE =
|
|
75
|
+
'This turn includes native cached web search. Cached results may not reflect current pages. Do not call web_search or web_fetch as client functions — those DSH tools are not available on this route.'
|
|
76
|
+
|
|
71
77
|
function responsesSearch(): Record<string, unknown> {
|
|
72
78
|
return { type: 'web_search' }
|
|
73
79
|
}
|
|
@@ -103,14 +109,15 @@ export function nativePlan(
|
|
|
103
109
|
guidance: policy.image ? SEARCH_AND_IMAGE_GUIDANCE : SEARCH_GUIDANCE,
|
|
104
110
|
}
|
|
105
111
|
case 'openai-codex:openai-codex-responses':
|
|
112
|
+
if (policy.codexSearch === 'off') return undefined
|
|
106
113
|
return {
|
|
107
114
|
providerId,
|
|
108
115
|
api: 'openai-codex-responses',
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
],
|
|
113
|
-
guidance: policy.
|
|
116
|
+
// Codex is a distinct transport. Its official tool specification makes
|
|
117
|
+
// external access explicit; the generic Responses default is not a
|
|
118
|
+
// substitute. Hosted image generation is not part of this contract.
|
|
119
|
+
hosted: [{ type: 'web_search', external_web_access: policy.codexSearch === 'live' }],
|
|
120
|
+
guidance: policy.codexSearch === 'live' ? SEARCH_GUIDANCE : CACHED_SEARCH_GUIDANCE,
|
|
114
121
|
}
|
|
115
122
|
case 'anthropic:anthropic-messages':
|
|
116
123
|
return {
|
|
@@ -352,15 +359,14 @@ export function applyNativeToolsToPayload(
|
|
|
352
359
|
const plan = nativePlan(providerId, api, policy)
|
|
353
360
|
if (plan === undefined || !isRecord(payload) || !Array.isArray(payload.tools)) return payload
|
|
354
361
|
const current = payload.tools
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const hosted = plan.hosted.
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return true
|
|
362
|
+
const managed = new Set(plan.hosted.map(hostedToolKey))
|
|
363
|
+
const kept = current.filter(tool => !isDshWebFunctionTool(tool)
|
|
364
|
+
&& (!isRecord(tool) || !managed.has(hostedToolKey(tool)))
|
|
365
|
+
&& !(providerId === 'openai-codex' && isRecord(tool) && tool.type === 'image_generation'))
|
|
366
|
+
const hosted = plan.hosted.map(tool => {
|
|
367
|
+
const previous = current.find(candidate => isRecord(candidate) && hostedToolKey(candidate) === hostedToolKey(tool))
|
|
368
|
+
// Preserve caller filters, but explicit transport capability fields win.
|
|
369
|
+
return { ...(isRecord(previous) ? previous : {}), ...tool }
|
|
364
370
|
})
|
|
365
371
|
return { ...payload, tools: [...hosted, ...kept] }
|
|
366
372
|
}
|
|
@@ -381,8 +387,10 @@ export function wrapOnPayload(
|
|
|
381
387
|
? { ...payload, tools: [] }
|
|
382
388
|
: payload
|
|
383
389
|
const injected = applyNativeToolsToPayload(requestPayload, providerId, api, policy)
|
|
384
|
-
|
|
385
|
-
|
|
390
|
+
// Preserve the existing callback's observation contract, then revalidate
|
|
391
|
+
// the actual returned payload so it cannot restore an unsupported tool.
|
|
392
|
+
const customized = existing === undefined ? undefined : await existing(injected, model)
|
|
393
|
+
return applyNativeToolsToPayload(customized === undefined ? injected : customized, providerId, api, policy)
|
|
386
394
|
}
|
|
387
395
|
}
|
|
388
396
|
|
package/src/plugin-config.ts
CHANGED
|
@@ -18,8 +18,10 @@ export interface Config {
|
|
|
18
18
|
* search, and attach those hosted tools to the provider request.
|
|
19
19
|
*/
|
|
20
20
|
nativeTools?: boolean
|
|
21
|
-
/** Also attach hosted image generation on
|
|
21
|
+
/** Also attach hosted image generation on transports that support it (Grok). */
|
|
22
22
|
nativeImage?: boolean
|
|
23
|
+
/** Codex defaults to cached search; live external access is explicit. */
|
|
24
|
+
codexSearch?: 'cached' | 'live' | 'off'
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export const Config: z<Config> = z.object({
|
|
@@ -27,4 +29,5 @@ export const Config: z<Config> = z.object({
|
|
|
27
29
|
retryPolicy: RetryPolicySchema,
|
|
28
30
|
nativeTools: z.boolean().default(true),
|
|
29
31
|
nativeImage: z.boolean().default(true),
|
|
32
|
+
codexSearch: z.union(['cached', 'live', 'off']).default('cached'),
|
|
30
33
|
})
|