Skip to content

Commit b8603b2

Browse files
ericc-chopencode
andcommitted
feat: add debug subcommand with version, runtime, paths, and auth status info
🤖 Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <noreply@opencode.ai>
1 parent 06db22a commit b8603b2

File tree

2 files changed

+129
-1
lines changed

2 files changed

+129
-1
lines changed

src/debug.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/usr/bin/env node
2+
3+
import { defineCommand } from "citty"
4+
import consola from "consola"
5+
import fs from "node:fs/promises"
6+
import os from "node:os"
7+
8+
import { PATHS } from "./lib/paths"
9+
10+
interface DebugInfo {
11+
version: string
12+
runtime: {
13+
name: string
14+
version: string
15+
platform: string
16+
arch: string
17+
}
18+
paths: {
19+
APP_DIR: string
20+
GITHUB_TOKEN_PATH: string
21+
}
22+
tokenExists: boolean
23+
}
24+
25+
interface RunDebugOptions {
26+
json: boolean
27+
}
28+
29+
async function getPackageVersion(): Promise<string> {
30+
try {
31+
const packageJsonPath = new URL("../package.json", import.meta.url).pathname
32+
// @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md
33+
// JSON.parse() can actually parse buffers
34+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {
35+
version: string
36+
}
37+
return packageJson.version
38+
} catch {
39+
return "unknown"
40+
}
41+
}
42+
43+
function getRuntimeInfo() {
44+
const isBun = typeof Bun !== "undefined"
45+
46+
return {
47+
name: isBun ? "bun" : "node",
48+
version: isBun ? Bun.version : process.version.slice(1),
49+
platform: os.platform(),
50+
arch: os.arch(),
51+
}
52+
}
53+
54+
async function checkTokenExists(): Promise<boolean> {
55+
try {
56+
const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)
57+
if (!stats.isFile()) return false
58+
59+
const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")
60+
return content.trim().length > 0
61+
} catch {
62+
return false
63+
}
64+
}
65+
66+
async function getDebugInfo(): Promise<DebugInfo> {
67+
const [version, tokenExists] = await Promise.all([
68+
getPackageVersion(),
69+
checkTokenExists(),
70+
])
71+
72+
return {
73+
version,
74+
runtime: getRuntimeInfo(),
75+
paths: {
76+
APP_DIR: PATHS.APP_DIR,
77+
GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,
78+
},
79+
tokenExists,
80+
}
81+
}
82+
83+
function printDebugInfoPlain(info: DebugInfo): void {
84+
consola.info(`copilot-api debug
85+
86+
Version: ${info.version}
87+
Runtime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})
88+
89+
Paths:
90+
- APP_DIR: ${info.paths.APP_DIR}
91+
- GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}
92+
93+
Token exists: ${info.tokenExists ? "Yes" : "No"}`)
94+
}
95+
96+
function printDebugInfoJson(info: DebugInfo): void {
97+
console.log(JSON.stringify(info, null, 2))
98+
}
99+
100+
export async function runDebug(options: RunDebugOptions): Promise<void> {
101+
const debugInfo = await getDebugInfo()
102+
103+
if (options.json) {
104+
printDebugInfoJson(debugInfo)
105+
} else {
106+
printDebugInfoPlain(debugInfo)
107+
}
108+
}
109+
110+
export const debug = defineCommand({
111+
meta: {
112+
name: "debug",
113+
description: "Print debug information about the application",
114+
},
115+
args: {
116+
json: {
117+
type: "boolean",
118+
default: false,
119+
description: "Output debug information as JSON",
120+
},
121+
},
122+
run({ args }) {
123+
return runDebug({
124+
json: args.json,
125+
})
126+
},
127+
})

src/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { defineCommand, runMain } from "citty"
44

55
import { auth } from "./auth"
66
import { checkUsage } from "./check-usage"
7+
import { debug } from "./debug"
78
import { start } from "./start"
89

910
const main = defineCommand({
@@ -12,7 +13,7 @@ const main = defineCommand({
1213
description:
1314
"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.",
1415
},
15-
subCommands: { auth, start, "check-usage": checkUsage },
16+
subCommands: { auth, start, "check-usage": checkUsage, debug },
1617
})
1718

1819
await runMain(main)

0 commit comments

Comments
 (0)