@p-sw/brainbox 0.1.0 → 0.1.1
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/dist/index.js +5312 -0
- package/package.json +7 -4
- package/scripts/smoke_providers.ts +0 -176
- package/src/brain/index.ts +0 -936
- package/src/brain/manager.ts +0 -144
- package/src/brain/memory.ts +0 -99
- package/src/brain/messageHistory.ts +0 -26
- package/src/brain/schedule.ts +0 -11
- package/src/brain/types.ts +0 -26
- package/src/channel/base.ts +0 -527
- package/src/channel/discord.ts +0 -227
- package/src/channel/telegram.ts +0 -150
- package/src/commands/auth.tsx +0 -306
- package/src/commands/brain.ts +0 -119
- package/src/commands/daemon/commands.ts +0 -56
- package/src/commands/daemon/pairingCommand.ts +0 -15
- package/src/commands/daemon/restartCommand.ts +0 -17
- package/src/commands/daemon.ts +0 -168
- package/src/commands/index.ts +0 -16
- package/src/commands/model.tsx +0 -138
- package/src/commands/onboard.tsx +0 -473
- package/src/commands/pairing.ts +0 -32
- package/src/commands/restart.ts +0 -24
- package/src/config/file/auth.ts +0 -105
- package/src/config/file/root.ts +0 -37
- package/src/config/index.ts +0 -21
- package/src/config/loader.ts +0 -115
- package/src/index.ts +0 -61
- package/src/provider/index.ts +0 -122
- package/src/provider/llm.ts +0 -191
- package/src/provider/promptLoader.ts +0 -36
- package/src/provider/providers/302ai.ts +0 -17
- package/src/provider/providers/MiniMax.ts +0 -17
- package/src/provider/providers/anthropic.ts +0 -257
- package/src/provider/providers/azure_cognitive.ts +0 -40
- package/src/provider/providers/azure_openai.ts +0 -49
- package/src/provider/providers/baseten.ts +0 -17
- package/src/provider/providers/bedrock.ts +0 -312
- package/src/provider/providers/cerebras.ts +0 -17
- package/src/provider/providers/cloudflare_gateway.ts +0 -34
- package/src/provider/providers/cloudflare_workers.ts +0 -178
- package/src/provider/providers/copilot.ts +0 -22
- package/src/provider/providers/cortecs.ts +0 -17
- package/src/provider/providers/deepinfra.ts +0 -17
- package/src/provider/providers/deepseek.ts +0 -17
- package/src/provider/providers/digitalocean.ts +0 -17
- package/src/provider/providers/fireworks.ts +0 -17
- package/src/provider/providers/gitlab_duo.ts +0 -184
- package/src/provider/providers/gmi.ts +0 -17
- package/src/provider/providers/groq.ts +0 -17
- package/src/provider/providers/helicone.ts +0 -17
- package/src/provider/providers/huggingface.ts +0 -17
- package/src/provider/providers/ionet.ts +0 -17
- package/src/provider/providers/llamacpp.ts +0 -17
- package/src/provider/providers/llmgateway.ts +0 -17
- package/src/provider/providers/lmstudio.ts +0 -17
- package/src/provider/providers/mistral.ts +0 -17
- package/src/provider/providers/moonshot.ts +0 -17
- package/src/provider/providers/nebius.ts +0 -17
- package/src/provider/providers/nvidia.ts +0 -17
- package/src/provider/providers/ollama.ts +0 -17
- package/src/provider/providers/ollama_cloud.ts +0 -17
- package/src/provider/providers/openai.ts +0 -17
- package/src/provider/providers/openai_compatible.ts +0 -293
- package/src/provider/providers/openrouter.ts +0 -175
- package/src/provider/providers/ovhcloud.ts +0 -17
- package/src/provider/providers/sap_aicore.ts +0 -22
- package/src/provider/providers/scaleway.ts +0 -17
- package/src/provider/providers/snowflake_cortex.ts +0 -207
- package/src/provider/providers/stackit.ts +0 -17
- package/src/provider/providers/together.ts +0 -17
- package/src/provider/providers/venice.ts +0 -17
- package/src/provider/providers/vercel.ts +0 -17
- package/src/provider/providers/vertex.ts +0 -229
- package/src/provider/providers/xai.ts +0 -17
- package/src/provider/providers/zai.ts +0 -17
- package/src/provider/providers/zenmux.ts +0 -17
- package/src/provider/schema.ts +0 -143
- package/src/ui/TextInput.tsx +0 -114
- package/src/utils/daemonClient.ts +0 -85
- package/src/utils/logger.ts +0 -204
- package/tsconfig.json +0 -34
- /package/{prompts → dist/prompts}/daily_schedule.md +0 -0
- /package/{prompts → dist/prompts}/memoir.md +0 -0
- /package/{prompts → dist/prompts}/monthly_schedule.md +0 -0
- /package/{prompts → dist/prompts}/objectifier.md +0 -0
- /package/{prompts → dist/prompts}/persona_base_system_prompt.md +0 -0
- /package/{prompts → dist/prompts}/persona_base_system_prompt_fixed.md +0 -0
- /package/{prompts → dist/prompts}/persona_init.md +0 -0
- /package/{prompts → dist/prompts}/schedule_availability.md +0 -0
- /package/{prompts → dist/prompts}/send_message.md +0 -0
- /package/{prompts → dist/prompts}/start_conversation.md +0 -0
package/src/config/loader.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { dirname, join, resolve } from "path";
|
|
2
|
-
import { z, ZodError } from "zod";
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
5
|
-
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
6
|
-
import { logger } from "@/utils/logger";
|
|
7
|
-
|
|
8
|
-
export const brainboxRoot = process.env["BRAINBOX_ROOT_PATH"]
|
|
9
|
-
? resolve(process.cwd(), process.env["BRAINBOX_ROOT_PATH"])
|
|
10
|
-
: join(homedir(), ".brainbox");
|
|
11
|
-
|
|
12
|
-
// ponytail: add a file → call configFile(name, schema) once and you get
|
|
13
|
-
// { read, write, update, path }. New writes / new files become one line each.
|
|
14
|
-
// ponytail: add a key → add it + its default to the schema. That's it.
|
|
15
|
-
export interface ConfigFile<T> {
|
|
16
|
-
/** Absolute path the file lives at. Resolved at call time. */
|
|
17
|
-
path(): string;
|
|
18
|
-
/** Read + validate against the schema. Creates the file from defaults on first run. */
|
|
19
|
-
read(): T;
|
|
20
|
-
/** Write a value (will be stringified as YAML). Creates parent dirs as needed. */
|
|
21
|
-
write(value: T): void;
|
|
22
|
-
/** read → fn → write → return the new value. */
|
|
23
|
-
update(fn: (current: T) => T): T;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface ConfigFileOptions<T> {
|
|
27
|
-
schema: z.ZodType<T>;
|
|
28
|
-
/** Optional comment prepended to the file on first creation only. */
|
|
29
|
-
header?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function configFile<T>(
|
|
33
|
-
file: string,
|
|
34
|
-
options: ConfigFileOptions<T>,
|
|
35
|
-
): ConfigFile<T> {
|
|
36
|
-
// ponytail: defer path resolution — module-load snapshot freezes BRAINBOX_ROOT_PATH.
|
|
37
|
-
const path = (): string => join(brainboxRoot, file);
|
|
38
|
-
const read = (): T => {
|
|
39
|
-
const p = path();
|
|
40
|
-
let raw: unknown;
|
|
41
|
-
try {
|
|
42
|
-
raw = parseYaml(readFileSync(p, "utf8")) ?? {};
|
|
43
|
-
} catch (err) {
|
|
44
|
-
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
45
|
-
const defaults = defaultsFromSchema(options.schema);
|
|
46
|
-
const templateStr =
|
|
47
|
-
(options.header ? options.header + "\n" : "") +
|
|
48
|
-
(defaults === undefined ? "" : stringifyYaml(defaults));
|
|
49
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
50
|
-
writeFileSync(p, templateStr);
|
|
51
|
-
raw = defaults ?? {};
|
|
52
|
-
}
|
|
53
|
-
try {
|
|
54
|
-
return options.schema.parse(raw);
|
|
55
|
-
} catch (err) {
|
|
56
|
-
if (err instanceof ZodError) {
|
|
57
|
-
logger.error(
|
|
58
|
-
`Invalid config in ${p}:\n` +
|
|
59
|
-
err.issues
|
|
60
|
-
.map((i) => ` ${i.path.join(".") || "(root)"}: ${i.message}`)
|
|
61
|
-
.join("\n"),
|
|
62
|
-
);
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
throw err;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const write = (value: T): void => {
|
|
69
|
-
const p = path();
|
|
70
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
71
|
-
writeFileSync(p, stringifyYaml(value));
|
|
72
|
-
};
|
|
73
|
-
const update = (fn: (current: T) => T): T => {
|
|
74
|
-
const next = fn(read());
|
|
75
|
-
write(next);
|
|
76
|
-
return next;
|
|
77
|
-
};
|
|
78
|
-
return { path, read, write, update };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// ponytail: kept for the two call sites that don't need write access — the
|
|
82
|
-
// module-load-time `config` snapshot still wants the parsed value, not a
|
|
83
|
-
// handle to a lazy reader.
|
|
84
|
-
export function parseConfigFile<T>(
|
|
85
|
-
file: string,
|
|
86
|
-
options: { header?: string; schema: z.ZodType<T> },
|
|
87
|
-
): T {
|
|
88
|
-
return configFile(file, options).read();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function defaultsFromSchema(schema: z.ZodType): unknown {
|
|
92
|
-
const json = z.toJSONSchema(schema) as Record<string, unknown>;
|
|
93
|
-
return extractDefaults(json);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function extractDefaults(node: unknown): unknown {
|
|
97
|
-
if (!node || typeof node !== "object") return undefined;
|
|
98
|
-
const obj = node as Record<string, unknown>;
|
|
99
|
-
if ("default" in obj) return obj.default;
|
|
100
|
-
if (
|
|
101
|
-
obj.type === "object" &&
|
|
102
|
-
obj.properties &&
|
|
103
|
-
typeof obj.properties === "object"
|
|
104
|
-
) {
|
|
105
|
-
const out: Record<string, unknown> = {};
|
|
106
|
-
for (const [k, v] of Object.entries(
|
|
107
|
-
obj.properties as Record<string, unknown>,
|
|
108
|
-
)) {
|
|
109
|
-
const d = extractDefaults(v);
|
|
110
|
-
if (d !== undefined) out[k] = d;
|
|
111
|
-
}
|
|
112
|
-
return Object.keys(out).length ? out : undefined;
|
|
113
|
-
}
|
|
114
|
-
return undefined;
|
|
115
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
import { readFileSync } from "fs";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
import { dirname, join } from "path";
|
|
6
|
-
import { logger } from "@/utils/logger";
|
|
7
|
-
import { config } from "@/config";
|
|
8
|
-
import { register as daemon } from "@/commands/daemon";
|
|
9
|
-
import { register as brain } from "@/commands/brain";
|
|
10
|
-
import { register as pairing } from "@/commands/pairing";
|
|
11
|
-
import { register as restart } from "@/commands/restart";
|
|
12
|
-
import { register as auth } from "@/commands/auth";
|
|
13
|
-
import { register as model } from "@/commands/model";
|
|
14
|
-
import { register as onboard } from "@/commands/onboard";
|
|
15
|
-
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = dirname(__filename);
|
|
18
|
-
|
|
19
|
-
// ponytail: one line to translate the user-facing `debug: true` flag in
|
|
20
|
-
// brainbox.yaml into the logger's internal level. The level is the only thing
|
|
21
|
-
// debug mode changes — no separate stream, no extra format.
|
|
22
|
-
logger.configure({ level: config.debug ? "debug" : "info" });
|
|
23
|
-
logger.debug(
|
|
24
|
-
`brainbox starting (debug=${config.debug}, root=${config.brainboxRoot})`,
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
function getVersion(): string {
|
|
28
|
-
try {
|
|
29
|
-
const pkgPath = join(__dirname, "..", "package.json");
|
|
30
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
31
|
-
return pkg.version ?? "0.0.0";
|
|
32
|
-
} catch {
|
|
33
|
-
return "0.0.0";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const argv = process.argv;
|
|
38
|
-
const program = new Command();
|
|
39
|
-
|
|
40
|
-
program
|
|
41
|
-
.name("brainbox")
|
|
42
|
-
.description("A CLI tool for brainbox")
|
|
43
|
-
.version(getVersion(), "-v, --version", "Display version number")
|
|
44
|
-
.helpOption("-h, --help", "Display help for command")
|
|
45
|
-
.configureOutput({
|
|
46
|
-
outputError: (str) => logger.error(str.replace("error: ", "")),
|
|
47
|
-
});
|
|
48
|
-
daemon(program);
|
|
49
|
-
brain(program);
|
|
50
|
-
pairing(program);
|
|
51
|
-
restart(program);
|
|
52
|
-
auth(program);
|
|
53
|
-
model(program);
|
|
54
|
-
onboard(program);
|
|
55
|
-
|
|
56
|
-
program.on("command:*", () => {
|
|
57
|
-
logger.error(`Unknown command: ${program.args.join(" ")}`);
|
|
58
|
-
program.help();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
program.parseAsync(argv);
|
package/src/provider/index.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
LLMExecutor,
|
|
3
|
-
defaultReasoningEffort,
|
|
4
|
-
readAuthString,
|
|
5
|
-
listProviderNames,
|
|
6
|
-
type CallOptions,
|
|
7
|
-
type ChatAssistantMessage,
|
|
8
|
-
type ChatChoice,
|
|
9
|
-
type ChatFunctionTool,
|
|
10
|
-
type ChatMessages,
|
|
11
|
-
type ChatWithToolsOptions,
|
|
12
|
-
type ProviderCtor,
|
|
13
|
-
type ReasoningEffort,
|
|
14
|
-
type ToolCall,
|
|
15
|
-
} from "./llm";
|
|
16
|
-
|
|
17
|
-
import { LLMExecutor } from "./llm";
|
|
18
|
-
import { OpenRouterExecutor } from "./providers/openrouter";
|
|
19
|
-
import { OpenAIExecutor } from "./providers/openai";
|
|
20
|
-
import { MistralExecutor } from "./providers/mistral";
|
|
21
|
-
import { DeepSeekExecutor } from "./providers/deepseek";
|
|
22
|
-
import { GroqExecutor } from "./providers/groq";
|
|
23
|
-
import { CerebrasExecutor } from "./providers/cerebras";
|
|
24
|
-
import { FireworksExecutor } from "./providers/fireworks";
|
|
25
|
-
import { TogetherExecutor } from "./providers/together";
|
|
26
|
-
import { XAIExecutor } from "./providers/xai";
|
|
27
|
-
import { MoonshotExecutor } from "./providers/moonshot";
|
|
28
|
-
import { NvidiaExecutor } from "./providers/nvidia";
|
|
29
|
-
import { DeepInfraExecutor } from "./providers/deepinfra";
|
|
30
|
-
import { Ai302Executor } from "./providers/302ai";
|
|
31
|
-
import { DigitalOceanExecutor } from "./providers/digitalocean";
|
|
32
|
-
import { HeliconeExecutor } from "./providers/helicone";
|
|
33
|
-
import { ScalewayExecutor } from "./providers/scaleway";
|
|
34
|
-
import { VeniceExecutor } from "./providers/venice";
|
|
35
|
-
import { NebiusExecutor } from "./providers/nebius";
|
|
36
|
-
import { OvhCloudExecutor } from "./providers/ovhcloud";
|
|
37
|
-
import { StackitExecutor } from "./providers/stackit";
|
|
38
|
-
import { GmiExecutor } from "./providers/gmi";
|
|
39
|
-
import { ZaiExecutor } from "./providers/zai";
|
|
40
|
-
import { ZenMuxExecutor } from "./providers/zenmux";
|
|
41
|
-
import { MiniMaxExecutor } from "./providers/MiniMax";
|
|
42
|
-
import { IoNetExecutor } from "./providers/ionet";
|
|
43
|
-
import { BasetenExecutor } from "./providers/baseten";
|
|
44
|
-
import { CortecsExecutor } from "./providers/cortecs";
|
|
45
|
-
import { HuggingFaceExecutor } from "./providers/huggingface";
|
|
46
|
-
import { LmStudioExecutor } from "./providers/lmstudio";
|
|
47
|
-
import { OllamaExecutor } from "./providers/ollama";
|
|
48
|
-
import { OllamaCloudExecutor } from "./providers/ollama_cloud";
|
|
49
|
-
import { LlamaCppExecutor } from "./providers/llamacpp";
|
|
50
|
-
import { VercelExecutor } from "./providers/vercel";
|
|
51
|
-
import { LlmGatewayExecutor } from "./providers/llmgateway";
|
|
52
|
-
import { CloudflareGatewayExecutor } from "./providers/cloudflare_gateway";
|
|
53
|
-
import { CloudflareWorkersExecutor } from "./providers/cloudflare_workers";
|
|
54
|
-
import { SapAiCoreExecutor } from "./providers/sap_aicore";
|
|
55
|
-
import { AzureOpenAIExecutor } from "./providers/azure_openai";
|
|
56
|
-
import { AzureCognitiveExecutor } from "./providers/azure_cognitive";
|
|
57
|
-
import { AnthropicExecutor } from "./providers/anthropic";
|
|
58
|
-
import { BedrockExecutor } from "./providers/bedrock";
|
|
59
|
-
import { VertexExecutor } from "./providers/vertex";
|
|
60
|
-
import { CopilotExecutor } from "./providers/copilot";
|
|
61
|
-
import { GitLabDuoExecutor } from "./providers/gitlab_duo";
|
|
62
|
-
import { SnowflakeCortexExecutor } from "./providers/snowflake_cortex";
|
|
63
|
-
|
|
64
|
-
function register(
|
|
65
|
-
name: string,
|
|
66
|
-
ctor: new (opts: {
|
|
67
|
-
apiKey: string;
|
|
68
|
-
conversationModel: string;
|
|
69
|
-
identityModel: string;
|
|
70
|
-
auth?: Record<string, unknown>;
|
|
71
|
-
}) => LLMExecutor,
|
|
72
|
-
): void {
|
|
73
|
-
LLMExecutor.registerProvider({ name, ctor: ctor as never });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
register("openrouter", OpenRouterExecutor);
|
|
77
|
-
register("openai", OpenAIExecutor);
|
|
78
|
-
register("mistral", MistralExecutor);
|
|
79
|
-
register("deepseek", DeepSeekExecutor);
|
|
80
|
-
register("groq", GroqExecutor);
|
|
81
|
-
register("cerebras", CerebrasExecutor);
|
|
82
|
-
register("fireworks", FireworksExecutor);
|
|
83
|
-
register("together", TogetherExecutor);
|
|
84
|
-
register("xai", XAIExecutor);
|
|
85
|
-
register("moonshot", MoonshotExecutor);
|
|
86
|
-
register("nvidia", NvidiaExecutor);
|
|
87
|
-
register("deepinfra", DeepInfraExecutor);
|
|
88
|
-
register("302ai", Ai302Executor);
|
|
89
|
-
register("digitalocean", DigitalOceanExecutor);
|
|
90
|
-
register("helicone", HeliconeExecutor);
|
|
91
|
-
register("scaleway", ScalewayExecutor);
|
|
92
|
-
register("venice", VeniceExecutor);
|
|
93
|
-
register("nebius", NebiusExecutor);
|
|
94
|
-
register("ovhcloud", OvhCloudExecutor);
|
|
95
|
-
register("stackit", StackitExecutor);
|
|
96
|
-
register("gmi", GmiExecutor);
|
|
97
|
-
register("zai", ZaiExecutor);
|
|
98
|
-
register("zenmux", ZenMuxExecutor);
|
|
99
|
-
register("MiniMax", MiniMaxExecutor);
|
|
100
|
-
register("ionet", IoNetExecutor);
|
|
101
|
-
register("baseten", BasetenExecutor);
|
|
102
|
-
register("cortecs", CortecsExecutor);
|
|
103
|
-
register("huggingface", HuggingFaceExecutor);
|
|
104
|
-
register("lmstudio", LmStudioExecutor);
|
|
105
|
-
register("ollama", OllamaExecutor);
|
|
106
|
-
register("ollama-cloud", OllamaCloudExecutor);
|
|
107
|
-
register("llamacpp", LlamaCppExecutor);
|
|
108
|
-
register("vercel", VercelExecutor);
|
|
109
|
-
register("llmgateway", LlmGatewayExecutor);
|
|
110
|
-
register("cloudflare-gateway", CloudflareGatewayExecutor);
|
|
111
|
-
register("cloudflare-workers", CloudflareWorkersExecutor);
|
|
112
|
-
register("sap-aicore", SapAiCoreExecutor);
|
|
113
|
-
register("azure-openai", AzureOpenAIExecutor);
|
|
114
|
-
register("azure-cognitive", AzureCognitiveExecutor);
|
|
115
|
-
register("anthropic", AnthropicExecutor);
|
|
116
|
-
register("bedrock", BedrockExecutor);
|
|
117
|
-
register("vertex", VertexExecutor);
|
|
118
|
-
register("copilot", CopilotExecutor);
|
|
119
|
-
register("gitlab-duo", GitLabDuoExecutor);
|
|
120
|
-
register("snowflake-cortex", SnowflakeCortexExecutor);
|
|
121
|
-
|
|
122
|
-
export const llm = LLMExecutor.init();
|
package/src/provider/llm.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { config } from "@/config";
|
|
2
|
-
import { logger } from "@/utils/logger";
|
|
3
|
-
|
|
4
|
-
const log = logger.child("llm");
|
|
5
|
-
|
|
6
|
-
// --- Provider-agnostic shapes -----------------------------------------------
|
|
7
|
-
|
|
8
|
-
export type ChatAssistantMessage = {
|
|
9
|
-
role: "assistant";
|
|
10
|
-
content?: string;
|
|
11
|
-
toolCalls?: ToolCall[];
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type ChatMessages =
|
|
15
|
-
| { role: "system"; content: string }
|
|
16
|
-
| { role: "user"; content: string }
|
|
17
|
-
| ChatAssistantMessage
|
|
18
|
-
| { role: "tool"; content: string; toolCallId: string };
|
|
19
|
-
|
|
20
|
-
export type ToolCall = {
|
|
21
|
-
id: string;
|
|
22
|
-
function: { name: string; arguments: string };
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type ChatFunctionTool = {
|
|
26
|
-
name: string;
|
|
27
|
-
description?: string;
|
|
28
|
-
parameters?: Record<string, unknown>;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type ChatChoice = {
|
|
32
|
-
message: {
|
|
33
|
-
content?: string;
|
|
34
|
-
toolCalls?: ToolCall[];
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type ReasoningEffort = "none" | "low" | "medium" | "high";
|
|
39
|
-
|
|
40
|
-
export type CallOptions = {
|
|
41
|
-
instruction: string;
|
|
42
|
-
message: string;
|
|
43
|
-
reasoningEffort?: ReasoningEffort;
|
|
44
|
-
} & (
|
|
45
|
-
| { jsonSchemaName: string; jsonSchema: Record<string, unknown> | undefined }
|
|
46
|
-
| object
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
export type ChatWithToolsOptions = {
|
|
50
|
-
instruction: string;
|
|
51
|
-
messages: ChatMessages[];
|
|
52
|
-
tools: ChatFunctionTool[];
|
|
53
|
-
reasoningEffort?: ReasoningEffort;
|
|
54
|
-
parallelToolCalls?: boolean;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// --- Abstract base ----------------------------------------------------------
|
|
58
|
-
|
|
59
|
-
export type ProviderCtor = new (opts: {
|
|
60
|
-
apiKey: string;
|
|
61
|
-
conversationModel: string;
|
|
62
|
-
identityModel: string;
|
|
63
|
-
// ponytail: per-provider knobs (region, project, deployment, endpoint) come
|
|
64
|
-
// from the auth record and are forwarded as-is. Concrete providers read the
|
|
65
|
-
// fields they need; new providers don't require editing this signature.
|
|
66
|
-
auth?: Record<string, unknown>;
|
|
67
|
-
}) => LLMExecutor;
|
|
68
|
-
|
|
69
|
-
export function defaultReasoningEffort(
|
|
70
|
-
effort: ReasoningEffort | undefined,
|
|
71
|
-
model: string,
|
|
72
|
-
identityModel: string,
|
|
73
|
-
): ReasoningEffort {
|
|
74
|
-
if (effort) return effort;
|
|
75
|
-
return model === identityModel ? "medium" : "none";
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function readAuthString(
|
|
79
|
-
auth: Record<string, unknown> | undefined,
|
|
80
|
-
key: string,
|
|
81
|
-
envName?: string,
|
|
82
|
-
): string {
|
|
83
|
-
const fromAuth =
|
|
84
|
-
typeof auth?.[key] === "string" ? (auth[key] as string) : undefined;
|
|
85
|
-
if (fromAuth) return fromAuth;
|
|
86
|
-
if (envName) {
|
|
87
|
-
const fromEnv = process.env[envName];
|
|
88
|
-
if (typeof fromEnv === "string" && fromEnv.length > 0) return fromEnv;
|
|
89
|
-
}
|
|
90
|
-
return "";
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export abstract class LLMExecutor {
|
|
94
|
-
abstract readonly providerName: string;
|
|
95
|
-
abstract readonly models: { conversation: string; identity: string };
|
|
96
|
-
|
|
97
|
-
abstract call<T>(model: string, options: CallOptions): Promise<T>;
|
|
98
|
-
abstract chatWithTools(
|
|
99
|
-
model: string,
|
|
100
|
-
options: ChatWithToolsOptions,
|
|
101
|
-
): Promise<ChatChoice>;
|
|
102
|
-
|
|
103
|
-
// ponytail: registry + factory. Adding a provider = one registerProvider call in index.ts.
|
|
104
|
-
private static providers: Array<{ name: string; ctor: ProviderCtor }> = [];
|
|
105
|
-
|
|
106
|
-
static registerProvider(p: { name: string; ctor: ProviderCtor }): void {
|
|
107
|
-
LLMExecutor.providers.push(p);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
static listProviderNames(): string[] {
|
|
111
|
-
return LLMExecutor.providers.map((p) => p.name);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private static lookup(name: string): ProviderCtor {
|
|
115
|
-
const entry = LLMExecutor.providers.find((p) => p.name === name);
|
|
116
|
-
if (!entry) {
|
|
117
|
-
log.error(
|
|
118
|
-
`init: unknown provider "${name}". Registered: ${LLMExecutor.providers.map((p) => p.name).join(", ") || "(none)"}`,
|
|
119
|
-
);
|
|
120
|
-
process.exit(1);
|
|
121
|
-
}
|
|
122
|
-
return entry.ctor;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
static init(): LLMExecutor {
|
|
126
|
-
const { conversationModel, identityModel, auth } = config;
|
|
127
|
-
const parseSlot = (slot: string): { provider: string; model: string } => {
|
|
128
|
-
const slash = slot.indexOf("/");
|
|
129
|
-
if (slash < 0) {
|
|
130
|
-
log.error(
|
|
131
|
-
`init: model slot "${slot}" must be in "provider/model" form`,
|
|
132
|
-
);
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
return { provider: slot.slice(0, slash), model: slot.slice(slash + 1) };
|
|
136
|
-
};
|
|
137
|
-
const conv = parseSlot(conversationModel);
|
|
138
|
-
const id = parseSlot(identityModel);
|
|
139
|
-
const build = (providerName: string): LLMExecutor => {
|
|
140
|
-
const ctor = LLMExecutor.lookup(providerName);
|
|
141
|
-
const providerAuth = (auth[providerName] ?? {}) as Record<
|
|
142
|
-
string,
|
|
143
|
-
unknown
|
|
144
|
-
>;
|
|
145
|
-
return new ctor({
|
|
146
|
-
apiKey: (providerAuth["apiKey"] as string) ?? "",
|
|
147
|
-
conversationModel: conv.model,
|
|
148
|
-
identityModel: id.model,
|
|
149
|
-
auth: providerAuth,
|
|
150
|
-
});
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
if (conv.provider === id.provider) {
|
|
154
|
-
return build(conv.provider);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const modelToProvider: Record<string, string> = {
|
|
158
|
-
[conv.model]: conv.provider,
|
|
159
|
-
[id.model]: id.provider,
|
|
160
|
-
};
|
|
161
|
-
const instances: Record<string, LLMExecutor> = {
|
|
162
|
-
[conv.provider]: build(conv.provider),
|
|
163
|
-
[id.provider]: build(id.provider),
|
|
164
|
-
};
|
|
165
|
-
const fallback = instances[conv.provider]!;
|
|
166
|
-
|
|
167
|
-
return new (class extends LLMExecutor {
|
|
168
|
-
readonly providerName = "dispatch";
|
|
169
|
-
readonly models = {
|
|
170
|
-
conversation: conv.model,
|
|
171
|
-
identity: id.model,
|
|
172
|
-
};
|
|
173
|
-
call<T>(model: string, options: CallOptions): Promise<T> {
|
|
174
|
-
const exec = instances[modelToProvider[model] ?? ""] ?? fallback;
|
|
175
|
-
return exec.call<T>(model, options);
|
|
176
|
-
}
|
|
177
|
-
chatWithTools(model: string, options: ChatWithToolsOptions) {
|
|
178
|
-
const exec = instances[modelToProvider[model] ?? ""] ?? fallback;
|
|
179
|
-
return exec.chatWithTools(model, options);
|
|
180
|
-
}
|
|
181
|
-
})();
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// ponytail: thin wrapper so callers can `import { listProviderNames }`
|
|
187
|
-
// without going through the class — static class members aren't a top-level
|
|
188
|
-
// binding under `verbatimModuleSyntax`.
|
|
189
|
-
export function listProviderNames(): string[] {
|
|
190
|
-
return LLMExecutor.listProviderNames();
|
|
191
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { readFile } from "fs/promises";
|
|
2
|
-
import path, { dirname } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { logger } from "@/utils/logger";
|
|
5
|
-
|
|
6
|
-
const log = logger.child("prompt-loader");
|
|
7
|
-
|
|
8
|
-
const prompts = [
|
|
9
|
-
"PERSONA_INIT",
|
|
10
|
-
"PERSONA_BASE_SYSTEM_PROMPT",
|
|
11
|
-
"PERSONA_BASE_SYSTEM_PROMPT_FIXED",
|
|
12
|
-
"DAILY_SCHEDULE",
|
|
13
|
-
"MONTHLY_SCHEDULE",
|
|
14
|
-
"SCHEDULE_AVAILABILITY",
|
|
15
|
-
"OBJECTIFIER",
|
|
16
|
-
"SEND_MESSAGE",
|
|
17
|
-
"START_CONVERSATION",
|
|
18
|
-
"MEMOIR",
|
|
19
|
-
] as const;
|
|
20
|
-
export type PromptKey = (typeof prompts)[number];
|
|
21
|
-
|
|
22
|
-
function fileName(promptKey: PromptKey): string {
|
|
23
|
-
return promptKey.toLowerCase() + ".md";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
-
const __dirname = dirname(__filename);
|
|
28
|
-
const PROMPTS_DIR = path.resolve(__dirname, "../../prompts");
|
|
29
|
-
|
|
30
|
-
export async function loadPrompt(promptKey: PromptKey): Promise<string> {
|
|
31
|
-
const filePath = path.join(PROMPTS_DIR, fileName(promptKey));
|
|
32
|
-
log.debug(`loadPrompt: ${promptKey} (${filePath})`);
|
|
33
|
-
const content = await readFile(filePath, "utf-8");
|
|
34
|
-
log.debug(`loadPrompt: ${promptKey} → ${content.length} chars`);
|
|
35
|
-
return content;
|
|
36
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { OpenAICompatibleExecutor } from "./openai_compatible";
|
|
2
|
-
|
|
3
|
-
export class Ai302Executor extends OpenAICompatibleExecutor {
|
|
4
|
-
constructor(opts: {
|
|
5
|
-
apiKey: string;
|
|
6
|
-
conversationModel: string;
|
|
7
|
-
identityModel: string;
|
|
8
|
-
}) {
|
|
9
|
-
super({
|
|
10
|
-
providerName: "302ai",
|
|
11
|
-
baseURL: "https://api.302.ai/v1",
|
|
12
|
-
apiKey: opts.apiKey,
|
|
13
|
-
conversationModel: opts.conversationModel,
|
|
14
|
-
identityModel: opts.identityModel,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { OpenAICompatibleExecutor } from "./openai_compatible";
|
|
2
|
-
|
|
3
|
-
export class MiniMaxExecutor extends OpenAICompatibleExecutor {
|
|
4
|
-
constructor(opts: {
|
|
5
|
-
apiKey: string;
|
|
6
|
-
conversationModel: string;
|
|
7
|
-
identityModel: string;
|
|
8
|
-
}) {
|
|
9
|
-
super({
|
|
10
|
-
providerName: "MiniMax",
|
|
11
|
-
baseURL: "https://api.MiniMax.chat/v1",
|
|
12
|
-
apiKey: opts.apiKey,
|
|
13
|
-
conversationModel: opts.conversationModel,
|
|
14
|
-
identityModel: opts.identityModel,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
}
|