forked from OpenKnots/okcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoctor.ts
More file actions
101 lines (89 loc) · 3.04 KB
/
doctor.ts
File metadata and controls
101 lines (89 loc) · 3.04 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
/**
* doctor - CLI diagnostic command.
*
* Runs provider health checks and prints a summary to the terminal
* without starting the full server.
*
* @module doctor
*/
import { Effect } from "effect";
import { Command } from "effect/unstable/cli";
import {
checkCopilotProviderStatus,
checkCodexProviderStatus,
checkClaudeProviderStatus,
} from "./provider/Layers/ProviderHealth";
import type { ServerProviderStatus } from "@okcode/contracts";
import { fixPath } from "./os-jank";
import { serverBuildInfo } from "./buildInfo";
const STATUS_ICONS: Record<string, string> = {
ready: "\u2705",
warning: "\u26A0\uFE0F",
error: "\u274C",
};
const AUTH_LABELS: Record<string, string> = {
authenticated: "authenticated",
unauthenticated: "not authenticated",
unknown: "unknown",
};
const PROVIDER_LABELS: Record<string, string> = {
codex: "Codex (OpenAI)",
claudeAgent: "Claude Code",
copilot: "GitHub Copilot",
};
function printStatus(status: ServerProviderStatus): void {
const icon = STATUS_ICONS[status.status] ?? "?";
const label = PROVIDER_LABELS[status.provider] ?? status.provider;
const auth = AUTH_LABELS[status.authStatus] ?? status.authStatus;
console.log("");
console.log(` ${icon} ${label}`);
console.log(` Status: ${status.status}`);
console.log(` Auth: ${auth}`);
if (status.message) {
console.log(` Detail: ${status.message}`);
}
}
const doctorProgram = Effect.gen(function* () {
// Fix PATH so CLIs installed via nvm/volta/etc. are reachable.
fixPath();
console.log("OK Code Doctor");
console.log("==============");
console.log("");
console.log(`Version: ${serverBuildInfo.version}`);
console.log(
`Surface: ${serverBuildInfo.surface} (${serverBuildInfo.platform}/${serverBuildInfo.arch})`,
);
console.log(`Channel: ${serverBuildInfo.channel}`);
console.log(`Commit: ${serverBuildInfo.commitHash ?? "unknown"}`);
console.log(`Built: ${serverBuildInfo.buildTimestamp}`);
console.log("");
console.log("Checking provider health...");
const statuses = yield* Effect.all(
[checkCodexProviderStatus, checkClaudeProviderStatus, checkCopilotProviderStatus],
{
concurrency: "unbounded",
},
);
for (const status of statuses) {
printStatus(status);
}
const readyCount = statuses.filter((s) => s.status === "ready").length;
console.log("");
if (readyCount === 0) {
console.log("No providers are ready. Set up at least one provider to start coding:");
console.log("");
console.log(" Codex: npm install -g @openai/codex && codex login");
console.log(
" Claude Code: npm install -g @anthropic-ai/claude-code && set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN",
);
} else if (readyCount === statuses.length) {
console.log("All providers are ready.");
} else {
console.log(`${readyCount} of ${statuses.length} providers ready.`);
}
console.log("");
});
export const doctorCmd = Command.make("doctor").pipe(
Command.withDescription("Check provider health and system requirements."),
Command.withHandler(() => doctorProgram),
);