Skip to content

Commit 871c63a

Browse files
committed
feat: add configuration management with extra prompt handling and ensure config file creation
1 parent 619d482 commit 871c63a

File tree

3 files changed

+93
-18
lines changed

3 files changed

+93
-18
lines changed

src/lib/config.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import fs from "node:fs"
2+
3+
import { PATHS } from "./paths"
4+
5+
export interface AppConfig {
6+
extraPrompt: string
7+
}
8+
9+
const defaultConfig: AppConfig = {
10+
extraPrompt: `
11+
## Tool use
12+
- You have access to many tools. If a tool exists to perform a specific task, you MUST use that tool instead of running a terminal command to perform that task.
13+
### Bash tool
14+
When using the Bash tool, follow these rules:
15+
- always run_in_background set to false, unless you are running a long-running command (e.g., a server or a watch command).
16+
### BashOutput tool
17+
When using the BashOutput tool, follow these rules:
18+
- Only Bash Tool run_in_background set to true, Use BashOutput to read the output later
19+
### TodoWrite tool
20+
When using the TodoWrite tool, follow these rules:
21+
- Skip using the TodoWrite tool for tasks with three or fewer steps.
22+
- Do not make single-step todo lists.
23+
- When you made a todo, update it after having performed one of the sub-tasks that you shared on the todo list.
24+
## Special user requests
25+
- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as 'date'), you should do so.
26+
`,
27+
}
28+
29+
let cachedConfig: AppConfig | null = null
30+
31+
function ensureConfigFile(): void {
32+
try {
33+
fs.accessSync(PATHS.CONFIG_PATH, fs.constants.R_OK | fs.constants.W_OK)
34+
} catch {
35+
fs.writeFileSync(
36+
PATHS.CONFIG_PATH,
37+
`${JSON.stringify(defaultConfig, null, 2)}\n`,
38+
"utf8",
39+
)
40+
try {
41+
fs.chmodSync(PATHS.CONFIG_PATH, 0o600)
42+
} catch {
43+
return
44+
}
45+
}
46+
}
47+
48+
function readConfigFromDisk(): AppConfig {
49+
ensureConfigFile()
50+
try {
51+
const raw = fs.readFileSync(PATHS.CONFIG_PATH, "utf8")
52+
if (!raw.trim()) {
53+
fs.writeFileSync(
54+
PATHS.CONFIG_PATH,
55+
`${JSON.stringify(defaultConfig, null, 2)}\n`,
56+
"utf8",
57+
)
58+
return defaultConfig
59+
}
60+
const parsed = JSON.parse(raw) as AppConfig
61+
return parsed
62+
} catch {
63+
fs.writeFileSync(
64+
PATHS.CONFIG_PATH,
65+
`${JSON.stringify(defaultConfig, null, 2)}\n`,
66+
"utf8",
67+
)
68+
return defaultConfig
69+
}
70+
}
71+
72+
export function getConfig(): AppConfig {
73+
if (!cachedConfig) {
74+
cachedConfig = readConfigFromDisk()
75+
}
76+
return cachedConfig
77+
}
78+
79+
export function reloadConfig(): AppConfig {
80+
cachedConfig = null
81+
return getConfig()
82+
}
83+
84+
export function getExtraPrompt(): string {
85+
return getConfig().extraPrompt
86+
}

src/lib/paths.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ import path from "node:path"
55
const APP_DIR = path.join(os.homedir(), ".local", "share", "copilot-api")
66

77
const GITHUB_TOKEN_PATH = path.join(APP_DIR, "github_token")
8+
const CONFIG_PATH = path.join(APP_DIR, "config.json")
89

910
export const PATHS = {
1011
APP_DIR,
1112
GITHUB_TOKEN_PATH,
13+
CONFIG_PATH,
1214
}
1315

1416
export async function ensurePaths(): Promise<void> {
1517
await fs.mkdir(PATHS.APP_DIR, { recursive: true })
1618
await ensureFile(PATHS.GITHUB_TOKEN_PATH)
19+
await ensureFile(PATHS.CONFIG_PATH)
1720
}
1821

1922
async function ensureFile(filePath: string): Promise<void> {

src/routes/messages/responses-translation.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import consola from "consola"
22

3+
import { getExtraPrompt } from "~/lib/config"
34
import {
45
type ResponsesPayload,
56
type ResponseInputContent,
@@ -282,31 +283,16 @@ const translateSystemPrompt = (
282283
return null
283284
}
284285

285-
const toolUsePrompt = `
286-
## Tool use
287-
- You have access to many tools. If a tool exists to perform a specific task, you MUST use that tool instead of running a terminal command to perform that task.
288-
### Bash tool
289-
When using the Bash tool, follow these rules:
290-
- always run_in_background set to false, unless you are running a long-running command (e.g., a server or a watch command).
291-
### BashOutput tool
292-
When using the BashOutput tool, follow these rules:
293-
- Only Bash Tool run_in_background set to true, Use BashOutput to read the output later
294-
### TodoWrite tool
295-
When using the TodoWrite tool, follow these rules:
296-
- Skip using the TodoWrite tool for tasks with three or fewer steps.
297-
- Do not make single-step todo lists.
298-
- When you made a todo, update it after having performed one of the sub-tasks that you shared on the todo list.
299-
## Special user requests
300-
- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as ''date''), you should do so.`
286+
const extraPrompt = getExtraPrompt()
301287

302288
if (typeof system === "string") {
303-
return system + toolUsePrompt
289+
return system + extraPrompt
304290
}
305291

306292
const text = system
307293
.map((block, index) => {
308294
if (index === 0) {
309-
return block.text + toolUsePrompt
295+
return block.text + extraPrompt
310296
}
311297
return block.text
312298
})

0 commit comments

Comments
 (0)