Skip to content

Commit e4da6f1

Browse files
tylergibbs1claude
andcommitted
Add missing test coverage: session.wait, hosted tool validation, debug streaming, baseUrl
- session.wait(): returns result, multi-turn, throws without send(), throws on closed - validateAgent: hosted + function tool name collision, empty tools - debug mode: stream(), session debug option - resolveResponsesBaseUrl: standard, foundry, full_url with/without /responses 683 total unit tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f04e8cc commit e4da6f1

4 files changed

Lines changed: 144 additions & 1 deletion

File tree

packages/stratus-sdk/tests/azure/endpoint.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
22
import {
33
detectEndpointKind,
44
resolveChatCompletionsUrl,
5+
resolveResponsesBaseUrl,
56
resolveResponsesUrl,
67
} from "../../src/azure/endpoint";
78

@@ -124,3 +125,46 @@ describe("resolveResponsesUrl", () => {
124125
expect(url).toBe("https://myresource.openai.azure.com/openai/v1/responses");
125126
});
126127
});
128+
129+
describe("resolveResponsesBaseUrl", () => {
130+
test("standard endpoint", () => {
131+
const url = resolveResponsesBaseUrl(
132+
"https://myresource.openai.azure.com",
133+
"2025-04-01-preview",
134+
);
135+
expect(url).toBe("https://myresource.openai.azure.com/openai/v1/responses");
136+
});
137+
138+
test("foundry endpoint includes api-version", () => {
139+
const url = resolveResponsesBaseUrl(
140+
"https://myproject.services.ai.azure.com",
141+
"2025-04-01-preview",
142+
);
143+
expect(url).toContain("api-version=2025-04-01-preview");
144+
expect(url).toContain("/openai/responses");
145+
});
146+
147+
test("full_url with /responses strips trailing path", () => {
148+
const url = resolveResponsesBaseUrl(
149+
"https://myresource.openai.azure.com/openai/v1/responses",
150+
"ignored",
151+
);
152+
expect(url).toBe("https://myresource.openai.azure.com/openai/v1/responses");
153+
});
154+
155+
test("full_url without /responses falls back to standard format", () => {
156+
const url = resolveResponsesBaseUrl(
157+
"https://myresource.openai.azure.com/openai/deployments/gpt-4o/chat/completions",
158+
"ignored",
159+
);
160+
expect(url).toBe("https://myresource.openai.azure.com/openai/v1/responses");
161+
});
162+
163+
test("full_url with /openai/deployments/ but no /responses falls back", () => {
164+
const url = resolveResponsesBaseUrl(
165+
"https://myresource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2025-03-01",
166+
"ignored",
167+
);
168+
expect(url).toBe("https://myresource.openai.azure.com/openai/v1/responses");
169+
});
170+
});

packages/stratus-sdk/tests/core/debug.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
22
import { z } from "zod";
33
import { Agent } from "../../src/core/agent";
4-
import { run } from "../../src/core/run";
4+
import { run, stream } from "../../src/core/run";
5+
import { createSession } from "../../src/core/session";
56
import { tool } from "../../src/core/tool";
67
import { createMockModel, textResponse, toolCallResponse } from "../../src/testing/index";
78

@@ -66,4 +67,30 @@ describe("debug mode", () => {
6667
expect(output).toContain("add");
6768
expect(output).toContain("results");
6869
});
70+
71+
test("logs with stream()", async () => {
72+
const model = createMockModel([textResponse("Streamed!")]);
73+
const agent = new Agent({ name: "streamer", model });
74+
75+
const { stream: s, result } = stream(agent, "Hi", { debug: true });
76+
for await (const _event of s) {
77+
// drain
78+
}
79+
await result;
80+
81+
const output = stderrOutput.join("");
82+
expect(output).toContain("[stratus:model]");
83+
expect(output).toContain("stream request to streamer");
84+
});
85+
86+
test("logs with session debug option", async () => {
87+
const model = createMockModel([textResponse("Session debug!")]);
88+
const session = createSession({ model, debug: true });
89+
90+
session.send("Hi");
91+
await session.wait();
92+
93+
const output = stderrOutput.join("");
94+
expect(output).toContain("[stratus:model]");
95+
});
6996
});

packages/stratus-sdk/tests/core/session.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,53 @@ describe("session", () => {
337337
expect(s1.id).not.toBe(s2.id);
338338
});
339339
});
340+
341+
describe("session.wait()", () => {
342+
test("returns result without manual stream draining", async () => {
343+
const model = mockModel([{ content: "Hello from wait!", toolCalls: [] }]);
344+
const session = createSession({ model });
345+
346+
session.send("Hi");
347+
const result = await session.wait();
348+
349+
expect(result.output).toBe("Hello from wait!");
350+
});
351+
352+
test("multi-turn with wait()", async () => {
353+
const model = mockModel([
354+
{ content: "First", toolCalls: [] },
355+
{ content: "Second", toolCalls: [] },
356+
]);
357+
const session = createSession({ model });
358+
359+
session.send("Turn 1");
360+
const r1 = await session.wait();
361+
expect(r1.output).toBe("First");
362+
363+
session.send("Turn 2");
364+
const r2 = await session.wait();
365+
expect(r2.output).toBe("Second");
366+
});
367+
368+
test("throws if called without send()", async () => {
369+
const model = mockModel([
370+
{ content: "First", toolCalls: [] },
371+
]);
372+
const session = createSession({ model });
373+
374+
// First: normal flow
375+
session.send("Hi");
376+
await session.wait();
377+
378+
// Second: no send() before wait()
379+
expect(() => session.wait()).toThrow("No new message");
380+
});
381+
382+
test("throws on closed session", async () => {
383+
const model = mockModel([{ content: "Hi", toolCalls: [] }]);
384+
const session = createSession({ model });
385+
session.close();
386+
387+
expect(() => session.wait()).toThrow("closed");
388+
});
389+
});

packages/stratus-sdk/tests/core/validate-agent.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,26 @@ describe("Agent constructor validation", () => {
108108
expect(agent.name).toBe("good");
109109
expect(agent.tools).toHaveLength(2);
110110
});
111+
112+
test("detects collision between hosted tool and function tool with same name", () => {
113+
const hostedTool = {
114+
type: "hosted" as const,
115+
name: "web_search_preview",
116+
definition: { type: "web_search_preview" },
117+
};
118+
const functionTool = dummyTool("web_search_preview");
119+
120+
expect(
121+
() =>
122+
new Agent({
123+
name: "collision",
124+
tools: [hostedTool, functionTool],
125+
}),
126+
).toThrow("Duplicate tool name");
127+
});
128+
129+
test("agent with no tools validates cleanly", () => {
130+
const agent = new Agent({ name: "empty" });
131+
expect(agent.tools).toHaveLength(0);
132+
});
111133
});

0 commit comments

Comments
 (0)