-
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathproviderAvailability.test.ts
More file actions
112 lines (102 loc) · 3.03 KB
/
providerAvailability.test.ts
File metadata and controls
112 lines (102 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { describe, expect, it } from "vitest";
import type { ProviderKind, ServerProviderStatus } from "@okcode/contracts";
import {
getSelectableThreadProviders,
isProviderReadyForThreadSelection,
resolveThreadProviderSelection,
} from "./providerAvailability";
function makeStatus(
provider: ProviderKind,
overrides: Partial<ServerProviderStatus> = {},
): ServerProviderStatus {
return {
provider,
status: "ready",
available: true,
authStatus: "authenticated",
checkedAt: "2026-04-12T12:00:00.000Z",
...overrides,
};
}
describe("providerAvailability", () => {
it("allows ready authenticated CLI providers", () => {
expect(
isProviderReadyForThreadSelection({
provider: "codex",
statuses: [makeStatus("codex")],
}),
).toBe(true);
});
it("allows ready providers with unknown auth when auth is handled externally", () => {
expect(
isProviderReadyForThreadSelection({
provider: "codex",
statuses: [makeStatus("codex", { authStatus: "unknown" })],
}),
).toBe(true);
});
it("blocks providers that are explicitly unauthenticated", () => {
expect(
isProviderReadyForThreadSelection({
provider: "claudeAgent",
statuses: [makeStatus("claudeAgent", { status: "error", authStatus: "unauthenticated" })],
}),
).toBe(false);
});
it("blocks claudeAgent when status is error", () => {
expect(
isProviderReadyForThreadSelection({
provider: "claudeAgent",
statuses: [
makeStatus("claudeAgent", {
status: "error",
available: true,
authStatus: "unauthenticated",
}),
],
}),
).toBe(false);
});
it("blocks unauthenticated claudeAgent even when the status is otherwise ready", () => {
expect(
isProviderReadyForThreadSelection({
provider: "claudeAgent",
statuses: [
makeStatus("claudeAgent", {
status: "ready",
available: true,
authStatus: "unauthenticated",
}),
],
}),
).toBe(false);
});
it("treats configured OpenClaw as selectable even when server auth state is unknown", () => {
expect(
isProviderReadyForThreadSelection({
provider: "openclaw",
statuses: [],
openclawGatewayUrl: "ws://localhost:8080",
}),
).toBe(true);
});
it("returns selectable providers in stable picker order", () => {
expect(
getSelectableThreadProviders({
statuses: [
makeStatus("openclaw", { authStatus: "unknown" }),
makeStatus("codex"),
makeStatus("claudeAgent", { status: "error", authStatus: "unauthenticated" }),
],
}),
).toEqual(["codex", "openclaw"]);
});
it("falls back to the first selectable provider when the preferred one is unavailable", () => {
expect(
resolveThreadProviderSelection({
preferredProvider: "claudeAgent",
selectableProviders: ["codex", "openclaw"],
}),
).toBe("codex");
});
});