config-loader.test.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { mkdtemp, rm, writeFile } from "node:fs/promises";
  2. import { tmpdir } from "node:os";
  3. import { join } from "node:path";
  4. import { afterEach, describe, expect, it } from "vitest";
  5. import { loadProjectConfig } from "../utils/config-loader.js";
  6. const ENV_KEYS = [
  7. "INKOS_LLM_PROVIDER",
  8. "INKOS_LLM_BASE_URL",
  9. "INKOS_LLM_MODEL",
  10. "INKOS_LLM_API_KEY",
  11. "INKOS_LLM_TEMPERATURE",
  12. "INKOS_LLM_MAX_TOKENS",
  13. "INKOS_LLM_THINKING_BUDGET",
  14. "INKOS_LLM_API_FORMAT",
  15. ] as const;
  16. describe("loadProjectConfig local provider auth", () => {
  17. let root = "";
  18. const previousEnv = new Map<string, string | undefined>();
  19. afterEach(async () => {
  20. for (const key of ENV_KEYS) {
  21. const previous = previousEnv.get(key);
  22. if (previous === undefined) delete process.env[key];
  23. else process.env[key] = previous;
  24. }
  25. previousEnv.clear();
  26. if (root) {
  27. await rm(root, { recursive: true, force: true });
  28. root = "";
  29. }
  30. });
  31. it("allows missing API keys for localhost OpenAI-compatible endpoints", async () => {
  32. root = await mkdtemp(join(tmpdir(), "inkos-config-loader-local-"));
  33. for (const key of ENV_KEYS) {
  34. previousEnv.set(key, process.env[key]);
  35. process.env[key] = "";
  36. }
  37. await writeFile(join(root, "inkos.json"), JSON.stringify({
  38. name: "local-project",
  39. version: "0.1.0",
  40. llm: {
  41. provider: "openai",
  42. baseUrl: "http://127.0.0.1:11434/v1",
  43. model: "gpt-oss:20b",
  44. },
  45. }, null, 2), "utf-8");
  46. await writeFile(join(root, ".env"), "", "utf-8");
  47. const config = await loadProjectConfig(root);
  48. expect(config.llm.baseUrl).toBe("http://127.0.0.1:11434/v1");
  49. expect(config.llm.model).toBe("gpt-oss:20b");
  50. expect(config.llm.apiKey).toBe("");
  51. });
  52. it("still requires API keys for remote hosted endpoints", async () => {
  53. root = await mkdtemp(join(tmpdir(), "inkos-config-loader-remote-"));
  54. for (const key of ENV_KEYS) {
  55. previousEnv.set(key, process.env[key]);
  56. process.env[key] = "";
  57. }
  58. await writeFile(join(root, "inkos.json"), JSON.stringify({
  59. name: "remote-project",
  60. version: "0.1.0",
  61. llm: {
  62. provider: "openai",
  63. baseUrl: "https://api.openai.com/v1",
  64. model: "gpt-5.4",
  65. },
  66. }, null, 2), "utf-8");
  67. await writeFile(join(root, ".env"), "", "utf-8");
  68. await expect(loadProjectConfig(root)).rejects.toThrow(/INKOS_LLM_API_KEY not set/i);
  69. });
  70. });