Skip to content

Commit f76ead9

Browse files
committed
test(session): minimize prompt agent-part coverage diff
1 parent a7ae97d commit f76ead9

1 file changed

Lines changed: 86 additions & 112 deletions

File tree

Lines changed: 86 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import path from "path";
2-
import { describe, expect, test } from "bun:test";
3-
import { fileURLToPath } from "url";
4-
import { Instance } from "../../src/project/instance";
5-
import { ModelID, ProviderID } from "../../src/provider/schema";
6-
import { Session } from "../../src/session";
7-
import { MessageV2 } from "../../src/session/message-v2";
8-
import { SessionPrompt } from "../../src/session/prompt";
9-
import { Log } from "../../src/util/log";
10-
import { tmpdir } from "../fixture/fixture";
11-
12-
Log.init({ print: false });
1+
import path from "path"
2+
import { describe, expect, test } from "bun:test"
3+
import { fileURLToPath } from "url"
4+
import { Instance } from "../../src/project/instance"
5+
import { ModelID, ProviderID } from "../../src/provider/schema"
6+
import { Session } from "../../src/session"
7+
import { MessageV2 } from "../../src/session/message-v2"
8+
import { SessionPrompt } from "../../src/session/prompt"
9+
import { Log } from "../../src/util/log"
10+
import { tmpdir } from "../fixture/fixture"
11+
12+
Log.init({ print: false })
1313

1414
describe("session.prompt missing file", () => {
1515
test("does not fail the prompt when a file part is missing", async () => {
@@ -22,14 +22,14 @@ describe("session.prompt missing file", () => {
2222
},
2323
},
2424
},
25-
});
25+
})
2626

2727
await Instance.provide({
2828
directory: tmp.path,
2929
fn: async () => {
30-
const session = await Session.create({});
30+
const session = await Session.create({})
3131

32-
const missing = path.join(tmp.path, "does-not-exist.ts");
32+
const missing = path.join(tmp.path, "does-not-exist.ts")
3333
const msg = await SessionPrompt.prompt({
3434
sessionID: session.id,
3535
agent: "build",
@@ -43,21 +43,19 @@ describe("session.prompt missing file", () => {
4343
filename: "does-not-exist.ts",
4444
},
4545
],
46-
});
46+
})
4747

48-
if (msg.info.role !== "user") throw new Error("expected user message");
48+
if (msg.info.role !== "user") throw new Error("expected user message")
4949

5050
const hasFailure = msg.parts.some(
51-
(part) =>
52-
part.type === "text" && part.synthetic &&
53-
part.text.includes("Read tool failed to read"),
54-
);
55-
expect(hasFailure).toBe(true);
51+
(part) => part.type === "text" && part.synthetic && part.text.includes("Read tool failed to read"),
52+
)
53+
expect(hasFailure).toBe(true)
5654

57-
await Session.remove(session.id);
55+
await Session.remove(session.id)
5856
},
59-
});
60-
});
57+
})
58+
})
6159

6260
test("keeps stored part order stable when file resolution is async", async () => {
6361
await using tmp = await tmpdir({
@@ -69,14 +67,14 @@ describe("session.prompt missing file", () => {
6967
},
7068
},
7169
},
72-
});
70+
})
7371

7472
await Instance.provide({
7573
directory: tmp.path,
7674
fn: async () => {
77-
const session = await Session.create({});
75+
const session = await Session.create({})
7876

79-
const missing = path.join(tmp.path, "still-missing.ts");
77+
const missing = path.join(tmp.path, "still-missing.ts")
8078
const msg = await SessionPrompt.prompt({
8179
sessionID: session.id,
8280
agent: "build",
@@ -90,76 +88,71 @@ describe("session.prompt missing file", () => {
9088
},
9189
{ type: "text", text: "after-file" },
9290
],
93-
});
91+
})
9492

95-
if (msg.info.role !== "user") throw new Error("expected user message");
93+
if (msg.info.role !== "user") throw new Error("expected user message")
9694

9795
const stored = await MessageV2.get({
9896
sessionID: session.id,
9997
messageID: msg.info.id,
100-
});
101-
const text = stored.parts.filter((part) => part.type === "text").map((
102-
part,
103-
) => part.text);
98+
})
99+
const text = stored.parts.filter((part) => part.type === "text").map((part) => part.text)
104100

