Skip to content

Commit 0c8ff3b

Browse files
committed
feat: Add show-token flag to display tokens on auth and refresh
1 parent 636f90c commit 0c8ff3b

File tree

14 files changed

+256
-873
lines changed

14 files changed

+256
-873
lines changed

eslint.config.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
"@types/bun": "^1.2.16",
5353
"bumpp": "^10.2.0",
5454
"eslint": "^9.29.0",
55-
"jiti": "^2.4.2",
5655
"knip": "^5.61.2",
5756
"lint-staged": "^16.1.2",
5857
"prettier-plugin-packagejson": "^2.5.15",

src/auth.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import { defineCommand } from "citty"
44
import consola from "consola"
55

66
import { PATHS, ensurePaths } from "./lib/paths"
7+
import { state } from "./lib/state"
78
import { setupGitHubToken } from "./lib/token"
89

910
interface RunAuthOptions {
1011
verbose: boolean
12+
showToken: boolean
1113
}
1214

1315
export async function runAuth(options: RunAuthOptions): Promise<void> {
@@ -16,6 +18,8 @@ export async function runAuth(options: RunAuthOptions): Promise<void> {
1618
consola.info("Verbose logging enabled")
1719
}
1820

21+
state.showToken = options.showToken
22+
1923
await ensurePaths()
2024
await setupGitHubToken({ force: true })
2125
consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH)
@@ -33,10 +37,16 @@ export const auth = defineCommand({
3337
default: false,
3438
description: "Enable verbose logging",
3539
},
40+
"show-token": {
41+
type: "boolean",
42+
default: false,
43+
description: "Show GitHub token on auth",
44+
},
3645
},
3746
run({ args }) {
3847
return runAuth({
3948
verbose: args.verbose,
49+
showToken: args["show-token"],
4050
})
4151
},
4252
})

