haroo 1.0.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 (60) hide show
  1. package/README.md +58 -0
  2. package/dist/index.js +84883 -0
  3. package/package.json +73 -0
  4. package/src/__tests__/e2e/EventService.test.ts +211 -0
  5. package/src/__tests__/unit/Event.test.ts +89 -0
  6. package/src/__tests__/unit/Memory.test.ts +130 -0
  7. package/src/application/graph/builder.ts +106 -0
  8. package/src/application/graph/edges.ts +37 -0
  9. package/src/application/graph/nodes/addEvent.ts +113 -0
  10. package/src/application/graph/nodes/chat.ts +128 -0
  11. package/src/application/graph/nodes/extractMemory.ts +135 -0
  12. package/src/application/graph/nodes/index.ts +8 -0
  13. package/src/application/graph/nodes/query.ts +194 -0
  14. package/src/application/graph/nodes/respond.ts +26 -0
  15. package/src/application/graph/nodes/router.ts +82 -0
  16. package/src/application/graph/nodes/toolExecutor.ts +79 -0
  17. package/src/application/graph/nodes/types.ts +2 -0
  18. package/src/application/index.ts +4 -0
  19. package/src/application/services/DiaryService.ts +188 -0
  20. package/src/application/services/EventService.ts +61 -0
  21. package/src/application/services/index.ts +2 -0
  22. package/src/application/tools/calendarTool.ts +179 -0
  23. package/src/application/tools/diaryTool.ts +182 -0
  24. package/src/application/tools/index.ts +68 -0
  25. package/src/config/env.ts +33 -0
  26. package/src/config/index.ts +1 -0
  27. package/src/domain/entities/DiaryEntry.ts +16 -0
  28. package/src/domain/entities/Event.ts +13 -0
  29. package/src/domain/entities/Memory.ts +20 -0
  30. package/src/domain/index.ts +5 -0
  31. package/src/domain/interfaces/IDiaryRepository.ts +21 -0
  32. package/src/domain/interfaces/IEventsRepository.ts +12 -0
  33. package/src/domain/interfaces/ILanguageModel.ts +23 -0
  34. package/src/domain/interfaces/IMemoriesRepository.ts +15 -0
  35. package/src/domain/interfaces/IMemory.ts +19 -0
  36. package/src/domain/interfaces/index.ts +4 -0
  37. package/src/domain/state/AgentState.ts +30 -0
  38. package/src/index.ts +5 -0
  39. package/src/infrastructure/database/factory.ts +52 -0
  40. package/src/infrastructure/database/index.ts +21 -0
  41. package/src/infrastructure/database/sqlite-checkpointer.ts +179 -0
  42. package/src/infrastructure/database/sqlite-client.ts +69 -0
  43. package/src/infrastructure/database/sqlite-diary-repository.ts +209 -0
  44. package/src/infrastructure/database/sqlite-events-repository.ts +167 -0
  45. package/src/infrastructure/database/sqlite-memories-repository.ts +284 -0
  46. package/src/infrastructure/database/sqlite-schema.ts +98 -0
  47. package/src/infrastructure/index.ts +3 -0
  48. package/src/infrastructure/llm/base.ts +14 -0
  49. package/src/infrastructure/llm/gemini.ts +139 -0
  50. package/src/infrastructure/llm/index.ts +22 -0
  51. package/src/infrastructure/llm/ollama.ts +126 -0
  52. package/src/infrastructure/llm/openai.ts +148 -0
  53. package/src/infrastructure/memory/checkpointer.ts +19 -0
  54. package/src/infrastructure/memory/index.ts +2 -0
  55. package/src/infrastructure/settings/index.ts +96 -0
  56. package/src/interface/cli/calendar.ts +120 -0
  57. package/src/interface/cli/chat.ts +185 -0
  58. package/src/interface/cli/commands.ts +337 -0
  59. package/src/interface/cli/printer.ts +65 -0
  60. package/src/interface/index.ts +1 -0
