History

fix(server): handle OpenCode text response format in commit message g… (#2202)

Abdul Azeez committed 6 months ago

Commit 37965da1 parent 57b59b54 files · +184 −68Browse files

Showing the changes to apps/server/src/git/Layers/OpenCodeTextGeneration.test.ts (1 of 4 files). Show all

Unified · Split

apps/server/src/git/Layers/OpenCodeTextGeneration.test.ts+73−8
@@ -17,7 +17,9 @@ const runtimeMock = vi.hoisted(() => { · 16 unmodified lines
17 promptUrls: [] as string[],17 promptUrls: [] as string[],
18 authHeaders: [] as Array<string | null>,18 authHeaders: [] as Array<string | null>,
19 closeCalls: [] as string[],19 closeCalls: [] as string[],
20 promptResult: undefined as { data?: { info?: { structured?: unknown } } } | undefined,20 promptResult: undefined as
21 | { data?: { info?: { error?: unknown }; parts?: Array<{ type: string; text?: string }> } }
22 | undefined,
21 };23 };
22 24
23 return {25 return {
@@ -63,12 +65,15 @@ vi.mock("../../provider/opencodeRuntime.ts", async () => { · 39 unmodified lines
63 return (65 return (
64 runtimeMock.state.promptResult ?? {66 runtimeMock.state.promptResult ?? {
65 data: {67 data: {
66 info: {68 parts: [
67 structured: {69 {
68 subject: "Improve OpenCode reuse",70 type: "text",
69 body: "Reuse one server for the full action.",71 text: JSON.stringify({
72 subject: "Improve OpenCode reuse",
73 body: "Reuse one server for the full action.",
74 }),
70 },75 },
71 },76 ],
72 },77 },
73 }78 }
74 );79 );
@@ -198,7 +203,7 @@ it.layer(OpenCodeTextGenerationTestLayer)("OpenCodeTextGenerationLive", (it) => · 123 unmodified lines
198 }).pipe(Effect.provide(TestClock.layer())),203 }).pipe(Effect.provide(TestClock.layer())),
199 );204 );
200 205
201 it.effect("returns a typed missing-output error when OpenCode omits info.structured", () =>206 it.effect("returns a typed empty-output error when OpenCode returns no text parts", () =>
202 Effect.gen(function* () {207 Effect.gen(function* () {
203 runtimeMock.state.promptResult = { data: {} };208 runtimeMock.state.promptResult = { data: {} };
204 const textGeneration = yield* TextGeneration;209 const textGeneration = yield* TextGeneration;
@@ -213,7 +218,67 @@ it.layer(OpenCodeTextGenerationTestLayer)("OpenCodeTextGenerationLive", (it) => · 8 unmodified lines
213 })218 })
214 .pipe(Effect.flip);219 .pipe(Effect.flip);
215 220
216 expect(error.message).toContain("OpenCode returned no structured output.");221 expect(error.message).toContain("OpenCode returned empty output.");
222 }),
223 );
224
225 it.effect("parses JSON returned as plain text output", () =>
226 Effect.gen(function* () {
227 runtimeMock.state.promptResult = {
228 data: {
229 parts: [
230 {
231 type: "text",
232 text: 'Here is the result:\n{"subject":"Tighten OpenCode parsing","body":"Handle JSON text output locally."}',
233 },
234 ],
235 },
236 };
237 const textGeneration = yield* TextGeneration;
238
239 const result = yield* textGeneration.generateCommitMessage({
240 cwd: process.cwd(),
241 branch: "feature/opencode-reuse",
242 stagedSummary: "M README.md",
243 stagedPatch: "diff --git a/README.md b/README.md",
244 modelSelection: DEFAULT_TEST_MODEL_SELECTION,
245 });
246
247 expect(result).toEqual({
248 subject: "Tighten OpenCode parsing",
249 body: "Handle JSON text output locally.",
250 });
251 }),
252 );
253
254 it.effect("surfaces the upstream OpenCode structured-output error message", () =>
255 Effect.gen(function* () {
256 runtimeMock.state.promptResult = {
257 data: {
258 info: {
259 error: {
260 name: "StructuredOutputError",
261 data: {
262 message: "Model did not produce structured output",
263 retries: 2,
264 },
265 },
266 },
267 },
268 };
269 const textGeneration = yield* TextGeneration;
270
271 const error = yield* textGeneration
272 .generateCommitMessage({
273 cwd: process.cwd(),
274 branch: "feature/opencode-reuse",
275 stagedSummary: "M README.md",
276 stagedPatch: "diff --git a/README.md b/README.md",
277 modelSelection: DEFAULT_TEST_MODEL_SELECTION,
278 })
279 .pipe(Effect.flip);
280
281 expect(error.message).toContain("Model did not produce structured output");
217 }),282 }),
218 );283 );
219});284});