@wingman-ai/gateway 0.2.2 → 0.2.4
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/README.md +7 -1
- package/.wingman/agents/coding/agent.md +299 -201
- package/.wingman/agents/coding-v2/agent.md +127 -0
- package/.wingman/agents/coding-v2/implementor.md +89 -0
- package/.wingman/agents/main/agent.md +4 -0
- package/README.md +1 -0
- package/dist/agent/config/agentConfig.cjs +31 -17
- package/dist/agent/config/agentConfig.d.ts +23 -1
- package/dist/agent/config/agentConfig.js +30 -19
- package/dist/agent/config/agentLoader.cjs +26 -8
- package/dist/agent/config/agentLoader.d.ts +4 -2
- package/dist/agent/config/agentLoader.js +26 -8
- package/dist/agent/config/modelFactory.cjs +95 -25
- package/dist/agent/config/modelFactory.d.ts +13 -1
- package/dist/agent/config/modelFactory.js +95 -25
- package/dist/agent/config/toolRegistry.cjs +19 -6
- package/dist/agent/config/toolRegistry.d.ts +5 -2
- package/dist/agent/config/toolRegistry.js +19 -6
- package/dist/agent/middleware/hooks/types.cjs +13 -13
- package/dist/agent/middleware/hooks/types.d.ts +1 -1
- package/dist/agent/middleware/hooks/types.js +14 -14
- package/dist/agent/tests/agentConfig.test.cjs +22 -2
- package/dist/agent/tests/agentConfig.test.js +22 -2
- package/dist/agent/tests/agentLoader.test.cjs +38 -1
- package/dist/agent/tests/agentLoader.test.js +38 -1
- package/dist/agent/tests/backgroundTerminal.test.cjs +70 -0
- package/dist/agent/tests/backgroundTerminal.test.d.ts +1 -0
- package/dist/agent/tests/backgroundTerminal.test.js +64 -0
- package/dist/agent/tests/commandExecuteTool.test.cjs +29 -0
- package/dist/agent/tests/commandExecuteTool.test.d.ts +1 -0
- package/dist/agent/tests/commandExecuteTool.test.js +23 -0
- package/dist/agent/tests/modelFactory.test.cjs +47 -5
- package/dist/agent/tests/modelFactory.test.js +47 -5
- package/dist/agent/tests/terminalSessionManager.test.cjs +121 -0
- package/dist/agent/tests/terminalSessionManager.test.d.ts +1 -0
- package/dist/agent/tests/terminalSessionManager.test.js +115 -0
- package/dist/agent/tests/toolRegistry.test.cjs +14 -2
- package/dist/agent/tests/toolRegistry.test.js +14 -2
- package/dist/agent/tools/background_terminal.cjs +128 -0
- package/dist/agent/tools/background_terminal.d.ts +41 -0
- package/dist/agent/tools/background_terminal.js +94 -0
- package/dist/agent/tools/code_search.cjs +6 -6
- package/dist/agent/tools/code_search.d.ts +1 -1
- package/dist/agent/tools/code_search.js +7 -7
- package/dist/agent/tools/command_execute.cjs +22 -7
- package/dist/agent/tools/command_execute.d.ts +3 -2
- package/dist/agent/tools/command_execute.js +23 -8
- package/dist/agent/tools/git_status.cjs +3 -3
- package/dist/agent/tools/git_status.d.ts +1 -1
- package/dist/agent/tools/git_status.js +4 -4
- package/dist/agent/tools/internet_search.cjs +6 -6
- package/dist/agent/tools/internet_search.d.ts +1 -1
- package/dist/agent/tools/internet_search.js +7 -7
- package/dist/agent/tools/terminal_session_manager.cjs +321 -0
- package/dist/agent/tools/terminal_session_manager.d.ts +77 -0
- package/dist/agent/tools/terminal_session_manager.js +284 -0
- package/dist/agent/tools/think.cjs +4 -4
- package/dist/agent/tools/think.d.ts +1 -1
- package/dist/agent/tools/think.js +5 -5
- package/dist/agent/tools/ui_registry.cjs +13 -13
- package/dist/agent/tools/ui_registry.d.ts +4 -4
- package/dist/agent/tools/ui_registry.js +14 -14
- package/dist/agent/tools/web_crawler.cjs +4 -4
- package/dist/agent/tools/web_crawler.d.ts +1 -1
- package/dist/agent/tools/web_crawler.js +5 -5
- package/dist/agent/utils.cjs +2 -1
- package/dist/agent/utils.js +2 -1
- 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 +146 -68
- package/dist/cli/config/schema.d.ts +89 -1
- package/dist/cli/config/schema.js +134 -68
- package/dist/cli/core/agentInvoker.cjs +344 -17
- package/dist/cli/core/agentInvoker.d.ts +63 -3
- package/dist/cli/core/agentInvoker.js +303 -12
- package/dist/cli/core/sessionManager.cjs +32 -5
- package/dist/cli/core/sessionManager.js +32 -5
- package/dist/cli/core/streamParser.cjs +15 -0
- package/dist/cli/core/streamParser.js +15 -0
- package/dist/cli/index.cjs +6 -5
- package/dist/cli/index.js +6 -5
- package/dist/cli/types.d.ts +32 -0
- package/dist/cli/ui/toolDisplayHelpers.cjs +2 -0
- package/dist/cli/ui/toolDisplayHelpers.js +2 -0
- package/dist/gateway/hooks/registry.cjs +2 -1
- package/dist/gateway/hooks/registry.d.ts +1 -1
- package/dist/gateway/hooks/registry.js +2 -1
- package/dist/gateway/hooks/types.cjs +11 -11
- package/dist/gateway/hooks/types.d.ts +1 -1
- package/dist/gateway/hooks/types.js +12 -12
- package/dist/gateway/http/agents.cjs +67 -4
- package/dist/gateway/http/agents.js +67 -4
- package/dist/gateway/http/sessions.cjs +7 -7
- package/dist/gateway/http/sessions.js +7 -7
- package/dist/gateway/http/types.d.ts +5 -3
- package/dist/gateway/http/webhooks.cjs +6 -5
- package/dist/gateway/http/webhooks.js +6 -5
- package/dist/gateway/server.cjs +198 -41
- package/dist/gateway/server.d.ts +9 -1
- package/dist/gateway/server.js +198 -41
- package/dist/gateway/types.d.ts +1 -0
- package/dist/gateway/validation.cjs +39 -39
- package/dist/gateway/validation.d.ts +1 -1
- package/dist/gateway/validation.js +40 -40
- 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/additionalMessageMiddleware.test.cjs +3 -0
- package/dist/tests/additionalMessageMiddleware.test.js +3 -0
- package/dist/tests/agentInvokerSummarization.test.cjs +455 -0
- package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
- package/dist/tests/agentInvokerSummarization.test.js +449 -0
- package/dist/tests/agents-api.test.cjs +45 -5
- package/dist/tests/agents-api.test.js +45 -5
- package/dist/tests/cli-config-loader.test.cjs +88 -0
- package/dist/tests/cli-config-loader.test.js +88 -0
- package/dist/tests/cli-init.test.cjs +27 -3
- package/dist/tests/cli-init.test.js +27 -3
- 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 +210 -0
- package/dist/tests/codex-provider.test.d.ts +1 -0
- package/dist/tests/codex-provider.test.js +204 -0
- package/dist/tests/gateway.test.cjs +115 -8
- package/dist/tests/gateway.test.js +115 -8
- 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/tests/toolDisplayHelpers.test.cjs +3 -0
- package/dist/tests/toolDisplayHelpers.test.js +3 -0
- package/dist/tools/mcp-finance.cjs +48 -48
- package/dist/tools/mcp-finance.js +48 -48
- package/dist/types/mcp.cjs +15 -15
- package/dist/types/mcp.d.ts +1 -1
- package/dist/types/mcp.js +16 -16
- package/dist/types/voice.cjs +21 -21
- package/dist/types/voice.d.ts +1 -1
- package/dist/types/voice.js +22 -22
- package/dist/webui/assets/index-DVWQluit.css +11 -0
- package/dist/webui/assets/index-Dlyzwalc.js +270 -0
- package/dist/webui/favicon-32x32.png +0 -0
- package/dist/webui/favicon-64x64.png +0 -0
- package/dist/webui/favicon.webp +0 -0
- package/dist/webui/index.html +4 -2
- package/package.json +13 -12
- package/.wingman/agents/coding/implementor.md +0 -79
- package/dist/webui/assets/index-CPhfGPHc.js +0 -182
- package/dist/webui/assets/index-DDsMIOTX.css +0 -11
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import { handleAgentsApi } from "../gateway/http/agents.js";
|
|
3
1
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
2
|
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
6
4
|
import { load } from "js-yaml";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { handleAgentsApi } from "../gateway/http/agents.js";
|
|
7
7
|
const isBunRuntime = void 0 !== globalThis.Bun;
|
|
8
8
|
const describeIfBun = isBunRuntime ? describe : describe.skip;
|
|
9
9
|
const parseMarkdownAgent = (raw)=>{
|
|
@@ -63,6 +63,7 @@ describeIfBun("agents API", ()=>{
|
|
|
63
63
|
"not_real_tool"
|
|
64
64
|
],
|
|
65
65
|
prompt: "You are the orchestrator.",
|
|
66
|
+
reasoningEffort: "high",
|
|
66
67
|
promptTraining: {
|
|
67
68
|
enabled: true,
|
|
68
69
|
instructionsPath: "/memories/agents/orchestrator/instructions.md"
|
|
@@ -76,6 +77,7 @@ describeIfBun("agents API", ()=>{
|
|
|
76
77
|
"not_real_tool"
|
|
77
78
|
],
|
|
78
79
|
prompt: "Plan tasks in detail.",
|
|
80
|
+
reasoningEffort: "low",
|
|
79
81
|
promptTraining: true
|
|
80
82
|
},
|
|
81
83
|
{
|
|
@@ -84,7 +86,8 @@ describeIfBun("agents API", ()=>{
|
|
|
84
86
|
tools: [
|
|
85
87
|
"command_execute"
|
|
86
88
|
],
|
|
87
|
-
prompt: "Execute planned tasks."
|
|
89
|
+
prompt: "Execute planned tasks.",
|
|
90
|
+
thinkingEffort: "minimal"
|
|
88
91
|
}
|
|
89
92
|
]
|
|
90
93
|
})
|
|
@@ -97,12 +100,15 @@ describeIfBun("agents API", ()=>{
|
|
|
97
100
|
enabled: true,
|
|
98
101
|
instructionsPath: "/memories/agents/orchestrator/instructions.md"
|
|
99
102
|
});
|
|
103
|
+
expect(created.reasoningEffort).toBe("high");
|
|
100
104
|
expect(created.promptRefinement).toEqual(created.promptTraining);
|
|
101
105
|
expect(created.subAgents).toHaveLength(2);
|
|
102
106
|
expect(created.subAgents[0].promptTraining).toBe(true);
|
|
103
107
|
expect(created.subAgents[0].tools).toEqual([
|
|
104
108
|
"think"
|
|
105
109
|
]);
|
|
110
|
+
expect(created.subAgents[0].reasoningEffort).toBe("low");
|
|
111
|
+
expect(created.subAgents[1].reasoningEffort).toBe("minimal");
|
|
106
112
|
const agentPath = join(tempDir, "agents", "orchestrator", "agent.md");
|
|
107
113
|
const parsed = parseMarkdownAgent(readFileSync(agentPath, "utf-8"));
|
|
108
114
|
expect(parsed.prompt).toBe("You are the orchestrator.");
|
|
@@ -110,10 +116,13 @@ describeIfBun("agents API", ()=>{
|
|
|
110
116
|
enabled: true,
|
|
111
117
|
instructionsPath: "/memories/agents/orchestrator/instructions.md"
|
|
112
118
|
});
|
|
119
|
+
expect(parsed.metadata.reasoningEffort).toBe("high");
|
|
113
120
|
expect(parsed.metadata.subAgents).toHaveLength(2);
|
|
114
121
|
expect(parsed.metadata.subAgents[0].name).toBe("planner");
|
|
122
|
+
expect(parsed.metadata.subAgents[0].reasoningEffort).toBe("low");
|
|
115
123
|
expect(parsed.metadata.subAgents[0].promptRefinement).toBe(true);
|
|
116
124
|
expect(parsed.metadata.subAgents[0].systemPrompt).toBe("Plan tasks in detail.");
|
|
125
|
+
expect(parsed.metadata.subAgents[1].reasoningEffort).toBe("minimal");
|
|
117
126
|
const detailReq = new Request("http://localhost/api/agents/orchestrator", {
|
|
118
127
|
method: "GET"
|
|
119
128
|
});
|
|
@@ -123,9 +132,11 @@ describeIfBun("agents API", ()=>{
|
|
|
123
132
|
const detail = await detailRes.json();
|
|
124
133
|
expect(detail.promptTraining).toEqual(created.promptTraining);
|
|
125
134
|
expect(detail.promptRefinement).toEqual(created.promptTraining);
|
|
135
|
+
expect(detail.reasoningEffort).toBe("high");
|
|
126
136
|
expect(detail.subAgents).toHaveLength(2);
|
|
127
137
|
expect(detail.subAgents[0].id).toBe("planner");
|
|
128
138
|
expect(detail.subAgents[0].prompt).toBe("Plan tasks in detail.");
|
|
139
|
+
expect(detail.subAgents[0].reasoningEffort).toBe("low");
|
|
129
140
|
});
|
|
130
141
|
it("updates promptTraining and subAgents in markdown", async ()=>{
|
|
131
142
|
const createReq = new Request("http://localhost/api/agents", {
|
|
@@ -139,6 +150,7 @@ describeIfBun("agents API", ()=>{
|
|
|
139
150
|
"think"
|
|
140
151
|
],
|
|
141
152
|
prompt: "Original prompt",
|
|
153
|
+
reasoningEffort: "low",
|
|
142
154
|
promptTraining: true,
|
|
143
155
|
subAgents: [
|
|
144
156
|
{
|
|
@@ -147,7 +159,8 @@ describeIfBun("agents API", ()=>{
|
|
|
147
159
|
tools: [
|
|
148
160
|
"think"
|
|
149
161
|
],
|
|
150
|
-
prompt: "Original planner prompt"
|
|
162
|
+
prompt: "Original planner prompt",
|
|
163
|
+
reasoningEffort: "minimal"
|
|
151
164
|
}
|
|
152
165
|
]
|
|
153
166
|
})
|
|
@@ -160,6 +173,7 @@ describeIfBun("agents API", ()=>{
|
|
|
160
173
|
"Content-Type": "application/json"
|
|
161
174
|
},
|
|
162
175
|
body: JSON.stringify({
|
|
176
|
+
reasoningEffort: "high",
|
|
163
177
|
promptTraining: false,
|
|
164
178
|
subAgents: [
|
|
165
179
|
{
|
|
@@ -169,6 +183,7 @@ describeIfBun("agents API", ()=>{
|
|
|
169
183
|
"git_status"
|
|
170
184
|
],
|
|
171
185
|
prompt: "Review carefully.",
|
|
186
|
+
thinkingEffort: "medium",
|
|
172
187
|
promptTraining: {
|
|
173
188
|
enabled: true,
|
|
174
189
|
instructionsPath: "/memories/reviewer.md"
|
|
@@ -184,8 +199,10 @@ describeIfBun("agents API", ()=>{
|
|
|
184
199
|
const updated = await updateRes.json();
|
|
185
200
|
expect(updated.promptTraining).toBe(false);
|
|
186
201
|
expect(updated.promptRefinement).toBe(false);
|
|
202
|
+
expect(updated.reasoningEffort).toBe("high");
|
|
187
203
|
expect(updated.subAgents).toHaveLength(1);
|
|
188
204
|
expect(updated.subAgents[0].id).toBe("reviewer");
|
|
205
|
+
expect(updated.subAgents[0].reasoningEffort).toBe("medium");
|
|
189
206
|
expect(updated.subAgents[0].promptTraining).toEqual({
|
|
190
207
|
enabled: true,
|
|
191
208
|
instructionsPath: "/memories/reviewer.md"
|
|
@@ -193,8 +210,10 @@ describeIfBun("agents API", ()=>{
|
|
|
193
210
|
const agentPath = join(tempDir, "agents", "editor-agent", "agent.md");
|
|
194
211
|
const parsed = parseMarkdownAgent(readFileSync(agentPath, "utf-8"));
|
|
195
212
|
expect(parsed.metadata.promptRefinement).toBe(false);
|
|
213
|
+
expect(parsed.metadata.reasoningEffort).toBe("high");
|
|
196
214
|
expect(parsed.metadata.subAgents).toHaveLength(1);
|
|
197
215
|
expect(parsed.metadata.subAgents[0].name).toBe("reviewer");
|
|
216
|
+
expect(parsed.metadata.subAgents[0].reasoningEffort).toBe("medium");
|
|
198
217
|
expect(parsed.metadata.subAgents[0].promptRefinement).toEqual({
|
|
199
218
|
enabled: true,
|
|
200
219
|
instructionsPath: "/memories/reviewer.md"
|
|
@@ -223,4 +242,25 @@ describeIfBun("agents API", ()=>{
|
|
|
223
242
|
expect(created.promptTraining).toBe(true);
|
|
224
243
|
expect(created.promptRefinement).toBe(true);
|
|
225
244
|
});
|
|
245
|
+
it("accepts legacy thinkingEffort input as reasoningEffort", async ()=>{
|
|
246
|
+
const createReq = new Request("http://localhost/api/agents", {
|
|
247
|
+
method: "POST",
|
|
248
|
+
headers: {
|
|
249
|
+
"Content-Type": "application/json"
|
|
250
|
+
},
|
|
251
|
+
body: JSON.stringify({
|
|
252
|
+
id: "legacy-thinking-agent",
|
|
253
|
+
tools: [
|
|
254
|
+
"think"
|
|
255
|
+
],
|
|
256
|
+
prompt: "Legacy thinking prompt",
|
|
257
|
+
thinkingEffort: "medium"
|
|
258
|
+
})
|
|
259
|
+
});
|
|
260
|
+
const createRes = await handleAgentsApi(ctx, createReq, new URL(createReq.url));
|
|
261
|
+
expect(createRes).not.toBeNull();
|
|
262
|
+
expect(createRes?.ok).toBe(true);
|
|
263
|
+
const created = await createRes.json();
|
|
264
|
+
expect(created.reasoningEffort).toBe("medium");
|
|
265
|
+
});
|
|
226
266
|
});
|
|
@@ -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",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_exports__ = {};
|
|
3
|
-
const external_vitest_namespaceObject = require("vitest");
|
|
4
|
-
const init_cjs_namespaceObject = require("../cli/commands/init.cjs");
|
|
5
3
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
6
|
-
const external_node_path_namespaceObject = require("node:path");
|
|
7
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 init_cjs_namespaceObject = require("../cli/commands/init.cjs");
|
|
8
8
|
(0, external_vitest_namespaceObject.describe)("CLI init", ()=>{
|
|
9
9
|
let workspace;
|
|
10
10
|
(0, external_vitest_namespaceObject.beforeEach)(()=>{
|
|
@@ -39,6 +39,30 @@ const external_node_os_namespaceObject = require("node:os");
|
|
|
39
39
|
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(agentPath)).toBe(true);
|
|
40
40
|
const agent = JSON.parse((0, external_node_fs_namespaceObject.readFileSync)(agentPath, "utf-8"));
|
|
41
41
|
(0, external_vitest_namespaceObject.expect)(agent.name).toBe("wingman");
|
|
42
|
+
const codingAgentPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding", "agent.md");
|
|
43
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingAgentPath)).toBe(true);
|
|
44
|
+
const codingPrompt = (0, external_node_fs_namespaceObject.readFileSync)(codingAgentPath, "utf-8");
|
|
45
|
+
(0, external_vitest_namespaceObject.expect)(codingPrompt).toContain("write_todos");
|
|
46
|
+
(0, external_vitest_namespaceObject.expect)(codingPrompt).not.toContain("update_plan");
|
|
47
|
+
(0, external_vitest_namespaceObject.expect)(codingPrompt).not.toContain("subAgents:");
|
|
48
|
+
(0, external_vitest_namespaceObject.expect)(codingPrompt).toContain("Do not delegate coding work to subagents");
|
|
49
|
+
const codingV2AgentPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding-v2", "agent.md");
|
|
50
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingV2AgentPath)).toBe(true);
|
|
51
|
+
const codingV2Prompt = (0, external_node_fs_namespaceObject.readFileSync)(codingV2AgentPath, "utf-8");
|
|
52
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("name: coding-v2");
|
|
53
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("subAgents:");
|
|
54
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("name: coding-worker");
|
|
55
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("promptFile: ./implementor.md");
|
|
56
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("`task` tool");
|
|
57
|
+
(0, external_vitest_namespaceObject.expect)(codingV2Prompt).toContain("write_todos");
|
|
58
|
+
const codingV2ImplementorPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding-v2", "implementor.md");
|
|
59
|
+
const codingV2PlannerPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding-v2", "planner.md");
|
|
60
|
+
const codingV2ReviewerPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding-v2", "reviewer.md");
|
|
61
|
+
const codingV2ResearcherPath = (0, external_node_path_namespaceObject.join)(workspace, ".wingman", "agents", "coding-v2", "researcher.md");
|
|
62
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingV2ImplementorPath)).toBe(true);
|
|
63
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingV2PlannerPath)).toBe(false);
|
|
64
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingV2ReviewerPath)).toBe(false);
|
|
65
|
+
(0, external_vitest_namespaceObject.expect)((0, external_node_fs_namespaceObject.existsSync)(codingV2ResearcherPath)).toBe(false);
|
|
42
66
|
});
|
|
43
67
|
(0, external_vitest_namespaceObject.it)("merges existing config when --merge is set", async ()=>{
|
|
44
68
|
const configDir = (0, external_node_path_namespaceObject.join)(workspace, ".wingman");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import { executeInitCommand } from "../cli/commands/init.js";
|
|
3
1
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
2
|
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { executeInitCommand } from "../cli/commands/init.js";
|
|
6
6
|
describe("CLI init", ()=>{
|
|
7
7
|
let workspace;
|
|
8
8
|
beforeEach(()=>{
|
|
@@ -37,6 +37,30 @@ describe("CLI init", ()=>{
|
|
|
37
37
|
expect(existsSync(agentPath)).toBe(true);
|
|
38
38
|
const agent = JSON.parse(readFileSync(agentPath, "utf-8"));
|
|
39
39
|
expect(agent.name).toBe("wingman");
|
|
40
|
+
const codingAgentPath = join(workspace, ".wingman", "agents", "coding", "agent.md");
|
|
41
|
+
expect(existsSync(codingAgentPath)).toBe(true);
|
|
42
|
+
const codingPrompt = readFileSync(codingAgentPath, "utf-8");
|
|
43
|
+
expect(codingPrompt).toContain("write_todos");
|
|
44
|
+
expect(codingPrompt).not.toContain("update_plan");
|
|
45
|
+
expect(codingPrompt).not.toContain("subAgents:");
|
|
46
|
+
expect(codingPrompt).toContain("Do not delegate coding work to subagents");
|
|
47
|
+
const codingV2AgentPath = join(workspace, ".wingman", "agents", "coding-v2", "agent.md");
|
|
48
|
+
expect(existsSync(codingV2AgentPath)).toBe(true);
|
|
49
|
+
const codingV2Prompt = readFileSync(codingV2AgentPath, "utf-8");
|
|
50
|
+
expect(codingV2Prompt).toContain("name: coding-v2");
|
|
51
|
+
expect(codingV2Prompt).toContain("subAgents:");
|
|
52
|
+
expect(codingV2Prompt).toContain("name: coding-worker");
|
|
53
|
+
expect(codingV2Prompt).toContain("promptFile: ./implementor.md");
|
|
54
|
+
expect(codingV2Prompt).toContain("`task` tool");
|
|
55
|
+
expect(codingV2Prompt).toContain("write_todos");
|
|
56
|
+
const codingV2ImplementorPath = join(workspace, ".wingman", "agents", "coding-v2", "implementor.md");
|
|
57
|
+
const codingV2PlannerPath = join(workspace, ".wingman", "agents", "coding-v2", "planner.md");
|
|
58
|
+
const codingV2ReviewerPath = join(workspace, ".wingman", "agents", "coding-v2", "reviewer.md");
|
|
59
|
+
const codingV2ResearcherPath = join(workspace, ".wingman", "agents", "coding-v2", "researcher.md");
|
|
60
|
+
expect(existsSync(codingV2ImplementorPath)).toBe(true);
|
|
61
|
+
expect(existsSync(codingV2PlannerPath)).toBe(false);
|
|
62
|
+
expect(existsSync(codingV2ReviewerPath)).toBe(false);
|
|
63
|
+
expect(existsSync(codingV2ResearcherPath)).toBe(false);
|
|
40
64
|
});
|
|
41
65
|
it("merges existing config when --merge is set", async ()=>{
|
|
42
66
|
const configDir = join(workspace, ".wingman");
|
|
@@ -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
|
+
});
|