First Release of Claw3D (#11)

Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
This commit is contained in:
Luke The Dev
2026-03-19 23:14:04 -05:00
committed by GitHub
parent 5ea96b2650
commit 4fa4f13558
431 changed files with 105438 additions and 14 deletions
+181
View File
@@ -0,0 +1,181 @@
import { describe, expect, it, vi } from "vitest";
import {
ensureGatewayReloadModeHotForLocalStudio,
shouldAwaitDisconnectRestartForRemoteMutation,
} from "@/lib/gateway/gatewayReloadMode";
import { GatewayResponseError, type GatewayClient } from "@/lib/gateway/GatewayClient";
describe("ensureGatewayReloadModeHotForLocalStudio", () => {
it("skips non-local upstream gateways", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
await ensureGatewayReloadModeHotForLocalStudio({
client,
upstreamGatewayUrl: "ws://10.0.0.5:18789",
});
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("sets gateway.reload.mode=hot when missing", async () => {
const client = {
call: vi.fn(async (method: string, params?: unknown) => {
if (method === "config.get") {
return { exists: true, hash: "hash-1", config: {} };
}
if (method === "config.set") {
const payload = params as { raw?: string; baseHash?: string };
expect(payload.baseHash).toBe("hash-1");
const parsed = JSON.parse(payload.raw ?? "{}") as {
gateway?: { reload?: { mode?: string } };
};
expect(parsed.gateway?.reload?.mode).toBe("hot");
return { ok: true };
}
throw new Error(`unexpected method: ${method}`);
}),
} as unknown as GatewayClient;
await ensureGatewayReloadModeHotForLocalStudio({
client,
upstreamGatewayUrl: "ws://127.0.0.1:18789",
});
});
it("does nothing when mode is already hot", async () => {
const client = {
call: vi.fn(async (method: string) => {
if (method === "config.get") {
return { exists: true, hash: "hash-1", config: { gateway: { reload: { mode: "hot" } } } };
}
if (method === "config.set") {
throw new Error("config.set should not be called");
}
throw new Error(`unexpected method: ${method}`);
}),
} as unknown as GatewayClient;
await ensureGatewayReloadModeHotForLocalStudio({
client,
upstreamGatewayUrl: "ws://localhost:18789",
});
});
it("retries once on base-hash mismatch", async () => {
let getCount = 0;
const client = {
call: vi.fn(async (method: string) => {
if (method === "config.get") {
getCount += 1;
return { exists: true, hash: getCount === 1 ? "hash-1" : "hash-2", config: {} };
}
if (method === "config.set") {
if (getCount === 1) {
throw new GatewayResponseError({
code: "INVALID_REQUEST",
message: "config changed since last load; re-run config.get and retry",
});
}
return { ok: true };
}
throw new Error(`unexpected method: ${method}`);
}),
} as unknown as GatewayClient;
await ensureGatewayReloadModeHotForLocalStudio({
client,
upstreamGatewayUrl: "ws://127.0.0.1:18789",
});
const setCalls = (client.call as ReturnType<typeof vi.fn>).mock.calls.filter(
([method]) => method === "config.set",
);
expect(setCalls.length).toBe(2);
expect(getCount).toBe(2);
});
});
describe("shouldAwaitDisconnectRestartForRemoteMutation", () => {
it("returns false for cached hot mode", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: { config: { gateway: { reload: { mode: "hot" } } } },
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("returns false for cached off mode", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: { config: { gateway: { reload: { mode: "off" } } } },
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("returns false for cached hybrid mode", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: { config: { gateway: { reload: { mode: "hybrid" } } } },
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("treats missing cached reload mode as hybrid", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: { config: {} },
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("returns true when reload mode is unknown", async () => {
const client = { call: vi.fn() } as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: { config: { gateway: { reload: { mode: "restart" } } } },
});
expect(shouldAwait).toBe(true);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls.length).toBe(0);
});
it("loads config when cache is missing and returns false for hot mode", async () => {
const client = {
call: vi.fn(async (method: string) => {
if (method !== "config.get") {
throw new Error(`unexpected method: ${method}`);
}
return { config: { gateway: { reload: { mode: "hot" } } } };
}),
} as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: null,
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls).toEqual([["config.get", {}]]);
});
it("loads config when cache is missing and treats missing reload mode as hybrid", async () => {
const client = {
call: vi.fn(async (method: string) => {
if (method !== "config.get") {
throw new Error(`unexpected method: ${method}`);
}
return { config: {} };
}),
} as unknown as GatewayClient;
const shouldAwait = await shouldAwaitDisconnectRestartForRemoteMutation({
client,
cachedConfigSnapshot: null,
});
expect(shouldAwait).toBe(false);
expect((client.call as ReturnType<typeof vi.fn>).mock.calls).toEqual([["config.get", {}]]);
});
});