From 03c1db30e0189467e6f24cf896bd6f6da3aff732 Mon Sep 17 00:00:00 2001 From: autocommit Date: Sun, 7 Jun 2026 00:19:01 -0700 Subject: [PATCH] =?UTF-8?q?fix(ai-copilot):=20=F0=9F=90=9B=20LiveCockpitAP?= =?UTF-8?q?I=20query-string=20URL=20building?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit appendingPathComponent percent-encoded '?' in 'content-posts?state=proposed' (→ %3F), 404ing fetchPending so the approval queue silently kept mock data. Split path/query and set query via URLComponents. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../CocotteCockpitKit/LiveCockpitAPI.swift | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/@platform/codebase/@features/ai-copilot/cockpit-kit/Sources/CocotteCockpitKit/LiveCockpitAPI.swift b/@platform/codebase/@features/ai-copilot/cockpit-kit/Sources/CocotteCockpitKit/LiveCockpitAPI.swift index 427916a..92d5cd4 100644 --- a/@platform/codebase/@features/ai-copilot/cockpit-kit/Sources/CocotteCockpitKit/LiveCockpitAPI.swift +++ b/@platform/codebase/@features/ai-copilot/cockpit-kit/Sources/CocotteCockpitKit/LiveCockpitAPI.swift @@ -24,8 +24,21 @@ public struct LiveCockpitAPI: CockpitAPI { return d } + /// Resolve a path (optionally carrying a `?query`) against `baseURL`. + /// `URL.appendingPathComponent` percent-encodes `?`/`=`, mangling queries + /// into the path — so split the query off and set it via URLComponents. + private func requestURL(_ pathAndQuery: String) -> URL { + let parts = pathAndQuery.split(separator: "?", maxSplits: 1, omittingEmptySubsequences: false) + let url = baseURL.appendingPathComponent(String(parts[0])) + guard parts.count > 1, var comps = URLComponents(url: url, resolvingAgainstBaseURL: false) else { + return url + } + comps.percentEncodedQuery = String(parts[1]) + return comps.url ?? url + } + private func get(_ path: String, _ type: T.Type) async throws -> T { - var req = URLRequest(url: baseURL.appendingPathComponent(path)) + var req = URLRequest(url: requestURL(path)) if let token = try await auth.authToken() { req.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") } @@ -38,7 +51,7 @@ public struct LiveCockpitAPI: CockpitAPI { @discardableResult private func post(_ path: String, body: [String: String] = [:]) async throws -> Data { - var req = URLRequest(url: baseURL.appendingPathComponent(path)) + var req = URLRequest(url: requestURL(path)) req.httpMethod = "POST" req.setValue("application/json", forHTTPHeaderField: "Content-Type") if let token = try await auth.authToken() {