dsh-codex-share 0.1.0
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/LICENSE +21 -0
- package/README.md +39 -0
- package/cordis.patch.yml +2 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.mjs +95 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# dsh-codex-share
|
|
2
|
+
|
|
3
|
+
A DeepSeek Harness LLM adapter that uses the same ChatGPT subscription login as the local Codex CLI. It reads Codex's current `auth.json` for each model call. Codex CLI owns sign-in and token refresh; this package has no OAuth flow and stores no credential. Calls go to the Codex subscription backend through pi-ai's Codex Responses implementation, not the OpenAI Platform API endpoint.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- DeepSeek Harness `0.1.5-rc.3` or a compatible later release, with Node.js `^22.19.0 || >=24`.
|
|
8
|
+
- Codex CLI signed in with a ChatGPT account and configured for **file credential storage**. Run `codex login` and check `codex login status`. Codex must be able to read and update `$CODEX_HOME/auth.json` (default `~/.codex/auth.json`).
|
|
9
|
+
- The harness process must run as the same OS user, or have read access to that same credential file. A keyring-only Codex login is not supported.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
Once published, install the bundle into a harness profile:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-codex-share
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
For this checkout before publication, from its directory:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Restart the profile after installation. The bundle mounts one provider route, `openai-codex`, with the model catalog supplied by pi-ai. Select that provider and a listed model in the harness model settings or agent preset. For a local Codex home outside the default location, set the absolute `CODEX_HOME` path in the environment that launches the harness. Direct Cordis composition can configure `codexHome` on the `dsh-codex-share` plugin instead.
|
|
26
|
+
|
|
27
|
+
The plugin intentionally does not refresh a stale token. When Codex writes a replacement, the next harness request reads it. When Codex's current access token has expired, harness calls fail until Codex refreshes its own login. An API-key-only Codex login is rejected; this route never falls back to `OPENAI_API_KEY`.
|
|
28
|
+
|
|
29
|
+
## Development
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
pnpm install --ignore-scripts
|
|
33
|
+
pnpm typecheck
|
|
34
|
+
pnpm test
|
|
35
|
+
pnpm build
|
|
36
|
+
pnpm pack
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The development links in `package.json` point to the adjacent `../deepseek-harness` checkout. Replace those dev links when developing elsewhere; they are not installed by consumers of the published package.
|
package/cordis.patch.yml
ADDED
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
//#region src/auth.d.ts
|
|
3
|
+
/** Resolve Codex's current auth.json path without retaining a token. */
|
|
4
|
+
declare function codexAuthPath(codexHome?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Read a ChatGPT bearer token for one request. Codex owns login and refresh;
|
|
7
|
+
* this plugin never persists or refreshes credentials. A later request sees
|
|
8
|
+
* any replacement written by Codex CLI.
|
|
9
|
+
*/
|
|
10
|
+
declare function readCodexAccessToken(codexHome?: string): Promise<string>;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/index.d.ts
|
|
13
|
+
/** Harness route for subscription-backed Codex models. */
|
|
14
|
+
declare const PROVIDER = "openai-codex";
|
|
15
|
+
declare const name = "llm-codex-share";
|
|
16
|
+
declare const inject: string[];
|
|
17
|
+
/** Plugin configuration. Omit codexHome to follow CODEX_HOME or ~/.codex. */
|
|
18
|
+
interface Config {
|
|
19
|
+
codexHome?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Register the Codex subscription model catalog and stream adapter. */
|
|
22
|
+
declare function apply(ctx: Context, config?: Config): void;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { Config, PROVIDER, apply, codexAuthPath, inject, name, readCodexAccessToken };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { LlmError, resolveImageAttachmentAccess } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
3
|
+
import { envApiKeyAuth } from "@earendil-works/pi-ai";
|
|
4
|
+
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { isAbsolute, join } from "node:path";
|
|
8
|
+
//#region src/auth.ts
|
|
9
|
+
/** Read the exact ChatGPT access token currently stored by Codex CLI. */
|
|
10
|
+
/** Resolve Codex's current auth.json path without retaining a token. */
|
|
11
|
+
function codexAuthPath(codexHome) {
|
|
12
|
+
const home = codexHome ?? process.env.CODEX_HOME ?? join(homedir(), ".codex");
|
|
13
|
+
if (!isAbsolute(home)) throw new LlmError("codexHome/CODEX_HOME must be an absolute path", "INVALID_CONFIG");
|
|
14
|
+
return join(home, "auth.json");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read a ChatGPT bearer token for one request. Codex owns login and refresh;
|
|
18
|
+
* this plugin never persists or refreshes credentials. A later request sees
|
|
19
|
+
* any replacement written by Codex CLI.
|
|
20
|
+
*/
|
|
21
|
+
async function readCodexAccessToken(codexHome) {
|
|
22
|
+
const path = codexAuthPath(codexHome);
|
|
23
|
+
let raw;
|
|
24
|
+
try {
|
|
25
|
+
raw = await readFile(path, "utf8");
|
|
26
|
+
} catch {
|
|
27
|
+
throw new LlmError(`No readable Codex login at ${path}; run codex login and use file credential storage`, "MISSING_CREDENTIAL");
|
|
28
|
+
}
|
|
29
|
+
let auth;
|
|
30
|
+
try {
|
|
31
|
+
auth = JSON.parse(raw);
|
|
32
|
+
} catch {
|
|
33
|
+
throw new LlmError(`Codex login at ${path} is not valid JSON`, "INVALID_CREDENTIAL");
|
|
34
|
+
}
|
|
35
|
+
if (auth === null || auth.auth_mode !== void 0 && auth.auth_mode !== "chatgpt" || typeof auth.OPENAI_API_KEY === "string" && auth.OPENAI_API_KEY.length > 0 || typeof auth.tokens?.access_token !== "string" || auth.tokens.access_token.length === 0) throw new LlmError(`Codex login at ${path} has no ChatGPT access token; run codex login with ChatGPT`, "MISSING_CREDENTIAL");
|
|
36
|
+
return auth.tokens.access_token;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/index.ts
|
|
40
|
+
/** Harness route for subscription-backed Codex models. */
|
|
41
|
+
const PROVIDER = "openai-codex";
|
|
42
|
+
const name = "llm-codex-share";
|
|
43
|
+
const inject = ["llm"];
|
|
44
|
+
/** Register the Codex subscription model catalog and stream adapter. */
|
|
45
|
+
function apply(ctx, config = {}) {
|
|
46
|
+
const provider = {
|
|
47
|
+
...openaiCodexProvider(),
|
|
48
|
+
auth: { apiKey: envApiKeyAuth("Codex CLI login", []) }
|
|
49
|
+
};
|
|
50
|
+
const profiles = /* @__PURE__ */ new Map([[PROVIDER, {
|
|
51
|
+
provider: PROVIDER,
|
|
52
|
+
displayName: "OpenAI Codex (local login)",
|
|
53
|
+
piProvider: provider,
|
|
54
|
+
modelErrors: /* @__PURE__ */ new Map(),
|
|
55
|
+
configuredMaxTokens: /* @__PURE__ */ new Map(),
|
|
56
|
+
streamIdleTimeoutMs: 12e4,
|
|
57
|
+
maxRequestImageBytes: 20971520,
|
|
58
|
+
requestImagePixelBudget: 4194304,
|
|
59
|
+
requestImageMaxBytes: 1048576,
|
|
60
|
+
transport: "sse",
|
|
61
|
+
retryPolicy: {
|
|
62
|
+
mode: "normal",
|
|
63
|
+
maxRetries: 0,
|
|
64
|
+
retryableCodes: [],
|
|
65
|
+
initialDelayMs: 0,
|
|
66
|
+
maxDelayMs: 0,
|
|
67
|
+
jitterRatio: 0
|
|
68
|
+
}
|
|
69
|
+
}]]);
|
|
70
|
+
const adapter = new PiAiAdapter({
|
|
71
|
+
profiles: () => profiles,
|
|
72
|
+
resolveApiKey: async () => readCodexAccessToken(config.codexHome),
|
|
73
|
+
resolveAttachments: () => ctx.get("attachments"),
|
|
74
|
+
resolveImageAccess: (attachments, ref) => resolveImageAttachmentAccess(attachments, (hostPath) => ctx.get("fs")?.processPathFromHostPath(hostPath), ref),
|
|
75
|
+
auth: {
|
|
76
|
+
credentials: {
|
|
77
|
+
read: async () => void 0,
|
|
78
|
+
list: async () => [],
|
|
79
|
+
modify: async () => {
|
|
80
|
+
throw new LlmError("Codex credentials are owned by Codex CLI", "UNSUPPORTED_OPERATION");
|
|
81
|
+
},
|
|
82
|
+
delete: async () => {
|
|
83
|
+
throw new LlmError("Codex credentials are owned by Codex CLI", "UNSUPPORTED_OPERATION");
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
authContext: {
|
|
87
|
+
env: async () => void 0,
|
|
88
|
+
fileExists: async () => false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
ctx.llm.registerAdapter([PROVIDER], adapter);
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { PROVIDER, apply, codexAuthPath, inject, name, readCodexAccessToken };
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-codex-share",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Use the local Codex CLI ChatGPT subscription login as a DeepSeek Harness LLM provider",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"cordis.patch.yml",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
25
|
+
},
|
|
26
|
+
"packageManager": "pnpm@11.7.0",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsdown src/index.ts --dts --platform node --format esm",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"prepack": "pnpm build"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
35
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.3",
|
|
36
|
+
"@deepseek-ai/dsh-attachment": "^0.1.5-rc.3",
|
|
37
|
+
"@deepseek-ai/dsh-fs": "^0.1.5-rc.3",
|
|
38
|
+
"@deepseek-ai/dsh-llm-pi-ai": "^0.1.5-rc.3"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@earendil-works/pi-ai": "^0.85.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@deepseek-ai/cordis": "link:../deepseek-harness/vendor/cordis",
|
|
45
|
+
"@deepseek-ai/dsh-llm": "link:../deepseek-harness/packages/llm/llm",
|
|
46
|
+
"@deepseek-ai/dsh-attachment": "link:../deepseek-harness/packages/attachment/attachment",
|
|
47
|
+
"@deepseek-ai/dsh-fs": "link:../deepseek-harness/packages/fs/fs",
|
|
48
|
+
"@deepseek-ai/dsh-llm-pi-ai": "link:../deepseek-harness/packages/llm/llm-pi-ai",
|
|
49
|
+
"@types/node": "^22.20.0",
|
|
50
|
+
"tsdown": "^0.22.2",
|
|
51
|
+
"typescript": "^6.0.3",
|
|
52
|
+
"vitest": "^4.1.8"
|
|
53
|
+
},
|
|
54
|
+
"dsh": {
|
|
55
|
+
"bundle": {
|
|
56
|
+
"patch": "./cordis.patch.yml"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|