105-
expect(
106-
text[0]?.startsWith("Called the Read tool with the following input:"),
107-
).toBe(true);
108-
expect(text[1]?.includes("Read tool failed to read")).toBe(true);
109-
expect(text[2]).toBe("after-file");
101+
expect(text[0]?.startsWith("Called the Read tool with the following input:")).toBe(true)
102+
expect(text[1]?.includes("Read tool failed to read")).toBe(true)
103+
expect(text[2]).toBe("after-file")
110104

111-
await Session.remove(session.id);
105+
await Session.remove(session.id)
112106
},
113-
});
114-
});
115-
});
107+
})
108+
})
109+
})
116110

117111
describe("session.prompt special characters", () => {
118112
test("handles filenames with # character", async () => {
119113
await using tmp = await tmpdir({
120114
git: true,
121115
init: async (dir) => {
122-
await Bun.write(path.join(dir, "file#name.txt"), "special content\n");
116+
await Bun.write(path.join(dir, "file#name.txt"), "special content\n")
123117
},
124-
});
118+
})
125119

126120
await Instance.provide({
127121
directory: tmp.path,
128122
fn: async () => {
129-
const session = await Session.create({});
130-
const template = "Read @file#name.txt";
131-
const parts = await SessionPrompt.resolvePromptParts(template);
132-
const fileParts = parts.filter((part) => part.type === "file");
123+
const session = await Session.create({})
124+
const template = "Read @file#name.txt"
125+
const parts = await SessionPrompt.resolvePromptParts(template)
126+
const fileParts = parts.filter((part) => part.type === "file")
133127

134-
expect(fileParts.length).toBe(1);
135-
expect(fileParts[0].filename).toBe("file#name.txt");
136-
expect(fileParts[0].url).toContain("%23");
128+
expect(fileParts.length).toBe(1)
129+
expect(fileParts[0].filename).toBe("file#name.txt")
130+
expect(fileParts[0].url).toContain("%23")
137131

138-
const decodedPath = fileURLToPath(fileParts[0].url);
139-
expect(decodedPath).toBe(path.join(tmp.path, "file#name.txt"));
132+
const decodedPath = fileURLToPath(fileParts[0].url)
133+
expect(decodedPath).toBe(path.join(tmp.path, "file#name.txt"))
140134

141135
const message = await SessionPrompt.prompt({
142136
sessionID: session.id,
143137
parts,
144138
noReply: true,
145-
});
146-
const stored = await MessageV2.get({
147-
sessionID: session.id,
148-
messageID: message.info.id,
149-
});
150-
const textParts = stored.parts.filter((part) => part.type === "text");
151-
const hasContent = textParts.some((part) =>
152-
part.text.includes("special content")
153-
);
154-
expect(hasContent).toBe(true);
139+
})
140+
const stored = await MessageV2.get({ sessionID: session.id, messageID: message.info.id })
141+
const textParts = stored.parts.filter((part) => part.type === "text")
142+
const hasContent = textParts.some((part) => part.text.includes("special content"))
143+
expect(hasContent).toBe(true)
155144

156-
await Session.remove(session.id);
145+
await Session.remove(session.id)
157146
},
158-
});
159-
});
160-
});
147+
})
148+
})
149+
})
150+
161151

