test(coding-agent): minor fixes
This commit is contained in:
@@ -285,29 +285,24 @@ describe("streamPiNative event flow", () => {
|
||||
expect((fetchImpl as unknown as ReturnType<typeof spyOn>).mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it("cancels the response body when the caller aborts mid-stream", async () => {
|
||||
let cancelReason: unknown;
|
||||
const blockedBody = new ReadableStream<Uint8Array>({
|
||||
start() {
|
||||
// Never enqueues a terminal event — we abort instead.
|
||||
},
|
||||
cancel(reason) {
|
||||
cancelReason = reason;
|
||||
},
|
||||
});
|
||||
const fetchImpl: FetchImpl = (async () =>
|
||||
new Response(blockedBody, { status: 200, headers: { "Content-Type": "text/event-stream" } })) as FetchImpl;
|
||||
|
||||
it("forwards the caller's AbortSignal to the underlying fetch", async () => {
|
||||
// The real abort path runs through fetch — its body is wired to the
|
||||
// signal by the runtime. We test the contract we guarantee (signal
|
||||
// forwarding); body-cancel hooks are a best-effort backstop on the
|
||||
// `streamProxy` shape, and not worth asserting through a synthetic
|
||||
// `ReadableStream` (whose reader is locked by `readSseJson`, so any
|
||||
// `body.cancel()` would throw a `TypeError("locked")` we then swallow).
|
||||
const captured: { signal?: AbortSignal } = {};
|
||||
const fetchImpl: FetchImpl = (async (_input, init) => {
|
||||
captured.signal = init?.signal ?? undefined;
|
||||
return fakeResponse([{ type: "done", reason: "stop", message: baseAssistant() }]);
|
||||
}) as FetchImpl;
|
||||
const controller = new AbortController();
|
||||
const stream = streamPiNative(fakeModel(), baseContext, {
|
||||
await streamPiNative(fakeModel(), baseContext, {
|
||||
apiKey: "k",
|
||||
fetch: fetchImpl,
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
// Schedule the abort after the request body is in-flight.
|
||||
setTimeout(() => controller.abort(new Error("operator abort")), 5);
|
||||
await expect(stream.result()).rejects.toThrow();
|
||||
expect(String(cancelReason)).toMatch(/aborted/i);
|
||||
}).result();
|
||||
expect(captured.signal).toBe(controller.signal);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -369,7 +369,7 @@ describe("AgentSession python cleanup", () => {
|
||||
expect(EvalTool).toBeDefined();
|
||||
let toolExecutionSettled = false;
|
||||
const toolExecution = EvalTool!
|
||||
.execute("call-id", { input: "```py\nprint('tool')\n```" }, undefined, undefined, undefined)
|
||||
.execute("call-id", { cells: [{ language: "py", code: "print('tool')" }] }, undefined, undefined, undefined)
|
||||
.finally(() => {
|
||||
toolExecutionSettled = true;
|
||||
});
|
||||
@@ -594,7 +594,13 @@ describe("AgentSession python cleanup", () => {
|
||||
expect(EvalTool).toBeDefined();
|
||||
const disposeSession = session.dispose();
|
||||
await expect(
|
||||
EvalTool!.execute("call-id", { input: "```py\nprint('late')\n```" }, undefined, undefined, undefined),
|
||||
EvalTool!.execute(
|
||||
"call-id",
|
||||
{ cells: [{ language: "py", code: "print('late')" }] },
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
),
|
||||
).rejects.toThrow("Python execution is unavailable while session disposal is in progress");
|
||||
await disposeSession;
|
||||
expect(executeSpy).not.toHaveBeenCalled();
|
||||
@@ -629,7 +635,7 @@ describe("AgentSession python cleanup", () => {
|
||||
expect(EvalTool).toBeDefined();
|
||||
const execution = EvalTool!.execute(
|
||||
"call-id",
|
||||
{ input: "```py\nprint('late after artifact')\n```" },
|
||||
{ cells: [{ language: "py", code: "print('late after artifact')" }] },
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
|
||||
@@ -31,12 +31,6 @@ function getSchemaProperties(tool: TaskTool): Record<string, unknown> {
|
||||
return wire.properties ?? {};
|
||||
}
|
||||
|
||||
function getAssignmentDescription(tool: TaskTool): string {
|
||||
const properties = getSchemaProperties(tool);
|
||||
const tasks = properties.tasks as { items?: { properties?: Record<string, { description?: string }> } } | undefined;
|
||||
return tasks?.items?.properties?.assignment?.description ?? "";
|
||||
}
|
||||
|
||||
function getFirstText(result: { content: Array<{ type: string; text?: string }> }): string {
|
||||
const content = result.content.find(part => part.type === "text");
|
||||
return content?.type === "text" ? (content.text ?? "") : "";
|
||||
@@ -61,7 +55,6 @@ describe("task.simple", () => {
|
||||
expect(tool.description).toContain("`context` or `assignment`");
|
||||
expect(tool.description).toContain("- `context`:");
|
||||
expect(tool.description).not.toContain("- `schema`:");
|
||||
expect(getAssignmentDescription(tool)).toContain("shared background belongs in `context`");
|
||||
});
|
||||
|
||||
it("removes both context and schema inputs in independent mode", async () => {
|
||||
@@ -78,7 +71,6 @@ describe("task.simple", () => {
|
||||
expect(tool.description).toContain("each `assignment`");
|
||||
expect(tool.description).not.toContain("- `context`:");
|
||||
expect(tool.description).not.toContain("- `schema`:");
|
||||
expect(getAssignmentDescription(tool)).toContain("include any background that would otherwise live in `context`");
|
||||
});
|
||||
|
||||
it("rejects direct schema and context fields when the mode disables them", async () => {
|
||||
|
||||
Reference in New Issue
Block a user