File size: 4,011 Bytes
96e86e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { describe, expect, it } from "vitest";
import {
  readRuntimeUiLocaleFromContextSnapshot,
  resolveEffectiveRuntimeUiLocale,
  resolveEffectiveRuntimeUiLocaleForContextSnapshot,
  resolveRuntimeLocalizationPrompt,
} from "../services/agent-runtime-localization.js";

describe("resolveEffectiveRuntimeUiLocale", () => {
  it("prefers the explicit request locale over the instance default", () => {
    expect(resolveEffectiveRuntimeUiLocale({
      requestedUiLocale: "en-US",
      runtimeDefaultLocale: "zh-CN",
    })).toBe("en");
  });

  it("falls back to the stored runtime locale when no explicit request locale was provided", () => {
    expect(resolveEffectiveRuntimeUiLocale({
      runtimeUiLocale: "en",
      runtimeDefaultLocale: "zh-CN",
    })).toBe("en");
  });

  it("uses the instance default locale when no request-scoped locale was provided", () => {
    expect(resolveEffectiveRuntimeUiLocale({
      runtimeDefaultLocale: "en",
    })).toBe("en");
  });

  it("keeps zh-CN as the final fallback", () => {
    expect(resolveEffectiveRuntimeUiLocale({})).toBe("zh-CN");
  });
});

describe("resolveEffectiveRuntimeUiLocaleForContextSnapshot", () => {
  it("reads runtimeUiLocale from the run context when present", () => {
    expect(
      resolveEffectiveRuntimeUiLocaleForContextSnapshot(
        { runtimeUiLocale: "en" },
        "zh-CN",
      ),
    ).toBe("en");
  });

  it("falls back to the instance default locale for contexts without a stored runtimeUiLocale", () => {
    expect(
      resolveEffectiveRuntimeUiLocaleForContextSnapshot(
        {},
        "en",
      ),
    ).toBe("en");
  });

  it("reads only the persisted runtime locale from the helper accessor", () => {
    expect(readRuntimeUiLocaleFromContextSnapshot({ runtimeUiLocale: "zh-CN" })).toBe("zh-CN");
    expect(readRuntimeUiLocaleFromContextSnapshot({ requestedUiLocale: "en" })).toBeNull();
  });
});

describe("resolveRuntimeLocalizationPrompt", () => {
  it("returns a concise zh-CN note for Windows PowerShell", () => {
    const note = resolveRuntimeLocalizationPrompt({
      locale: "zh-CN",
      platform: "win32",
      shell: "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
    });

    expect(note).toContain("## 语言与运行时契约");
    expect(note).toContain("所有面向用户的自然语言输出必须使用简体中文");
    expect(note).toContain("宿主环境:Windows PowerShell。");
    expect(note).toContain("CLI 契约:执行 Paperclip 命令一律使用 `penclip ...`");
    expect(note).toContain("`paperclipai ...`");
    expect(note).toContain("API 契约:优先使用 `penclip` CLI 完成 Paperclip 操作");
    expect(note).toContain("只有在 CLI 无法覆盖时");
    expect(note).not.toContain("Python / Node");
  });

  it("describes WSL precisely when the runtime is WSL", () => {
    const note = resolveRuntimeLocalizationPrompt({
      locale: "zh-CN",
      platform: "linux",
      shell: "/bin/bash",
      env: { WSL_DISTRO_NAME: "Ubuntu" },
      osRelease: "6.6.87.2-microsoft-standard-WSL2",
    });

    expect(note).toContain("宿主环境:WSL bash。");
    expect(note).toContain("优先使用 `penclip` CLI");
  });

  it("returns an English note with a detected POSIX shell label", () => {
    const note = resolveRuntimeLocalizationPrompt({
      locale: "en",
      platform: "darwin",
      shell: "/bin/zsh",
    });

    expect(note).toContain("## Language and Runtime Contract");
    expect(note).toContain("all user-facing natural-language output must be in English");
    expect(note).toContain("Host runtime: zsh on darwin.");
    expect(note).toContain("CLI contract: use `penclip ...` for Paperclip commands");
    expect(note).toContain("`paperclipai ...`");
    expect(note).toContain("API contract: prefer the `penclip` CLI for Paperclip operations");
    expect(note).toContain("only call the HTTP API directly when the CLI cannot cover the action");
    expect(note).not.toContain("Python / Node");
  });
});