@duckcodeailabs/dql-cli 1.6.29 → 1.6.31
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/dist/assets/dql-notebook/assets/{index-QJKCrLXe.js → index-BpPs6_rz.js} +176 -176
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/llm/providers/claude-agent-sdk.d.ts.map +1 -1
- package/dist/llm/providers/claude-agent-sdk.js +5 -3
- package/dist/llm/providers/claude-agent-sdk.js.map +1 -1
- package/dist/llm/providers/dql-agent-provider.d.ts.map +1 -1
- package/dist/llm/providers/dql-agent-provider.js +20 -6
- package/dist/llm/providers/dql-agent-provider.js.map +1 -1
- package/dist/llm/providers/native-sdk-provider.d.ts.map +1 -1
- package/dist/llm/providers/native-sdk-provider.js +7 -1
- package/dist/llm/providers/native-sdk-provider.js.map +1 -1
- package/dist/llm/types.d.ts +7 -1
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +113 -4
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +11 -11
- package/dist/providers/oauth/claude-oauth.d.ts +80 -0
- package/dist/providers/oauth/claude-oauth.d.ts.map +1 -0
- package/dist/providers/oauth/claude-oauth.js +352 -0
- package/dist/providers/oauth/claude-oauth.js.map +1 -0
- package/dist/providers/oauth/codex-oauth.d.ts +71 -0
- package/dist/providers/oauth/codex-oauth.d.ts.map +1 -0
- package/dist/providers/oauth/codex-oauth.js +410 -0
- package/dist/providers/oauth/codex-oauth.js.map +1 -0
- package/dist/providers/oauth/oauth-store.d.ts +31 -0
- package/dist/providers/oauth/oauth-store.d.ts.map +1 -0
- package/dist/providers/oauth/oauth-store.js +61 -0
- package/dist/providers/oauth/oauth-store.js.map +1 -0
- package/dist/settings/provider-settings.d.ts +17 -0
- package/dist/settings/provider-settings.d.ts.map +1 -1
- package/dist/settings/provider-settings.js +43 -9
- package/dist/settings/provider-settings.js.map +1 -1
- package/package.json +12 -12
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duckcodeailabs/dql-cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.31",
|
|
4
4
|
"description": "Public CLI for parsing, formatting, testing, and certifying DQL blocks",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@anthropic-ai/sdk": "^0.104.2",
|
|
28
|
-
"@duckcodeailabs/dql-agent": "^1.6.
|
|
29
|
-
"@duckcodeailabs/dql-compiler": "^1.6.
|
|
30
|
-
"@duckcodeailabs/dql-connectors": "^1.6.
|
|
31
|
-
"@duckcodeailabs/dql-core": "^1.6.
|
|
32
|
-
"@duckcodeailabs/dql-governance": "^1.6.
|
|
33
|
-
"@duckcodeailabs/dql-mcp": "^1.6.
|
|
34
|
-
"@duckcodeailabs/dql-notebook": "^1.6.
|
|
35
|
-
"@duckcodeailabs/dql-project": "^1.6.
|
|
36
|
-
"@duckcodeailabs/dql-slack": "^1.6.
|
|
28
|
+
"@duckcodeailabs/dql-agent": "^1.6.31",
|
|
29
|
+
"@duckcodeailabs/dql-compiler": "^1.6.31",
|
|
30
|
+
"@duckcodeailabs/dql-connectors": "^1.6.31",
|
|
31
|
+
"@duckcodeailabs/dql-core": "^1.6.31",
|
|
32
|
+
"@duckcodeailabs/dql-governance": "^1.6.31",
|
|
33
|
+
"@duckcodeailabs/dql-mcp": "^1.6.31",
|
|
34
|
+
"@duckcodeailabs/dql-notebook": "^1.6.31",
|
|
35
|
+
"@duckcodeailabs/dql-project": "^1.6.31",
|
|
36
|
+
"@duckcodeailabs/dql-slack": "^1.6.31",
|
|
37
37
|
"isomorphic-git": "^1.27.0",
|
|
38
38
|
"js-yaml": "^4.1.0",
|
|
39
39
|
"node-cron": "^3.0.3",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
"openai": "^6.44.0"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
|
-
"node": ">=20
|
|
44
|
+
"node": ">=20"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { AgentProvider, AgentMessage, ProviderRunOptions } from '@duckcodeailabs/dql-agent';
|
|
2
|
+
import { type ClaudeOAuthCredentials } from './oauth-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Claude Pro/Max subscription login via OAuth 2.0 + PKCE, and a provider that
|
|
5
|
+
* drives `api.anthropic.com` with the resulting bearer token (no API key).
|
|
6
|
+
*
|
|
7
|
+
* Ported from the reference coding-extension flow. Tokens are stored in the
|
|
8
|
+
* `chmod 600` `.dql/oauth-credentials.json` file rather than VSCode secrets.
|
|
9
|
+
*
|
|
10
|
+
* NOTE (governance / ToS): this reuses the official Claude Code OAuth client id
|
|
11
|
+
* to authenticate a user's *subscription*. It is subject to Anthropic's terms —
|
|
12
|
+
* the client id can be revoked and accounts can be rate-limited/flagged. The
|
|
13
|
+
* provider falls back to the CLI-passthrough path when not connected.
|
|
14
|
+
*/
|
|
15
|
+
export declare const CLAUDE_OAUTH_CONFIG: {
|
|
16
|
+
readonly authorizationEndpoint: "https://claude.ai/oauth/authorize";
|
|
17
|
+
readonly tokenEndpoint: "https://console.anthropic.com/v1/oauth/token";
|
|
18
|
+
readonly clientId: "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
19
|
+
readonly redirectUri: "http://localhost:54545/callback";
|
|
20
|
+
readonly scopes: "org:create_api_key user:profile user:inference";
|
|
21
|
+
readonly callbackPort: 54545;
|
|
22
|
+
};
|
|
23
|
+
/** Claude subscription models exposed after login (static list; default first). */
|
|
24
|
+
export declare const CLAUDE_OAUTH_MODELS: readonly ["claude-sonnet-4-5", "claude-opus-4-5", "claude-haiku-4-5"];
|
|
25
|
+
export declare const CLAUDE_OAUTH_DEFAULT_MODEL = "claude-sonnet-4-5";
|
|
26
|
+
export declare function generateCodeVerifier(): string;
|
|
27
|
+
export declare function generateCodeChallenge(verifier: string): string;
|
|
28
|
+
export declare function generateState(): string;
|
|
29
|
+
/** Claude Code identifies the caller with a synthetic `user_<hash>_account_<uuid>_session_<uuid>` id. */
|
|
30
|
+
export declare function generateUserId(email?: string): string;
|
|
31
|
+
export declare function buildAuthorizationUrl(codeChallenge: string, state: string): string;
|
|
32
|
+
export declare function exchangeCodeForTokens(code: string, codeVerifier: string, state: string): Promise<ClaudeOAuthCredentials>;
|
|
33
|
+
export declare function refreshAccessToken(credentials: ClaudeOAuthCredentials): Promise<ClaudeOAuthCredentials>;
|
|
34
|
+
export declare function isTokenExpired(credentials: ClaudeOAuthCredentials): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Project-scoped manager: owns the pending-auth state during a login and the
|
|
37
|
+
* lazy access-token refresh. File-backed, so the login flow (backend endpoints)
|
|
38
|
+
* and the provider (`generate`) see the same credentials.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ClaudeOAuthManager {
|
|
41
|
+
private readonly projectRoot;
|
|
42
|
+
private pendingAuth;
|
|
43
|
+
private refreshPromise;
|
|
44
|
+
constructor(projectRoot: string);
|
|
45
|
+
cancelAuthorizationFlow(): void;
|
|
46
|
+
/** True while a login is in flight (callback server listening). */
|
|
47
|
+
isPending(): boolean;
|
|
48
|
+
startAuthorizationFlow(): string;
|
|
49
|
+
/** Starts the loopback callback server on the fixed OAuth port and resolves when the browser returns. */
|
|
50
|
+
waitForCallback(): Promise<ClaudeOAuthCredentials>;
|
|
51
|
+
/** Returns a valid access token, refreshing (and persisting) if within the expiry buffer. */
|
|
52
|
+
getAccessToken(): Promise<string | null>;
|
|
53
|
+
getEmail(): string | null;
|
|
54
|
+
isAuthenticated(): Promise<boolean>;
|
|
55
|
+
signOut(): void;
|
|
56
|
+
}
|
|
57
|
+
/** True if a Claude subscription is connected (a credential exists on disk). */
|
|
58
|
+
export declare function claudeOAuthConnected(projectRoot: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* AgentProvider that drives Claude via the subscription OAuth token. Requires a
|
|
61
|
+
* prior `Sign in with Claude`. The "You are Claude Code…" system preamble and the
|
|
62
|
+
* `oauth-2025-04-20` beta header are required for the subscription API to accept
|
|
63
|
+
* the request.
|
|
64
|
+
*/
|
|
65
|
+
export declare class ClaudeOAuthProvider implements AgentProvider {
|
|
66
|
+
readonly name: "claude";
|
|
67
|
+
private readonly manager;
|
|
68
|
+
private readonly projectRoot;
|
|
69
|
+
private readonly defaultModel;
|
|
70
|
+
private readonly maxTokens;
|
|
71
|
+
private readonly cliModel?;
|
|
72
|
+
private cliFallback?;
|
|
73
|
+
constructor(opts: {
|
|
74
|
+
projectRoot: string;
|
|
75
|
+
model?: string;
|
|
76
|
+
});
|
|
77
|
+
available(): Promise<boolean>;
|
|
78
|
+
generate(messages: AgentMessage[], options?: ProviderRunOptions): Promise<string>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=claude-oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-oauth.d.ts","sourceRoot":"","sources":["../../../src/providers/oauth/claude-oauth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAG1B;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB;;;;;;;CAOtB,CAAC;AAEX,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,uEAAwE,CAAC;AACzG,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAE9D,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAWlF;AAiBD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0B9H;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkB7G;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,sBAAsB,GAAG,OAAO,CAG3E;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAIjB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAHxC,OAAO,CAAC,WAAW,CAA6G;IAChI,OAAO,CAAC,cAAc,CAAgD;gBAEzC,WAAW,EAAE,MAAM;IAEhD,uBAAuB,IAAI,IAAI;IAY/B,mEAAmE;IACnE,SAAS,IAAI,OAAO;IAIpB,sBAAsB,IAAI,MAAM;IAShC,yGAAyG;IACnG,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAyDxD,6FAA6F;IACvF,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiB9C,QAAQ,IAAI,MAAM,GAAG,IAAI;IAInB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC,OAAO,IAAI,IAAI;CAIhB;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEjE;AAoBD;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,WAAW,CAAC,CAAwB;gBAEhC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAQnD,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAI7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;CAgD5F"}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import * as http from 'node:http';
|
|
3
|
+
import { URL } from 'node:url';
|
|
4
|
+
import { getClaudeCredentials, setClaudeCredentials, clearOAuthProvider, } from './oauth-store.js';
|
|
5
|
+
import { ClaudeCodeCliProvider } from '../subscription-cli.js';
|
|
6
|
+
/**
|
|
7
|
+
* Claude Pro/Max subscription login via OAuth 2.0 + PKCE, and a provider that
|
|
8
|
+
* drives `api.anthropic.com` with the resulting bearer token (no API key).
|
|
9
|
+
*
|
|
10
|
+
* Ported from the reference coding-extension flow. Tokens are stored in the
|
|
11
|
+
* `chmod 600` `.dql/oauth-credentials.json` file rather than VSCode secrets.
|
|
12
|
+
*
|
|
13
|
+
* NOTE (governance / ToS): this reuses the official Claude Code OAuth client id
|
|
14
|
+
* to authenticate a user's *subscription*. It is subject to Anthropic's terms —
|
|
15
|
+
* the client id can be revoked and accounts can be rate-limited/flagged. The
|
|
16
|
+
* provider falls back to the CLI-passthrough path when not connected.
|
|
17
|
+
*/
|
|
18
|
+
export const CLAUDE_OAUTH_CONFIG = {
|
|
19
|
+
authorizationEndpoint: 'https://claude.ai/oauth/authorize',
|
|
20
|
+
tokenEndpoint: 'https://console.anthropic.com/v1/oauth/token',
|
|
21
|
+
clientId: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
|
|
22
|
+
redirectUri: 'http://localhost:54545/callback',
|
|
23
|
+
scopes: 'org:create_api_key user:profile user:inference',
|
|
24
|
+
callbackPort: 54545,
|
|
25
|
+
};
|
|
26
|
+
/** Claude subscription models exposed after login (static list; default first). */
|
|
27
|
+
export const CLAUDE_OAUTH_MODELS = ['claude-sonnet-4-5', 'claude-opus-4-5', 'claude-haiku-4-5'];
|
|
28
|
+
export const CLAUDE_OAUTH_DEFAULT_MODEL = 'claude-sonnet-4-5';
|
|
29
|
+
export function generateCodeVerifier() {
|
|
30
|
+
return crypto.randomBytes(32).toString('base64url');
|
|
31
|
+
}
|
|
32
|
+
export function generateCodeChallenge(verifier) {
|
|
33
|
+
return crypto.createHash('sha256').update(verifier).digest().toString('base64url');
|
|
34
|
+
}
|
|
35
|
+
export function generateState() {
|
|
36
|
+
return crypto.randomBytes(16).toString('hex');
|
|
37
|
+
}
|
|
38
|
+
/** Claude Code identifies the caller with a synthetic `user_<hash>_account_<uuid>_session_<uuid>` id. */
|
|
39
|
+
export function generateUserId(email) {
|
|
40
|
+
const userHash = email
|
|
41
|
+
? crypto.createHash('sha256').update(email).digest('hex').slice(0, 16)
|
|
42
|
+
: crypto.randomBytes(8).toString('hex');
|
|
43
|
+
const accountUuid = crypto.randomUUID().replace(/-/g, '');
|
|
44
|
+
const sessionUuid = crypto.randomUUID().replace(/-/g, '');
|
|
45
|
+
return `user_${userHash}_account_${accountUuid}_session_${sessionUuid}`;
|
|
46
|
+
}
|
|
47
|
+
export function buildAuthorizationUrl(codeChallenge, state) {
|
|
48
|
+
const params = new URLSearchParams({
|
|
49
|
+
client_id: CLAUDE_OAUTH_CONFIG.clientId,
|
|
50
|
+
redirect_uri: CLAUDE_OAUTH_CONFIG.redirectUri,
|
|
51
|
+
scope: CLAUDE_OAUTH_CONFIG.scopes,
|
|
52
|
+
code_challenge: codeChallenge,
|
|
53
|
+
code_challenge_method: 'S256',
|
|
54
|
+
response_type: 'code',
|
|
55
|
+
state,
|
|
56
|
+
});
|
|
57
|
+
return `${CLAUDE_OAUTH_CONFIG.authorizationEndpoint}?${params.toString()}`;
|
|
58
|
+
}
|
|
59
|
+
function parseTokenResponse(data) {
|
|
60
|
+
const d = data;
|
|
61
|
+
if (!d || typeof d.access_token !== 'string' || typeof d.expires_in !== 'number') {
|
|
62
|
+
throw new Error('Claude OAuth: malformed token response');
|
|
63
|
+
}
|
|
64
|
+
return { access_token: d.access_token, refresh_token: d.refresh_token, expires_in: d.expires_in, email: d.email };
|
|
65
|
+
}
|
|
66
|
+
export async function exchangeCodeForTokens(code, codeVerifier, state) {
|
|
67
|
+
const response = await fetch(CLAUDE_OAUTH_CONFIG.tokenEndpoint, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
code,
|
|
72
|
+
state,
|
|
73
|
+
grant_type: 'authorization_code',
|
|
74
|
+
client_id: CLAUDE_OAUTH_CONFIG.clientId,
|
|
75
|
+
redirect_uri: CLAUDE_OAUTH_CONFIG.redirectUri,
|
|
76
|
+
code_verifier: codeVerifier,
|
|
77
|
+
}),
|
|
78
|
+
signal: AbortSignal.timeout(30000),
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`Claude OAuth token exchange failed: ${response.status} ${await response.text().catch(() => response.statusText)}`);
|
|
82
|
+
}
|
|
83
|
+
const token = parseTokenResponse(await response.json());
|
|
84
|
+
if (!token.refresh_token)
|
|
85
|
+
throw new Error('Claude OAuth: token exchange did not return a refresh_token');
|
|
86
|
+
return {
|
|
87
|
+
type: 'claude',
|
|
88
|
+
access_token: token.access_token,
|
|
89
|
+
refresh_token: token.refresh_token,
|
|
90
|
+
expired: new Date(Date.now() + token.expires_in * 1000).toISOString(),
|
|
91
|
+
email: token.email,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export async function refreshAccessToken(credentials) {
|
|
95
|
+
const response = await fetch(CLAUDE_OAUTH_CONFIG.tokenEndpoint, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: { 'Content-Type': 'application/json' },
|
|
98
|
+
body: JSON.stringify({ grant_type: 'refresh_token', client_id: CLAUDE_OAUTH_CONFIG.clientId, refresh_token: credentials.refresh_token }),
|
|
99
|
+
signal: AbortSignal.timeout(30000),
|
|
100
|
+
});
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
throw new Error(`Claude OAuth token refresh failed: ${response.status} ${await response.text().catch(() => response.statusText)}`);
|
|
103
|
+
}
|
|
104
|
+
const token = parseTokenResponse(await response.json());
|
|
105
|
+
return {
|
|
106
|
+
type: 'claude',
|
|
107
|
+
access_token: token.access_token,
|
|
108
|
+
refresh_token: token.refresh_token ?? credentials.refresh_token,
|
|
109
|
+
expired: new Date(Date.now() + token.expires_in * 1000).toISOString(),
|
|
110
|
+
email: token.email ?? credentials.email,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export function isTokenExpired(credentials) {
|
|
114
|
+
const bufferMs = 5 * 60 * 1000;
|
|
115
|
+
return Date.now() >= new Date(credentials.expired).getTime() - bufferMs;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Project-scoped manager: owns the pending-auth state during a login and the
|
|
119
|
+
* lazy access-token refresh. File-backed, so the login flow (backend endpoints)
|
|
120
|
+
* and the provider (`generate`) see the same credentials.
|
|
121
|
+
*/
|
|
122
|
+
export class ClaudeOAuthManager {
|
|
123
|
+
projectRoot;
|
|
124
|
+
pendingAuth = null;
|
|
125
|
+
refreshPromise = null;
|
|
126
|
+
constructor(projectRoot) {
|
|
127
|
+
this.projectRoot = projectRoot;
|
|
128
|
+
}
|
|
129
|
+
cancelAuthorizationFlow() {
|
|
130
|
+
const prior = this.pendingAuth;
|
|
131
|
+
this.pendingAuth = null;
|
|
132
|
+
if (!prior)
|
|
133
|
+
return;
|
|
134
|
+
// Settle the in-flight callback promise so its port + closure are released
|
|
135
|
+
// deterministically (server.close() alone would leave the promise dangling).
|
|
136
|
+
if (prior.reject)
|
|
137
|
+
prior.reject(new Error('Authorization flow superseded'));
|
|
138
|
+
if (prior.server) {
|
|
139
|
+
try {
|
|
140
|
+
prior.server.close();
|
|
141
|
+
}
|
|
142
|
+
catch { /* noop */ }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** True while a login is in flight (callback server listening). */
|
|
146
|
+
isPending() {
|
|
147
|
+
return this.pendingAuth !== null;
|
|
148
|
+
}
|
|
149
|
+
startAuthorizationFlow() {
|
|
150
|
+
this.cancelAuthorizationFlow();
|
|
151
|
+
const codeVerifier = generateCodeVerifier();
|
|
152
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
153
|
+
const state = generateState();
|
|
154
|
+
this.pendingAuth = { codeVerifier, state };
|
|
155
|
+
return buildAuthorizationUrl(codeChallenge, state);
|
|
156
|
+
}
|
|
157
|
+
/** Starts the loopback callback server on the fixed OAuth port and resolves when the browser returns. */
|
|
158
|
+
async waitForCallback() {
|
|
159
|
+
if (!this.pendingAuth)
|
|
160
|
+
throw new Error('No pending authorization flow');
|
|
161
|
+
const pending = this.pendingAuth;
|
|
162
|
+
const { codeVerifier, state } = pending;
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
pending.reject = reject;
|
|
165
|
+
const server = http.createServer(async (req, res) => {
|
|
166
|
+
try {
|
|
167
|
+
const url = new URL(req.url || '', `http://localhost:${CLAUDE_OAUTH_CONFIG.callbackPort}`);
|
|
168
|
+
if (url.pathname !== '/callback') {
|
|
169
|
+
res.writeHead(404);
|
|
170
|
+
res.end('Not Found');
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const code = url.searchParams.get('code');
|
|
174
|
+
const receivedState = url.searchParams.get('state');
|
|
175
|
+
if (!code || !receivedState) {
|
|
176
|
+
res.writeHead(400);
|
|
177
|
+
res.end('Missing code or state');
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (receivedState !== state) {
|
|
181
|
+
res.writeHead(400);
|
|
182
|
+
res.end('Invalid state');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const credentials = await exchangeCodeForTokens(code, codeVerifier, receivedState);
|
|
186
|
+
setClaudeCredentials(this.projectRoot, credentials);
|
|
187
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
188
|
+
res.end('<html><body style="font-family:system-ui;padding:40px">Signed in to Claude. You can close this tab and return to DQL.</body></html>');
|
|
189
|
+
server.close();
|
|
190
|
+
this.pendingAuth = null;
|
|
191
|
+
resolve(credentials);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
try {
|
|
195
|
+
res.writeHead(500);
|
|
196
|
+
res.end('Authentication failed');
|
|
197
|
+
}
|
|
198
|
+
catch { /* noop */ }
|
|
199
|
+
try {
|
|
200
|
+
server.close();
|
|
201
|
+
}
|
|
202
|
+
catch { /* noop */ }
|
|
203
|
+
this.pendingAuth = null;
|
|
204
|
+
reject(error);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
pending.server = server;
|
|
208
|
+
const timeout = setTimeout(() => {
|
|
209
|
+
try {
|
|
210
|
+
server.close();
|
|
211
|
+
}
|
|
212
|
+
catch { /* noop */ }
|
|
213
|
+
if (this.pendingAuth === pending)
|
|
214
|
+
this.pendingAuth = null;
|
|
215
|
+
reject(new Error('Claude OAuth callback timed out'));
|
|
216
|
+
}, 5 * 60 * 1000);
|
|
217
|
+
server.on('close', () => clearTimeout(timeout));
|
|
218
|
+
server.on('error', (err) => {
|
|
219
|
+
clearTimeout(timeout);
|
|
220
|
+
if (this.pendingAuth === pending)
|
|
221
|
+
this.pendingAuth = null;
|
|
222
|
+
reject(err);
|
|
223
|
+
});
|
|
224
|
+
server.listen(CLAUDE_OAUTH_CONFIG.callbackPort);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/** Returns a valid access token, refreshing (and persisting) if within the expiry buffer. */
|
|
228
|
+
async getAccessToken() {
|
|
229
|
+
let creds = getClaudeCredentials(this.projectRoot);
|
|
230
|
+
if (!creds)
|
|
231
|
+
return null;
|
|
232
|
+
if (isTokenExpired(creds)) {
|
|
233
|
+
try {
|
|
234
|
+
if (!this.refreshPromise)
|
|
235
|
+
this.refreshPromise = refreshAccessToken(creds);
|
|
236
|
+
creds = await this.refreshPromise;
|
|
237
|
+
this.refreshPromise = null;
|
|
238
|
+
setClaudeCredentials(this.projectRoot, creds);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
this.refreshPromise = null;
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return creds.access_token;
|
|
246
|
+
}
|
|
247
|
+
getEmail() {
|
|
248
|
+
return getClaudeCredentials(this.projectRoot)?.email ?? null;
|
|
249
|
+
}
|
|
250
|
+
async isAuthenticated() {
|
|
251
|
+
return (await this.getAccessToken()) !== null;
|
|
252
|
+
}
|
|
253
|
+
signOut() {
|
|
254
|
+
this.cancelAuthorizationFlow();
|
|
255
|
+
clearOAuthProvider(this.projectRoot, 'claude');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/** True if a Claude subscription is connected (a credential exists on disk). */
|
|
259
|
+
export function claudeOAuthConnected(projectRoot) {
|
|
260
|
+
return getClaudeCredentials(projectRoot) !== null;
|
|
261
|
+
}
|
|
262
|
+
const ANTHROPIC_OAUTH_BETAS = [
|
|
263
|
+
'prompt-caching-2024-07-31',
|
|
264
|
+
'claude-code-20250219',
|
|
265
|
+
'oauth-2025-04-20',
|
|
266
|
+
'interleaved-thinking-2025-05-14',
|
|
267
|
+
'fine-grained-tool-streaming-2025-05-14',
|
|
268
|
+
].join(',');
|
|
269
|
+
/** effort → extended-thinking token budget (matches the reference flow). */
|
|
270
|
+
function thinkingFor(effort, maxTokens) {
|
|
271
|
+
const budget = effort === 'high' ? 20000 : effort === 'medium' ? 8192 : effort === 'low' ? 2048 : 0;
|
|
272
|
+
if (budget <= 0)
|
|
273
|
+
return { type: 'disabled' };
|
|
274
|
+
const clamped = Math.min(budget, Math.floor(maxTokens * 0.8));
|
|
275
|
+
// Anthropic requires budget_tokens >= 1024; if the output cap leaves no room, skip thinking.
|
|
276
|
+
if (clamped < 1024)
|
|
277
|
+
return { type: 'disabled' };
|
|
278
|
+
return { type: 'enabled', budget_tokens: clamped };
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* AgentProvider that drives Claude via the subscription OAuth token. Requires a
|
|
282
|
+
* prior `Sign in with Claude`. The "You are Claude Code…" system preamble and the
|
|
283
|
+
* `oauth-2025-04-20` beta header are required for the subscription API to accept
|
|
284
|
+
* the request.
|
|
285
|
+
*/
|
|
286
|
+
export class ClaudeOAuthProvider {
|
|
287
|
+
name = 'claude';
|
|
288
|
+
manager;
|
|
289
|
+
projectRoot;
|
|
290
|
+
defaultModel;
|
|
291
|
+
maxTokens;
|
|
292
|
+
cliModel;
|
|
293
|
+
cliFallback;
|
|
294
|
+
constructor(opts) {
|
|
295
|
+
this.manager = new ClaudeOAuthManager(opts.projectRoot);
|
|
296
|
+
this.projectRoot = opts.projectRoot;
|
|
297
|
+
this.defaultModel = opts.model || CLAUDE_OAUTH_DEFAULT_MODEL;
|
|
298
|
+
this.cliModel = opts.model;
|
|
299
|
+
this.maxTokens = 32768;
|
|
300
|
+
}
|
|
301
|
+
async available() {
|
|
302
|
+
return this.manager.isAuthenticated();
|
|
303
|
+
}
|
|
304
|
+
async generate(messages, options = {}) {
|
|
305
|
+
const accessToken = await this.manager.getAccessToken();
|
|
306
|
+
if (!accessToken) {
|
|
307
|
+
// A credential exists but is unusable (expired + refresh failed, or revoked):
|
|
308
|
+
// honor the OAuth-first, CLI-fallback contract. With no credential at all,
|
|
309
|
+
// prompt to sign in.
|
|
310
|
+
if (claudeOAuthConnected(this.projectRoot)) {
|
|
311
|
+
if (!this.cliFallback)
|
|
312
|
+
this.cliFallback = new ClaudeCodeCliProvider({ model: this.cliModel });
|
|
313
|
+
if (await this.cliFallback.available()) {
|
|
314
|
+
return this.cliFallback.generate(messages, options);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
throw new Error('Your Claude subscription session expired. Open Settings → Claude subscription and click "Sign in with Claude" again.');
|
|
318
|
+
}
|
|
319
|
+
const systemText = messages.filter((m) => m.role === 'system').map((m) => m.content).join('\n\n');
|
|
320
|
+
const turns = messages.filter((m) => m.role !== 'system').map((m) => ({ role: m.role, content: m.content }));
|
|
321
|
+
const userId = generateUserId(this.manager.getEmail() || undefined);
|
|
322
|
+
const maxTokens = options.maxTokens ?? this.maxTokens;
|
|
323
|
+
const body = {
|
|
324
|
+
model: options.model || this.defaultModel,
|
|
325
|
+
max_tokens: maxTokens,
|
|
326
|
+
system: [
|
|
327
|
+
{ type: 'text', text: "You are Claude Code, Anthropic's official CLI for Claude." },
|
|
328
|
+
...(systemText ? [{ type: 'text', text: systemText }] : []),
|
|
329
|
+
],
|
|
330
|
+
messages: turns,
|
|
331
|
+
thinking: thinkingFor(options.reasoningEffort, maxTokens),
|
|
332
|
+
metadata: { user_id: userId },
|
|
333
|
+
};
|
|
334
|
+
const res = await fetch('https://api.anthropic.com/v1/messages', {
|
|
335
|
+
method: 'POST',
|
|
336
|
+
headers: {
|
|
337
|
+
Authorization: `Bearer ${accessToken}`,
|
|
338
|
+
'Content-Type': 'application/json',
|
|
339
|
+
'Anthropic-Version': '2023-06-01',
|
|
340
|
+
'Anthropic-Beta': ANTHROPIC_OAUTH_BETAS,
|
|
341
|
+
},
|
|
342
|
+
body: JSON.stringify(body),
|
|
343
|
+
signal: options.signal,
|
|
344
|
+
});
|
|
345
|
+
if (!res.ok) {
|
|
346
|
+
throw new Error(`claude (subscription): ${res.status} ${await res.text().catch(() => res.statusText)}`);
|
|
347
|
+
}
|
|
348
|
+
const json = (await res.json());
|
|
349
|
+
return (json.content ?? []).filter((b) => b.type === 'text').map((b) => b.text ?? '').join('');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=claude-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-oauth.js","sourceRoot":"","sources":["../../../src/providers/oauth/claude-oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { AgentProvider, AgentMessage, ProviderRunOptions } from '@duckcodeailabs/dql-agent';
|
|
2
|
+
import { type CodexOAuthCredentials } from './oauth-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* ChatGPT Plus/Pro subscription login via OpenAI OAuth 2.0 + PKCE, and a provider
|
|
5
|
+
* that drives the ChatGPT Codex backend with the resulting bearer token.
|
|
6
|
+
*
|
|
7
|
+
* Ported from the reference coding-extension flow. Tokens live in the `chmod 600`
|
|
8
|
+
* `.dql/oauth-credentials.json` file. Same ToS caveat as the Claude flow: this
|
|
9
|
+
* reuses the official Codex OAuth client id against a subscription; the provider
|
|
10
|
+
* falls back to the CLI-passthrough path when not connected.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CODEX_OAUTH_CONFIG: {
|
|
13
|
+
readonly authorizationEndpoint: "https://auth.openai.com/oauth/authorize";
|
|
14
|
+
readonly tokenEndpoint: "https://auth.openai.com/oauth/token";
|
|
15
|
+
readonly clientId: "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
16
|
+
readonly redirectUri: "http://localhost:1455/auth/callback";
|
|
17
|
+
readonly scopes: "openid profile email offline_access";
|
|
18
|
+
readonly callbackPort: 1455;
|
|
19
|
+
};
|
|
20
|
+
/** ChatGPT subscription models exposed after login (static list; default first). */
|
|
21
|
+
export declare const CODEX_OAUTH_MODELS: readonly ["gpt-5.2-codex", "gpt-5.1-codex", "gpt-5-codex", "gpt-5-codex-mini"];
|
|
22
|
+
export declare const CODEX_OAUTH_DEFAULT_MODEL = "gpt-5.2-codex";
|
|
23
|
+
export declare function generateCodeVerifier(): string;
|
|
24
|
+
export declare function generateCodeChallenge(verifier: string): string;
|
|
25
|
+
export declare function generateState(): string;
|
|
26
|
+
export declare function buildAuthorizationUrl(codeChallenge: string, state: string): string;
|
|
27
|
+
export declare function extractAccountId(tokens: {
|
|
28
|
+
id_token?: string;
|
|
29
|
+
access_token: string;
|
|
30
|
+
}): string | undefined;
|
|
31
|
+
export declare function exchangeCodeForTokens(code: string, codeVerifier: string): Promise<CodexOAuthCredentials>;
|
|
32
|
+
export declare function refreshAccessToken(credentials: CodexOAuthCredentials): Promise<CodexOAuthCredentials>;
|
|
33
|
+
export declare function isTokenExpired(credentials: CodexOAuthCredentials): boolean;
|
|
34
|
+
export declare class CodexOAuthManager {
|
|
35
|
+
private readonly projectRoot;
|
|
36
|
+
private pendingAuth;
|
|
37
|
+
private refreshPromise;
|
|
38
|
+
constructor(projectRoot: string);
|
|
39
|
+
cancelAuthorizationFlow(): void;
|
|
40
|
+
/** True while a login is in flight (callback server listening). */
|
|
41
|
+
isPending(): boolean;
|
|
42
|
+
startAuthorizationFlow(): string;
|
|
43
|
+
waitForCallback(): Promise<CodexOAuthCredentials>;
|
|
44
|
+
getAccessToken(): Promise<string | null>;
|
|
45
|
+
getAccountId(): string | null;
|
|
46
|
+
getEmail(): string | null;
|
|
47
|
+
isAuthenticated(): Promise<boolean>;
|
|
48
|
+
signOut(): void;
|
|
49
|
+
}
|
|
50
|
+
export declare function codexOAuthConnected(projectRoot: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* AgentProvider that drives ChatGPT Codex via the subscription OAuth token.
|
|
53
|
+
* Streams the Responses SSE and accumulates visible text (reasoning deltas are
|
|
54
|
+
* dropped from the returned string). Requires a prior `Sign in with ChatGPT`.
|
|
55
|
+
*/
|
|
56
|
+
export declare class CodexOAuthProvider implements AgentProvider {
|
|
57
|
+
readonly name: "openai";
|
|
58
|
+
private readonly manager;
|
|
59
|
+
private readonly projectRoot;
|
|
60
|
+
private readonly defaultModel;
|
|
61
|
+
private readonly cliModel?;
|
|
62
|
+
private readonly sessionId;
|
|
63
|
+
private cliFallback?;
|
|
64
|
+
constructor(opts: {
|
|
65
|
+
projectRoot: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
});
|
|
68
|
+
available(): Promise<boolean>;
|
|
69
|
+
generate(messages: AgentMessage[], options?: ProviderRunOptions): Promise<string>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=codex-oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-oauth.d.ts","sourceRoot":"","sources":["../../../src/providers/oauth/codex-oauth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,kBAAkB,CAAC;AAG1B;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;;;;;;;CAOrB,CAAC;AAIX,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,gFAAiF,CAAC;AACjH,eAAO,MAAM,yBAAyB,kBAAkB,CAAC;AAEzD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAalF;AA2BD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAQxG;AAkBD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2B9G;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwB3G;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAG1E;AAED,qBAAa,iBAAiB;IAIhB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAHxC,OAAO,CAAC,WAAW,CAA6G;IAChI,OAAO,CAAC,cAAc,CAA+C;gBAExC,WAAW,EAAE,MAAM;IAEhD,uBAAuB,IAAI,IAAI;IAW/B,mEAAmE;IACnE,SAAS,IAAI,OAAO;IAIpB,sBAAsB,IAAI,MAAM;IAS1B,eAAe,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAyDjD,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiB9C,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,QAAQ,IAAI,MAAM,GAAG,IAAI;IAInB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC,OAAO,IAAI,IAAI;CAIhB;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEhE;AA+BD;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,WAAW,CAAC,CAAmB;gBAE3B,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAQnD,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAI7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;CAsE5F"}
|