162152
describe("session.prompt agent part", () => {
153+
const delegationNudge =
154+
"Use the above message and context to generate a prompt and call the task tool with subagent:";
155+
163156
test("injects synthetic delegation nudge in root sessions", async () => {
164157
await using tmp = await tmpdir({ git: true });
165158

@@ -185,11 +178,8 @@ describe("session.prompt agent part", () => {
185178
});
186179
const syntheticDelegation = stored.parts.find(
187180
(part) =>
188-
part.type === "text" &&
189-
part.synthetic &&
190-
part.text.includes(
191-
"Use the above message and context to generate a prompt and call the task tool with subagent:",
192-
),
181+
part.type === "text" && part.synthetic &&
182+
part.text.includes(delegationNudge),
193183
);
194184
expect(syntheticDelegation).toBeDefined();
195185

@@ -224,15 +214,11 @@ describe("session.prompt agent part", () => {
224214
});
225215
const syntheticDelegation = stored.parts.find(
226216
(part) =>
227-
part.type === "text" &&
228-
part.synthetic &&
229-
part.text.includes(
230-
"Use the above message and context to generate a prompt and call the task tool with subagent:",
231-
),
217+
part.type === "text" && part.synthetic &&
218+
part.text.includes(delegationNudge),
232219
);
233220
expect(syntheticDelegation).toBeUndefined();
234221

235-
// The agent part itself should still be present
236222
const agentPart = stored.parts.find((part) => part.type === "agent");
237223
expect(agentPart).toBeDefined();
238224

@@ -245,8 +231,8 @@ describe("session.prompt agent part", () => {
245231

246232
describe("session.prompt agent variant", () => {
247233
test("applies agent variant only when using agent model", async () => {
248-
const prev = process.env.OPENAI_API_KEY;
249-
process.env.OPENAI_API_KEY = "test-openai-key";
234+
const prev = process.env.OPENAI_API_KEY
235+
process.env.OPENAI_API_KEY = "test-openai-key"
250236

251237
try {
252238
await using tmp = await tmpdir({
@@ -259,61 +245,49 @@ describe("session.prompt agent variant", () => {
259245
},
260246
},
261247
},
262-
});
248+
})
263249

264250
await Instance.provide({
265251
directory: tmp.path,
266252
fn: async () => {
267-
const session = await Session.create({});
253+
const session = await Session.create({})
268254

269255
const other = await SessionPrompt.prompt({
270256
sessionID: session.id,
271257
agent: "build",
272-
model: {
273-
providerID: ProviderID.make("opencode"),
274-
modelID: ModelID.make("kimi-k2.5-free"),
275-
},
258+
model: { providerID: ProviderID.make("opencode"), modelID: ModelID.make("kimi-k2.5-free") },
276259
noReply: true,
277260
parts: [{ type: "text", text: "hello" }],
278-
});
279-
if (other.info.role !== "user") {
280-
throw new Error("expected user message");
281-
}
282-
expect(other.info.variant).toBeUndefined();
261+
})
262+
if (other.info.role !== "user") throw new Error("expected user message")
263+
expect(other.info.variant).toBeUndefined()
283264

284265
const match = await SessionPrompt.prompt({
285266
sessionID: session.id,
286267
agent: "build",
287268
noReply: true,
288269
parts: [{ type: "text", text: "hello again" }],
289-
});
290-
if (match.info.role !== "user") {
291-
throw new Error("expected user message");
292-
}
293-
expect(match.info.model).toEqual({
294-
providerID: ProviderID.make("openai"),
295-
modelID: ModelID.make("gpt-5.2"),
296-
});
297-
expect(match.info.variant).toBe("xhigh");
270+
})
271+
if (match.info.role !== "user") throw new Error("expected user message")
272+
expect(match.info.model).toEqual({ providerID: ProviderID.make("openai"), modelID: ModelID.make("gpt-5.2") })
273+
expect(match.info.variant).toBe("xhigh")
298274

299275
const override = await SessionPrompt.prompt({
300276
sessionID: session.id,
301277
agent: "build",
302278
noReply: true,
303279
variant: "high",
304280
parts: [{ type: "text", text: "hello third" }],
305-
});
306-
if (override.info.role !== "user") {
307-
throw new Error("expected user message");
308-
}
309-
expect(override.info.variant).toBe("high");
281+
})
282+
if (override.info.role !== "user") throw new Error("expected user message")
283+
expect(override.info.variant).toBe("high")
310284

311-
await Session.remove(session.id);
285+
await Session.remove(session.id)
312286
},
313-
});
287+
})
314288
} finally {
315-
if (prev === undefined) delete process.env.OPENAI_API_KEY;
316-
else process.env.OPENAI_API_KEY = prev;
289+
if (prev === undefined) delete process.env.OPENAI_API_KEY
290+
else process.env.OPENAI_API_KEY = prev
317291
}
318-
});
319-
});
292+
})
293+
})

0 commit comments

Comments
 (0)