From f51036fa8a1b76e96fbe4ac0bc93b360a7ff7ec5 Mon Sep 17 00:00:00 2001 From: Wenzheng Jiang Date: Thu, 5 Mar 2026 07:37:51 +0900 Subject: [PATCH] Add license auth header to Miyo requests (#2260) * Add license auth header to Miyo requests * Remove unused self-host API key setting * Keep self-host API key in settings * Log Miyo auth header presence --- src/miyo/MiyoClient.test.ts | 15 ++++++++++++++- src/miyo/MiyoClient.ts | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/miyo/MiyoClient.test.ts b/src/miyo/MiyoClient.test.ts index 0327cffe..342d0ce2 100644 --- a/src/miyo/MiyoClient.test.ts +++ b/src/miyo/MiyoClient.test.ts @@ -1,3 +1,4 @@ +import { logInfo } from "@/logger"; import { MiyoClient } from "@/miyo/MiyoClient"; import { MiyoServiceDiscovery } from "@/miyo/MiyoServiceDiscovery"; import { getSettings } from "@/settings/model"; @@ -31,11 +32,12 @@ describe("MiyoClient.parseDoc", () => { const mockedRequestUrl = requestUrl as jest.MockedFunction; const mockedGetSettings = getSettings as jest.MockedFunction; const mockedGetInstance = MiyoServiceDiscovery.getInstance as unknown as jest.Mock; + const mockedLogInfo = logInfo as jest.MockedFunction; beforeEach(() => { jest.clearAllMocks(); mockedGetSettings.mockReturnValue({ - selfHostApiKey: "", + plusLicenseKey: "plus-test-license", debug: false, } as any); mockResolveBaseUrl.mockResolvedValue("http://127.0.0.1:8742"); @@ -71,10 +73,21 @@ describe("MiyoClient.parseDoc", () => { expect.objectContaining({ url: "http://127.0.0.1:8742/v0/parse-doc", method: "POST", + headers: { + Authorization: "Bearer plus-test-license", + }, contentType: "application/json", body: JSON.stringify({ path: "/tmp/sample.pdf" }), }) ); + expect(mockedLogInfo).toHaveBeenCalledWith( + "Miyo request:", + expect.objectContaining({ + method: "POST", + url: "http://127.0.0.1:8742/v0/parse-doc", + hasAuthorizationHeader: true, + }) + ); }); it("throws when /v0/parse-doc returns an error status", async () => { diff --git a/src/miyo/MiyoClient.ts b/src/miyo/MiyoClient.ts index 7a5e8604..da946a3f 100644 --- a/src/miyo/MiyoClient.ts +++ b/src/miyo/MiyoClient.ts @@ -1,3 +1,4 @@ +import { getDecryptedKey } from "@/encryptionService"; import { logError, logInfo, logWarn } from "@/logger"; import { getSettings } from "@/settings/model"; import { err2String } from "@/utils"; @@ -360,18 +361,21 @@ export class MiyoClient { /** * Build request headers, including auth when configured. - * Both `Authorization: Bearer` and `X-API-Key` are sent for compatibility - * with different Miyo server configurations. + * `Authorization` uses the Copilot Plus license key. * * @returns Headers object for requestUrl. */ - private buildHeaders(): Record { - const apiKey = getSettings().selfHostApiKey; + private async buildHeaders(): Promise> { + const settings = getSettings(); const headers: Record = {}; - if (apiKey) { - headers.Authorization = `Bearer ${apiKey}`; - headers["X-API-Key"] = apiKey; + + const licenseKey = settings.plusLicenseKey + ? await getDecryptedKey(settings.plusLicenseKey) + : ""; + if (licenseKey) { + headers.Authorization = `Bearer ${licenseKey}`; } + return headers; } @@ -402,10 +406,12 @@ export class MiyoClient { } const body = options.body ? JSON.stringify(options.body) : undefined; + const headers = await this.buildHeaders(); logInfo("Miyo request:", { method: options.method, url: url.toString(), hasBody: Boolean(body), + hasAuthorizationHeader: Boolean(headers.Authorization), ...(getSettings().debug && options.method === "POST" ? { postBody: options.body } : {}), }); @@ -415,7 +421,7 @@ export class MiyoClient { const response = await requestUrl({ url: url.toString(), method: options.method, - headers: this.buildHeaders(), + headers, contentType: body ? "application/json" : undefined, body, throw: false,