@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
|
@@ -14,7 +14,8 @@ const isBun = void 0 !== globalThis.Bun;
|
|
|
14
14
|
const describeIfBun = isBun ? describe : describe.skip;
|
|
15
15
|
vi.mock("@/cli/core/agentInvoker.js", ()=>({
|
|
16
16
|
AgentInvoker: class {
|
|
17
|
-
async invokeAgent(_agentId,
|
|
17
|
+
async invokeAgent(_agentId, content, _sessionId, _attachments, options) {
|
|
18
|
+
if ("throw-no-event" === content) throw new Error("Synthetic invocation failure");
|
|
18
19
|
const signal = options?.signal;
|
|
19
20
|
await new Promise((resolve)=>{
|
|
20
21
|
const timer = setTimeout(resolve, 75);
|
|
@@ -173,14 +174,15 @@ describeIfBun("Gateway", ()=>{
|
|
|
173
174
|
}));
|
|
174
175
|
it("should broadcast messages to group members", async ()=>new Promise((resolve, reject)=>{
|
|
175
176
|
let client1NodeId = null;
|
|
176
|
-
let
|
|
177
|
+
let broadcastGroupId = null;
|
|
177
178
|
const client1 = new GatewayClient(`ws://localhost:${port}/ws`, "broadcaster", {
|
|
178
179
|
events: {
|
|
179
180
|
registered: async (nodeId)=>{
|
|
180
181
|
client1NodeId = nodeId;
|
|
181
182
|
await client1.joinGroup("broadcast-test");
|
|
182
183
|
},
|
|
183
|
-
joinedGroup: ()=>{
|
|
184
|
+
joinedGroup: (groupId)=>{
|
|
185
|
+
broadcastGroupId = groupId;
|
|
184
186
|
client2.connect().catch(reject);
|
|
185
187
|
}
|
|
186
188
|
}
|
|
@@ -191,14 +193,13 @@ describeIfBun("Gateway", ()=>{
|
|
|
191
193
|
await client2.joinGroup("broadcast-test");
|
|
192
194
|
},
|
|
193
195
|
joinedGroup: ()=>{
|
|
194
|
-
client1.broadcast("broadcast-test", {
|
|
196
|
+
client1.broadcast(broadcastGroupId || "broadcast-test", {
|
|
195
197
|
message: "Hello from client 1"
|
|
196
198
|
});
|
|
197
199
|
},
|
|
198
200
|
broadcast: (message, fromNodeId)=>{
|
|
199
201
|
expect(fromNodeId).toBe(client1NodeId);
|
|
200
202
|
expect(message.message).toBe("Hello from client 1");
|
|
201
|
-
messagesReceived++;
|
|
202
203
|
client1.disconnect();
|
|
203
204
|
client2.disconnect();
|
|
204
205
|
resolve();
|
|
@@ -331,6 +332,26 @@ describeIfBun("Gateway", ()=>{
|
|
|
331
332
|
desktopClient.close();
|
|
332
333
|
requester.close();
|
|
333
334
|
});
|
|
335
|
+
it("should emit agent-error to requester when invocation throws without emitting", async ()=>{
|
|
336
|
+
const requester = await connectClient("session-error-requester");
|
|
337
|
+
const requestId = "req-invocation-error";
|
|
338
|
+
const sessionId = "session-error-test";
|
|
339
|
+
requester.send(JSON.stringify({
|
|
340
|
+
type: "req:agent",
|
|
341
|
+
id: requestId,
|
|
342
|
+
payload: {
|
|
343
|
+
agentId: "main",
|
|
344
|
+
sessionKey: sessionId,
|
|
345
|
+
content: "throw-no-event"
|
|
346
|
+
},
|
|
347
|
+
timestamp: Date.now()
|
|
348
|
+
}));
|
|
349
|
+
const errorMsg = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-error");
|
|
350
|
+
expect(errorMsg.payload?.error).toContain("Synthetic invocation failure");
|
|
351
|
+
expect(errorMsg.payload?.sessionId).toBe(sessionId);
|
|
352
|
+
expect(errorMsg.payload?.agentId).toBe("main");
|
|
353
|
+
requester.close();
|
|
354
|
+
});
|
|
334
355
|
it("should cancel an in-flight agent request", async ()=>{
|
|
335
356
|
const requester = await connectClient("session-cancel-requester");
|
|
336
357
|
const requestId = "req-cancel-test";
|
|
@@ -359,6 +380,92 @@ describeIfBun("Gateway", ()=>{
|
|
|
359
380
|
]).toContain(ack.payload?.status);
|
|
360
381
|
requester.close();
|
|
361
382
|
});
|
|
383
|
+
it("should queue and dequeue requests for the same session", async ()=>{
|
|
384
|
+
const requester = await connectClient("session-queue-requester");
|
|
385
|
+
const sessionId = `session-queue-${Date.now()}`;
|
|
386
|
+
const firstRequestId = `req-queue-first-${Date.now()}`;
|
|
387
|
+
const secondRequestId = `req-queue-second-${Date.now()}`;
|
|
388
|
+
const firstCompletePromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === firstRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
389
|
+
const queuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "queued", 10000);
|
|
390
|
+
const queuedEventPromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === secondRequestId && msg.payload?.type === "request-queued", 10000);
|
|
391
|
+
const dequeuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "dequeued", 10000);
|
|
392
|
+
const secondCompletePromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === secondRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
393
|
+
requester.send(JSON.stringify({
|
|
394
|
+
type: "req:agent",
|
|
395
|
+
id: firstRequestId,
|
|
396
|
+
payload: {
|
|
397
|
+
agentId: "main",
|
|
398
|
+
sessionKey: sessionId,
|
|
399
|
+
content: "First queued request"
|
|
400
|
+
},
|
|
401
|
+
timestamp: Date.now()
|
|
402
|
+
}));
|
|
403
|
+
requester.send(JSON.stringify({
|
|
404
|
+
type: "req:agent",
|
|
405
|
+
id: secondRequestId,
|
|
406
|
+
payload: {
|
|
407
|
+
agentId: "main",
|
|
408
|
+
sessionKey: sessionId,
|
|
409
|
+
content: "Second queued request"
|
|
410
|
+
},
|
|
411
|
+
timestamp: Date.now()
|
|
412
|
+
}));
|
|
413
|
+
const queuedAck = await queuedAckPromise;
|
|
414
|
+
expect(queuedAck.payload?.position).toBe(1);
|
|
415
|
+
const queuedEvent = await queuedEventPromise;
|
|
416
|
+
expect(queuedEvent.payload?.position).toBe(1);
|
|
417
|
+
expect(queuedEvent.payload?.sessionId).toBe(sessionId);
|
|
418
|
+
await firstCompletePromise;
|
|
419
|
+
const dequeuedAck = await dequeuedAckPromise;
|
|
420
|
+
expect(dequeuedAck.payload?.remaining).toBe(0);
|
|
421
|
+
await secondCompletePromise;
|
|
422
|
+
requester.close();
|
|
423
|
+
});
|
|
424
|
+
it("should cancel a queued request", async ()=>{
|
|
425
|
+
const requester = await connectClient("session-cancel-queued-requester");
|
|
426
|
+
const sessionId = `session-cancel-queued-${Date.now()}`;
|
|
427
|
+
const firstRequestId = `req-cancel-queued-first-${Date.now()}`;
|
|
428
|
+
const secondRequestId = `req-cancel-queued-second-${Date.now()}`;
|
|
429
|
+
const queuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "queued", 10000);
|
|
430
|
+
requester.send(JSON.stringify({
|
|
431
|
+
type: "req:agent",
|
|
432
|
+
id: firstRequestId,
|
|
433
|
+
payload: {
|
|
434
|
+
agentId: "main",
|
|
435
|
+
sessionKey: sessionId,
|
|
436
|
+
content: "First request"
|
|
437
|
+
},
|
|
438
|
+
timestamp: Date.now()
|
|
439
|
+
}));
|
|
440
|
+
requester.send(JSON.stringify({
|
|
441
|
+
type: "req:agent",
|
|
442
|
+
id: secondRequestId,
|
|
443
|
+
payload: {
|
|
444
|
+
agentId: "main",
|
|
445
|
+
sessionKey: sessionId,
|
|
446
|
+
content: "Second request"
|
|
447
|
+
},
|
|
448
|
+
timestamp: Date.now()
|
|
449
|
+
}));
|
|
450
|
+
await queuedAckPromise;
|
|
451
|
+
requester.send(JSON.stringify({
|
|
452
|
+
type: "req:agent:cancel",
|
|
453
|
+
id: `cancel-${secondRequestId}`,
|
|
454
|
+
payload: {
|
|
455
|
+
requestId: secondRequestId
|
|
456
|
+
},
|
|
457
|
+
timestamp: Date.now()
|
|
458
|
+
}));
|
|
459
|
+
const cancelAck = await waitForMessage(requester, (msg)=>"ack" === msg.type && msg.payload?.action === "req:agent:cancel" && msg.payload?.requestId === secondRequestId && msg.payload?.status === "cancelled_queued", 10000);
|
|
460
|
+
expect(cancelAck.payload?.status).toBe("cancelled_queued");
|
|
461
|
+
await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === firstRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
462
|
+
const queuedRequests = server.queuedSessionRequests;
|
|
463
|
+
const isStillQueued = [
|
|
464
|
+
...queuedRequests.values()
|
|
465
|
+
].some((queue)=>queue.some((item)=>item.msg?.id === secondRequestId));
|
|
466
|
+
expect(isStillQueued).toBe(false);
|
|
467
|
+
requester.close();
|
|
468
|
+
});
|
|
362
469
|
it("should clear session messages via API", async ()=>{
|
|
363
470
|
const createRes = await fetch(`http://localhost:${port}/api/sessions`, {
|
|
364
471
|
method: "POST",
|
|
@@ -366,18 +473,18 @@ describeIfBun("Gateway", ()=>{
|
|
|
366
473
|
"Content-Type": "application/json"
|
|
367
474
|
},
|
|
368
475
|
body: JSON.stringify({
|
|
369
|
-
agentId: "main",
|
|
370
476
|
name: "Clear Test"
|
|
371
477
|
})
|
|
372
478
|
});
|
|
373
479
|
expect(createRes.ok).toBe(true);
|
|
374
480
|
const session = await createRes.json();
|
|
375
|
-
const
|
|
481
|
+
const sessionAgentId = session.agentId || "main";
|
|
482
|
+
const manager = await server.getSessionManager(sessionAgentId);
|
|
376
483
|
manager.updateSession(session.id, {
|
|
377
484
|
messageCount: 3,
|
|
378
485
|
lastMessagePreview: "Hello"
|
|
379
486
|
});
|
|
380
|
-
const clearRes = await fetch(`http://localhost:${port}/api/sessions/${encodeURIComponent(session.id)}/messages?agentId
|
|
487
|
+
const clearRes = await fetch(`http://localhost:${port}/api/sessions/${encodeURIComponent(session.id)}/messages?agentId=${encodeURIComponent(sessionAgentId)}`, {
|
|
381
488
|
method: "DELETE"
|
|
382
489
|
});
|
|
383
490
|
expect(clearRes.ok).toBe(true);
|
|
@@ -0,0 +1,57 @@
|
|
|
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 provider_cjs_namespaceObject = require("../cli/commands/provider.cjs");
|
|
8
|
+
const codex_cjs_namespaceObject = require("../providers/codex.cjs");
|
|
9
|
+
(0, external_vitest_namespaceObject.describe)("provider command codex login", ()=>{
|
|
10
|
+
let codexHome;
|
|
11
|
+
const originalCodexHome = process.env.CODEX_HOME;
|
|
12
|
+
(0, external_vitest_namespaceObject.beforeEach)(()=>{
|
|
13
|
+
codexHome = (0, external_node_fs_namespaceObject.mkdtempSync)((0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), "wingman-provider-codex-"));
|
|
14
|
+
process.env.CODEX_HOME = codexHome;
|
|
15
|
+
});
|
|
16
|
+
(0, external_vitest_namespaceObject.afterEach)(()=>{
|
|
17
|
+
if (void 0 === originalCodexHome) delete process.env.CODEX_HOME;
|
|
18
|
+
else process.env.CODEX_HOME = originalCodexHome;
|
|
19
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(codexHome)) (0, external_node_fs_namespaceObject.rmSync)(codexHome, {
|
|
20
|
+
recursive: true,
|
|
21
|
+
force: true
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
(0, external_vitest_namespaceObject.it)("uses existing codex login without requiring a token", async ()=>{
|
|
25
|
+
const authPath = (0, codex_cjs_namespaceObject.getCodexAuthPath)();
|
|
26
|
+
(0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(authPath), {
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(authPath, JSON.stringify({
|
|
30
|
+
tokens: {
|
|
31
|
+
access_token: "codex-access-token",
|
|
32
|
+
account_id: "acct_123"
|
|
33
|
+
}
|
|
34
|
+
}, null, 2));
|
|
35
|
+
const exitSpy = external_vitest_namespaceObject.vi.spyOn(process, "exit").mockImplementation((code)=>{
|
|
36
|
+
throw new Error(`process.exit(${code ?? "undefined"})`);
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
await (0, external_vitest_namespaceObject.expect)((0, provider_cjs_namespaceObject.executeProviderCommand)({
|
|
40
|
+
subcommand: "login",
|
|
41
|
+
args: [
|
|
42
|
+
"codex"
|
|
43
|
+
],
|
|
44
|
+
verbosity: "silent",
|
|
45
|
+
outputMode: "json",
|
|
46
|
+
options: {}
|
|
47
|
+
})).resolves.toBeUndefined();
|
|
48
|
+
(0, external_vitest_namespaceObject.expect)(exitSpy).not.toHaveBeenCalled();
|
|
49
|
+
} finally{
|
|
50
|
+
exitSpy.mockRestore();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
55
|
+
Object.defineProperty(exports, '__esModule', {
|
|
56
|
+
value: true
|
|
57
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, 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
|
+
import { executeProviderCommand } from "../cli/commands/provider.js";
|
|
6
|
+
import { getCodexAuthPath } from "../providers/codex.js";
|
|
7
|
+
describe("provider command codex login", ()=>{
|
|
8
|
+
let codexHome;
|
|
9
|
+
const originalCodexHome = process.env.CODEX_HOME;
|
|
10
|
+
beforeEach(()=>{
|
|
11
|
+
codexHome = mkdtempSync(join(tmpdir(), "wingman-provider-codex-"));
|
|
12
|
+
process.env.CODEX_HOME = codexHome;
|
|
13
|
+
});
|
|
14
|
+
afterEach(()=>{
|
|
15
|
+
if (void 0 === originalCodexHome) delete process.env.CODEX_HOME;
|
|
16
|
+
else process.env.CODEX_HOME = originalCodexHome;
|
|
17
|
+
if (existsSync(codexHome)) rmSync(codexHome, {
|
|
18
|
+
recursive: true,
|
|
19
|
+
force: true
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
it("uses existing codex login without requiring a token", async ()=>{
|
|
23
|
+
const authPath = getCodexAuthPath();
|
|
24
|
+
mkdirSync(dirname(authPath), {
|
|
25
|
+
recursive: true
|
|
26
|
+
});
|
|
27
|
+
writeFileSync(authPath, JSON.stringify({
|
|
28
|
+
tokens: {
|
|
29
|
+
access_token: "codex-access-token",
|
|
30
|
+
account_id: "acct_123"
|
|
31
|
+
}
|
|
32
|
+
}, null, 2));
|
|
33
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation((code)=>{
|
|
34
|
+
throw new Error(`process.exit(${code ?? "undefined"})`);
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
await expect(executeProviderCommand({
|
|
38
|
+
subcommand: "login",
|
|
39
|
+
args: [
|
|
40
|
+
"codex"
|
|
41
|
+
],
|
|
42
|
+
verbosity: "silent",
|
|
43
|
+
outputMode: "json",
|
|
44
|
+
options: {}
|
|
45
|
+
})).resolves.toBeUndefined();
|
|
46
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
47
|
+
} finally{
|
|
48
|
+
exitSpy.mockRestore();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -65,6 +65,44 @@ const sessionManager_cjs_namespaceObject = require("../cli/core/sessionManager.c
|
|
|
65
65
|
content: "keep"
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
|
+
(0, external_vitest_namespaceObject.it)("extracts content from responses-style text blocks", ()=>{
|
|
69
|
+
const state = {
|
|
70
|
+
createdAt: 2000,
|
|
71
|
+
values: {
|
|
72
|
+
messages: [
|
|
73
|
+
{
|
|
74
|
+
role: "user",
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "input_text",
|
|
78
|
+
text: "Build a plan"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
role: "assistant",
|
|
84
|
+
content: [
|
|
85
|
+
{
|
|
86
|
+
type: "output_text",
|
|
87
|
+
text: "Here is the plan."
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const result = (0, sessionManager_cjs_namespaceObject.extractMessagesFromState)(state);
|
|
95
|
+
(0, external_vitest_namespaceObject.expect)(result).not.toBeNull();
|
|
96
|
+
(0, external_vitest_namespaceObject.expect)(result).toHaveLength(2);
|
|
97
|
+
(0, external_vitest_namespaceObject.expect)(result?.[0]).toMatchObject({
|
|
98
|
+
role: "user",
|
|
99
|
+
content: "Build a plan"
|
|
100
|
+
});
|
|
101
|
+
(0, external_vitest_namespaceObject.expect)(result?.[1]).toMatchObject({
|
|
102
|
+
role: "assistant",
|
|
103
|
+
content: "Here is the plan."
|
|
104
|
+
});
|
|
105
|
+
});
|
|
68
106
|
});
|
|
69
107
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
70
108
|
Object.defineProperty(exports, '__esModule', {
|
|
@@ -63,4 +63,42 @@ describe("extractMessagesFromState", ()=>{
|
|
|
63
63
|
content: "keep"
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
+
it("extracts content from responses-style text blocks", ()=>{
|
|
67
|
+
const state = {
|
|
68
|
+
createdAt: 2000,
|
|
69
|
+
values: {
|
|
70
|
+
messages: [
|
|
71
|
+
{
|
|
72
|
+
role: "user",
|
|
73
|
+
content: [
|
|
74
|
+
{
|
|
75
|
+
type: "input_text",
|
|
76
|
+
text: "Build a plan"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
role: "assistant",
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "output_text",
|
|
85
|
+
text: "Here is the plan."
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const result = extractMessagesFromState(state);
|
|
93
|
+
expect(result).not.toBeNull();
|
|
94
|
+
expect(result).toHaveLength(2);
|
|
95
|
+
expect(result?.[0]).toMatchObject({
|
|
96
|
+
role: "user",
|
|
97
|
+
content: "Build a plan"
|
|
98
|
+
});
|
|
99
|
+
expect(result?.[1]).toMatchObject({
|
|
100
|
+
role: "assistant",
|
|
101
|
+
content: "Here is the plan."
|
|
102
|
+
});
|
|
103
|
+
});
|
|
66
104
|
});
|
|
@@ -19,6 +19,9 @@ const toolDisplayHelpers_cjs_namespaceObject = require("../cli/ui/toolDisplayHel
|
|
|
19
19
|
(0, external_vitest_namespaceObject.expect)((0, toolDisplayHelpers_cjs_namespaceObject.extractSubagentName)({
|
|
20
20
|
subagent: "Runner"
|
|
21
21
|
})).toBe("Runner");
|
|
22
|
+
(0, external_vitest_namespaceObject.expect)((0, toolDisplayHelpers_cjs_namespaceObject.extractSubagentName)({
|
|
23
|
+
subagent_type: "reviewer"
|
|
24
|
+
})).toBe("reviewer");
|
|
22
25
|
(0, external_vitest_namespaceObject.expect)((0, toolDisplayHelpers_cjs_namespaceObject.extractSubagentName)({
|
|
23
26
|
agent: {
|
|
24
27
|
name: "Writer"
|
|
@@ -17,6 +17,9 @@ describe("toolDisplayHelpers", ()=>{
|
|
|
17
17
|
expect(extractSubagentName({
|
|
18
18
|
subagent: "Runner"
|
|
19
19
|
})).toBe("Runner");
|
|
20
|
+
expect(extractSubagentName({
|
|
21
|
+
subagent_type: "reviewer"
|
|
22
|
+
})).toBe("reviewer");
|
|
20
23
|
expect(extractSubagentName({
|
|
21
24
|
agent: {
|
|
22
25
|
name: "Writer"
|
|
@@ -246,8 +246,8 @@ var __webpack_modules__ = {
|
|
|
246
246
|
server.registerTool("finnhub.symbolSearch", {
|
|
247
247
|
title: "Finnhub Symbol Search",
|
|
248
248
|
description: "Search for symbols or companies by query.",
|
|
249
|
-
inputSchema: zod__rspack_import_2.
|
|
250
|
-
query: zod__rspack_import_2.
|
|
249
|
+
inputSchema: zod__rspack_import_2.object({
|
|
250
|
+
query: zod__rspack_import_2.string().min(1)
|
|
251
251
|
})
|
|
252
252
|
}, async ({ query })=>{
|
|
253
253
|
const data = await fetchFinnhub("/search", {
|
|
@@ -258,8 +258,8 @@ var __webpack_modules__ = {
|
|
|
258
258
|
server.registerTool("finnhub.quote", {
|
|
259
259
|
title: "Finnhub Quote",
|
|
260
260
|
description: "Get the latest quote for a symbol.",
|
|
261
|
-
inputSchema: zod__rspack_import_2.
|
|
262
|
-
symbol: zod__rspack_import_2.
|
|
261
|
+
inputSchema: zod__rspack_import_2.object({
|
|
262
|
+
symbol: zod__rspack_import_2.string().min(1)
|
|
263
263
|
})
|
|
264
264
|
}, async ({ symbol })=>{
|
|
265
265
|
const data = await fetchFinnhub("/quote", {
|
|
@@ -270,8 +270,8 @@ var __webpack_modules__ = {
|
|
|
270
270
|
server.registerTool("finnhub.companyProfile", {
|
|
271
271
|
title: "Finnhub Company Profile",
|
|
272
272
|
description: "Get company profile data for a symbol.",
|
|
273
|
-
inputSchema: zod__rspack_import_2.
|
|
274
|
-
symbol: zod__rspack_import_2.
|
|
273
|
+
inputSchema: zod__rspack_import_2.object({
|
|
274
|
+
symbol: zod__rspack_import_2.string().min(1)
|
|
275
275
|
})
|
|
276
276
|
}, async ({ symbol })=>{
|
|
277
277
|
const data = await fetchFinnhub("/stock/profile2", {
|
|
@@ -282,9 +282,9 @@ var __webpack_modules__ = {
|
|
|
282
282
|
server.registerTool("finnhub.financials", {
|
|
283
283
|
title: "Finnhub Financial Metrics",
|
|
284
284
|
description: "Get financial metrics (including P/E) for a symbol.",
|
|
285
|
-
inputSchema: zod__rspack_import_2.
|
|
286
|
-
symbol: zod__rspack_import_2.
|
|
287
|
-
metric: zod__rspack_import_2.
|
|
285
|
+
inputSchema: zod__rspack_import_2.object({
|
|
286
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
287
|
+
metric: zod__rspack_import_2.string().optional().default("all")
|
|
288
288
|
})
|
|
289
289
|
}, async ({ symbol, metric })=>{
|
|
290
290
|
const data = await fetchFinnhub("/stock/metric", {
|
|
@@ -296,9 +296,9 @@ var __webpack_modules__ = {
|
|
|
296
296
|
server.registerTool("finnhub.earnings", {
|
|
297
297
|
title: "Finnhub Earnings",
|
|
298
298
|
description: "Get earnings history for a symbol.",
|
|
299
|
-
inputSchema: zod__rspack_import_2.
|
|
300
|
-
symbol: zod__rspack_import_2.
|
|
301
|
-
limit: zod__rspack_import_2.
|
|
299
|
+
inputSchema: zod__rspack_import_2.object({
|
|
300
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
301
|
+
limit: zod__rspack_import_2.number().int().min(1).max(20).optional()
|
|
302
302
|
})
|
|
303
303
|
}, async ({ symbol, limit })=>{
|
|
304
304
|
const data = await fetchFinnhub("/stock/earnings", {
|
|
@@ -312,10 +312,10 @@ var __webpack_modules__ = {
|
|
|
312
312
|
server.registerTool("finnhub.news", {
|
|
313
313
|
title: "Finnhub Company News",
|
|
314
314
|
description: "Get recent company news for a symbol.",
|
|
315
|
-
inputSchema: zod__rspack_import_2.
|
|
316
|
-
symbol: zod__rspack_import_2.
|
|
317
|
-
from: zod__rspack_import_2.
|
|
318
|
-
to: zod__rspack_import_2.
|
|
315
|
+
inputSchema: zod__rspack_import_2.object({
|
|
316
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
317
|
+
from: zod__rspack_import_2.string().optional(),
|
|
318
|
+
to: zod__rspack_import_2.string().optional()
|
|
319
319
|
})
|
|
320
320
|
}, async ({ symbol, from, to })=>{
|
|
321
321
|
const toDate = to || new Date().toISOString().slice(0, 10);
|
|
@@ -335,8 +335,8 @@ var __webpack_modules__ = {
|
|
|
335
335
|
server.registerTool("finnhub.marketNews", {
|
|
336
336
|
title: "Finnhub Market News",
|
|
337
337
|
description: "Get broad market news (general category) for theme detection.",
|
|
338
|
-
inputSchema: zod__rspack_import_2.
|
|
339
|
-
category: zod__rspack_import_2.
|
|
338
|
+
inputSchema: zod__rspack_import_2.object({
|
|
339
|
+
category: zod__rspack_import_2.string().min(1).optional().default("general")
|
|
340
340
|
})
|
|
341
341
|
}, async ({ category })=>{
|
|
342
342
|
const data = await fetchFinnhub("/news", {
|
|
@@ -347,8 +347,8 @@ var __webpack_modules__ = {
|
|
|
347
347
|
server.registerTool("finnhub.peers", {
|
|
348
348
|
title: "Finnhub Stock Peers",
|
|
349
349
|
description: "Get peer symbols for a company.",
|
|
350
|
-
inputSchema: zod__rspack_import_2.
|
|
351
|
-
symbol: zod__rspack_import_2.
|
|
350
|
+
inputSchema: zod__rspack_import_2.object({
|
|
351
|
+
symbol: zod__rspack_import_2.string().min(1)
|
|
352
352
|
})
|
|
353
353
|
}, async ({ symbol })=>{
|
|
354
354
|
const data = await fetchFinnhub("/stock/peers", {
|
|
@@ -359,12 +359,12 @@ var __webpack_modules__ = {
|
|
|
359
359
|
server.registerTool("finnhub.candles", {
|
|
360
360
|
title: "Finnhub Candles",
|
|
361
361
|
description: `Get OHLCV candles for a symbol. ${candleCapSummary} ${candleSourceSummary} ${candleSessionSummary}`,
|
|
362
|
-
inputSchema: zod__rspack_import_2.
|
|
363
|
-
symbol: zod__rspack_import_2.
|
|
364
|
-
resolution: zod__rspack_import_2.
|
|
365
|
-
from: zod__rspack_import_2.
|
|
366
|
-
to: zod__rspack_import_2.
|
|
367
|
-
lookbackDays: zod__rspack_import_2.
|
|
362
|
+
inputSchema: zod__rspack_import_2.object({
|
|
363
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
364
|
+
resolution: zod__rspack_import_2.string().optional().default("D"),
|
|
365
|
+
from: zod__rspack_import_2.number().int().optional(),
|
|
366
|
+
to: zod__rspack_import_2.number().int().optional(),
|
|
367
|
+
lookbackDays: zod__rspack_import_2.number().int().positive().optional()
|
|
368
368
|
})
|
|
369
369
|
}, async ({ symbol, resolution, from, to, lookbackDays })=>{
|
|
370
370
|
const range = (0, _finance_candleRange_js__rspack_import_5.resolveCandleRange)({
|
|
@@ -390,12 +390,12 @@ var __webpack_modules__ = {
|
|
|
390
390
|
server.registerTool("finnhub.technicalSnapshot", {
|
|
391
391
|
title: "Finnhub Technical Snapshot",
|
|
392
392
|
description: `Fetch candles and compute RSI/EMA/ATR locally. ${candleCapSummary} ${candleSourceSummary} ${candleSessionSummary}`,
|
|
393
|
-
inputSchema: zod__rspack_import_2.
|
|
394
|
-
symbol: zod__rspack_import_2.
|
|
395
|
-
resolution: zod__rspack_import_2.
|
|
396
|
-
from: zod__rspack_import_2.
|
|
397
|
-
to: zod__rspack_import_2.
|
|
398
|
-
lookbackDays: zod__rspack_import_2.
|
|
393
|
+
inputSchema: zod__rspack_import_2.object({
|
|
394
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
395
|
+
resolution: zod__rspack_import_2.string().optional().default("D"),
|
|
396
|
+
from: zod__rspack_import_2.number().int().optional(),
|
|
397
|
+
to: zod__rspack_import_2.number().int().optional(),
|
|
398
|
+
lookbackDays: zod__rspack_import_2.number().int().positive().optional()
|
|
399
399
|
})
|
|
400
400
|
}, async ({ symbol, resolution, from, to, lookbackDays })=>{
|
|
401
401
|
const range = (0, _finance_candleRange_js__rspack_import_5.resolveCandleRange)({
|
|
@@ -440,9 +440,9 @@ var __webpack_modules__ = {
|
|
|
440
440
|
server.registerTool("finnhub.optionChain", {
|
|
441
441
|
title: "Finnhub Option Chain",
|
|
442
442
|
description: "Get option chain data for a symbol (date optional).",
|
|
443
|
-
inputSchema: zod__rspack_import_2.
|
|
444
|
-
symbol: zod__rspack_import_2.
|
|
445
|
-
date: zod__rspack_import_2.
|
|
443
|
+
inputSchema: zod__rspack_import_2.object({
|
|
444
|
+
symbol: zod__rspack_import_2.string().min(1),
|
|
445
|
+
date: zod__rspack_import_2.string().optional()
|
|
446
446
|
})
|
|
447
447
|
}, async ({ symbol, date })=>{
|
|
448
448
|
const data = await fetchFinnhub("/stock/option-chain", {
|
|
@@ -456,25 +456,25 @@ var __webpack_modules__ = {
|
|
|
456
456
|
server.registerTool("options.analyze", {
|
|
457
457
|
title: "Options Structure Analyzer",
|
|
458
458
|
description: "Compute payoff metrics and optional Greeks for an options structure using supplied leg prices.",
|
|
459
|
-
inputSchema: zod__rspack_import_2.
|
|
460
|
-
underlyingPrice: zod__rspack_import_2.
|
|
461
|
-
daysToExpiry: zod__rspack_import_2.
|
|
462
|
-
riskFreeRate: zod__rspack_import_2.
|
|
463
|
-
dividendYield: zod__rspack_import_2.
|
|
464
|
-
legs: zod__rspack_import_2.
|
|
465
|
-
type: zod__rspack_import_2
|
|
459
|
+
inputSchema: zod__rspack_import_2.object({
|
|
460
|
+
underlyingPrice: zod__rspack_import_2.number().positive(),
|
|
461
|
+
daysToExpiry: zod__rspack_import_2.number().positive().optional(),
|
|
462
|
+
riskFreeRate: zod__rspack_import_2.number().optional().default(0),
|
|
463
|
+
dividendYield: zod__rspack_import_2.number().optional().default(0),
|
|
464
|
+
legs: zod__rspack_import_2.array(zod__rspack_import_2.object({
|
|
465
|
+
type: zod__rspack_import_2["enum"]([
|
|
466
466
|
"call",
|
|
467
467
|
"put"
|
|
468
468
|
]),
|
|
469
|
-
side: zod__rspack_import_2
|
|
469
|
+
side: zod__rspack_import_2["enum"]([
|
|
470
470
|
"buy",
|
|
471
471
|
"sell"
|
|
472
472
|
]),
|
|
473
|
-
strike: zod__rspack_import_2.
|
|
474
|
-
premium: zod__rspack_import_2.
|
|
475
|
-
qty: zod__rspack_import_2.
|
|
476
|
-
contractMultiplier: zod__rspack_import_2.
|
|
477
|
-
impliedVol: zod__rspack_import_2.
|
|
473
|
+
strike: zod__rspack_import_2.number().positive(),
|
|
474
|
+
premium: zod__rspack_import_2.number().nonnegative(),
|
|
475
|
+
qty: zod__rspack_import_2.number().int().positive().optional(),
|
|
476
|
+
contractMultiplier: zod__rspack_import_2.number().positive().optional(),
|
|
477
|
+
impliedVol: zod__rspack_import_2.number().positive().optional()
|
|
478
478
|
})).min(1)
|
|
479
479
|
})
|
|
480
480
|
}, async (input)=>{
|