File size: 3,898 Bytes
f778c12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/** Tests runtime config-option serialization against advertised backend keys. */
import { describe, expect, it } from "vitest";
import type { AcpSessionRuntimeOptions } from "../../config/sessions/types.js";
import { buildRuntimeConfigOptionPairs, mergeRuntimeOptions } from "./runtime-options.js";

describe("mergeRuntimeOptions", () => {
  it("clears top-level options when a patch explicitly sets them to undefined", () => {
    const patch = {
      runtimeMode: undefined,
      model: undefined,
      thinking: undefined,
      cwd: undefined,
      permissionProfile: undefined,
      timeoutSeconds: undefined,
    } as Partial<AcpSessionRuntimeOptions>;

    expect(
      mergeRuntimeOptions({
        current: {
          runtimeMode: "plan",
          model: "claude-sonnet-4.6",
          thinking: "high",
          cwd: "/tmp/project",
          permissionProfile: "trusted",
          timeoutSeconds: 120,
        },
        patch,
      }),
    ).toEqual({});
  });

  it("clears backend extras when a patch explicitly clears them", () => {
    expect(
      mergeRuntimeOptions({
        current: {
          model: "claude-sonnet-4.6",
          backendExtras: { provider: "anthropic", profile: "work" },
        },
        patch: { backendExtras: undefined } as Partial<AcpSessionRuntimeOptions>,
      }),
    ).toEqual({ model: "claude-sonnet-4.6" });
  });

  it("keeps merging backend extras when a patch provides new entries", () => {
    expect(
      mergeRuntimeOptions({
        current: { backendExtras: { provider: "anthropic" } },
        patch: { backendExtras: { profile: "work" } },
      }),
    ).toEqual({ backendExtras: { provider: "anthropic", profile: "work" } });
  });
});

describe("buildRuntimeConfigOptionPairs timeout advertisement", () => {
  it("omits the timeout pair when advertised keys exclude every timeout alias", () => {
    const pairs = buildRuntimeConfigOptionPairs({ timeoutSeconds: 60 }, [
      "model",
      "thinking",
      "approval_policy",
    ]);
    expect(pairs).toEqual([]);
  });

  it("keeps the timeout pair when advertised keys include `timeout`", () => {
    const pairs = buildRuntimeConfigOptionPairs({ timeoutSeconds: 60 }, ["model", "timeout"]);
    expect(pairs).toEqual([["timeout", "60"]]);
  });

  it("keeps the timeout pair using the advertised `timeout_seconds` alias", () => {
    const pairs = buildRuntimeConfigOptionPairs({ timeoutSeconds: 60 }, [
      "model",
      "timeout_seconds",
    ]);
    expect(pairs).toEqual([["timeout_seconds", "60"]]);
  });

  it("keeps the timeout pair when advertised keys are unknown (empty or undefined)", () => {
    expect(buildRuntimeConfigOptionPairs({ timeoutSeconds: 60 })).toEqual([["timeout", "60"]]);
    expect(buildRuntimeConfigOptionPairs({ timeoutSeconds: 60 }, [])).toEqual([["timeout", "60"]]);
  });

  it("does not affect model or thinking emission when only timeout is unadvertised", () => {
    const pairs = buildRuntimeConfigOptionPairs(
      { model: "claude-sonnet-4.6", thinking: "high", timeoutSeconds: 60 },
      ["model", "thinking"],
    );
    expect(pairs).toEqual([
      ["model", "claude-sonnet-4.6"],
      ["thinking", "high"],
    ]);
  });
});

describe("buildRuntimeConfigOptionPairs thinking advertisement", () => {
  it("omits automatic thinking when the backend advertises no thinking alias", () => {
    expect(buildRuntimeConfigOptionPairs({ thinking: "high" }, ["mode", "model"])).toEqual([]);
  });

  it("maps automatic thinking to the advertised reasoning_effort alias", () => {
    expect(
      buildRuntimeConfigOptionPairs({ thinking: "high" }, ["model", "reasoning_effort"]),
    ).toEqual([["reasoning_effort", "high"]]);
  });

  it("keeps automatic thinking when advertised keys are unknown", () => {
    expect(buildRuntimeConfigOptionPairs({ thinking: "high" })).toEqual([["thinking", "high"]]);
  });
});