@p-sw/brainbox 0.1.0 → 0.1.2-alpha.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.
Files changed (92) hide show
  1. package/dist/index.js +5319 -0
  2. package/package.json +10 -4
  3. package/scripts/smoke_providers.ts +0 -176
  4. package/src/brain/index.ts +0 -936
  5. package/src/brain/manager.ts +0 -144
  6. package/src/brain/memory.ts +0 -99
  7. package/src/brain/messageHistory.ts +0 -26
  8. package/src/brain/schedule.ts +0 -11
  9. package/src/brain/types.ts +0 -26
  10. package/src/channel/base.ts +0 -527
  11. package/src/channel/discord.ts +0 -227
  12. package/src/channel/telegram.ts +0 -150
  13. package/src/commands/auth.tsx +0 -306
  14. package/src/commands/brain.ts +0 -119
  15. package/src/commands/daemon/commands.ts +0 -56
  16. package/src/commands/daemon/pairingCommand.ts +0 -15
  17. package/src/commands/daemon/restartCommand.ts +0 -17
  18. package/src/commands/daemon.ts +0 -168
  19. package/src/commands/index.ts +0 -16
  20. package/src/commands/model.tsx +0 -138
  21. package/src/commands/onboard.tsx +0 -473
  22. package/src/commands/pairing.ts +0 -32
  23. package/src/commands/restart.ts +0 -24
  24. package/src/config/file/auth.ts +0 -105
  25. package/src/config/file/root.ts +0 -37
  26. package/src/config/index.ts +0 -21
  27. package/src/config/loader.ts +0 -115
  28. package/src/index.ts +0 -61
  29. package/src/provider/index.ts +0 -122
  30. package/src/provider/llm.ts +0 -191
  31. package/src/provider/promptLoader.ts +0 -36
  32. package/src/provider/providers/302ai.ts +0 -17
  33. package/src/provider/providers/MiniMax.ts +0 -17
  34. package/src/provider/providers/anthropic.ts +0 -257
  35. package/src/provider/providers/azure_cognitive.ts +0 -40
  36. package/src/provider/providers/azure_openai.ts +0 -49
  37. package/src/provider/providers/baseten.ts +0 -17
  38. package/src/provider/providers/bedrock.ts +0 -312
  39. package/src/provider/providers/cerebras.ts +0 -17
  40. package/src/provider/providers/cloudflare_gateway.ts +0 -34
  41. package/src/provider/providers/cloudflare_workers.ts +0 -178
  42. package/src/provider/providers/copilot.ts +0 -22
  43. package/src/provider/providers/cortecs.ts +0 -17
  44. package/src/provider/providers/deepinfra.ts +0 -17
  45. package/src/provider/providers/deepseek.ts +0 -17
  46. package/src/provider/providers/digitalocean.ts +0 -17
  47. package/src/provider/providers/fireworks.ts +0 -17
  48. package/src/provider/providers/gitlab_duo.ts +0 -184
  49. package/src/provider/providers/gmi.ts +0 -17
  50. package/src/provider/providers/groq.ts +0 -17
  51. package/src/provider/providers/helicone.ts +0 -17
  52. package/src/provider/providers/huggingface.ts +0 -17
  53. package/src/provider/providers/ionet.ts +0 -17
  54. package/src/provider/providers/llamacpp.ts +0 -17
  55. package/src/provider/providers/llmgateway.ts +0 -17
  56. package/src/provider/providers/lmstudio.ts +0 -17
  57. package/src/provider/providers/mistral.ts +0 -17
  58. package/src/provider/providers/moonshot.ts +0 -17
  59. package/src/provider/providers/nebius.ts +0 -17
  60. package/src/provider/providers/nvidia.ts +0 -17
  61. package/src/provider/providers/ollama.ts +0 -17
  62. package/src/provider/providers/ollama_cloud.ts +0 -17
  63. package/src/provider/providers/openai.ts +0 -17
  64. package/src/provider/providers/openai_compatible.ts +0 -293
  65. package/src/provider/providers/openrouter.ts +0 -175
  66. package/src/provider/providers/ovhcloud.ts +0 -17
  67. package/src/provider/providers/sap_aicore.ts +0 -22
  68. package/src/provider/providers/scaleway.ts +0 -17
  69. package/src/provider/providers/snowflake_cortex.ts +0 -207
  70. package/src/provider/providers/stackit.ts +0 -17
  71. package/src/provider/providers/together.ts +0 -17
  72. package/src/provider/providers/venice.ts +0 -17
  73. package/src/provider/providers/vercel.ts +0 -17
  74. package/src/provider/providers/vertex.ts +0 -229
  75. package/src/provider/providers/xai.ts +0 -17
  76. package/src/provider/providers/zai.ts +0 -17
  77. package/src/provider/providers/zenmux.ts +0 -17
  78. package/src/provider/schema.ts +0 -143
  79. package/src/ui/TextInput.tsx +0 -114
  80. package/src/utils/daemonClient.ts +0 -85
  81. package/src/utils/logger.ts +0 -204
  82. package/tsconfig.json +0 -34
  83. /package/{prompts → dist/prompts}/daily_schedule.md +0 -0
  84. /package/{prompts → dist/prompts}/memoir.md +0 -0
  85. /package/{prompts → dist/prompts}/monthly_schedule.md +0 -0
  86. /package/{prompts → dist/prompts}/objectifier.md +0 -0
  87. /package/{prompts → dist/prompts}/persona_base_system_prompt.md +0 -0
  88. /package/{prompts → dist/prompts}/persona_base_system_prompt_fixed.md +0 -0
  89. /package/{prompts → dist/prompts}/persona_init.md +0 -0
  90. /package/{prompts → dist/prompts}/schedule_availability.md +0 -0
  91. /package/{prompts → dist/prompts}/send_message.md +0 -0
  92. /package/{prompts → dist/prompts}/start_conversation.md +0 -0
