Skip to content

Commit 9380a50

Browse files
committed
feat: Implement manual approval and rate limiting features
1 parent fe791f4 commit 9380a50

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed

src/lib/approval.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import consola from "consola"
2+
3+
import { HTTPError } from "./http-error"
4+
5+
export const awaitApproval = async () => {
6+
const response = await consola.prompt(`Accept incoming request?`, {
7+
type: "confirm",
8+
})
9+
10+
if (!response)
11+
throw new HTTPError("Request rejected", Response.json({ status: 429 }))
12+
}

src/lib/state.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ export interface State {
99
vsCodeVersion?: string
1010

1111
manualApprove: boolean
12+
13+
// Rate limiting configuration
14+
rateLimitSeconds?: number
15+
lastRequestTimestamp?: number
1216
}
1317

1418
export const state: State = {

src/main.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface RunServerOptions {
1616
verbose: boolean
1717
business: boolean
1818
manual: boolean
19+
rateLimit: number
1920
}
2021

2122
export async function runServer(options: RunServerOptions): Promise<void> {
@@ -30,6 +31,7 @@ export async function runServer(options: RunServerOptions): Promise<void> {
3031
}
3132

3233
state.manualApprove = options.manual
34+
state.rateLimitSeconds = options.rateLimit
3335

3436
await ensurePaths()
3537
await cacheVSCodeVersion()
@@ -70,15 +72,23 @@ const main = defineCommand({
7072
default: false,
7173
description: "Enable manual request approval",
7274
},
75+
rateLimit: {
76+
alias: "r",
77+
type: "string",
78+
default: "5",
79+
description: "Rate limit in seconds between requests",
80+
},
7381
},
7482
run({ args }) {
7583
const port = Number.parseInt(args.port, 10)
84+
const rateLimit = Number.parseInt(args.rateLimit, 10)
7685

7786
return runServer({
7887
port,
7988
verbose: args.verbose,
8089
business: args.business,
8190
manual: args.manual,
91+
rateLimit,
8292
})
8393
},
8494
})

src/routes/chat-completions/handler.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import type { Context } from "hono"
33
import consola from "consola"
44
import { streamSSE, type SSEMessage } from "hono/streaming"
55

6+
import { awaitApproval } from "~/lib/approval"
67
import { isNullish } from "~/lib/is-nullish"
8+
import { checkRateLimit } from "~/lib/rate-limit"
79
import { state } from "~/lib/state"
810
import { getTokenCount } from "~/lib/tokenizer"
911
import {
@@ -13,17 +15,13 @@ import {
1315
} from "~/services/copilot/create-chat-completions"
1416

1517
export async function handleCompletion(c: Context) {
18+
checkRateLimit(state)
19+
1620
let payload = await c.req.json<ChatCompletionsPayload>()
1721

1822
consola.info("Current token count:", getTokenCount(payload.messages))
1923

20-
if (state.manualApprove) {
21-
const response = await consola.prompt(`Accept incoming request?`, {
22-
type: "confirm",
23-
})
24-
25-
if (!response) throw new Error("Request cancelled")
26-
}
24+
if (state.manualApprove) await awaitApproval()
2725

2826
if (isNullish(payload.max_tokens)) {
2927
const selectedModel = state.models?.data.find(

0 commit comments

Comments
 (0)