Changed model identification from using model.id to model.target when calling providers, allowing users to specify alternate model IDs while maintaining internal references. This enables more flexible provider configurations and better model mapping.
148 lines
4.6 KiB
TypeScript
148 lines
4.6 KiB
TypeScript
import { Ripgrep } from "../file/ripgrep"
|
|
import { Global } from "../global"
|
|
import { Filesystem } from "../util/filesystem"
|
|
import { Config } from "../config/config"
|
|
|
|
import { Instance } from "../project/instance"
|
|
import path from "path"
|
|
import os from "os"
|
|
|
|
import PROMPT_ANTHROPIC from "./prompt/anthropic.txt"
|
|
import PROMPT_ANTHROPIC_WITHOUT_TODO from "./prompt/qwen.txt"
|
|
import PROMPT_POLARIS from "./prompt/polaris.txt"
|
|
import PROMPT_BEAST from "./prompt/beast.txt"
|
|
import PROMPT_GEMINI from "./prompt/gemini.txt"
|
|
import PROMPT_ANTHROPIC_SPOOF from "./prompt/anthropic_spoof.txt"
|
|
import PROMPT_COMPACTION from "./prompt/compaction.txt"
|
|
import PROMPT_SUMMARIZE from "./prompt/summarize.txt"
|
|
import PROMPT_TITLE from "./prompt/title.txt"
|
|
import PROMPT_CODEX from "./prompt/codex.txt"
|
|
import type { ModelsDev } from "@/provider/models"
|
|
|
|
export namespace SystemPrompt {
|
|
export function header(providerID: string) {
|
|
if (providerID.includes("anthropic")) return [PROMPT_ANTHROPIC_SPOOF.trim()]
|
|
return []
|
|
}
|
|
|
|
export function provider(model: ModelsDev.Model) {
|
|
if (model.target.includes("gpt-5")) return [PROMPT_CODEX]
|
|
if (model.target.includes("gpt-") || model.target.includes("o1") || model.target.includes("o3"))
|
|
return [PROMPT_BEAST]
|
|
if (model.target.includes("gemini-")) return [PROMPT_GEMINI]
|
|
if (model.target.includes("claude")) return [PROMPT_ANTHROPIC]
|
|
if (model.target.includes("polaris-alpha")) return [PROMPT_POLARIS]
|
|
return [PROMPT_ANTHROPIC_WITHOUT_TODO]
|
|
}
|
|
|
|
export async function environment() {
|
|
const project = Instance.project
|
|
return [
|
|
[
|
|
`Here is some useful information about the environment you are running in:`,
|
|
`<env>`,
|
|
` Working directory: ${Instance.directory}`,
|
|
` Is directory a git repo: ${project.vcs === "git" ? "yes" : "no"}`,
|
|
` Platform: ${process.platform}`,
|
|
` Today's date: ${new Date().toDateString()}`,
|
|
`</env>`,
|
|
`<files>`,
|
|
` ${
|
|
project.vcs === "git"
|
|
? await Ripgrep.tree({
|
|
cwd: Instance.directory,
|
|
limit: 200,
|
|
})
|
|
: ""
|
|
}`,
|
|
`</files>`,
|
|
].join("\n"),
|
|
]
|
|
}
|
|
|
|
const LOCAL_RULE_FILES = [
|
|
"AGENTS.md",
|
|
"CLAUDE.md",
|
|
"CONTEXT.md", // deprecated
|
|
]
|
|
const GLOBAL_RULE_FILES = [
|
|
path.join(Global.Path.config, "AGENTS.md"),
|
|
path.join(os.homedir(), ".claude", "CLAUDE.md"),
|
|
]
|
|
|
|
export async function custom() {
|
|
const config = await Config.get()
|
|
const paths = new Set<string>()
|
|
|
|
for (const localRuleFile of LOCAL_RULE_FILES) {
|
|
const matches = await Filesystem.findUp(localRuleFile, Instance.directory, Instance.worktree)
|
|
if (matches.length > 0) {
|
|
matches.forEach((path) => paths.add(path))
|
|
break
|
|
}
|
|
}
|
|
|
|
for (const globalRuleFile of GLOBAL_RULE_FILES) {
|
|
if (await Bun.file(globalRuleFile).exists()) {
|
|
paths.add(globalRuleFile)
|
|
break
|
|
}
|
|
}
|
|
|
|
if (config.instructions) {
|
|
for (let instruction of config.instructions) {
|
|
if (instruction.startsWith("~/")) {
|
|
instruction = path.join(os.homedir(), instruction.slice(2))
|
|
}
|
|
let matches: string[] = []
|
|
if (path.isAbsolute(instruction)) {
|
|
matches = await Array.fromAsync(
|
|
new Bun.Glob(path.basename(instruction)).scan({
|
|
cwd: path.dirname(instruction),
|
|
absolute: true,
|
|
onlyFiles: true,
|
|
}),
|
|
).catch(() => [])
|
|
} else {
|
|
matches = await Filesystem.globUp(instruction, Instance.directory, Instance.worktree).catch(() => [])
|
|
}
|
|
matches.forEach((path) => paths.add(path))
|
|
}
|
|
}
|
|
|
|
const found = Array.from(paths).map((p) =>
|
|
Bun.file(p)
|
|
.text()
|
|
.catch(() => "")
|
|
.then((x) => "Instructions from: " + p + "\n" + x),
|
|
)
|
|
return Promise.all(found).then((result) => result.filter(Boolean))
|
|
}
|
|
|
|
export function compaction(providerID: string) {
|
|
switch (providerID) {
|
|
case "anthropic":
|
|
return [PROMPT_ANTHROPIC_SPOOF.trim(), PROMPT_COMPACTION]
|
|
default:
|
|
return [PROMPT_COMPACTION]
|
|
}
|
|
}
|
|
|
|
export function summarize(providerID: string) {
|
|
switch (providerID) {
|
|
case "anthropic":
|
|
return [PROMPT_ANTHROPIC_SPOOF.trim(), PROMPT_SUMMARIZE]
|
|
default:
|
|
return [PROMPT_SUMMARIZE]
|
|
}
|
|
}
|
|
|
|
export function title(providerID: string) {
|
|
switch (providerID) {
|
|
case "anthropic":
|
|
return [PROMPT_ANTHROPIC_SPOOF.trim(), PROMPT_TITLE]
|
|
default:
|
|
return [PROMPT_TITLE]
|
|
}
|
|
}
|
|
}
|