@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,207 +0,0 @@
1
- import { logger } from "@/utils/logger";
2
- import { z } from "zod";
3
- import {
4
- LLMExecutor,
5
- defaultReasoningEffort,
6
- readAuthString,
7
- type CallOptions,
8
- type ChatChoice,
9
- type ChatFunctionTool,
10
- type ChatMessages,
11
- type ChatWithToolsOptions,
12
- type ToolCall,
13
- } from "../llm";
14
-
15
- const CortexAuthSchema = z
16
- .object({
17
- account: z.string().optional(),
18
- })
19
- .loose();
20
-
21
- type CortexTool = {
22
- type: "function";
23
- function: {
24
- name: string;
25
- description?: string;
26
- parameters?: Record<string, unknown>;
27
- };
28
- };
29
-
30
- type CortexMessageWire =
31
- | { role: "system" | "user"; content: string }
32
- | {
33
- role: "assistant";
34
- content: string | null;
35
- tool_calls?: Array<{
36
- id: string;
37
- type: "function";
38
- function: { name: string; arguments: unknown };
39
- }>;
40
- }
41
- | { role: "tool"; content: string; tool_call_id: string };
42
-
43
- type CortexResponse = {
44
- choices?: Array<{
45
- message?: {
46
- content?: string | null;
47
- tool_calls?: Array<{
48
- id: string;
49
- type: "function";
50
- function: { name: string; arguments: unknown };
51
- }>;
52
- };
53
- }>;
54
- message?: string;
55
- error?: { message?: string };
56
- };
57
-
58
- function toCortexMessage(m: ChatMessages): CortexMessageWire {
59
- if (m.role === "assistant") {
60
- return {
61
- role: "assistant",
62
- content: m.content ?? null,
63
- tool_calls: m.toolCalls?.map((c) => ({
64
- id: c.id,
65
- type: "function",
66
- function: { name: c.function.name, arguments: c.function.arguments },
67
- })),
68
- };
69
- }
70
- if (m.role === "tool") {
71
- return { role: "tool", content: m.content, tool_call_id: m.toolCallId };
72
- }
73
- return { role: m.role, content: m.content };
74
- }
75
-
76
- function toCortexTool(t: ChatFunctionTool): CortexTool {
77
- return {
78
- type: "function",
79
- function: {
80
- name: t.name,
81
- description: t.description,
82
- parameters: t.parameters ?? { type: "object", properties: {} },
83
- },
84
- };
85
- }
86
-
87
- export class SnowflakeCortexExecutor extends LLMExecutor {
88
- readonly providerName = "snowflake-cortex";
89
- readonly models: { conversation: string; identity: string };
90
-
91
- private readonly apiKey: string;
92
- private readonly baseURL: string;
93
-
94
- constructor(opts: {
95
- apiKey: string;
96
- conversationModel: string;
97
- identityModel: string;
98
- auth?: Record<string, unknown>;
99
- }) {
100
- super();
101
- this.models = {
102
- conversation: opts.conversationModel,
103
- identity: opts.identityModel,
104
- };
105
- this.apiKey = opts.apiKey;
106
- const parsed = CortexAuthSchema.safeParse(opts.auth ?? {});
107
- const extra = parsed.success ? parsed.data : {};
108
- const account =
109
- extra.account ??
110
- readAuthString(opts.auth, "account", "SNOWFLAKE_ACCOUNT") ??
111
- "";
112
- this.baseURL = account
113
- ? `https://${account}.snowflakecomputing.com/api/v2/cortex/inference:complete`
114
- : "https://__account__.snowflakecomputing.com/api/v2/cortex/inference:complete";
115
- }
116
-
117
- private async send(body: Record<string, unknown>): Promise<CortexResponse> {
118
- const res = await fetch(this.baseURL, {
119
- method: "POST",
120
- headers: {
121
- Authorization: `Bearer ${this.apiKey}`,
122
- "Content-Type": "application/json",
123
- },
124
- body: JSON.stringify(body),
125
- });
126
- if (!res.ok) {
127
- const text = await res.text().catch(() => "");
128
- throw new Error(
129
- `snowflake-cortex request failed: ${res.status} ${res.statusText} body=${text.slice(0, 500)}`,
130
- );
131
- }
132
- return (await res.json()) as CortexResponse;
133
- }
134
-
135
- async call<T>(model: string, options: CallOptions): Promise<T> {
136
- const jsonMode = "jsonSchemaName" in options;
137
- const reasoning = defaultReasoningEffort(
138
- options.reasoningEffort,
139
- model,
140
- this.models.identity,
141
- );
142
- const log = logger.child("llm:snowflake-cortex");
143
- log.debug(
144
- `call: model=${model} jsonSchema=${jsonMode ? options.jsonSchemaName : "-"} msgLen=${options.message.length}`,
145
- );
146
- const body: Record<string, unknown> = {
147
- model,
148
- messages: [
149
- { role: "system", content: options.instruction },
150
- { role: "user", content: options.message },
151
- ],
152
- };
153
- if (reasoning !== "none") {
154
- body["reasoning_effort"] = reasoning;
155
- }
156
- const data = await this.send(body);
157
- if (data.error) {
158
- throw new Error(
159
- `snowflake-cortex API error: ${data.error.message ?? "unknown"}`,
160
- );
161
- }
162
- const content = data.choices?.[0]?.message?.content ?? data.message ?? "";
163
- if (!content) {
164
- throw new Error("Empty response from model");
165
- }
166
- return (jsonMode ? JSON.parse(content) : content) as T;
167
- }
168
-
169
- async chatWithTools(
170
- model: string,
171
- options: ChatWithToolsOptions,
172
- ): Promise<ChatChoice> {
173
- const log = logger.child("llm:snowflake-cortex");
174
- log.debug(
175
- `chatWithTools: model=${model} msgs=${options.messages.length} tools=${options.tools.length}`,
176
- );
177
- const body: Record<string, unknown> = {
178
- model,
179
- messages: [
180
- { role: "system", content: options.instruction },
181
- ...options.messages.map(toCortexMessage),
182
- ],
183
- tools: options.tools.map(toCortexTool),
184
- };
185
- const data = await this.send(body);
186
- if (data.error) {
187
- throw new Error(
188
- `snowflake-cortex API error: ${data.error.message ?? "unknown"}`,
189
- );
190
- }
191
- const choice = data.choices?.[0];
192
- const content = choice?.message?.content ?? data.message ?? "";
193
- const toolCalls: ToolCall[] | undefined = choice?.message?.tool_calls?.map(
194
- (c) => ({
195
- id: c.id,
196
- function: {
197
- name: c.function.name,
198
- arguments:
199
- typeof c.function.arguments === "string"
200
- ? c.function.arguments
201
- : JSON.stringify(c.function.arguments ?? {}),
202
- },
203
- }),
204
- );
205
- return { message: { content: content || undefined, toolCalls } };
206
- }
207
- }
@@ -1,17 +0,0 @@
1
- import { OpenAICompatibleExecutor } from "./openai_compatible";
2
-
3
- export class StackitExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "stackit",
11
- baseURL: "https://api.openai-compat.openai-stackit.com/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 TogetherExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "together",
11
- baseURL: "https://api.together.xyz/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 VeniceExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "venice",
11
- baseURL: "https://api.venice.ai/api/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 VercelExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "vercel",
11
- baseURL: "https://ai-gateway.vercel.sh/v1",
12
- apiKey: opts.apiKey,
13
- conversationModel: opts.conversationModel,
14
- identityModel: opts.identityModel,
15
- });
16
- }
17
- }
@@ -1,229 +0,0 @@
1
- import { logger } from "@/utils/logger";
2
- import { z } from "zod";
3
- import {
4
- LLMExecutor,
5
- defaultReasoningEffort,
6
- readAuthString,
7
- type CallOptions,
8
- type ChatChoice,
9
- type ChatFunctionTool,
10
- type ChatMessages,
11
- type ChatWithToolsOptions,
12
- type ToolCall,
13
- } from "../llm";
14
-
15
- const VertexAuthSchema = z
16
- .object({
17
- project: z.string().optional(),
18
- region: z.string().optional(),
19
- })
20
- .loose();
21
-
22
- type GeminiPart =
23
- | { text: string }
24
- | { functionCall: { name: string; args: Record<string, unknown> } }
25
- | { functionResponse: { name: string; response: Record<string, unknown> } };
26
-
27
- type GeminiResponse = {
28
- candidates?: Array<{
29
- content?: { parts?: GeminiPart[]; role?: string };
30
- finishReason?: string;
31
- }>;
32
- error?: { message?: string; code?: number };
33
- };
34
-
35
- function toGeminiContents(
36
- messages: ChatMessages[],
37
- ): Array<{ role: string; parts: GeminiPart[] }> {
38
- const out: Array<{ role: string; parts: GeminiPart[] }> = [];
39
- for (const m of messages) {
40
- if (m.role === "system") continue; // system goes into systemInstruction
41
- if (m.role === "user") {
42
- out.push({ role: "user", parts: [{ text: m.content }] });
43
- continue;
44
- }
45
- if (m.role === "assistant") {
46
- const parts: GeminiPart[] = [];
47
- if (m.content) parts.push({ text: m.content });
48
- if (m.toolCalls) {
49
- for (const c of m.toolCalls) {
50
- let args: Record<string, unknown> = {};
51
- try {
52
- args = c.function.arguments ? JSON.parse(c.function.arguments) : {};
53
- } catch {
54
- args = {};
55
- }
56
- parts.push({ functionCall: { name: c.function.name, args } });
57
- }
58
- }
59
- out.push({ role: "model", parts });
60
- continue;
61
- }
62
- if (m.role === "tool") {
63
- let response: Record<string, unknown> = {};
64
- try {
65
- response = JSON.parse(m.content);
66
- } catch {
67
- response = { result: m.content };
68
- }
69
- // ponytail: We don't track the original tool name on tool messages; the
70
- // caller names the response. The wire response uses an empty name.
71
- out.push({
72
- role: "user",
73
- parts: [{ functionResponse: { name: "", response } }],
74
- });
75
- }
76
- }
77
- return out;
78
- }
79
-
80
- function toGeminiTool(t: ChatFunctionTool) {
81
- return {
82
- functionDeclarations: [
83
- {
84
- name: t.name,
85
- description: t.description,
86
- parameters: t.parameters ?? { type: "object", properties: {} },
87
- },
88
- ],
89
- };
90
- }
91
-
92
- function extractFromGemini(data: GeminiResponse): {
93
- text: string;
94
- toolCalls: ToolCall[] | undefined;
95
- } {
96
- const parts = data.candidates?.[0]?.content?.parts ?? [];
97
- let text = "";
98
- const toolCalls: ToolCall[] = [];
99
- let idx = 0;
100
- for (const p of parts) {
101
- if ("text" in p) text += p.text;
102
- if ("functionCall" in p) {
103
- toolCalls.push({
104
- id: `call_${idx++}`,
105
- function: {
106
- name: p.functionCall.name,
107
- arguments: JSON.stringify(p.functionCall.args ?? {}),
108
- },
109
- });
110
- }
111
- }
112
- return { text, toolCalls: toolCalls.length > 0 ? toolCalls : undefined };
113
- }
114
-
115
- export class VertexExecutor extends LLMExecutor {
116
- readonly providerName = "vertex";
117
- readonly models: { conversation: string; identity: string };
118
-
119
- private readonly apiKey: string;
120
- private readonly project: string;
121
- private readonly region: string;
122
- private readonly baseURL: string;
123
-
124
- constructor(opts: {
125
- apiKey: string;
126
- conversationModel: string;
127
- identityModel: string;
128
- auth?: Record<string, unknown>;
129
- }) {
130
- super();
131
- this.models = {
132
- conversation: opts.conversationModel,
133
- identity: opts.identityModel,
134
- };
135
- this.apiKey = opts.apiKey;
136
- const parsed = VertexAuthSchema.safeParse(opts.auth ?? {});
137
- const extra = parsed.success ? parsed.data : {};
138
- this.project =
139
- extra.project ??
140
- readAuthString(opts.auth, "project", "GOOGLE_CLOUD_PROJECT") ??
141
- "";
142
- this.region =
143
- extra.region ??
144
- readAuthString(opts.auth, "region", "GOOGLE_CLOUD_REGION") ??
145
- "us-central1";
146
- this.baseURL = this.project
147
- ? `https://${this.region}-aiplatform.googleapis.com/v1/projects/${this.project}/locations/${this.region}/publishers/google/models`
148
- : "https://us-central1-aiplatform.googleapis.com/v1";
149
- }
150
-
151
- private async generate(
152
- model: string,
153
- body: Record<string, unknown>,
154
- ): Promise<GeminiResponse> {
155
- const url = `${this.baseURL}/${encodeURIComponent(model)}:generateContent`;
156
- const res = await fetch(url, {
157
- method: "POST",
158
- headers: {
159
- Authorization: `Bearer ${this.apiKey}`,
160
- "Content-Type": "application/json",
161
- },
162
- body: JSON.stringify(body),
163
- });
164
- if (!res.ok) {
165
- const text = await res.text().catch(() => "");
166
- throw new Error(
167
- `vertex request failed: ${res.status} ${res.statusText} body=${text.slice(0, 500)}`,
168
- );
169
- }
170
- return (await res.json()) as GeminiResponse;
171
- }
172
-
173
- async call<T>(model: string, options: CallOptions): Promise<T> {
174
- const jsonMode = "jsonSchemaName" in options;
175
- const log = logger.child("llm:vertex");
176
- log.debug(
177
- `call: model=${model} jsonSchema=${jsonMode ? options.jsonSchemaName : "-"} msgLen=${options.message.length}`,
178
- );
179
- const body: Record<string, unknown> = {
180
- contents: [
181
- {
182
- role: "user",
183
- parts: [{ text: options.message }],
184
- },
185
- ],
186
- systemInstruction: { parts: [{ text: options.instruction }] },
187
- };
188
- if (jsonMode) {
189
- body["generationConfig"] = {
190
- responseMimeType: "application/json",
191
- responseSchema: options.jsonSchema,
192
- };
193
- }
194
- const data = await this.generate(model, body);
195
- if (data.error) {
196
- throw new Error(`vertex API error: ${data.error.message ?? "unknown"}`);
197
- }
198
- const { text } = extractFromGemini(data);
199
- if (!text) {
200
- throw new Error("Empty response from model");
201
- }
202
- return (jsonMode ? JSON.parse(text) : text) as T;
203
- }
204
-
205
- async chatWithTools(
206
- model: string,
207
- options: ChatWithToolsOptions,
208
- ): Promise<ChatChoice> {
209
- const log = logger.child("llm:vertex");
210
- log.debug(
211
- `chatWithTools: model=${model} msgs=${options.messages.length} tools=${options.tools.length}`,
212
- );
213
- const contents = toGeminiContents(options.messages);
214
- const body: Record<string, unknown> = {
215
- contents,
216
- systemInstruction: { parts: [{ text: options.instruction }] },
217
- tools:
218
- options.tools.length > 0
219
- ? [toGeminiTool(options.tools[0]!)]
220
- : undefined,
221
- };
222
- const data = await this.generate(model, body);
223
- if (data.error) {
224
- throw new Error(`vertex API error: ${data.error.message ?? "unknown"}`);
225
- }
226
- const { text, toolCalls } = extractFromGemini(data);
227
- return { message: { content: text || undefined, toolCalls } };
228
- }
229
- }
@@ -1,17 +0,0 @@
1
- import { OpenAICompatibleExecutor } from "./openai_compatible";
2
-
3
- export class XAIExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "xai",
11
- baseURL: "https://api.x.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 ZaiExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "zai",
11
- baseURL: "https://api.z.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 ZenMuxExecutor extends OpenAICompatibleExecutor {
4
- constructor(opts: {
5
- apiKey: string;
6
- conversationModel: string;
7
- identityModel: string;
8
- }) {
9
- super({
10
- providerName: "zenmux",
11
- baseURL: "https://zenmux.ai/api/v1",
12
- apiKey: opts.apiKey,
13
- conversationModel: opts.conversationModel,
14
- identityModel: opts.identityModel,
15
- });
16
- }
17
- }
@@ -1,143 +0,0 @@
1
- const timeString = {
2
- type: "string",
3
- pattern: "^([01][0-9]|2[0-3]):[0-5][0-9]$",
4
- };
5
- const endTimeString = {
6
- type: "string",
7
- pattern: "^([01][0-9]|2[0-3]):[0-5][0-9]$|^24:00$",
8
- };
9
-
10
- export const dailyScheduleSchema = {
11
- type: "object",
12
- additionalProperties: false,
13
- properties: {
14
- items: {
15
- type: "array",
16
- minItems: 48,
17
- maxItems: 48,
18
- items: {
19
- type: "object",
20
- additionalProperties: false,
21
- properties: {
22
- start: timeString,
23
- end: endTimeString,
24
- activity: { type: "string" },
25
- notes: { type: "string" },
26
- },
27
- required: ["start", "end", "activity", "notes"],
28
- },
29
- },
30
- },
31
- required: ["items"],
32
- };
33
-
34
- export const monthlyScheduleSchema = {
35
- type: "object",
36
- additionalProperties: false,
37
- properties: {
38
- items: {
39
- type: "array",
40
- minItems: 28,
41
- maxItems: 31,
42
- items: {
43
- type: "object",
44
- additionalProperties: false,
45
- properties: {
46
- day: { type: "integer", minimum: 1, maximum: 31 },
47
- summary: { type: "string" },
48
- },
49
- required: ["day", "summary"],
50
- },
51
- },
52
- },
53
- required: ["items"],
54
- };
55
-
56
- export const availabilitySchema = {
57
- type: "object",
58
- additionalProperties: false,
59
- properties: {
60
- items: {
61
- type: "array",
62
- minItems: 1,
63
- items: {
64
- type: "object",
65
- additionalProperties: false,
66
- properties: {
67
- start: timeString,
68
- end: endTimeString,
69
- status: {
70
- type: "string",
71
- enum: ["online", "do-not-disturb", "offline"],
72
- },
73
- },
74
- required: ["start", "end", "status"],
75
- },
76
- },
77
- },
78
- required: ["items"],
79
- };
80
-
81
- // ----------------------------------------------------------------------------
82
- // Types — co-located with their schemas.
83
- // ----------------------------------------------------------------------------
84
-
85
- export type DailySlot = {
86
- start: string;
87
- end: string;
88
- activity: string;
89
- notes: string;
90
- };
91
-
92
- export type DailySchedule = {
93
- items: DailySlot[];
94
- };
95
-
96
- export type MonthlyDay = {
97
- day: number;
98
- summary: string;
99
- };
100
-
101
- export type MonthlySchedule = {
102
- items: MonthlyDay[];
103
- };
104
-
105
- export type AvailabilityStatus = "online" | "do-not-disturb" | "offline";
106
-
107
- export type Availability = {
108
- start: string;
109
- end: string;
110
- status: AvailabilityStatus;
111
- };
112
-
113
- export type AvailabilityWindows = {
114
- items: Availability[];
115
- };
116
-
117
- export const baseSystemPromptSchema = {
118
- type: "object",
119
- additionalProperties: false,
120
- properties: {
121
- baseSystemPrompt: { type: "string" },
122
- dndReplyProbability: { type: "number", minimum: 0, maximum: 1 },
123
- startConversationCountThreshold: { type: "integer", minimum: 0, maximum: 10 },
124
- startConversationTimeThreshold: {
125
- type: "integer",
126
- minimum: 30,
127
- maximum: 720,
128
- },
129
- },
130
- required: [
131
- "baseSystemPrompt",
132
- "dndReplyProbability",
133
- "startConversationCountThreshold",
134
- "startConversationTimeThreshold",
135
- ],
136
- };
137
-
138
- export type BaseSystemPromptGeneration = {
139
- baseSystemPrompt: string;
140
- dndReplyProbability: number;
141
- startConversationCountThreshold: number;
142
- startConversationTimeThreshold: number;
143
- };