@@ -1,114 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { Text, useInput, useStdin } from "ink";
3
-
4
- export interface TextInputProps {
5
- prompt: string;
6
- initialValue?: string;
7
- placeholder?: string;
8
- onSubmit: (value: string) => void;
9
- }
10
-
11
- // ponytail: piped mode (no TTY) drains the entire stdin buffer up front
12
- // and hands one line at a time to whichever TextInput is mounted.
13
- type Buffer = string[];
14
- let pipedBuffer: Buffer | null = null;
15
- let pipedSubscribers: Array<(line: string) => void> = [];
16
-
17
- function drainPiped(stdin: NodeJS.ReadStream): void {
18
- if (pipedBuffer !== null) return;
19
- const buf: Buffer = [];
20
- pipedBuffer = buf;
21
- const tryRead = (): void => {
22
- let chunk: string | Buffer | null;
23
- while ((chunk = stdin.read()) !== null) {
24
- const text = chunk.toString();
25
- for (const line of text.split(/\r?\n/)) {
26
- if (line.length > 0) buf.push(line);
27
- }
28
- }
29
- if (buf.length === 0) {
30
- stdin.once("readable", tryRead);
31
- stdin.once("end", tryRead);
32
- return;
33
- }
34
- while (pipedSubscribers.length > 0 && buf.length > 0) {
35
- const next = pipedSubscribers.shift();
36
- if (!next) break;
37
- const line = buf.shift();
38
- if (line === undefined) break;
39
- next(line);
40
- }
41
- };
42
- tryRead();
43
- }
44
-
45
- function PipedInput({
46
- prompt,
47
- initialValue = "",
48
- placeholder = "",
49
- onSubmit,
50
- stdin,
51
- }: TextInputProps & { stdin: NodeJS.ReadStream }): React.ReactElement {
52
- const [value] = useState(initialValue);
53
- useEffect(() => {
54
- drainPiped(stdin);
55
- pipedSubscribers.push(onSubmit);
56
- // ponytail: if buffer already holds lines, fire newest subscriber
57
- // immediately so validation-error re-prompts do not deadlock.
58
- if (pipedBuffer && pipedBuffer.length > 0) {
59
- const line = pipedBuffer.shift();
60
- if (line !== undefined) onSubmit(line);
61
- }
62
- return () => {
63
- pipedSubscribers = pipedSubscribers.filter((s) => s !== onSubmit);
64
- };
65
- }, [stdin, onSubmit]);
66
- const shown = value.length > 0 ? value : placeholder;
67
- return (
68
- <Text>
69
- {prompt}
70
- {shown.length > 0 ? shown : <Text dimColor>{placeholder}</Text>}
71
- </Text>
72
- );
73
- }
74
-
75
- function RawInput({
76
- prompt,
77
- initialValue = "",
78
- placeholder = "",
79
- onSubmit,
80
- }: TextInputProps): React.ReactElement {
81
- const [value, setValue] = useState(initialValue);
82
- useInput((input, key) => {
83
- if (key.return) {
84
- onSubmit(value);
85
- return;
86
- }
87
- if (key.backspace || key.delete) {
88
- setValue((v) => v.slice(0, -1));
89
- return;
90
- }
91
- if (key.ctrl && input === "c") {
92
- process.exit(130);
93
- }
94
- if (input.length > 0 && !key.ctrl && !key.meta) {
95
- setValue((v) => v + input);
96
- }
97
- });
98
- const shown = value.length > 0 ? value : placeholder;
99
- return (
100
- <Text>
101
- {prompt}
102
- {shown.length > 0 ? shown : <Text dimColor>{placeholder}</Text>}
103
- <Text color="cyan">|</Text>
104
- </Text>
105
- );
106
- }
107
-
108
- // ponytail: branch on raw-mode support so ink useInput is never mounted
109
- // on a non-TTY stdin (which would crash inside App.setRawMode).
110
- export function TextInput(props: TextInputProps): React.ReactElement {
111
- const { isRawModeSupported, stdin } = useStdin();
112
- if (!isRawModeSupported) return <PipedInput {...props} stdin={stdin} />;
113
- return <RawInput {...props} />;
114
- }
@@ -1,85 +0,0 @@
1
- import { connect, type Socket } from "node:net";
2
- import { join } from "node:path";
3
- import { config } from "@/config";
4
- import { logger } from "@/utils/logger";
5
-
6
- export const DAEMON_SOCKET_PATH = join(config.brainboxRoot, "daemon.sock");
7
-
8
- export interface DaemonResponse<T = unknown> {
9
- ok: boolean;
10
- result?: T;
11
- error?: string;
12
- [key: string]: unknown;
13
- }
14
-
15
- /**
16
- * Send one JSON-line command to the daemon and return the parsed reply.
17
- *
18
- * Error policy: any failure — socket connect error, malformed reply, or a
19
- * `{ok:false, error:"..."}` reply — is logged via the shared logger and the
20
- * process is terminated via `process.exit(1)`. Callers can rely on the
21
- * returned `Promise` resolving only with a successful reply.
22
- */
23
- export async function sendToDaemon<
24
- T extends DaemonResponse = DaemonResponse,
25
- >(payload: { command: string; args?: unknown }): Promise<T> {
26
- logger.debug(
27
- `sendToDaemon: command="${payload.command}" args=${JSON.stringify(payload.args) ?? "null"}`,
28
- );
29
- let reply: T;
30
- try {
31
- reply = await exchangeOnce<T>(payload);
32
- } catch (error) {
33
- const reason = error instanceof Error ? error.message : String(error);
34
- logger.error(
35
- `Could not reach the daemon at ${DAEMON_SOCKET_PATH} (is it running?): ${reason}`,
36
- );
37
- process.exit(1);
38
- }
39
- logger.debug(
40
- `sendToDaemon: command="${payload.command}" reply ok=${reply.ok}`,
41
- );
42
- if (!reply.ok) {
43
- logger.error(reply.error ?? `daemon command "${payload.command}" failed`);
44
- process.exit(1);
45
- }
46
- return reply;
47
- }
48
-
49
- function exchangeOnce<T>(payload: object): Promise<T> {
50
- return new Promise((resolve, reject) => {
51
- const socket: Socket = connect(DAEMON_SOCKET_PATH);
52
- let buf = "";
53
- let settled = false;
54
- const finish = (fn: () => void) => {
55
- if (settled) return;
56
- settled = true;
57
- socket.destroy();
58
- fn();
59
- };
60
- socket.on("data", (chunk) => {
61
- buf += chunk.toString("utf8");
62
- let idx = buf.indexOf("\n");
63
- while (idx >= 0) {
64
- const line = buf.slice(0, idx).trim();
65
- buf = buf.slice(idx + 1);
66
- idx = buf.indexOf("\n");
67
- if (line.length === 0) continue;
68
- try {
69
- finish(() => resolve(JSON.parse(line) as T));
70
- } catch (parseErr) {
71
- logger.debug(
72
- `exchangeOnce: invalid daemon reply: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,
73
- );
74
- finish(() => reject(new Error("invalid response from daemon")));
75
- }
76
- return;
77
- }
78
- });
79
- socket.on("error", (err) => {
80
- logger.debug(`exchangeOnce: socket error: ${err.message}`);
81
- finish(() => reject(err));
82
- });
83
- socket.write(JSON.stringify(payload) + "\n");
84
- });
85
- }
@@ -1,204 +0,0 @@
1
- import chalk, { type ChalkInstance } from "chalk";
2
- import { existsSync, mkdirSync, createWriteStream, type WriteStream } from "fs";
3
- import { dirname } from "path";
4
-
5
- export type LogLevel =
6
- | "debug"
7
- | "info"
8
- | "success"
9
- | "warn"
10
- | "error"
11
- | "fatal";
12
-
13
- const LEVELS: Record<
14
- LogLevel,
15
- { rank: number; color: ChalkInstance; stderr: boolean }
16
- > = {
17
- debug: { rank: 0, color: chalk.gray, stderr: false },
18
- info: { rank: 1, color: chalk.blue, stderr: false },
19
- success: { rank: 2, color: chalk.green, stderr: false },
20
- warn: { rank: 3, color: chalk.yellow, stderr: true },
21
- error: { rank: 4, color: chalk.red, stderr: true },
22
- fatal: { rank: 5, color: chalk.bgRed.white, stderr: true },
23
- };
24
-
25
- const ICONS: Record<LogLevel, string> = {
26
- debug: "◆",
27
- info: "ℹ",
28
- success: "✔",
29
- warn: "⚠",
30
- error: "✖",
31
- fatal: "▲",
32
- };
33
-
34
- export interface LoggerOptions {
35
- /** Minimum log level to output. Default: "info" */
36
- level?: LogLevel;
37
- /** Include timestamps. Default: true */
38
- timestamps?: boolean;
39
- /** Enable colors. Default: auto-detected from TTY */
40
- colors?: boolean;
41
- /** Tag prefix for all messages. Default: none */
42
- tag?: string;
43
- /** File path to append logs to. Default: none */
44
- file?: string;
45
- /** Write JSON lines to file instead of plain text. Default: false */
46
- json?: boolean;
47
- /** Completely suppress console output. Default: false */
48
- silent?: boolean;
49
- }
50
-
51
- class Logger {
52
- private level: LogLevel;
53
- private timestamps: boolean;
54
- private colors: boolean;
55
- private tag?: string;
56
- private file?: string;
57
- private json: boolean;
58
- private silent: boolean;
59
- private fileStream?: WriteStream;
60
-
61
- constructor(options: LoggerOptions = {}) {
62
- this.level = options.level ?? "info";
63
- this.timestamps = options.timestamps ?? true;
64
- this.colors = options.colors ?? chalk.level > 0;
65
- this.tag = options.tag;
66
- this.file = options.file;
67
- this.json = options.json ?? false;
68
- this.silent = options.silent ?? false;
69
-
70
- if (this.file) {
71
- const dir = dirname(this.file);
72
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
73
- this.fileStream = createWriteStream(this.file, { flags: "a" });
74
- }
75
- }
76
-
77
- private shouldLog(level: LogLevel): boolean {
78
- return LEVELS[level].rank >= LEVELS[this.level].rank;
79
- }
80
-
81
- private formatTimestamp(): string {
82
- const now = new Date();
83
- const pad = (n: number) => n.toString().padStart(2, "0");
84
- return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
85
- }
86
-
87
- private format(
88
- level: LogLevel,
89
- message: string,
90
- ): { console: string; file: string } {
91
- const ts = this.timestamps ? `[${this.formatTimestamp()}]` : "";
92
- const tag = this.tag ? `[${this.tag}]` : "";
93
- const icon = ICONS[level];
94
- const levelStr = level.toUpperCase();
95
-
96
- const consoleParts = [
97
- ts,
98
- tag,
99
- this.colors ? LEVELS[level].color(icon) : icon,
100
- message,
101
- ].filter(Boolean);
102
- const consoleLine = consoleParts.join(" ");
103
-
104
- const fileParts = [ts, tag, `[${levelStr}]`, message].filter(Boolean);
105
- const fileLine = fileParts.join(" ") + "\n";
106
-
107
- return { console: consoleLine, file: fileLine };
108
- }
109
-
110
- private formatJson(level: LogLevel, message: string): string {
111
- return (
112
- JSON.stringify({
113
- timestamp: new Date().toISOString(),
114
- level,
115
- tag: this.tag,
116
- message,
117
- }) + "\n"
118
- );
119
- }
120
-
121
- private write(level: LogLevel, message: string) {
122
- if (!this.shouldLog(level)) return;
123
-
124
- const { console: consoleLine, file: fileLine } = this.format(
125
- level,
126
- message,
127
- );
128
- const jsonLine = this.formatJson(level, message);
129
-
130
- if (!this.silent) {
131
- const out = LEVELS[level].stderr ? process.stderr : process.stdout;
132
- out.write(consoleLine + "\n");
133
- }
134
-
135
- if (this.fileStream) {
136
- this.fileStream.write(this.json ? jsonLine : fileLine);
137
- }
138
- }
139
-
140
- debug(message: string) {
141
- this.write("debug", message);
142
- }
143
- info(message: string) {
144
- this.write("info", message);
145
- }
146
- success(message: string) {
147
- this.write("success", message);
148
- }
149
- warn(message: string) {
150
- this.write("warn", message);
151
- }
152
- error(message: string) {
153
- this.write("error", message);
154
- }
155
- fatal(message: string) {
156
- this.write("fatal", message);
157
- }
158
-
159
- child(tag: string): Logger {
160
- const combined = this.tag ? `${this.tag}:${tag}` : tag;
161
- return new Logger({
162
- level: this.level,
163
- timestamps: this.timestamps,
164
- colors: this.colors,
165
- tag: combined,
166
- file: this.file,
167
- json: this.json,
168
- silent: this.silent,
169
- });
170
- }
171
-
172
- configure(options: Partial<LoggerOptions>) {
173
- if (options.level !== undefined) this.level = options.level;
174
- if (options.timestamps !== undefined) this.timestamps = options.timestamps;
175
- if (options.colors !== undefined) this.colors = options.colors;
176
- if (options.tag !== undefined) this.tag = options.tag;
177
- if (options.silent !== undefined) this.silent = options.silent;
178
- if (options.json !== undefined) this.json = options.json;
179
-
180
- if (options.file !== undefined && options.file !== this.file) {
181
- this.fileStream?.end();
182
- this.file = options.file;
183
- if (this.file) {
184
- const dir = dirname(this.file);
185
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
186
- this.fileStream = createWriteStream(this.file, { flags: "a" });
187
- } else {
188
- this.fileStream = undefined;
189
- }
190
- }
191
- }
192
-
193
- close() {
194
- this.fileStream?.end();
195
- }
196
- }
197
-
198
- export const logger = new Logger();
199
-
200
- export function createLogger(options: LoggerOptions): Logger {
201
- return new Logger(options);
202
- }
203
-
204
- export type { Logger };
package/tsconfig.json DELETED
@@ -1,34 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "ignoreDeprecations": "6.0",
4
- // Environment setup & latest features
5
- "lib": ["ESNext"],
6
- "target": "ESNext",
7
- "module": "Preserve",
8
- "moduleDetection": "force",
9
- "jsx": "react-jsx",
10
- "allowJs": true,
11
-
12
- // Bundler mode
13
- "baseUrl": ".",
14
- "paths": {
15
- "@/*": ["src/*"]
16
- },
17
- "moduleResolution": "bundler",
18
- "allowImportingTsExtensions": true,
19
- "verbatimModuleSyntax": true,
20
- "noEmit": true,
21
-
22
- // Best practices
23
- "strict": true,
24
- "skipLibCheck": true,
25
- "noFallthroughCasesInSwitch": true,
26
- "noUncheckedIndexedAccess": true,
27
- "noImplicitOverride": true,
28
-
29
- // Some stricter flags (disabled by default)
30
- "noUnusedLocals": false,
31
- "noUnusedParameters": false,
32
- "noPropertyAccessFromIndexSignature": false
33
- }
34
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes