novacode 0.5.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/app-CbJSUNmf.mjs +22 -0
- package/dist/app-CbJSUNmf.mjs.map +1 -0
- package/dist/main.mjs +51 -61
- package/dist/main.mjs.map +1 -1
- package/package.json +3 -5
- package/dist/app-QfQR2FN9.mjs +0 -21
- package/dist/app-QfQR2FN9.mjs.map +0 -1
- package/src/agent/agent.ts +0 -87
- package/src/agent/loop.ts +0 -237
- package/src/agent/prompt.ts +0 -50
- package/src/commands/compact.ts +0 -28
- package/src/commands/index.ts +0 -86
- package/src/commands/models.ts +0 -85
- package/src/commands/providers.ts +0 -213
- package/src/commands/session.ts +0 -40
- package/src/config/providers.ts +0 -207
- package/src/config/store.ts +0 -66
- package/src/main.ts +0 -175
- package/src/onboarding/wizard.ts +0 -54
- package/src/provider/gemini.ts +0 -261
- package/src/provider/openai.ts +0 -215
- package/src/provider/stream.ts +0 -138
- package/src/session/compact.ts +0 -126
- package/src/session/store.ts +0 -229
- package/src/tools/fs.ts +0 -189
- package/src/tools/git.ts +0 -99
- package/src/tools/index.ts +0 -33
- package/src/tools/search.ts +0 -274
- package/src/tools/shell.ts +0 -90
- package/src/tools/web.ts +0 -239
- package/src/tui/app.tsx +0 -364
- package/src/tui/components/liveArea.tsx +0 -73
- package/src/tui/components/message.tsx +0 -113
- package/src/tui/components/statusBar.tsx +0 -58
- package/src/tui/markdown.ts +0 -62
- package/src/tui/prompts.tsx +0 -205
- package/src/types.ts +0 -248
- package/src/update.ts +0 -89
- package/src/util.ts +0 -61
package/src/commands/index.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk"
|
|
2
|
-
import type { Agent } from "../agent/agent.ts"
|
|
3
|
-
import type { SessionStore } from "../session/store.ts"
|
|
4
|
-
import type { Cmd, Prompts } from "../types.ts"
|
|
5
|
-
import { checkForUpdate, runUpdate } from "../update.ts"
|
|
6
|
-
import { handleCompact } from "./compact.ts"
|
|
7
|
-
import { handleModels } from "./models.ts"
|
|
8
|
-
import { handleProviders } from "./providers.ts"
|
|
9
|
-
|
|
10
|
-
export const COMMANDS: Cmd[] = [
|
|
11
|
-
{ name: "models", desc: "Switch model", aliases: ["model"] },
|
|
12
|
-
{ name: "providers", desc: "Manage providers", aliases: ["prov", "config", "cfg"] },
|
|
13
|
-
{ name: "compact", desc: "Compact context" },
|
|
14
|
-
{ name: "update", desc: "Update novacode" },
|
|
15
|
-
{ name: "help", desc: "Show help" },
|
|
16
|
-
{ name: "clear", desc: "Clear screen" },
|
|
17
|
-
{ name: "quit", desc: "Exit (Ctrl+D)", aliases: ["exit"] },
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
const HELP = `
|
|
21
|
-
${chalk.bold("Commands:")}
|
|
22
|
-
${COMMANDS.map((c) => ` /${c.name.padEnd(12)} ${c.desc}`).join("\n")}
|
|
23
|
-
|
|
24
|
-
${chalk.bold("CLI:")}
|
|
25
|
-
nova update Update to latest version
|
|
26
|
-
nova session ls List sessions
|
|
27
|
-
|
|
28
|
-
${chalk.dim("Keys:")}
|
|
29
|
-
Esc Abort
|
|
30
|
-
↑ / ↓ History
|
|
31
|
-
`
|
|
32
|
-
|
|
33
|
-
export async function dispatch(
|
|
34
|
-
input: string,
|
|
35
|
-
agent: Agent,
|
|
36
|
-
store?: SessionStore,
|
|
37
|
-
sessionId?: string,
|
|
38
|
-
prompts?: Prompts,
|
|
39
|
-
): Promise<string | null> {
|
|
40
|
-
const [cmd, ...rest] = input.slice(1).split(" ")
|
|
41
|
-
const args = rest.join(" ")
|
|
42
|
-
|
|
43
|
-
switch (cmd) {
|
|
44
|
-
case "models":
|
|
45
|
-
case "model":
|
|
46
|
-
return handleModels(args, agent, prompts)
|
|
47
|
-
case "providers":
|
|
48
|
-
case "prov":
|
|
49
|
-
case "config":
|
|
50
|
-
case "cfg":
|
|
51
|
-
return handleProviders(agent, prompts)
|
|
52
|
-
case "compact":
|
|
53
|
-
if (!store || !sessionId) return chalk.red("Session store not available")
|
|
54
|
-
return handleCompact(agent, store, sessionId)
|
|
55
|
-
case "update":
|
|
56
|
-
return handleUpdate()
|
|
57
|
-
case "help":
|
|
58
|
-
return HELP
|
|
59
|
-
case "clear":
|
|
60
|
-
console.clear()
|
|
61
|
-
return ""
|
|
62
|
-
case "quit":
|
|
63
|
-
process.exit(0)
|
|
64
|
-
return null
|
|
65
|
-
case "exit":
|
|
66
|
-
process.exit(0)
|
|
67
|
-
return null
|
|
68
|
-
default:
|
|
69
|
-
return chalk.yellow(`Unknown: /${cmd}. Type /help`)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async function handleUpdate(): Promise<string> {
|
|
74
|
-
const info = await checkForUpdate()
|
|
75
|
-
if (!info) return chalk.yellow("Could not check for updates.")
|
|
76
|
-
if (!info.hasUpdate) return chalk.green(`✓ Already up to date (v${info.current})`)
|
|
77
|
-
|
|
78
|
-
console.log(chalk.yellow(`\n⚡ Updating novacode to v${info.latest}...`))
|
|
79
|
-
const success = await runUpdate(true)
|
|
80
|
-
if (success) {
|
|
81
|
-
return chalk.green(
|
|
82
|
-
`✓ Successfully updated to v${info.latest}! Please restart nova to apply changes.`,
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
return chalk.red("✗ Update failed. Please try running 'nova update' manually in your terminal.")
|
|
86
|
-
}
|
package/src/commands/models.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk"
|
|
2
|
-
import type { Agent } from "../agent/agent.ts"
|
|
3
|
-
import { getProvider, MODELS } from "../config/providers.ts"
|
|
4
|
-
import { loadAuth, loadConfig, saveConfig } from "../config/store.ts"
|
|
5
|
-
import type { Prompts } from "../types.ts"
|
|
6
|
-
|
|
7
|
-
export async function handleModels(args: string, agent: Agent, prompts?: Prompts): Promise<string> {
|
|
8
|
-
const config = await loadConfig()
|
|
9
|
-
const auth = await loadAuth()
|
|
10
|
-
|
|
11
|
-
if (args) return await switchDirect(args.trim(), agent)
|
|
12
|
-
|
|
13
|
-
if (!prompts) return chalk.red("Prompts not available in this context")
|
|
14
|
-
|
|
15
|
-
const options: Array<{ value: string; label: string; hint?: string }> = []
|
|
16
|
-
for (const m of MODELS) {
|
|
17
|
-
const cur = m.id === config.model && m.provider === config.provider
|
|
18
|
-
const pDef = getProvider(m.provider)
|
|
19
|
-
if (!pDef) continue
|
|
20
|
-
|
|
21
|
-
const hasKey = !!auth.apiKeys[m.provider]
|
|
22
|
-
if (!hasKey) continue
|
|
23
|
-
|
|
24
|
-
options.push({
|
|
25
|
-
value: `${m.provider}:${m.id}`,
|
|
26
|
-
label: `${cur ? chalk.green("●") : "○"} ${m.id.padEnd(20)} ${fmt(m.contextWindow).padEnd(8)}`,
|
|
27
|
-
hint: pDef.name,
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!options.length)
|
|
32
|
-
return chalk.yellow("No models available. Use /providers to add a provider API key.")
|
|
33
|
-
|
|
34
|
-
const pick = await prompts.select({ message: "Model", options })
|
|
35
|
-
if (!pick) return ""
|
|
36
|
-
|
|
37
|
-
const [pk, mid] = pick.split(":")
|
|
38
|
-
const selectedModel = MODELS.find((m) => m.provider === pk && m.id === mid)
|
|
39
|
-
const selectedProvider = getProvider(pk!)
|
|
40
|
-
|
|
41
|
-
if (!selectedModel || !selectedProvider) return chalk.red("Error: Model or provider not found")
|
|
42
|
-
|
|
43
|
-
config.provider = pk!
|
|
44
|
-
config.model = mid!
|
|
45
|
-
await saveConfig(config)
|
|
46
|
-
|
|
47
|
-
agent.updateConfig({
|
|
48
|
-
api: selectedProvider.api,
|
|
49
|
-
model: selectedModel,
|
|
50
|
-
apiKey: auth.apiKeys[pk!] ?? "",
|
|
51
|
-
baseUrl: selectedProvider.baseUrl,
|
|
52
|
-
})
|
|
53
|
-
return chalk.green(`✓ Switched to ${mid}`)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function switchDirect(id: string, agent: Agent): Promise<string> {
|
|
57
|
-
const config = await loadConfig()
|
|
58
|
-
const auth = await loadAuth()
|
|
59
|
-
|
|
60
|
-
const m = MODELS.find((m) => m.id === id)
|
|
61
|
-
if (!m) return chalk.yellow(`"${id}" not found. Use /models`)
|
|
62
|
-
|
|
63
|
-
const pk = m.provider
|
|
64
|
-
if (!auth.apiKeys[pk]) {
|
|
65
|
-
return chalk.yellow(`No API key configured for ${pk}. Use /providers`)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const selectedProvider = getProvider(pk)
|
|
69
|
-
if (!selectedProvider) return chalk.red("Error: Provider not found")
|
|
70
|
-
|
|
71
|
-
config.provider = pk
|
|
72
|
-
config.model = id
|
|
73
|
-
await saveConfig(config)
|
|
74
|
-
|
|
75
|
-
agent.updateConfig({
|
|
76
|
-
api: selectedProvider.api,
|
|
77
|
-
model: m,
|
|
78
|
-
apiKey: auth.apiKeys[pk],
|
|
79
|
-
baseUrl: selectedProvider.baseUrl,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
return chalk.green(`✓ Switched to ${id}`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const fmt = (n: number) => (n >= 1_000_000 ? `${n / 1_000_000}M` : `${n / 1000}K`)
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk"
|
|
2
|
-
import type { Agent } from "../agent/agent.ts"
|
|
3
|
-
import { getProvider, MODELS, PROVIDERS } from "../config/providers.ts"
|
|
4
|
-
import { loadAuth, loadConfig, saveAuth, saveConfig } from "../config/store.ts"
|
|
5
|
-
import type { Prompts } from "../types.ts"
|
|
6
|
-
|
|
7
|
-
export async function handleProviders(agent: Agent, prompts?: Prompts): Promise<string> {
|
|
8
|
-
if (!prompts) return chalk.red("Prompts not available in this context")
|
|
9
|
-
|
|
10
|
-
const config = await loadConfig()
|
|
11
|
-
const auth = await loadAuth()
|
|
12
|
-
const configured = PROVIDERS.filter((p) => !!auth.apiKeys[p.id])
|
|
13
|
-
|
|
14
|
-
const headerLines =
|
|
15
|
-
configured.length === 0
|
|
16
|
-
? chalk.dim("No providers configured. Use 'Add Provider' below.")
|
|
17
|
-
: configured
|
|
18
|
-
.map((p) => {
|
|
19
|
-
const isDefault = p.id === config.provider
|
|
20
|
-
const active = isDefault ? chalk.green(" ●") : ""
|
|
21
|
-
const currentModel = isDefault
|
|
22
|
-
? config.model
|
|
23
|
-
: (MODELS.find((m) => m.provider === p.id)?.id ?? "")
|
|
24
|
-
return ` ✅ ${p.name.padEnd(24)} ${currentModel}${active}`
|
|
25
|
-
})
|
|
26
|
-
.join("\n")
|
|
27
|
-
|
|
28
|
-
const act = await prompts.select({
|
|
29
|
-
message: "Action",
|
|
30
|
-
header: headerLines,
|
|
31
|
-
options: [
|
|
32
|
-
{ value: "add", label: "Add Provider" },
|
|
33
|
-
{ value: "update", label: "Update API Key" },
|
|
34
|
-
{ value: "remove", label: "Remove API Key" },
|
|
35
|
-
{ value: "default", label: "Set Default Provider" },
|
|
36
|
-
{ value: "back", label: "Back" },
|
|
37
|
-
],
|
|
38
|
-
})
|
|
39
|
-
if (!act || act === "back") return ""
|
|
40
|
-
|
|
41
|
-
if (act === "add") return addProvider(agent, prompts)
|
|
42
|
-
if (act === "update") return updateKey(agent, prompts)
|
|
43
|
-
if (act === "remove") return removeKey(agent, prompts)
|
|
44
|
-
if (act === "default") return setDefault(agent, prompts)
|
|
45
|
-
return ""
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function addProvider(agent: Agent, prompts: Prompts): Promise<string> {
|
|
49
|
-
const auth = await loadAuth()
|
|
50
|
-
const config = await loadConfig()
|
|
51
|
-
|
|
52
|
-
const available = PROVIDERS.filter((p) => !auth.apiKeys[p.id])
|
|
53
|
-
if (available.length === 0) {
|
|
54
|
-
return chalk.yellow("All providers already have API keys configured.")
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const pick = await prompts.select({
|
|
58
|
-
message: "Add Provider",
|
|
59
|
-
options: available.map((p) => ({ value: p.id, label: p.name })),
|
|
60
|
-
})
|
|
61
|
-
if (!pick) return ""
|
|
62
|
-
|
|
63
|
-
const pDef = getProvider(pick)
|
|
64
|
-
if (!pDef) return chalk.red("Error: Provider not found")
|
|
65
|
-
|
|
66
|
-
const key = await prompts.password({
|
|
67
|
-
message: `${pDef.name} API Key`,
|
|
68
|
-
validate: (v) => (!v || v.length < 8 ? "Enter a valid key" : undefined),
|
|
69
|
-
})
|
|
70
|
-
if (!key) return ""
|
|
71
|
-
|
|
72
|
-
auth.apiKeys[pDef.id] = key
|
|
73
|
-
await saveAuth(auth)
|
|
74
|
-
|
|
75
|
-
if (!config.provider) {
|
|
76
|
-
config.provider = pDef.id
|
|
77
|
-
const mDef = MODELS.find((m) => m.provider === pDef.id)
|
|
78
|
-
if (mDef) {
|
|
79
|
-
config.model = mDef.id
|
|
80
|
-
}
|
|
81
|
-
await saveConfig(config)
|
|
82
|
-
agent.updateConfig({
|
|
83
|
-
api: pDef.api,
|
|
84
|
-
model: MODELS.find((m) => m.id === config.model)!,
|
|
85
|
-
apiKey: key,
|
|
86
|
-
baseUrl: pDef.baseUrl,
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return chalk.green(`✓ ${pDef.name} configured`)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async function updateKey(agent: Agent, prompts: Prompts): Promise<string> {
|
|
94
|
-
const auth = await loadAuth()
|
|
95
|
-
|
|
96
|
-
const configured = PROVIDERS.filter((p) => !!auth.apiKeys[p.id])
|
|
97
|
-
if (configured.length === 0) {
|
|
98
|
-
return chalk.yellow("No providers configured. Use 'Add Provider' first.")
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const pick = await prompts.select({
|
|
102
|
-
message: "Update API Key",
|
|
103
|
-
options: configured.map((p) => ({ value: p.id, label: p.name })),
|
|
104
|
-
})
|
|
105
|
-
if (!pick) return ""
|
|
106
|
-
|
|
107
|
-
const pDef = getProvider(pick)
|
|
108
|
-
if (!pDef) return chalk.red("Error: Provider not found")
|
|
109
|
-
|
|
110
|
-
const key = await prompts.password({ message: `New key for ${pDef.name}` })
|
|
111
|
-
if (!key) return ""
|
|
112
|
-
|
|
113
|
-
auth.apiKeys[pDef.id] = key
|
|
114
|
-
await saveAuth(auth)
|
|
115
|
-
|
|
116
|
-
const config = await loadConfig()
|
|
117
|
-
if (config.provider === pDef.id) {
|
|
118
|
-
const currentModel = MODELS.find((m) => m.id === config.model && m.provider === config.provider)
|
|
119
|
-
if (currentModel) {
|
|
120
|
-
agent.updateConfig({
|
|
121
|
-
api: pDef.api,
|
|
122
|
-
model: currentModel,
|
|
123
|
-
apiKey: key,
|
|
124
|
-
baseUrl: pDef.baseUrl,
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return chalk.green("✓ Key updated")
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function removeKey(agent: Agent, prompts: Prompts): Promise<string> {
|
|
133
|
-
const auth = await loadAuth()
|
|
134
|
-
const config = await loadConfig()
|
|
135
|
-
|
|
136
|
-
const configured = PROVIDERS.filter((p) => !!auth.apiKeys[p.id])
|
|
137
|
-
if (configured.length === 0) {
|
|
138
|
-
return chalk.yellow("No configured providers to remove.")
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const pick = await prompts.select({
|
|
142
|
-
message: "Remove API Key",
|
|
143
|
-
options: configured.map((p) => ({ value: p.id, label: p.name })),
|
|
144
|
-
})
|
|
145
|
-
if (!pick) return ""
|
|
146
|
-
|
|
147
|
-
const confirm = await prompts.confirm({
|
|
148
|
-
message: `Are you sure you want to remove the API key for ${pick}?`,
|
|
149
|
-
})
|
|
150
|
-
if (!confirm) return ""
|
|
151
|
-
|
|
152
|
-
delete auth.apiKeys[pick]
|
|
153
|
-
await saveAuth(auth)
|
|
154
|
-
|
|
155
|
-
if (config.provider === pick) {
|
|
156
|
-
config.provider = ""
|
|
157
|
-
config.model = ""
|
|
158
|
-
const next = Object.keys(auth.apiKeys)[0]
|
|
159
|
-
if (next) {
|
|
160
|
-
const pDef = getProvider(next)
|
|
161
|
-
const mDef = MODELS.find((m) => m.provider === next)
|
|
162
|
-
if (pDef && mDef) {
|
|
163
|
-
config.provider = next
|
|
164
|
-
config.model = mDef.id
|
|
165
|
-
agent.updateConfig({
|
|
166
|
-
api: pDef.api,
|
|
167
|
-
model: mDef,
|
|
168
|
-
apiKey: auth.apiKeys[next]!,
|
|
169
|
-
baseUrl: pDef.baseUrl,
|
|
170
|
-
})
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
await saveConfig(config)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return chalk.green(`✓ Removed API key for ${pick}`)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async function setDefault(agent: Agent, prompts: Prompts): Promise<string> {
|
|
180
|
-
const config = await loadConfig()
|
|
181
|
-
const auth = await loadAuth()
|
|
182
|
-
|
|
183
|
-
const pick = await prompts.select({
|
|
184
|
-
message: "Default Provider",
|
|
185
|
-
options: PROVIDERS.map((p) => ({
|
|
186
|
-
value: p.id,
|
|
187
|
-
label: `${auth.apiKeys[p.id] ? "✅" : "❌"} ${p.name}`,
|
|
188
|
-
})),
|
|
189
|
-
})
|
|
190
|
-
if (!pick) return ""
|
|
191
|
-
|
|
192
|
-
if (!auth.apiKeys[pick]) {
|
|
193
|
-
return chalk.yellow(`No API key for ${pick}. Please set one first.`)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const pDef = getProvider(pick)
|
|
197
|
-
const mDef = MODELS.find((m) => m.provider === pick)
|
|
198
|
-
|
|
199
|
-
if (!pDef || !mDef) return chalk.red("Error: Provider or model not found")
|
|
200
|
-
|
|
201
|
-
config.provider = pick
|
|
202
|
-
config.model = mDef.id
|
|
203
|
-
await saveConfig(config)
|
|
204
|
-
|
|
205
|
-
agent.updateConfig({
|
|
206
|
-
api: pDef.api,
|
|
207
|
-
model: mDef,
|
|
208
|
-
apiKey: auth.apiKeys[pick],
|
|
209
|
-
baseUrl: pDef.baseUrl,
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
return chalk.green(`✓ Default set to ${pDef.name} (${mDef.id})`)
|
|
213
|
-
}
|
package/src/commands/session.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { getSessionStore } from "../session/store.ts"
|
|
2
|
-
|
|
3
|
-
export async function handleSessionCommand(args: string[]): Promise<void> {
|
|
4
|
-
const store = getSessionStore()
|
|
5
|
-
const [subcommand, id] = args
|
|
6
|
-
|
|
7
|
-
if (subcommand === "list" || subcommand === "ls") {
|
|
8
|
-
const sessions = store.list()
|
|
9
|
-
if (sessions.length === 0) {
|
|
10
|
-
console.log("No sessions found.")
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
console.log("ID".padEnd(25), "MODEL".padEnd(20), "UPDATED")
|
|
15
|
-
console.log("-".repeat(70))
|
|
16
|
-
for (const s of sessions) {
|
|
17
|
-
const date = new Date(s.updated).toLocaleString()
|
|
18
|
-
console.log(s.id.padEnd(25), s.model.padEnd(20), date)
|
|
19
|
-
}
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (subcommand === "delete" || subcommand === "rm") {
|
|
24
|
-
if (!id) {
|
|
25
|
-
console.error("Usage: novacode session delete <id>")
|
|
26
|
-
process.exit(1)
|
|
27
|
-
}
|
|
28
|
-
const success = store.delete(id)
|
|
29
|
-
if (success) {
|
|
30
|
-
console.log(`Deleted session: ${id}`)
|
|
31
|
-
} else {
|
|
32
|
-
console.error(`Session not found: ${id}`)
|
|
33
|
-
process.exit(1)
|
|
34
|
-
}
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
console.error("Unknown session subcommand. Use 'list' or 'delete'.")
|
|
39
|
-
process.exit(1)
|
|
40
|
-
}
|
package/src/config/providers.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import type { Model, ProviderDef } from "../types.ts"
|
|
2
|
-
|
|
3
|
-
export const PROVIDERS: ProviderDef[] = [
|
|
4
|
-
{
|
|
5
|
-
id: "glm",
|
|
6
|
-
name: "GLM (Z.AI)",
|
|
7
|
-
api: "openai",
|
|
8
|
-
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
|
9
|
-
envKey: "GLM_API_KEY",
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
id: "gemini",
|
|
13
|
-
name: "Gemini (Google)",
|
|
14
|
-
api: "gemini",
|
|
15
|
-
baseUrl: "https://generativelanguage.googleapis.com",
|
|
16
|
-
envKey: "GEMINI_API_KEY",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: "deepseek",
|
|
20
|
-
name: "DeepSeek",
|
|
21
|
-
api: "openai",
|
|
22
|
-
baseUrl: "https://api.deepseek.com",
|
|
23
|
-
envKey: "DEEPSEEK_API_KEY",
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
id: "openai",
|
|
27
|
-
name: "OpenAI",
|
|
28
|
-
api: "openai",
|
|
29
|
-
baseUrl: "https://api.openai.com/v1",
|
|
30
|
-
envKey: "OPENAI_API_KEY",
|
|
31
|
-
},
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
export const MODELS: Model[] = [
|
|
35
|
-
// GLM
|
|
36
|
-
{
|
|
37
|
-
id: "glm-5.1",
|
|
38
|
-
name: "GLM-5.1",
|
|
39
|
-
provider: "glm",
|
|
40
|
-
contextWindow: 128_000,
|
|
41
|
-
maxTokens: 4096,
|
|
42
|
-
supportsThinking: false,
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: "glm-5",
|
|
46
|
-
name: "GLM-5",
|
|
47
|
-
provider: "glm",
|
|
48
|
-
contextWindow: 128_000,
|
|
49
|
-
maxTokens: 4096,
|
|
50
|
-
supportsThinking: false,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: "glm-5-turbo",
|
|
54
|
-
name: "GLM-5 Turbo",
|
|
55
|
-
provider: "glm",
|
|
56
|
-
contextWindow: 128_000,
|
|
57
|
-
maxTokens: 4096,
|
|
58
|
-
supportsThinking: false,
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: "glm-4.7",
|
|
62
|
-
name: "GLM-4.7",
|
|
63
|
-
provider: "glm",
|
|
64
|
-
contextWindow: 128_000,
|
|
65
|
-
maxTokens: 4096,
|
|
66
|
-
supportsThinking: false,
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
id: "glm-4.7-flash",
|
|
70
|
-
name: "GLM-4.7 Flash (Free)",
|
|
71
|
-
provider: "glm",
|
|
72
|
-
contextWindow: 128_000,
|
|
73
|
-
maxTokens: 4096,
|
|
74
|
-
supportsThinking: false,
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: "glm-4.5-flash",
|
|
78
|
-
name: "GLM-4.5 Flash (Free)",
|
|
79
|
-
provider: "glm",
|
|
80
|
-
contextWindow: 128_000,
|
|
81
|
-
maxTokens: 4096,
|
|
82
|
-
supportsThinking: false,
|
|
83
|
-
},
|
|
84
|
-
// Gemini
|
|
85
|
-
{
|
|
86
|
-
id: "gemini-3.5-flash",
|
|
87
|
-
name: "Gemini 3.5 Flash",
|
|
88
|
-
provider: "gemini",
|
|
89
|
-
contextWindow: 1_000_000,
|
|
90
|
-
maxTokens: 65_536,
|
|
91
|
-
supportsThinking: true,
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: "gemini-3.1-pro-preview",
|
|
95
|
-
name: "Gemini 3.1 Pro Preview",
|
|
96
|
-
provider: "gemini",
|
|
97
|
-
contextWindow: 2_000_000,
|
|
98
|
-
maxTokens: 65_536,
|
|
99
|
-
supportsThinking: true,
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: "gemini-3.1-pro-preview-customtools",
|
|
103
|
-
name: "Gemini 3.1 Pro (Custom Tools)",
|
|
104
|
-
provider: "gemini",
|
|
105
|
-
contextWindow: 2_000_000,
|
|
106
|
-
maxTokens: 65_536,
|
|
107
|
-
supportsThinking: true,
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
id: "gemini-3.1-flash-lite",
|
|
111
|
-
name: "Gemini 3.1 Flash-Lite",
|
|
112
|
-
provider: "gemini",
|
|
113
|
-
contextWindow: 1_000_000,
|
|
114
|
-
maxTokens: 65_536,
|
|
115
|
-
supportsThinking: true,
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
id: "gemini-3.1-flash-lite-preview",
|
|
119
|
-
name: "Gemini 3.1 Flash-Lite Preview",
|
|
120
|
-
provider: "gemini",
|
|
121
|
-
contextWindow: 1_000_000,
|
|
122
|
-
maxTokens: 65_536,
|
|
123
|
-
supportsThinking: true,
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
id: "gemini-3-flash-preview",
|
|
127
|
-
name: "Gemini 3 Flash Preview",
|
|
128
|
-
provider: "gemini",
|
|
129
|
-
contextWindow: 1_000_000,
|
|
130
|
-
maxTokens: 65_536,
|
|
131
|
-
supportsThinking: true,
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
id: "gemini-2.5-pro",
|
|
135
|
-
name: "Gemini 2.5 Pro",
|
|
136
|
-
provider: "gemini",
|
|
137
|
-
contextWindow: 2_000_000,
|
|
138
|
-
maxTokens: 65_536,
|
|
139
|
-
supportsThinking: false,
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
id: "gemini-2.5-flash",
|
|
143
|
-
name: "Gemini 2.5 Flash",
|
|
144
|
-
provider: "gemini",
|
|
145
|
-
contextWindow: 1_000_000,
|
|
146
|
-
maxTokens: 65_536,
|
|
147
|
-
supportsThinking: false,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: "gemini-2.5-flash-lite",
|
|
151
|
-
name: "Gemini 2.5 Flash-Lite",
|
|
152
|
-
provider: "gemini",
|
|
153
|
-
contextWindow: 1_000_000,
|
|
154
|
-
maxTokens: 65_536,
|
|
155
|
-
supportsThinking: false,
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
id: "gemini-2.5-computer-use-preview-10-2025",
|
|
159
|
-
name: "Gemini 2.5 Computer Use",
|
|
160
|
-
provider: "gemini",
|
|
161
|
-
contextWindow: 1_000_000,
|
|
162
|
-
maxTokens: 65_536,
|
|
163
|
-
supportsThinking: false,
|
|
164
|
-
},
|
|
165
|
-
// DeepSeek
|
|
166
|
-
{
|
|
167
|
-
id: "deepseek-chat",
|
|
168
|
-
name: "DeepSeek V3",
|
|
169
|
-
provider: "deepseek",
|
|
170
|
-
contextWindow: 64_000,
|
|
171
|
-
maxTokens: 8_192,
|
|
172
|
-
supportsThinking: false,
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
id: "deepseek-reasoner",
|
|
176
|
-
name: "DeepSeek R1",
|
|
177
|
-
provider: "deepseek",
|
|
178
|
-
contextWindow: 64_000,
|
|
179
|
-
maxTokens: 8_192,
|
|
180
|
-
supportsThinking: true,
|
|
181
|
-
},
|
|
182
|
-
// OpenAI
|
|
183
|
-
{
|
|
184
|
-
id: "gpt-4o",
|
|
185
|
-
name: "GPT-4o",
|
|
186
|
-
provider: "openai",
|
|
187
|
-
contextWindow: 128_000,
|
|
188
|
-
maxTokens: 16_384,
|
|
189
|
-
supportsThinking: false,
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
id: "o4-mini",
|
|
193
|
-
name: "o4-mini",
|
|
194
|
-
provider: "openai",
|
|
195
|
-
contextWindow: 200_000,
|
|
196
|
-
maxTokens: 100_000,
|
|
197
|
-
supportsThinking: true,
|
|
198
|
-
},
|
|
199
|
-
]
|
|
200
|
-
|
|
201
|
-
export function getProvider(id: string): ProviderDef | undefined {
|
|
202
|
-
return PROVIDERS.find((p) => p.id === id)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function getModelsForProvider(providerId: string): Model[] {
|
|
206
|
-
return MODELS.filter((m) => m.provider === providerId)
|
|
207
|
-
}
|
package/src/config/store.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises"
|
|
2
|
-
import { join } from "node:path"
|
|
3
|
-
import type { NovaAuth, NovaConfig } from "../types.ts"
|
|
4
|
-
|
|
5
|
-
const NOVA_DIR = () => join(process.env.HOME ?? "~", ".novacode")
|
|
6
|
-
const CONFIG_PATH = () => join(NOVA_DIR(), "config.json")
|
|
7
|
-
const AUTH_PATH = () => join(NOVA_DIR(), "auth.json")
|
|
8
|
-
|
|
9
|
-
const defaultConfig: NovaConfig = {
|
|
10
|
-
provider: "",
|
|
11
|
-
model: "",
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const defaultAuth: NovaAuth = {
|
|
15
|
-
apiKeys: {},
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function configExists(): Promise<boolean> {
|
|
19
|
-
try {
|
|
20
|
-
await stat(CONFIG_PATH())
|
|
21
|
-
return true
|
|
22
|
-
} catch {
|
|
23
|
-
return false
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function loadConfig(): Promise<NovaConfig> {
|
|
28
|
-
try {
|
|
29
|
-
const raw = JSON.parse(await readFile(CONFIG_PATH(), "utf-8"))
|
|
30
|
-
return { ...defaultConfig, ...raw }
|
|
31
|
-
} catch {
|
|
32
|
-
return { ...defaultConfig }
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function loadAuth(): Promise<NovaAuth> {
|
|
37
|
-
try {
|
|
38
|
-
const raw = JSON.parse(await readFile(AUTH_PATH(), "utf-8"))
|
|
39
|
-
return { ...defaultAuth, ...raw }
|
|
40
|
-
} catch {
|
|
41
|
-
return { ...defaultAuth }
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function ensureDir(): Promise<void> {
|
|
46
|
-
await mkdir(NOVA_DIR(), { recursive: true })
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function saveConfig(config: NovaConfig): Promise<void> {
|
|
50
|
-
await ensureDir()
|
|
51
|
-
await writeFile(CONFIG_PATH(), JSON.stringify(config, null, 2))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function saveAuth(auth: NovaAuth): Promise<void> {
|
|
55
|
-
await ensureDir()
|
|
56
|
-
await writeFile(AUTH_PATH(), JSON.stringify(auth, null, 2))
|
|
57
|
-
try {
|
|
58
|
-
await chmod(AUTH_PATH(), 0o600)
|
|
59
|
-
} catch {
|
|
60
|
-
// chmod may fail on some platforms, non-fatal
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function getNovaDir(): string {
|
|
65
|
-
return NOVA_DIR()
|
|
66
|
-
}
|