src/lib/state.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface State {
1010

1111
manualApprove: boolean
1212
rateLimitWait: boolean
13+
showToken: boolean
1314

1415
// Rate limiting configuration
1516
rateLimitSeconds?: number
@@ -20,4 +21,5 @@ export const state: State = {
2021
accountType: "individual",
2122
manualApprove: false,
2223
rateLimitWait: false,
24+
showToken: false,
2325
}

src/lib/token.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,21 @@ export const setupCopilotToken = async () => {
2020
state.copilotToken = token
2121

2222
// Display the Copilot token to the screen
23-
consola.success("GitHub Copilot Token fetched successfully!")
24-
consola.info(`Token: ${token}`)
25-
consola.info(`Token validity: ${Math.floor(refresh_in / 60)} minutes`)
23+
consola.debug("GitHub Copilot Token fetched successfully!")
24+
if (state.showToken) {
25+
consola.info("Copilot token:", token)
26+
}
2627

2728
const refreshInterval = (refresh_in - 60) * 1000
2829
setInterval(async () => {
29-
consola.start("Refreshing Copilot token")
30+
consola.debug("Refreshing Copilot token")
3031
try {
3132
const { token } = await getCopilotToken()
3233
state.copilotToken = token
33-
consola.success("Copilot token refreshed")
34-
consola.info(`New Token: ${token}`)
34+
consola.debug("Copilot token refreshed")
35+
if (state.showToken) {
36+
consola.info("Refreshed Copilot token:", token)
37+
}
3538
} catch (error) {
3639
consola.error("Failed to refresh Copilot token:", error)
3740
throw error
@@ -51,6 +54,9 @@ export async function setupGitHubToken(
5154

5255
if (githubToken && !options?.force) {
5356
state.githubToken = githubToken
57+
if (state.showToken) {
58+
consola.info("GitHub token:", githubToken)
59+
}
5460
await logUser()
5561

5662
return
@@ -68,6 +74,9 @@ export async function setupGitHubToken(
6874
await writeGithubToken(token)
6975
state.githubToken = token
7076

77+
if (state.showToken) {
78+
consola.info("GitHub token:", token)
79+
}
7180
await logUser()
7281
} catch (error) {
7382
if (error instanceof HTTPError) {

src/main.ts

Lines changed: 1 addition & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,9 @@
11
#!/usr/bin/env node
22

33
import { defineCommand, runMain } from "citty"
4-
import clipboard from "clipboardy"
5-
import consola from "consola"
6-
import { serve, type ServerHandler } from "srvx"
7-
import invariant from "tiny-invariant"
84

95
import { auth } from "./auth"
10-
import { ensurePaths } from "./lib/paths"
11-
import { generateEnvScript } from "./lib/shell"
12-
import { state } from "./lib/state"
13-
import { setupCopilotToken, setupGitHubToken } from "./lib/token"
14-
import { cacheModels, cacheVSCodeVersion } from "./lib/utils"
15-
import { server } from "./server"
16-
17-
interface RunServerOptions {
18-
port: number
19-
verbose: boolean
20-
accountType: string
21-
manual: boolean
22-
rateLimit?: number
23-
rateLimitWait: boolean
24-
githubToken?: string
25-
launchClaudeCode: boolean
26-
}
27-
28-
// eslint-disable-next-line max-lines-per-function
29-
export async function runServer(options: RunServerOptions): Promise<void> {
30-
if (options.verbose) {
31-
consola.level = 5
32-
consola.info("Verbose logging enabled")
33-
}
34-
35-
state.accountType = options.accountType
36-
if (options.accountType !== "individual") {
37-
consola.info(`Using ${options.accountType} plan GitHub account`)
38-
}
39-
40-
state.manualApprove = options.manual
41-
state.rateLimitSeconds = options.rateLimit
42-
state.rateLimitWait = options.rateLimitWait
43-
44-
await ensurePaths()
45-
await cacheVSCodeVersion()
46-
47-
if (options.githubToken) {
48-
state.githubToken = options.githubToken
49-
consola.info("Using provided GitHub token")
50-
} else {
51-
await setupGitHubToken()
52-
} await setupCopilotToken()
53-
await cacheModels() // Display token information prominently
54-
consola.info("=".repeat(50))
55-
consola.success("🚀 GitHub Copilot API has been successfully started!")
56-
consola.info(`🔑 Current Copilot Token: ${state.copilotToken}`)
57-
consola.info(`🌐 Usage Viewer: http://localhost:${options.port}/public/usage.html`)
58-
consola.info("=".repeat(50))
59-
60-
consola.info(
61-
`Available models: \n${state.models?.data.map((model) => `- ${model.id}`).join("\n")}`,
62-
)
63-
64-
const serverUrl = `http://localhost:${options.port}`
65-
66-
if (options.launchClaudeCode) {
67-
invariant(state.models, "Models should be loaded by now")
68-
69-
const selectedModel = await consola.prompt(
70-
"Select a model to use with Claude Code",
71-
{
72-
type: "select",
73-
options: state.models.data.map((model) => model.id),
74-
},
75-
)
76-
77-
const selectedSmallModel = await consola.prompt(
78-
"Select a small model to use with Claude Code",
79-
{
80-
type: "select",
81-
options: state.models.data.map((model) => model.id),
82-
},
83-
)
84-
85-
const command = generateEnvScript(
86-
{
87-
ANTHROPIC_BASE_URL: serverUrl,
88-
ANTHROPIC_AUTH_TOKEN: "dummy",
89-
ANTHROPIC_MODEL: selectedModel,
90-
ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,
91-
},
92-
"claude",
93-
)
94-
95-
clipboard.writeSync(command)
96-
consola.success("Copied Claude Code command to clipboard!")
97-
}
98-
99-
serve({
100-
fetch: server.fetch as ServerHandler,
101-
port: options.port,
102-
})
103-
}
104-
105-
const start = defineCommand({
106-
meta: {
107-
name: "start",
108-
description: "Start the Copilot API server",
109-
},
110-
args: {
111-
port: {
112-
alias: "p",
113-
type: "string",
114-
default: "4141",
115-
description: "Port to listen on",
116-
},
117-
verbose: {
118-
alias: "v",
119-
type: "boolean",
120-
default: false,
121-
description: "Enable verbose logging",
122-
},
123-
"account-type": {
124-
alias: "a",
125-
type: "string",
126-
default: "individual",
127-
description: "Account type to use (individual, business, enterprise)",
128-
},
129-
manual: {
130-
type: "boolean",
131-
default: false,
132-
description: "Enable manual request approval",
133-
},
134-
"rate-limit": {
135-
alias: "r",
136-
type: "string",
137-
description: "Rate limit in seconds between requests",
138-
},
139-
wait: {
140-
alias: "w",
141-
type: "boolean",
142-
default: false,
143-
description:
144-
"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set",
145-
},
146-
"github-token": {
147-
alias: "g",
148-
type: "string",
149-
description:
150-
"Provide GitHub token directly (must be generated using the `auth` subcommand)",
151-
},
152-
"claude-code": {
153-
alias: "c",
154-
type: "boolean",
155-
default: false,
156-
description:
157-
"Generate a command to launch Claude Code with Copilot API config",
158-
},
159-
},
160-
run({ args }) {
161-
const rateLimitRaw = args["rate-limit"]
162-
const rateLimit =
163-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
164-
rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)
165-
166-
return runServer({
167-
port: Number.parseInt(args.port, 10),
168-
verbose: args.verbose,
169-
accountType: args["account-type"],
170-
manual: args.manual,
171-
rateLimit,
172-
rateLimitWait: Boolean(args.wait),
173-
githubToken: args["github-token"],
174-
launchClaudeCode: args["claude-code"],
175-
})
176-
},
177-
})
6+
import { start } from "./start"
1787

1798
const main = defineCommand({
1809
meta: {

0 commit comments

Comments
 (0)