@wingman-ai/gateway 0.2.2 → 0.2.3
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/.wingman/agents/coding/agent.md +174 -169
- package/.wingman/agents/coding/implementor.md +25 -1
- package/.wingman/agents/main/agent.md +4 -0
- package/README.md +1 -0
- package/dist/agent/config/agentConfig.cjs +1 -1
- package/dist/agent/config/agentConfig.js +1 -1
- package/dist/agent/config/modelFactory.cjs +22 -2
- package/dist/agent/config/modelFactory.d.ts +2 -0
- package/dist/agent/config/modelFactory.js +22 -2
- package/dist/agent/tests/modelFactory.test.cjs +12 -5
- package/dist/agent/tests/modelFactory.test.js +12 -5
- package/dist/cli/commands/init.cjs +7 -6
- package/dist/cli/commands/init.js +7 -6
- package/dist/cli/commands/provider.cjs +17 -3
- package/dist/cli/commands/provider.js +17 -3
- package/dist/cli/config/loader.cjs +27 -0
- package/dist/cli/config/loader.js +27 -0
- package/dist/cli/config/schema.cjs +80 -2
- package/dist/cli/config/schema.d.ts +88 -0
- package/dist/cli/config/schema.js +67 -1
- package/dist/cli/core/agentInvoker.cjs +191 -13
- package/dist/cli/core/agentInvoker.d.ts +42 -3
- package/dist/cli/core/agentInvoker.js +163 -9
- package/dist/cli/core/sessionManager.cjs +32 -5
- package/dist/cli/core/sessionManager.js +32 -5
- package/dist/cli/index.cjs +6 -5
- package/dist/cli/index.js +6 -5
- package/dist/cli/types.d.ts +32 -0
- package/dist/gateway/http/sessions.cjs +7 -7
- package/dist/gateway/http/sessions.js +7 -7
- package/dist/gateway/server.cjs +191 -41
- package/dist/gateway/server.d.ts +8 -1
- package/dist/gateway/server.js +191 -41
- package/dist/gateway/types.d.ts +1 -0
- package/dist/providers/codex.cjs +167 -0
- package/dist/providers/codex.d.ts +15 -0
- package/dist/providers/codex.js +127 -0
- package/dist/providers/credentials.cjs +8 -0
- package/dist/providers/credentials.js +8 -0
- package/dist/providers/registry.cjs +11 -0
- package/dist/providers/registry.d.ts +1 -1
- package/dist/providers/registry.js +11 -0
- package/dist/tests/agentInvokerSummarization.test.cjs +296 -0
- package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
- package/dist/tests/agentInvokerSummarization.test.js +290 -0
- package/dist/tests/cli-config-loader.test.cjs +88 -0
- package/dist/tests/cli-config-loader.test.js +88 -0
- package/dist/tests/codex-credentials-precedence.test.cjs +94 -0
- package/dist/tests/codex-credentials-precedence.test.d.ts +1 -0
- package/dist/tests/codex-credentials-precedence.test.js +88 -0
- package/dist/tests/codex-provider.test.cjs +186 -0
- package/dist/tests/codex-provider.test.d.ts +1 -0
- package/dist/tests/codex-provider.test.js +180 -0
- package/dist/tests/gateway.test.cjs +108 -1
- package/dist/tests/gateway.test.js +108 -1
- package/dist/tests/provider-command-codex.test.cjs +57 -0
- package/dist/tests/provider-command-codex.test.d.ts +1 -0
- package/dist/tests/provider-command-codex.test.js +51 -0
- package/dist/tests/sessionStateMessages.test.cjs +38 -0
- package/dist/tests/sessionStateMessages.test.js +38 -0
- package/dist/webui/assets/{index-DDsMIOTX.css → index-BVMavpud.css} +1 -1
- package/dist/webui/assets/index-DCB2aVVf.js +182 -0
- package/dist/webui/index.html +2 -2
- package/package.json +1 -1
- package/dist/webui/assets/index-CPhfGPHc.js +0 -182
|
@@ -33,6 +33,33 @@ const external_os_namespaceObject = require("os");
|
|
|
33
33
|
(0, external_vitest_namespaceObject.expect)(config).toEqual({
|
|
34
34
|
logLevel: "info",
|
|
35
35
|
recursionLimit: 5000,
|
|
36
|
+
summarization: {
|
|
37
|
+
enabled: true,
|
|
38
|
+
maxTokensBeforeSummary: 12000,
|
|
39
|
+
messagesToKeep: 8
|
|
40
|
+
},
|
|
41
|
+
modelRetry: {
|
|
42
|
+
enabled: true,
|
|
43
|
+
maxRetries: 2,
|
|
44
|
+
backoffFactor: 2,
|
|
45
|
+
initialDelayMs: 1000,
|
|
46
|
+
maxDelayMs: 60000,
|
|
47
|
+
jitter: true,
|
|
48
|
+
onFailure: "continue"
|
|
49
|
+
},
|
|
50
|
+
toolRetry: {
|
|
51
|
+
enabled: false,
|
|
52
|
+
maxRetries: 2,
|
|
53
|
+
backoffFactor: 2,
|
|
54
|
+
initialDelayMs: 1000,
|
|
55
|
+
maxDelayMs: 60000,
|
|
56
|
+
jitter: true,
|
|
57
|
+
onFailure: "continue"
|
|
58
|
+
},
|
|
59
|
+
humanInTheLoop: {
|
|
60
|
+
enabled: false,
|
|
61
|
+
interruptOn: {}
|
|
62
|
+
},
|
|
36
63
|
search: {
|
|
37
64
|
provider: "duckduckgo",
|
|
38
65
|
maxResults: 5
|
|
@@ -111,6 +138,11 @@ const external_os_namespaceObject = require("os");
|
|
|
111
138
|
logLevel: "debug",
|
|
112
139
|
defaultAgent: "coder",
|
|
113
140
|
recursionLimit: 5,
|
|
141
|
+
summarization: {
|
|
142
|
+
enabled: true,
|
|
143
|
+
maxTokensBeforeSummary: 18000,
|
|
144
|
+
messagesToKeep: 10
|
|
145
|
+
},
|
|
114
146
|
search: {
|
|
115
147
|
provider: "perplexity",
|
|
116
148
|
maxResults: 10
|
|
@@ -130,6 +162,62 @@ const external_os_namespaceObject = require("os");
|
|
|
130
162
|
const config = loader.loadConfig();
|
|
131
163
|
(0, external_vitest_namespaceObject.expect)(config).toMatchObject(configData);
|
|
132
164
|
});
|
|
165
|
+
(0, external_vitest_namespaceObject.it)("should allow disabling summarization middleware", ()=>{
|
|
166
|
+
const configData = {
|
|
167
|
+
summarization: {
|
|
168
|
+
enabled: false
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
(0, external_fs_namespaceObject.writeFileSync)((0, external_path_namespaceObject.join)(configDir, "wingman.config.json"), JSON.stringify(configData));
|
|
172
|
+
const loader = new loader_cjs_namespaceObject.WingmanConfigLoader(".wingman", testDir);
|
|
173
|
+
const config = loader.loadConfig();
|
|
174
|
+
(0, external_vitest_namespaceObject.expect)(config.summarization).toEqual({
|
|
175
|
+
enabled: false,
|
|
176
|
+
maxTokensBeforeSummary: 12000,
|
|
177
|
+
messagesToKeep: 8
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
(0, external_vitest_namespaceObject.it)("should load retry and HITL middleware config", ()=>{
|
|
181
|
+
const configData = {
|
|
182
|
+
modelRetry: {
|
|
183
|
+
enabled: true,
|
|
184
|
+
maxRetries: 3,
|
|
185
|
+
backoffFactor: 1.5,
|
|
186
|
+
initialDelayMs: 250,
|
|
187
|
+
maxDelayMs: 4000,
|
|
188
|
+
jitter: false,
|
|
189
|
+
onFailure: "error"
|
|
190
|
+
},
|
|
191
|
+
toolRetry: {
|
|
192
|
+
enabled: true,
|
|
193
|
+
maxRetries: 4,
|
|
194
|
+
backoffFactor: 2,
|
|
195
|
+
initialDelayMs: 500,
|
|
196
|
+
maxDelayMs: 8000,
|
|
197
|
+
jitter: true,
|
|
198
|
+
onFailure: "continue",
|
|
199
|
+
tools: [
|
|
200
|
+
"internet_search",
|
|
201
|
+
"web_crawler"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
humanInTheLoop: {
|
|
205
|
+
enabled: true,
|
|
206
|
+
interruptOn: {
|
|
207
|
+
command_execute: {
|
|
208
|
+
allowedDecisions: [
|
|
209
|
+
"approve",
|
|
210
|
+
"reject"
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
(0, external_fs_namespaceObject.writeFileSync)((0, external_path_namespaceObject.join)(configDir, "wingman.config.json"), JSON.stringify(configData));
|
|
217
|
+
const loader = new loader_cjs_namespaceObject.WingmanConfigLoader(".wingman", testDir);
|
|
218
|
+
const config = loader.loadConfig();
|
|
219
|
+
(0, external_vitest_namespaceObject.expect)(config).toMatchObject(configData);
|
|
220
|
+
});
|
|
133
221
|
(0, external_vitest_namespaceObject.it)("should handle all valid log levels", ()=>{
|
|
134
222
|
const levels = [
|
|
135
223
|
"debug",
|
|
@@ -31,6 +31,33 @@ describe("CLI Config Loader", ()=>{
|
|
|
31
31
|
expect(config).toEqual({
|
|
32
32
|
logLevel: "info",
|
|
33
33
|
recursionLimit: 5000,
|
|
34
|
+
summarization: {
|
|
35
|
+
enabled: true,
|
|
36
|
+
maxTokensBeforeSummary: 12000,
|
|
37
|
+
messagesToKeep: 8
|
|
38
|
+
},
|
|
39
|
+
modelRetry: {
|
|
40
|
+
enabled: true,
|
|
41
|
+
maxRetries: 2,
|
|
42
|
+
backoffFactor: 2,
|
|
43
|
+
initialDelayMs: 1000,
|
|
44
|
+
maxDelayMs: 60000,
|
|
45
|
+
jitter: true,
|
|
46
|
+
onFailure: "continue"
|
|
47
|
+
},
|
|
48
|
+
toolRetry: {
|
|
49
|
+
enabled: false,
|
|
50
|
+
maxRetries: 2,
|
|
51
|
+
backoffFactor: 2,
|
|
52
|
+
initialDelayMs: 1000,
|
|
53
|
+
maxDelayMs: 60000,
|
|
54
|
+
jitter: true,
|
|
55
|
+
onFailure: "continue"
|
|
56
|
+
},
|
|
57
|
+
humanInTheLoop: {
|
|
58
|
+
enabled: false,
|
|
59
|
+
interruptOn: {}
|
|
60
|
+
},
|
|
34
61
|
search: {
|
|
35
62
|
provider: "duckduckgo",
|
|
36
63
|
maxResults: 5
|
|
@@ -109,6 +136,11 @@ describe("CLI Config Loader", ()=>{
|
|
|
109
136
|
logLevel: "debug",
|
|
110
137
|
defaultAgent: "coder",
|
|
111
138
|
recursionLimit: 5,
|
|
139
|
+
summarization: {
|
|
140
|
+
enabled: true,
|
|
141
|
+
maxTokensBeforeSummary: 18000,
|
|
142
|
+
messagesToKeep: 10
|
|
143
|
+
},
|
|
112
144
|
search: {
|
|
113
145
|
provider: "perplexity",
|
|
114
146
|
maxResults: 10
|
|
@@ -128,6 +160,62 @@ describe("CLI Config Loader", ()=>{
|
|
|
128
160
|
const config = loader.loadConfig();
|
|
129
161
|
expect(config).toMatchObject(configData);
|
|
130
162
|
});
|
|
163
|
+
it("should allow disabling summarization middleware", ()=>{
|
|
164
|
+
const configData = {
|
|
165
|
+
summarization: {
|
|
166
|
+
enabled: false
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
writeFileSync(join(configDir, "wingman.config.json"), JSON.stringify(configData));
|
|
170
|
+
const loader = new WingmanConfigLoader(".wingman", testDir);
|
|
171
|
+
const config = loader.loadConfig();
|
|
172
|
+
expect(config.summarization).toEqual({
|
|
173
|
+
enabled: false,
|
|
174
|
+
maxTokensBeforeSummary: 12000,
|
|
175
|
+
messagesToKeep: 8
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
it("should load retry and HITL middleware config", ()=>{
|
|
179
|
+
const configData = {
|
|
180
|
+
modelRetry: {
|
|
181
|
+
enabled: true,
|
|
182
|
+
maxRetries: 3,
|
|
183
|
+
backoffFactor: 1.5,
|
|
184
|
+
initialDelayMs: 250,
|
|
185
|
+
maxDelayMs: 4000,
|
|
186
|
+
jitter: false,
|
|
187
|
+
onFailure: "error"
|
|
188
|
+
},
|
|
189
|
+
toolRetry: {
|
|
190
|
+
enabled: true,
|
|
191
|
+
maxRetries: 4,
|
|
192
|
+
backoffFactor: 2,
|
|
193
|
+
initialDelayMs: 500,
|
|
194
|
+
maxDelayMs: 8000,
|
|
195
|
+
jitter: true,
|
|
196
|
+
onFailure: "continue",
|
|
197
|
+
tools: [
|
|
198
|
+
"internet_search",
|
|
199
|
+
"web_crawler"
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
humanInTheLoop: {
|
|
203
|
+
enabled: true,
|
|
204
|
+
interruptOn: {
|
|
205
|
+
command_execute: {
|
|
206
|
+
allowedDecisions: [
|
|
207
|
+
"approve",
|
|
208
|
+
"reject"
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
writeFileSync(join(configDir, "wingman.config.json"), JSON.stringify(configData));
|
|
215
|
+
const loader = new WingmanConfigLoader(".wingman", testDir);
|
|
216
|
+
const config = loader.loadConfig();
|
|
217
|
+
expect(config).toMatchObject(configData);
|
|
218
|
+
});
|
|
131
219
|
it("should handle all valid log levels", ()=>{
|
|
132
220
|
const levels = [
|
|
133
221
|
"debug",
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_exports__ = {};
|
|
3
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
4
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
5
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
6
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
7
|
+
(0, external_vitest_namespaceObject.describe)("codex credential precedence", ()=>{
|
|
8
|
+
let homeDir;
|
|
9
|
+
let codexHome;
|
|
10
|
+
const originalHome = process.env.HOME;
|
|
11
|
+
const originalCodexHome = process.env.CODEX_HOME;
|
|
12
|
+
const originalCodexAccessToken = process.env.CODEX_ACCESS_TOKEN;
|
|
13
|
+
const originalChatGptAccessToken = process.env.CHATGPT_ACCESS_TOKEN;
|
|
14
|
+
(0, external_vitest_namespaceObject.beforeEach)(()=>{
|
|
15
|
+
homeDir = (0, external_node_fs_namespaceObject.mkdtempSync)((0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), "wingman-home-"));
|
|
16
|
+
codexHome = (0, external_node_fs_namespaceObject.mkdtempSync)((0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), "wingman-codex-home-"));
|
|
17
|
+
process.env.HOME = homeDir;
|
|
18
|
+
process.env.CODEX_HOME = codexHome;
|
|
19
|
+
delete process.env.CODEX_ACCESS_TOKEN;
|
|
20
|
+
delete process.env.CHATGPT_ACCESS_TOKEN;
|
|
21
|
+
});
|
|
22
|
+
(0, external_vitest_namespaceObject.afterEach)(()=>{
|
|
23
|
+
if (void 0 === originalHome) delete process.env.HOME;
|
|
24
|
+
else process.env.HOME = originalHome;
|
|
25
|
+
if (void 0 === originalCodexHome) delete process.env.CODEX_HOME;
|
|
26
|
+
else process.env.CODEX_HOME = originalCodexHome;
|
|
27
|
+
if (void 0 === originalCodexAccessToken) delete process.env.CODEX_ACCESS_TOKEN;
|
|
28
|
+
else process.env.CODEX_ACCESS_TOKEN = originalCodexAccessToken;
|
|
29
|
+
if (void 0 === originalChatGptAccessToken) delete process.env.CHATGPT_ACCESS_TOKEN;
|
|
30
|
+
else process.env.CHATGPT_ACCESS_TOKEN = originalChatGptAccessToken;
|
|
31
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(homeDir)) (0, external_node_fs_namespaceObject.rmSync)(homeDir, {
|
|
32
|
+
recursive: true,
|
|
33
|
+
force: true
|
|
34
|
+
});
|
|
35
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(codexHome)) (0, external_node_fs_namespaceObject.rmSync)(codexHome, {
|
|
36
|
+
recursive: true,
|
|
37
|
+
force: true
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
(0, external_vitest_namespaceObject.it)("prefers Codex auth file over stored Wingman credentials for codex", async ()=>{
|
|
41
|
+
external_vitest_namespaceObject.vi.resetModules();
|
|
42
|
+
const credentials = await import("../providers/credentials.cjs");
|
|
43
|
+
const codex = await import("../providers/codex.cjs");
|
|
44
|
+
const credsPath = credentials.getCredentialsPath();
|
|
45
|
+
(0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(credsPath), {
|
|
46
|
+
recursive: true
|
|
47
|
+
});
|
|
48
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(credsPath, JSON.stringify({
|
|
49
|
+
version: 1,
|
|
50
|
+
updatedAt: new Date().toISOString(),
|
|
51
|
+
providers: {
|
|
52
|
+
codex: {
|
|
53
|
+
apiKey: "stale-wingman-token"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, null, 2));
|
|
57
|
+
const authPath = codex.getCodexAuthPath();
|
|
58
|
+
(0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(authPath), {
|
|
59
|
+
recursive: true
|
|
60
|
+
});
|
|
61
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(authPath, JSON.stringify({
|
|
62
|
+
tokens: {
|
|
63
|
+
access_token: "codex-file-token",
|
|
64
|
+
account_id: "acct_123"
|
|
65
|
+
}
|
|
66
|
+
}, null, 2));
|
|
67
|
+
const resolved = credentials.resolveProviderToken("codex");
|
|
68
|
+
(0, external_vitest_namespaceObject.expect)(resolved.token).toBe("codex-file-token");
|
|
69
|
+
(0, external_vitest_namespaceObject.expect)(resolved.source).toBe("credentials");
|
|
70
|
+
});
|
|
71
|
+
(0, external_vitest_namespaceObject.it)("still prefers env vars over Codex auth file", async ()=>{
|
|
72
|
+
process.env.CODEX_ACCESS_TOKEN = "env-token";
|
|
73
|
+
external_vitest_namespaceObject.vi.resetModules();
|
|
74
|
+
const credentials = await import("../providers/credentials.cjs");
|
|
75
|
+
const codex = await import("../providers/codex.cjs");
|
|
76
|
+
const authPath = codex.getCodexAuthPath();
|
|
77
|
+
(0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(authPath), {
|
|
78
|
+
recursive: true
|
|
79
|
+
});
|
|
80
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(authPath, JSON.stringify({
|
|
81
|
+
tokens: {
|
|
82
|
+
access_token: "codex-file-token"
|
|
83
|
+
}
|
|
84
|
+
}, null, 2));
|
|
85
|
+
const resolved = credentials.resolveProviderToken("codex");
|
|
86
|
+
(0, external_vitest_namespaceObject.expect)(resolved.token).toBe("env-token");
|
|
87
|
+
(0, external_vitest_namespaceObject.expect)(resolved.source).toBe("env");
|
|
88
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.readFileSync)(authPath, "utf-8")).toContain("codex-file-token");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
92
|
+
Object.defineProperty(exports, '__esModule', {
|
|
93
|
+
value: true
|
|
94
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
describe("codex credential precedence", ()=>{
|
|
6
|
+
let homeDir;
|
|
7
|
+
let codexHome;
|
|
8
|
+
const originalHome = process.env.HOME;
|
|
9
|
+
const originalCodexHome = process.env.CODEX_HOME;
|
|
10
|
+
const originalCodexAccessToken = process.env.CODEX_ACCESS_TOKEN;
|
|
11
|
+
const originalChatGptAccessToken = process.env.CHATGPT_ACCESS_TOKEN;
|
|
12
|
+
beforeEach(()=>{
|
|
13
|
+
homeDir = mkdtempSync(join(tmpdir(), "wingman-home-"));
|
|
14
|
+
codexHome = mkdtempSync(join(tmpdir(), "wingman-codex-home-"));
|
|
15
|
+
process.env.HOME = homeDir;
|
|
16
|
+
process.env.CODEX_HOME = codexHome;
|
|
17
|
+
delete process.env.CODEX_ACCESS_TOKEN;
|
|
18
|
+
delete process.env.CHATGPT_ACCESS_TOKEN;
|
|
19
|
+
});
|
|
20
|
+
afterEach(()=>{
|
|
21
|
+
if (void 0 === originalHome) delete process.env.HOME;
|
|
22
|
+
else process.env.HOME = originalHome;
|
|
23
|
+
if (void 0 === originalCodexHome) delete process.env.CODEX_HOME;
|
|
24
|
+
else process.env.CODEX_HOME = originalCodexHome;
|
|
25
|
+
if (void 0 === originalCodexAccessToken) delete process.env.CODEX_ACCESS_TOKEN;
|
|
26
|
+
else process.env.CODEX_ACCESS_TOKEN = originalCodexAccessToken;
|
|
27
|
+
if (void 0 === originalChatGptAccessToken) delete process.env.CHATGPT_ACCESS_TOKEN;
|
|
28
|
+
else process.env.CHATGPT_ACCESS_TOKEN = originalChatGptAccessToken;
|
|
29
|
+
if (existsSync(homeDir)) rmSync(homeDir, {
|
|
30
|
+
recursive: true,
|
|
31
|
+
force: true
|
|
32
|
+
});
|
|
33
|
+
if (existsSync(codexHome)) rmSync(codexHome, {
|
|
34
|
+
recursive: true,
|
|
35
|
+
force: true
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("prefers Codex auth file over stored Wingman credentials for codex", async ()=>{
|
|
39
|
+
vi.resetModules();
|
|
40
|
+
const credentials = await import("../providers/credentials.js");
|
|
41
|
+
const codex = await import("../providers/codex.js");
|
|
42
|
+
const credsPath = credentials.getCredentialsPath();
|
|
43
|
+
mkdirSync(dirname(credsPath), {
|
|
44
|
+
recursive: true
|
|
45
|
+
});
|
|
46
|
+
writeFileSync(credsPath, JSON.stringify({
|
|
47
|
+
version: 1,
|
|
48
|
+
updatedAt: new Date().toISOString(),
|
|
49
|
+
providers: {
|
|
50
|
+
codex: {
|
|
51
|
+
apiKey: "stale-wingman-token"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}, null, 2));
|
|
55
|
+
const authPath = codex.getCodexAuthPath();
|
|
56
|
+
mkdirSync(dirname(authPath), {
|
|
57
|
+
recursive: true
|
|
58
|
+
});
|
|
59
|
+
writeFileSync(authPath, JSON.stringify({
|
|
60
|
+
tokens: {
|
|
61
|
+
access_token: "codex-file-token",
|
|
62
|
+
account_id: "acct_123"
|
|
63
|
+
}
|
|
64
|
+
}, null, 2));
|
|
65
|
+
const resolved = credentials.resolveProviderToken("codex");
|
|
66
|
+
expect(resolved.token).toBe("codex-file-token");
|
|
67
|
+
expect(resolved.source).toBe("credentials");
|
|
68
|
+
});
|
|
69
|
+
it("still prefers env vars over Codex auth file", async ()=>{
|
|
70
|
+
process.env.CODEX_ACCESS_TOKEN = "env-token";
|
|
71
|
+
vi.resetModules();
|
|
72
|
+
const credentials = await import("../providers/credentials.js");
|
|
73
|
+
const codex = await import("../providers/codex.js");
|
|
74
|
+
const authPath = codex.getCodexAuthPath();
|
|
75
|
+
mkdirSync(dirname(authPath), {
|
|
76
|
+
recursive: true
|
|
77
|
+
});
|
|
78
|
+
writeFileSync(authPath, JSON.stringify({
|
|
79
|
+
tokens: {
|
|
80
|
+
access_token: "codex-file-token"
|
|
81
|
+
}
|
|
82
|
+
}, null, 2));
|
|
83
|
+
const resolved = credentials.resolveProviderToken("codex");
|
|
84
|
+
expect(resolved.token).toBe("env-token");
|
|
85
|
+
expect(resolved.source).toBe("env");
|
|
86
|
+
expect(readFileSync(authPath, "utf-8")).toContain("codex-file-token");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_exports__ = {};
|
|
3
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
4
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
5
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
6
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
7
|
+
const codex_cjs_namespaceObject = require("../providers/codex.cjs");
|
|
8
|
+
(0, external_vitest_namespaceObject.describe)("codex provider", ()=>{
|
|
9
|
+
let codexHome;
|
|
10
|
+
const originalCodexHome = process.env.CODEX_HOME;
|
|
11
|
+
(0, external_vitest_namespaceObject.beforeEach)(()=>{
|
|
12
|
+
codexHome = (0, external_node_fs_namespaceObject.mkdtempSync)((0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), "wingman-codex-"));
|
|
13
|
+
process.env.CODEX_HOME = codexHome;
|
|
14
|
+
delete process.env.CODEX_ACCESS_TOKEN;
|
|
15
|
+
delete process.env.CHATGPT_ACCESS_TOKEN;
|
|
16
|
+
});
|
|
17
|
+
(0, external_vitest_namespaceObject.afterEach)(()=>{
|
|
18
|
+
if (void 0 === originalCodexHome) delete process.env.CODEX_HOME;
|
|
19
|
+
else process.env.CODEX_HOME = originalCodexHome;
|
|
20
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(codexHome)) (0, external_node_fs_namespaceObject.rmSync)(codexHome, {
|
|
21
|
+
recursive: true,
|
|
22
|
+
force: true
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
(0, external_vitest_namespaceObject.it)("reads access token and account id from codex auth file", ()=>{
|
|
26
|
+
writeCodexAuth({
|
|
27
|
+
tokens: {
|
|
28
|
+
access_token: "codex-access-token",
|
|
29
|
+
account_id: "acct_123"
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const resolved = (0, codex_cjs_namespaceObject.resolveCodexAuthFromFile)();
|
|
33
|
+
(0, external_vitest_namespaceObject.expect)(resolved.accessToken).toBe("codex-access-token");
|
|
34
|
+
(0, external_vitest_namespaceObject.expect)(resolved.accountId).toBe("acct_123");
|
|
35
|
+
(0, external_vitest_namespaceObject.expect)(resolved.authPath).toBe((0, external_node_path_namespaceObject.join)(codexHome, "auth.json"));
|
|
36
|
+
});
|
|
37
|
+
(0, external_vitest_namespaceObject.it)("applies codex auth headers and forces store=false", async ()=>{
|
|
38
|
+
writeCodexAuth({
|
|
39
|
+
tokens: {
|
|
40
|
+
access_token: "file-token",
|
|
41
|
+
account_id: "acct_file"
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const baseFetch = external_vitest_namespaceObject.vi.fn(async (_input, _init)=>new Response("{}", {
|
|
45
|
+
status: 200
|
|
46
|
+
}));
|
|
47
|
+
const codexFetch = (0, codex_cjs_namespaceObject.createCodexFetch)({
|
|
48
|
+
baseFetch
|
|
49
|
+
});
|
|
50
|
+
await codexFetch("https://chatgpt.com/backend-api/codex/responses", {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: {
|
|
53
|
+
"x-api-key": "placeholder"
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
model: "codex-mini-latest",
|
|
57
|
+
input: "hello",
|
|
58
|
+
temperature: 1
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
(0, external_vitest_namespaceObject.expect)(baseFetch).toHaveBeenCalledTimes(1);
|
|
62
|
+
const requestInit = baseFetch.mock.calls[0]?.[1];
|
|
63
|
+
(0, external_vitest_namespaceObject.expect)(requestInit).toBeDefined();
|
|
64
|
+
const headers = new Headers(requestInit?.headers);
|
|
65
|
+
const payload = JSON.parse(String(requestInit?.body));
|
|
66
|
+
(0, external_vitest_namespaceObject.expect)(headers.get("authorization")).toBe("Bearer file-token");
|
|
67
|
+
(0, external_vitest_namespaceObject.expect)(headers.get("chatgpt-account-id")).toBe("acct_file");
|
|
68
|
+
(0, external_vitest_namespaceObject.expect)(headers.get("x-api-key")).toBeNull();
|
|
69
|
+
(0, external_vitest_namespaceObject.expect)(payload.store).toBe(false);
|
|
70
|
+
(0, external_vitest_namespaceObject.expect)(payload.temperature).toBeUndefined();
|
|
71
|
+
(0, external_vitest_namespaceObject.expect)(typeof payload.instructions).toBe("string");
|
|
72
|
+
(0, external_vitest_namespaceObject.expect)(payload.instructions.length).toBeGreaterThan(0);
|
|
73
|
+
});
|
|
74
|
+
(0, external_vitest_namespaceObject.it)("derives instructions from system/developer input when missing", async ()=>{
|
|
75
|
+
writeCodexAuth({
|
|
76
|
+
tokens: {
|
|
77
|
+
access_token: "file-token"
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const baseFetch = external_vitest_namespaceObject.vi.fn(async (_input, _init)=>new Response("{}", {
|
|
81
|
+
status: 200
|
|
82
|
+
}));
|
|
83
|
+
const codexFetch = (0, codex_cjs_namespaceObject.createCodexFetch)({
|
|
84
|
+
baseFetch
|
|
85
|
+
});
|
|
86
|
+
await codexFetch("https://chatgpt.com/backend-api/codex/responses", {
|
|
87
|
+
method: "POST",
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
model: "gpt-5.3-codex",
|
|
90
|
+
input: [
|
|
91
|
+
{
|
|
92
|
+
role: "developer",
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: "input_text",
|
|
96
|
+
text: "Always run tests first."
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
role: "user",
|
|
102
|
+
content: [
|
|
103
|
+
{
|
|
104
|
+
type: "input_text",
|
|
105
|
+
text: "Fix the bug."
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
})
|
|
111
|
+
});
|
|
112
|
+
const requestInit = baseFetch.mock.calls[0]?.[1];
|
|
113
|
+
const payload = JSON.parse(String(requestInit?.body));
|
|
114
|
+
(0, external_vitest_namespaceObject.expect)(payload.instructions).toBe("Always run tests first.");
|
|
115
|
+
});
|
|
116
|
+
(0, external_vitest_namespaceObject.it)("preserves explicit instructions when provided", async ()=>{
|
|
117
|
+
writeCodexAuth({
|
|
118
|
+
tokens: {
|
|
119
|
+
access_token: "file-token"
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const baseFetch = external_vitest_namespaceObject.vi.fn(async (_input, _init)=>new Response("{}", {
|
|
123
|
+
status: 200
|
|
124
|
+
}));
|
|
125
|
+
const codexFetch = (0, codex_cjs_namespaceObject.createCodexFetch)({
|
|
126
|
+
baseFetch
|
|
127
|
+
});
|
|
128
|
+
await codexFetch("https://chatgpt.com/backend-api/codex/responses", {
|
|
129
|
+
method: "POST",
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
model: "gpt-5.3-codex",
|
|
132
|
+
instructions: "Use concise answers.",
|
|
133
|
+
input: "hello"
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
const requestInit = baseFetch.mock.calls[0]?.[1];
|
|
137
|
+
const payload = JSON.parse(String(requestInit?.body));
|
|
138
|
+
(0, external_vitest_namespaceObject.expect)(payload.instructions).toBe("Use concise answers.");
|
|
139
|
+
});
|
|
140
|
+
(0, external_vitest_namespaceObject.it)("uses fallback token when codex auth file is unavailable", async ()=>{
|
|
141
|
+
const baseFetch = external_vitest_namespaceObject.vi.fn(async (_input, _init)=>new Response("{}", {
|
|
142
|
+
status: 200
|
|
143
|
+
}));
|
|
144
|
+
const codexFetch = (0, codex_cjs_namespaceObject.createCodexFetch)({
|
|
145
|
+
baseFetch,
|
|
146
|
+
fallbackToken: "fallback-token"
|
|
147
|
+
});
|
|
148
|
+
await codexFetch("https://chatgpt.com/backend-api/codex/responses", {
|
|
149
|
+
method: "POST",
|
|
150
|
+
body: JSON.stringify({
|
|
151
|
+
model: "codex-mini-latest",
|
|
152
|
+
input: "hello"
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
const requestInit = baseFetch.mock.calls[0]?.[1];
|
|
156
|
+
(0, external_vitest_namespaceObject.expect)(requestInit).toBeDefined();
|
|
157
|
+
const headers = new Headers(requestInit?.headers);
|
|
158
|
+
(0, external_vitest_namespaceObject.expect)(headers.get("authorization")).toBe("Bearer fallback-token");
|
|
159
|
+
});
|
|
160
|
+
(0, external_vitest_namespaceObject.it)("throws when no codex token is available", async ()=>{
|
|
161
|
+
const baseFetch = external_vitest_namespaceObject.vi.fn(async (_input, _init)=>new Response("{}", {
|
|
162
|
+
status: 200
|
|
163
|
+
}));
|
|
164
|
+
const codexFetch = (0, codex_cjs_namespaceObject.createCodexFetch)({
|
|
165
|
+
baseFetch
|
|
166
|
+
});
|
|
167
|
+
await (0, external_vitest_namespaceObject.expect)(codexFetch("https://chatgpt.com/backend-api/codex/responses", {
|
|
168
|
+
method: "POST",
|
|
169
|
+
body: JSON.stringify({
|
|
170
|
+
model: "codex-mini-latest",
|
|
171
|
+
input: "hello"
|
|
172
|
+
})
|
|
173
|
+
})).rejects.toThrow(/Codex credentials missing/);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
function writeCodexAuth(payload) {
|
|
177
|
+
const authPath = (0, codex_cjs_namespaceObject.getCodexAuthPath)();
|
|
178
|
+
(0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(authPath), {
|
|
179
|
+
recursive: true
|
|
180
|
+
});
|
|
181
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(authPath, JSON.stringify(payload, null, 2));
|
|
182
|
+
}
|
|
183
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
184
|
+
Object.defineProperty(exports, '__esModule', {
|
|
185
|
+
value: true
|
|
186
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|