@@ -0,0 +1,182 @@
1
+ import { z } from "zod";
2
+ import type { ToolDefinition } from "../../domain/interfaces/ILanguageModel";
3
+ import type { ToolExecutor } from "../graph/nodes";
4
+ import type { IDiaryRepository } from "../../domain/interfaces/IDiaryRepository";
5
+
6
+ // ============================================================================
7
+ // Schemas
8
+ // ============================================================================
9
+
10
+ export const QueryDiarySchema = z.object({
11
+ type: z.enum(["today", "yesterday", "week", "date", "range"]),
12
+ date: z.string().optional().describe("Specific date (YYYY-MM-DD) for 'date' type"),
13
+ startDate: z.string().optional().describe("Start date for 'range' type"),
14
+ endDate: z.string().optional().describe("End date for 'range' type"),
15
+ });
16
+
17
+ export type QueryDiaryInput = z.infer<typeof QueryDiarySchema>;
18
+
19
+ export const GetMoodTrendSchema = z.object({
20
+ days: z.number().optional().describe("Number of days for trend analysis (default: 30)"),
21
+ });
22
+
23
+ export type GetMoodTrendInput = z.infer<typeof GetMoodTrendSchema>;
24
+
25
+ // ============================================================================
26
+ // Tool Definitions (for LLM binding)
27
+ // ============================================================================
28
+
29
+ export const queryDiaryToolDefinition: ToolDefinition = {
30
+ name: "query_diary",
31
+ description:
32
+ "Query diary/journal entries by date or range. Returns conversation summaries, mood, and therapeutic advice from past days.",
33
+ parameters: {
34
+ type: "object",
35
+ properties: {
36
+ type: {
37
+ type: "string",
38
+ enum: ["today", "yesterday", "week", "date", "range"],
39
+ description: "Query type",
40
+ },
41
+ date: { type: "string", description: "Specific date (YYYY-MM-DD) for 'date' type" },
42
+ startDate: { type: "string", description: "Start date for 'range' type (YYYY-MM-DD)" },
43
+ endDate: { type: "string", description: "End date for 'range' type (YYYY-MM-DD)" },
44
+ },
45
+ required: ["type"],
46
+ },
47
+ };
48
+
49
+ export const getMoodTrendToolDefinition: ToolDefinition = {
50
+ name: "get_mood_trend",
51
+ description:
52
+ "Get mood trend analysis over time to understand emotional patterns. Returns mood scores and labels for recent days.",
53
+ parameters: {
54
+ type: "object",
55
+ properties: {
56
+ days: { type: "number", description: "Number of days for trend analysis (default: 30)" },
57
+ },
58
+ required: [],
59
+ },
60
+ };
61
+
62
+ export const diaryToolDefinitions: ToolDefinition[] = [
63
+ queryDiaryToolDefinition,
64
+ getMoodTrendToolDefinition,
65
+ ];
66
+
67
+ // ============================================================================
68
+ // Tool Executor Factory - Creates executors with database repository
69
+ // ============================================================================
70
+
71
+ export function createDiaryToolExecutors(
72
+ diaryRepository: IDiaryRepository
73
+ ): Record<string, ToolExecutor> {
74
+ const queryDiaryExecutor: ToolExecutor = async (args) => {
75
+ const result = QueryDiarySchema.safeParse(args);
76
+ if (!result.success) {
77
+ throw new Error(`Validation Failed: ${result.error.message}`);
78
+ }
79
+
80
+ const input = result.data;
81
+ const now = new Date();
82
+ let startDate: Date;
83
+ let endDate: Date;
84
+
85
+ switch (input.type) {
86
+ case "today":
87
+ startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
88
+ endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
89
+ break;
90
+ case "yesterday": {
91
+ const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
92
+ startDate = yesterday;
93
+ endDate = yesterday;
94
+ break;
95
+ }
96
+ case "week":
97
+ startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7);
98
+ endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
99
+ break;
100
+ case "date":
101
+ if (!input.date) {
102
+ throw new Error("Validation Failed: 'date' field is required for type 'date'");
103
+ }
104
+ startDate = new Date(input.date);
105
+ endDate = new Date(input.date);
106
+ break;
107
+ case "range":
108
+ if (!input.startDate || !input.endDate) {
109
+ throw new Error(
110
+ "Validation Failed: 'startDate' and 'endDate' are required for type 'range'"
111
+ );
112
+ }
113
+ startDate = new Date(input.startDate);
114
+ endDate = new Date(input.endDate);
115
+ break;
116
+ }
117
+
118
+ const entries = await diaryRepository.getByDateRange(startDate, endDate);
119
+
120
+ return JSON.stringify({
121
+ success: true,
122
+ query: {
123
+ type: input.type,
124
+ startDate: startDate.toISOString().split("T")[0],
125
+ endDate: endDate.toISOString().split("T")[0],
126
+ },
127
+ entries: entries.map((e) => ({
128
+ id: e.id,
129
+ date: e.entryDate.toISOString().split("T")[0],
130
+ summary: e.summary,
131
+ mood: e.mood,
132
+ moodScore: e.moodScore,
133
+ therapeuticAdvice: e.therapeuticAdvice,
134
+ messageCount: e.messageCount,
135
+ })),
136
+ });
137
+ };
138
+
139
+ const getMoodTrendExecutor: ToolExecutor = async (args) => {
140
+ const result = GetMoodTrendSchema.safeParse(args);
141
+ if (!result.success) {
142
+ throw new Error(`Validation Failed: ${result.error.message}`);
143
+ }
144
+
145
+ const input = result.data;
146
+ const days = input.days ?? 30;
147
+
148
+ const trend = await diaryRepository.getMoodTrend(days);
149
+
150
+ // Calculate average mood score
151
+ const avgMoodScore =
152
+ trend.length > 0 ? trend.reduce((sum, t) => sum + t.moodScore, 0) / trend.length : null;
153
+
154
+ // Find most common mood
155
+ const moodCounts = trend.reduce(
156
+ (acc, t) => {
157
+ acc[t.mood] = (acc[t.mood] || 0) + 1;
158
+ return acc;
159
+ },
160
+ {} as Record<string, number>
161
+ );
162
+ const dominantMood = Object.entries(moodCounts).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;
163
+
164
+ return JSON.stringify({
165
+ success: true,
166
+ days,
167
+ entryCount: trend.length,
168
+ averageMoodScore: avgMoodScore ? Math.round(avgMoodScore * 10) / 10 : null,
169
+ dominantMood,
170
+ trend: trend.map((t) => ({
171
+ date: t.date.toISOString().split("T")[0],
172
+ mood: t.mood,
173
+ moodScore: t.moodScore,
174
+ })),
175
+ });
176
+ };
177
+
178
+ return {
179
+ query_diary: queryDiaryExecutor,
180
+ get_mood_trend: getMoodTrendExecutor,
181
+ };
182
+ }
@@ -0,0 +1,68 @@
1
+ import type { ToolRegistry, ToolExecutor } from "../graph/nodes";
2
+ import type { IEventsRepository } from "../../domain/interfaces/IEventsRepository";
3
+ import type { IDiaryRepository } from "../../domain/interfaces/IDiaryRepository";
4
+ import {
5
+ createCalendarToolExecutors,
6
+ calendarToolDefinitions,
7
+ AddEventSchema,
8
+ QueryEventsSchema,
9
+ type AddEventInput,
10
+ type QueryEventsInput,
11
+ } from "./calendarTool";
12
+ import {
13
+ createDiaryToolExecutors,
14
+ diaryToolDefinitions,
15
+ QueryDiarySchema,
16
+ GetMoodTrendSchema,
17
+ type QueryDiaryInput,
18
+ type GetMoodTrendInput,
19
+ } from "./diaryTool";
20
+
21
+ export interface ToolRegistryDeps {
22
+ eventsRepository: IEventsRepository;
23
+ diaryRepository?: IDiaryRepository;
24
+ }
25
+
26
+ export function createToolRegistry(deps: ToolRegistryDeps): ToolRegistry {
27
+ const registry: ToolRegistry = new Map();
28
+
29
+ // Register calendar tools with database repository
30
+ const calendarExecutors = createCalendarToolExecutors(deps.eventsRepository);
31
+ for (const [name, executor] of Object.entries(calendarExecutors)) {
32
+ registry.set(name, executor);
33
+ }
34
+
35
+ // Register diary tools if repository provided
36
+ if (deps.diaryRepository) {
37
+ const diaryExecutors = createDiaryToolExecutors(deps.diaryRepository);
38
+ for (const [name, executor] of Object.entries(diaryExecutors)) {
39
+ registry.set(name, executor);
40
+ }
41
+ }
42
+
43
+ return registry;
44
+ }
45
+
46
+ // Re-export calendar tool components
47
+ export {
48
+ createCalendarToolExecutors,
49
+ calendarToolDefinitions,
50
+ AddEventSchema,
51
+ QueryEventsSchema,
52
+ type AddEventInput,
53
+ type QueryEventsInput,
54
+ };
55
+
56
+ // Re-export diary tool components
57
+ export {
58
+ createDiaryToolExecutors,
59
+ diaryToolDefinitions,
60
+ QueryDiarySchema,
61
+ GetMoodTrendSchema,
62
+ type QueryDiaryInput,
63
+ type GetMoodTrendInput,
64
+ };
65
+
66
+ export function registerTool(registry: ToolRegistry, name: string, executor: ToolExecutor): void {
67
+ registry.set(name, executor);
68
+ }
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import "dotenv/config";
3
+
4
+ const envSchema = z.object({
5
+ // LLM Providers
6
+ OPENAI_API_KEY: z.string().optional(),
7
+ GEMINI_API_KEY: z.string().optional(),
8
+ OLLAMA_BASE_URL: z.string().url().default("http://localhost:11434"),
9
+
10
+ // Default provider
11
+ DEFAULT_PROVIDER: z.enum(["openai", "gemini", "ollama"]).default("ollama"),
12
+ DEFAULT_MODEL: z.string().optional(),
13
+
14
+ // App settings
15
+ NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
16
+ LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
17
+ });
18
+
19
+ export type Env = z.infer<typeof envSchema>;
20
+
21
+ function validateEnv(): Env {
22
+ const result = envSchema.safeParse(process.env);
23
+
24
+ if (!result.success) {
25
+ console.error("Environment validation failed:");
26
+ console.error(result.error.format());
27
+ process.exit(1);
28
+ }
29
+
30
+ return result.data;
31
+ }
32
+
33
+ export const env = validateEnv();
@@ -0,0 +1 @@
1
+ export { type Env, env } from "./env";
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+
3
+ export const DiaryEntrySchema = z.object({
4
+ id: z.string().uuid(),
5
+ entryDate: z.coerce.date(),
6
+ summary: z.string(),
7
+ mood: z.string(),
8
+ moodScore: z.number().min(1).max(10),
9
+ therapeuticAdvice: z.string(),
10
+ sessionIds: z.array(z.string()).default([]),
11
+ messageCount: z.number().default(0),
12
+ createdAt: z.coerce.date(),
13
+ updatedAt: z.coerce.date(),
14
+ });
15
+
16
+ export type DiaryEntry = z.infer<typeof DiaryEntrySchema>;
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+
3
+ export const EventSchema = z.object({
4
+ id: z.string().uuid(),
5
+ title: z.string().min(1),
6
+ datetime: z.coerce.date(),
7
+ endTime: z.coerce.date().optional(),
8
+ notes: z.string().optional(),
9
+ tags: z.array(z.string()).default([]),
10
+ createdAt: z.coerce.date().default(() => new Date()),
11
+ });
12
+
13
+ export type Event = z.infer<typeof EventSchema>;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+
3
+ export const MemorySchema = z.object({
4
+ id: z.string().uuid(),
5
+ type: z.enum([
6
+ "fact",
7
+ "preference",
8
+ "routine",
9
+ "relationship",
10
+ "communication_style",
11
+ "interest",
12
+ ]),
13
+ content: z.string(),
14
+ source: z.string().optional(),
15
+ importance: z.number().min(1).max(10).default(5),
16
+ lastAccessed: z.coerce.date(),
17
+ createdAt: z.coerce.date(),
18
+ });
19
+
20
+ export type Memory = z.infer<typeof MemorySchema>;
@@ -0,0 +1,5 @@
1
+ export * from "./entities/Event";
2
+ export * from "./entities/Memory";
3
+ export * from "./interfaces/ILanguageModel";
4
+ export * from "./interfaces/IMemory";
5
+ export { GraphState, type GraphStateType, type Intent } from "./state/AgentState";
@@ -0,0 +1,21 @@
1
+ import type { DiaryEntry } from "../entities/DiaryEntry";
2
+
3
+ export interface MoodTrendEntry {
4
+ date: Date;
5
+ mood: string;
6
+ moodScore: number;
7
+ }
8
+
9
+ export interface IDiaryRepository {
10
+ create(entry: DiaryEntry): Promise<DiaryEntry>;
11
+ getById(id: string): Promise<DiaryEntry | null>;
12
+ getByDate(date: Date): Promise<DiaryEntry | null>;
13
+ getByDateRange(startDate: Date, endDate: Date): Promise<DiaryEntry[]>;
14
+ getRecent(limit?: number): Promise<DiaryEntry[]>;
15
+ update(
16
+ id: string,
17
+ updates: Partial<Omit<DiaryEntry, "id" | "createdAt">>
18
+ ): Promise<DiaryEntry | null>;
19
+ delete(id: string): Promise<boolean>;
20
+ getMoodTrend(days?: number): Promise<MoodTrendEntry[]>;
21
+ }
@@ -0,0 +1,12 @@
1
+ import type { Event } from "../entities/Event";
2
+
3
+ export interface IEventsRepository {
4
+ create(event: Event): Promise<Event>;
5
+ getById(id: string): Promise<Event | null>;
6
+ getByDateRange(startDate: Date, endDate: Date): Promise<Event[]>;
7
+ getToday(): Promise<Event[]>;
8
+ getUpcoming(limit?: number): Promise<Event[]>;
9
+ update(id: string, updates: Partial<Omit<Event, "id" | "createdAt">>): Promise<Event | null>;
10
+ delete(id: string): Promise<boolean>;
11
+ searchByTitle(query: string): Promise<Event[]>;
12
+ }
@@ -0,0 +1,23 @@
1
+ import type { BaseMessage } from "@langchain/core/messages";
2
+
3
+ export interface ToolDefinition {
4
+ name: string;
5
+ description: string;
6
+ parameters: Record<string, unknown>;
7
+ }
8
+
9
+ export interface ToolCall {
10
+ id: string;
11
+ name: string;
12
+ arguments: Record<string, unknown>;
13
+ }
14
+
15
+ export interface LLMResponse {
16
+ content: string;
17
+ toolCalls?: ToolCall[];
18
+ }
19
+
20
+ export interface ILanguageModel {
21
+ generate(messages: BaseMessage[], tools?: ToolDefinition[]): Promise<LLMResponse>;
22
+ withStructuredOutput<_T>(schema: unknown): ILanguageModel;
23
+ }
@@ -0,0 +1,15 @@
1
+ import type { Memory } from "../entities/Memory";
2
+
3
+ export type EmbeddingFunction = (text: string) => Promise<number[]>;
4
+
5
+ export interface IMemoriesRepository {
6
+ create(memory: Memory, embedding?: number[]): Promise<Memory>;
7
+ getById(id: string): Promise<Memory | null>;
8
+ getByType(type: Memory["type"]): Promise<Memory[]>;
9
+ getAll(limit?: number): Promise<Memory[]>;
10
+ semanticSearch(embedding: number[], limit?: number, threshold?: number): Promise<Memory[]>;
11
+ update(id: string, updates: Partial<Omit<Memory, "id" | "createdAt">>): Promise<Memory | null>;
12
+ delete(id: string): Promise<boolean>;
13
+ updateLastAccessed(id: string): Promise<void>;
14
+ getRecent(limit?: number): Promise<Memory[]>;
15
+ }
@@ -0,0 +1,19 @@
1
+ import type { GraphStateType } from "../state/AgentState";
2
+
3
+ export interface CheckpointMetadata {
4
+ createdAt: Date;
5
+ updatedAt: Date;
6
+ }
7
+
8
+ export interface ICheckpointer {
9
+ save(sessionId: string, state: GraphStateType): Promise<void>;
10
+ load(sessionId: string): Promise<GraphStateType | null>;
11
+ list(): Promise<string[]>;
12
+ getMetadata?(sessionId: string): Promise<CheckpointMetadata | null>;
13
+ getSessionsForDate?(date: Date): Promise<string[]>;
14
+ }
15
+
16
+ export interface IVectorStore {
17
+ addDocuments(docs: { content: string; metadata?: Record<string, unknown> }[]): Promise<void>;
18
+ search(query: string, limit?: number): Promise<{ content: string; score: number }[]>;
19
+ }
@@ -0,0 +1,4 @@
1
+ export type { IEventsRepository } from "./IEventsRepository";
2
+ export type { ILanguageModel } from "./ILanguageModel";
3
+ export type { EmbeddingFunction, IMemoriesRepository } from "./IMemoriesRepository";
4
+ export type { ICheckpointer, IVectorStore } from "./IMemory";
@@ -0,0 +1,30 @@
1
+ import type { BaseMessage } from "@langchain/core/messages";
2
+ import { Annotation } from "@langchain/langgraph";
3
+ import type { Event } from "../entities/Event";
4
+ import type { Memory } from "../entities/Memory";
5
+
6
+ export type Intent = "add_event" | "query" | "chat" | null;
7
+
8
+ export const GraphState = Annotation.Root({
9
+ messages: Annotation<BaseMessage[]>({
10
+ reducer: (prev, next) => [...prev, ...next],
11
+ default: () => [],
12
+ }),
13
+ intent: Annotation<Intent>(),
14
+ pendingEvent: Annotation<Event | null>(),
15
+ queryResult: Annotation<string | null>(),
16
+ relevantMemories: Annotation<Memory[]>({
17
+ reducer: (_, next) => next,
18
+ default: () => [],
19
+ }),
20
+ todayEvents: Annotation<Event[]>({
21
+ reducer: (_, next) => next,
22
+ default: () => [],
23
+ }),
24
+ response: Annotation<string>({
25
+ reducer: (_, next) => next,
26
+ default: () => "",
27
+ }),
28
+ });
29
+
30
+ export type GraphStateType = typeof GraphState.State;
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bun
2
+ import { createProgram } from "./interface";
3
+
4
+ const program = createProgram();
5
+ program.parse();
@@ -0,0 +1,52 @@
1
+ import type { Database } from "bun:sqlite";
2
+ import type { IEventsRepository } from "../../domain/interfaces/IEventsRepository";
3
+ import type { IMemoriesRepository } from "../../domain/interfaces/IMemoriesRepository";
4
+ import type { IDiaryRepository } from "../../domain/interfaces/IDiaryRepository";
5
+ import type { ICheckpointer } from "../../domain/interfaces/IMemory";
6
+
7
+ import { SqliteCheckpointer } from "./sqlite-checkpointer";
8
+ import { SqliteEventsRepository } from "./sqlite-events-repository";
9
+ import { SqliteMemoriesRepository } from "./sqlite-memories-repository";
10
+ import { SqliteDiaryRepository } from "./sqlite-diary-repository";
11
+
12
+ import { createSqliteClient } from "./sqlite-client";
13
+ import { initializeSqliteSchema } from "./sqlite-schema";
14
+
15
+ export interface RepositoryBundle {
16
+ checkpointer: ICheckpointer;
17
+ events: IEventsRepository;
18
+ memories: IMemoriesRepository & {
19
+ setEmbeddingFunction?: (fn: (text: string) => Promise<number[]>) => void;
20
+ };
21
+ diary: IDiaryRepository;
22
+ }
23
+
24
+ /**
25
+ * Creates the complete repository bundle using SQLite backend.
26
+ */
27
+ export function createRepositories(client: Database): RepositoryBundle {
28
+ const memories = new SqliteMemoriesRepository(client);
29
+ return {
30
+ checkpointer: new SqliteCheckpointer(client),
31
+ events: new SqliteEventsRepository(client),
32
+ memories,
33
+ diary: new SqliteDiaryRepository(client),
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Create SQLite backend client with schema initialized.
39
+ */
40
+ export function createBackend(): Database {
41
+ const client = createSqliteClient();
42
+ initializeSqliteSchema(client);
43
+ return client;
44
+ }
45
+
46
+ /**
47
+ * Convenience function to create repositories with auto-initialized SQLite.
48
+ */
49
+ export function createRepositoriesFromEnv(): RepositoryBundle {
50
+ const client = createBackend();
51
+ return createRepositories(client);
52
+ }
@@ -0,0 +1,21 @@
1
+ // Re-export interfaces from domain
2
+ export type { IEventsRepository } from "../../domain/interfaces/IEventsRepository";
3
+ export type {
4
+ EmbeddingFunction,
5
+ IMemoriesRepository,
6
+ } from "../../domain/interfaces/IMemoriesRepository";
7
+ export type { ICheckpointer } from "../../domain/interfaces/IMemory";
8
+
9
+ // Factory with auto-detection
10
+ export type { RepositoryBundle } from "./factory";
11
+ export { createBackend, createRepositories, createRepositoriesFromEnv } from "./factory";
12
+
13
+ // SQLite implementations
14
+ export { SqliteCheckpointer } from "./sqlite-checkpointer";
15
+ export { SqliteEventsRepository } from "./sqlite-events-repository";
16
+ export { SqliteMemoriesRepository } from "./sqlite-memories-repository";
17
+ export { SqliteDiaryRepository } from "./sqlite-diary-repository";
18
+
19
+ // SQLite client
20
+ export { createSqliteClient, getDefaultDbPath } from "./sqlite-client";
21
+ export { initializeSqliteSchema } from "./sqlite-schema";