@ottocode/sdk 0.1.180 → 0.1.181
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/package.json +1 -1
- package/src/core/src/index.ts +2 -0
- package/src/core/src/tools/builtin/edit/replacers.ts +461 -0
- package/src/core/src/tools/builtin/edit.ts +166 -0
- package/src/core/src/tools/builtin/edit.txt +10 -0
- package/src/core/src/tools/builtin/multiedit.ts +190 -0
- package/src/core/src/tools/builtin/multiedit.txt +15 -0
- package/src/core/src/tools/builtin/patch/apply.ts +265 -30
- package/src/core/src/tools/builtin/patch/constants.ts +3 -0
- package/src/core/src/tools/builtin/patch/normalize.ts +173 -3
- package/src/core/src/tools/builtin/patch/parse-enveloped.ts +99 -3
- package/src/core/src/tools/builtin/patch/repair.ts +47 -0
- package/src/core/src/tools/builtin/patch.ts +3 -0
- package/src/core/src/tools/loader.ts +7 -0
- package/src/index.ts +2 -0
- package/src/prompts/src/agents/build.txt +190 -55
- package/src/prompts/src/base.txt +4 -5
- package/src/prompts/src/providers/anthropic.txt +19 -1
- package/src/prompts/src/providers/default.txt +31 -20
- package/src/prompts/src/providers/google.txt +33 -0
- package/src/prompts/src/providers/moonshot.txt +31 -19
- package/src/prompts/src/providers/openai.txt +21 -12
- package/src/providers/src/openai-oauth-client.ts +85 -30
|
@@ -3,35 +3,50 @@ import type { OAuth } from '../../types/src/index.ts';
|
|
|
3
3
|
import { refreshOpenAIToken } from '../../auth/src/openai-oauth.ts';
|
|
4
4
|
import { setAuth, getAuth } from '../../auth/src/index.ts';
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const CODEX_BASE_URL = 'https://chatgpt.com/backend-api/codex';
|
|
7
7
|
|
|
8
8
|
export type OpenAIOAuthConfig = {
|
|
9
9
|
oauth: OAuth;
|
|
10
10
|
projectRoot?: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
async function refreshAndPersist(
|
|
14
|
+
oauth: OAuth,
|
|
15
|
+
projectRoot?: string,
|
|
16
|
+
): Promise<OAuth> {
|
|
17
|
+
const newTokens = await refreshOpenAIToken(oauth.refresh);
|
|
18
|
+
const updated: OAuth = {
|
|
19
|
+
type: 'oauth',
|
|
20
|
+
access: newTokens.access,
|
|
21
|
+
refresh: newTokens.refresh,
|
|
22
|
+
expires: newTokens.expires,
|
|
23
|
+
accountId: oauth.accountId,
|
|
24
|
+
idToken: newTokens.idToken,
|
|
25
|
+
};
|
|
26
|
+
await setAuth('openai', updated, projectRoot, 'global');
|
|
27
|
+
return updated;
|
|
28
|
+
}
|
|
29
|
+
|
|
13
30
|
async function ensureValidToken(
|
|
14
31
|
oauth: OAuth,
|
|
15
32
|
projectRoot?: string,
|
|
16
|
-
): Promise<{ access: string; accountId?: string }> {
|
|
33
|
+
): Promise<{ oauth: OAuth; access: string; accountId?: string }> {
|
|
17
34
|
if (oauth.access && oauth.expires > Date.now()) {
|
|
18
|
-
return { access: oauth.access, accountId: oauth.accountId };
|
|
35
|
+
return { oauth, access: oauth.access, accountId: oauth.accountId };
|
|
19
36
|
}
|
|
20
37
|
|
|
21
38
|
try {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
access:
|
|
26
|
-
|
|
27
|
-
expires: newTokens.expires,
|
|
28
|
-
accountId: oauth.accountId,
|
|
29
|
-
idToken: newTokens.idToken,
|
|
39
|
+
const updated = await refreshAndPersist(oauth, projectRoot);
|
|
40
|
+
return {
|
|
41
|
+
oauth: updated,
|
|
42
|
+
access: updated.access,
|
|
43
|
+
accountId: updated.accountId,
|
|
30
44
|
};
|
|
31
|
-
await setAuth('openai', updatedOAuth, projectRoot, 'global');
|
|
32
|
-
return { access: newTokens.access, accountId: oauth.accountId };
|
|
33
45
|
} catch {
|
|
34
|
-
|
|
46
|
+
console.error(
|
|
47
|
+
'[openai-oauth] Token refresh failed, falling back to expired token',
|
|
48
|
+
);
|
|
49
|
+
return { oauth, access: oauth.access, accountId: oauth.accountId };
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
|
|
@@ -41,11 +56,27 @@ function rewriteUrl(url: string): string {
|
|
|
41
56
|
parsed.pathname.includes('/v1/responses') ||
|
|
42
57
|
parsed.pathname.includes('/chat/completions')
|
|
43
58
|
) {
|
|
44
|
-
return
|
|
59
|
+
return `${CODEX_BASE_URL}${parsed.pathname.replace(/^.*\/v1/, '/v1')}`;
|
|
45
60
|
}
|
|
46
61
|
return url;
|
|
47
62
|
}
|
|
48
63
|
|
|
64
|
+
function buildHeaders(
|
|
65
|
+
init: RequestInit | undefined,
|
|
66
|
+
accessToken: string,
|
|
67
|
+
accountId?: string,
|
|
68
|
+
): Headers {
|
|
69
|
+
const headers = new Headers(init?.headers);
|
|
70
|
+
headers.delete('Authorization');
|
|
71
|
+
headers.delete('authorization');
|
|
72
|
+
headers.set('authorization', `Bearer ${accessToken}`);
|
|
73
|
+
headers.set('originator', 'otto');
|
|
74
|
+
if (accountId) {
|
|
75
|
+
headers.set('ChatGPT-Account-Id', accountId);
|
|
76
|
+
}
|
|
77
|
+
return headers;
|
|
78
|
+
}
|
|
79
|
+
|
|
49
80
|
export function createOpenAIOAuthFetch(config: OpenAIOAuthConfig) {
|
|
50
81
|
let currentOAuth = config.oauth;
|
|
51
82
|
|
|
@@ -53,10 +84,8 @@ export function createOpenAIOAuthFetch(config: OpenAIOAuthConfig) {
|
|
|
53
84
|
input: Parameters<typeof fetch>[0],
|
|
54
85
|
init?: Parameters<typeof fetch>[1],
|
|
55
86
|
): Promise<Response> => {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
config.projectRoot,
|
|
59
|
-
);
|
|
87
|
+
const validated = await ensureValidToken(currentOAuth, config.projectRoot);
|
|
88
|
+
currentOAuth = validated.oauth;
|
|
60
89
|
|
|
61
90
|
const originalUrl =
|
|
62
91
|
typeof input === 'string'
|
|
@@ -66,24 +95,49 @@ export function createOpenAIOAuthFetch(config: OpenAIOAuthConfig) {
|
|
|
66
95
|
: input.url;
|
|
67
96
|
const targetUrl = rewriteUrl(originalUrl);
|
|
68
97
|
|
|
69
|
-
const headers =
|
|
70
|
-
headers.delete('Authorization');
|
|
71
|
-
headers.delete('authorization');
|
|
72
|
-
headers.set('authorization', `Bearer ${accessToken}`);
|
|
73
|
-
headers.set('originator', 'otto');
|
|
74
|
-
if (accountId) {
|
|
75
|
-
headers.set('ChatGPT-Account-Id', accountId);
|
|
76
|
-
}
|
|
98
|
+
const headers = buildHeaders(init, validated.access, validated.accountId);
|
|
77
99
|
|
|
78
100
|
const response = await fetch(targetUrl, {
|
|
79
101
|
...init,
|
|
80
102
|
headers,
|
|
103
|
+
// biome-ignore lint/suspicious/noTsIgnore: Bun-specific fetch option
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
timeout: false,
|
|
81
106
|
});
|
|
82
107
|
|
|
83
108
|
if (response.status === 401) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
109
|
+
try {
|
|
110
|
+
const refreshedFromDisk = await getAuth('openai', config.projectRoot);
|
|
111
|
+
if (
|
|
112
|
+
refreshedFromDisk?.type === 'oauth' &&
|
|
113
|
+
refreshedFromDisk.access !== validated.access
|
|
114
|
+
) {
|
|
115
|
+
currentOAuth = refreshedFromDisk;
|
|
116
|
+
} else {
|
|
117
|
+
currentOAuth = await refreshAndPersist(
|
|
118
|
+
currentOAuth,
|
|
119
|
+
config.projectRoot,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const retryHeaders = buildHeaders(
|
|
124
|
+
init,
|
|
125
|
+
currentOAuth.access,
|
|
126
|
+
currentOAuth.accountId,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return fetch(targetUrl, {
|
|
130
|
+
...init,
|
|
131
|
+
headers: retryHeaders,
|
|
132
|
+
// biome-ignore lint/suspicious/noTsIgnore: Bun-specific fetch option
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
timeout: false,
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
console.error(
|
|
138
|
+
'[openai-oauth] 401 retry failed, returning original 401 response',
|
|
139
|
+
);
|
|
140
|
+
return response;
|
|
87
141
|
}
|
|
88
142
|
}
|
|
89
143
|
|
|
@@ -101,6 +155,7 @@ export function createOpenAIOAuthModel(
|
|
|
101
155
|
|
|
102
156
|
const provider = createOpenAI({
|
|
103
157
|
apiKey: 'chatgpt-oauth',
|
|
158
|
+
baseURL: CODEX_BASE_URL,
|
|
104
159
|
fetch: customFetch,
|
|
105
160
|
});
|
|
106
161
|
|