File size: 2,556 Bytes
837e3ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { describe, expect, it } from "vitest";

const { recoverInvalidLlmResponse } = await import("./llm-response").catch(
  () => ({ recoverInvalidLlmResponse: undefined }),
);

describe("recoverInvalidLlmResponse", () => {
  it("keeps a live ask reply even when the model does not return JSON", () => {
    expect(recoverInvalidLlmResponse).toBeTypeOf("function");

    const response = recoverInvalidLlmResponse?.({
      rawText:
        "The validation of verbal concept output explains how the concept statement should be checked with users before visual development.",
      parsedCommand: {
        referencedPackageName: "Final Concept",
        mode: "ask",
        instruction: "What does this sentence mean?",
      },
    });

    expect(response?.assistantMessage).toContain(
      "validation of verbal concept output",
    );
    expect(response?.boardAction.type).toBe("none");
  });

  it("extracts a human assistant message from a JSON-looking ask reply", () => {
    expect(recoverInvalidLlmResponse).toBeTypeOf("function");

    const response = recoverInvalidLlmResponse?.({
      rawText:
        '{"assistantMessage":"Verification method explains how each requirement will be tested.","boardAction":{"type":"none","workPackageId":null}}',
      parsedCommand: {
        referencedPackageName: "System Requirements Specification",
        mode: "ask",
        instruction: "What does verification method mean?",
      },
    });

    expect(response?.assistantMessage).toBe(
      "Verification method explains how each requirement will be tested.",
    );
    expect(response?.assistantMessage.trim().startsWith("{")).toBe(false);
    expect(response?.boardAction.type).toBe("none");
  });

  it("falls back to a structured local response for change commands", () => {
    expect(recoverInvalidLlmResponse).toBeTypeOf("function");

    const response = recoverInvalidLlmResponse?.({
      rawText: "Sure, I would update the objective and keep the package in progress.",
      parsedCommand: {
        referencedPackageName: "SRS",
        mode: "change",
        instruction: "Add cybersecurity acceptance criteria.",
      },
      fallbackResponse: {
        assistantMessage: "Updated SRS locally.",
        boardAction: {
          type: "update",
          workPackageId: "wp-srs",
          fields: {
            objective: "Updated objective",
          },
        },
      },
    });

    expect(response?.assistantMessage).toContain("Updated SRS locally");
    expect(response?.boardAction.type).toBe("update");
  });
});