fix: stabilize ci protocol + openai batch retry

This commit is contained in:
Peter Steinberger
2026-01-18 17:05:21 +00:00
parent a4ee933022
commit f16b0cf80d
5 changed files with 96 additions and 19 deletions

View File

@@ -1660,6 +1660,40 @@ public struct ExecApprovalsSetParams: Codable, Sendable {
} }
} }
public struct ExecApprovalsNodeGetParams: Codable, Sendable {
public let nodeid: String
public init(
nodeid: String
) {
self.nodeid = nodeid
}
private enum CodingKeys: String, CodingKey {
case nodeid = "nodeId"
}
}
public struct ExecApprovalsNodeSetParams: Codable, Sendable {
public let nodeid: String
public let file: [String: AnyCodable]
public let basehash: String?
public init(
nodeid: String,
file: [String: AnyCodable],
basehash: String?
) {
self.nodeid = nodeid
self.file = file
self.basehash = basehash
}
private enum CodingKeys: String, CodingKey {
case nodeid = "nodeId"
case file
case basehash = "baseHash"
}
}
public struct ExecApprovalsSnapshot: Codable, Sendable { public struct ExecApprovalsSnapshot: Codable, Sendable {
public let path: String public let path: String
public let exists: Bool public let exists: Bool

View File

@@ -23,8 +23,10 @@ vi.mock("../logger.js", () => {
}; };
}); });
vi.mock("../logging.js", () => { vi.mock("../logging.js", async () => {
const actual = await vi.importActual<typeof import("../logging.js")>("../logging.js");
return { return {
...actual,
getLogger: () => ({ info: (...args: unknown[]) => getLoggerInfo(...args) }), getLogger: () => ({ info: (...args: unknown[]) => getLoggerInfo(...args) }),
}; };
}); });

View File

@@ -36,7 +36,20 @@ function extractErrorMessage(err: unknown): string | undefined {
if (typeof err === "object" && "message" in err && typeof err.message === "string") { if (typeof err === "object" && "message" in err && typeof err.message === "string") {
return err.message; return err.message;
} }
return String(err); if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
return String(err);
}
if (typeof err === "symbol") {
return err.toString();
}
if (typeof err === "object") {
try {
return JSON.stringify(err);
} catch {
return undefined;
}
}
return undefined;
} }
function logRemoteBinProbeFailure(nodeId: string, err: unknown) { function logRemoteBinProbeFailure(nodeId: string, err: unknown) {

View File

@@ -1,3 +1,4 @@
import { retryAsync } from "../infra/retry.js";
import type { OpenAiEmbeddingClient } from "./embeddings-openai.js"; import type { OpenAiEmbeddingClient } from "./embeddings-openai.js";
import { hashText } from "./internal.js"; import { hashText } from "./internal.js";
@@ -92,23 +93,42 @@ async function submitOpenAiBatch(params: {
throw new Error("openai batch file upload failed: missing file id"); throw new Error("openai batch file upload failed: missing file id");
} }
const batchRes = await fetch(`${baseUrl}/batches`, { const batchRes = await retryAsync(
method: "POST", async () => {
headers: getOpenAiHeaders(params.openAi, { json: true }), const res = await fetch(`${baseUrl}/batches`, {
body: JSON.stringify({ method: "POST",
input_file_id: filePayload.id, headers: getOpenAiHeaders(params.openAi, { json: true }),
endpoint: OPENAI_BATCH_ENDPOINT, body: JSON.stringify({
completion_window: OPENAI_BATCH_COMPLETION_WINDOW, input_file_id: filePayload.id,
metadata: { endpoint: OPENAI_BATCH_ENDPOINT,
source: "clawdbot-memory", completion_window: OPENAI_BATCH_COMPLETION_WINDOW,
agent: params.agentId, metadata: {
source: "clawdbot-memory",
agent: params.agentId,
},
}),
});
if (!res.ok) {
const text = await res.text();
const err = new Error(`openai batch create failed: ${res.status} ${text}`) as Error & {
status?: number;
};
err.status = res.status;
throw err;
}
return res;
},
{
attempts: 3,
minDelayMs: 300,
maxDelayMs: 2000,
jitter: 0.2,
shouldRetry: (err) => {
const status = (err as { status?: number }).status;
return status === 429 || (typeof status === "number" && status >= 500);
}, },
}), },
}); );
if (!batchRes.ok) {
const text = await batchRes.text();
throw new Error(`openai batch create failed: ${batchRes.status} ${text}`);
}
return (await batchRes.json()) as OpenAiBatchStatus; return (await batchRes.json()) as OpenAiBatchStatus;
} }

View File

@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
const loadJsonFile = vi.fn(); const loadJsonFile = vi.fn();
const saveJsonFile = vi.fn(); const saveJsonFile = vi.fn();
@@ -14,6 +14,14 @@ vi.mock("../config/paths.js", () => ({
})); }));
describe("github-copilot token", () => { describe("github-copilot token", () => {
beforeEach(() => {
vi.resetModules();
loadJsonFile.mockReset();
saveJsonFile.mockReset();
resolveStateDir.mockReset();
resolveStateDir.mockReturnValue("/tmp/clawdbot-state");
});
it("derives baseUrl from token", async () => { it("derives baseUrl from token", async () => {
const { deriveCopilotApiBaseUrlFromToken } = await import("./github-copilot-token.js"); const { deriveCopilotApiBaseUrlFromToken } = await import("./github-copilot-token.js");