confused-ai-core 0.1.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 (114) hide show
  1. package/FEATURES.md +169 -0
  2. package/package.json +119 -0
  3. package/src/agent.ts +187 -0
  4. package/src/agentic/index.ts +87 -0
  5. package/src/agentic/runner.ts +386 -0
  6. package/src/agentic/types.ts +91 -0
  7. package/src/artifacts/artifact.ts +417 -0
  8. package/src/artifacts/index.ts +42 -0
  9. package/src/artifacts/media.ts +304 -0
  10. package/src/cli/index.ts +122 -0
  11. package/src/core/base-agent.ts +151 -0
  12. package/src/core/context-builder.ts +106 -0
  13. package/src/core/index.ts +8 -0
  14. package/src/core/schemas.ts +17 -0
  15. package/src/core/types.ts +158 -0
  16. package/src/create-agent.ts +309 -0
  17. package/src/debug-logger.ts +188 -0
  18. package/src/dx/agent.ts +88 -0
  19. package/src/dx/define-agent.ts +183 -0
  20. package/src/dx/dev-logger.ts +57 -0
  21. package/src/dx/index.ts +11 -0
  22. package/src/errors.ts +175 -0
  23. package/src/execution/engine.ts +522 -0
  24. package/src/execution/graph-builder.ts +362 -0
  25. package/src/execution/index.ts +8 -0
  26. package/src/execution/types.ts +257 -0
  27. package/src/execution/worker-pool.ts +308 -0
  28. package/src/extensions/index.ts +123 -0
  29. package/src/guardrails/allowlist.ts +155 -0
  30. package/src/guardrails/index.ts +17 -0
  31. package/src/guardrails/types.ts +159 -0
  32. package/src/guardrails/validator.ts +265 -0
  33. package/src/index.ts +74 -0
  34. package/src/knowledge/index.ts +5 -0
  35. package/src/knowledge/types.ts +52 -0
  36. package/src/learning/in-memory-store.ts +72 -0
  37. package/src/learning/index.ts +6 -0
  38. package/src/learning/types.ts +42 -0
  39. package/src/llm/cache.ts +300 -0
  40. package/src/llm/index.ts +22 -0
  41. package/src/llm/model-resolver.ts +81 -0
  42. package/src/llm/openai-provider.ts +313 -0
  43. package/src/llm/openrouter-provider.ts +29 -0
  44. package/src/llm/types.ts +131 -0
  45. package/src/memory/in-memory-store.ts +255 -0
  46. package/src/memory/index.ts +7 -0
  47. package/src/memory/types.ts +193 -0
  48. package/src/memory/vector-store.ts +251 -0
  49. package/src/observability/console-logger.ts +123 -0
  50. package/src/observability/index.ts +12 -0
  51. package/src/observability/metrics.ts +85 -0
  52. package/src/observability/otlp-exporter.ts +417 -0
  53. package/src/observability/tracer.ts +105 -0
  54. package/src/observability/types.ts +341 -0
  55. package/src/orchestration/agent-adapter.ts +33 -0
  56. package/src/orchestration/index.ts +34 -0
  57. package/src/orchestration/load-balancer.ts +151 -0
  58. package/src/orchestration/mcp-types.ts +59 -0
  59. package/src/orchestration/message-bus.ts +192 -0
  60. package/src/orchestration/orchestrator.ts +349 -0
  61. package/src/orchestration/pipeline.ts +66 -0
  62. package/src/orchestration/supervisor.ts +107 -0
  63. package/src/orchestration/swarm.ts +1099 -0
  64. package/src/orchestration/toolkit.ts +47 -0
  65. package/src/orchestration/types.ts +339 -0
  66. package/src/planner/classical-planner.ts +383 -0
  67. package/src/planner/index.ts +8 -0
  68. package/src/planner/llm-planner.ts +353 -0
  69. package/src/planner/types.ts +227 -0
  70. package/src/planner/validator.ts +297 -0
  71. package/src/production/circuit-breaker.ts +290 -0
  72. package/src/production/graceful-shutdown.ts +251 -0
  73. package/src/production/health.ts +333 -0
  74. package/src/production/index.ts +57 -0
  75. package/src/production/latency-eval.ts +62 -0
  76. package/src/production/rate-limiter.ts +287 -0
  77. package/src/production/resumable-stream.ts +289 -0
  78. package/src/production/types.ts +81 -0
  79. package/src/sdk/index.ts +374 -0
  80. package/src/session/db-driver.ts +50 -0
  81. package/src/session/in-memory-store.ts +235 -0
  82. package/src/session/index.ts +12 -0
  83. package/src/session/sql-store.ts +315 -0
  84. package/src/session/sqlite-store.ts +61 -0
  85. package/src/session/types.ts +153 -0
  86. package/src/tools/base-tool.ts +223 -0
  87. package/src/tools/browser-tool.ts +123 -0
  88. package/src/tools/calculator-tool.ts +265 -0
  89. package/src/tools/file-tools.ts +394 -0
  90. package/src/tools/github-tool.ts +432 -0
  91. package/src/tools/hackernews-tool.ts +187 -0
  92. package/src/tools/http-tool.ts +118 -0
  93. package/src/tools/index.ts +99 -0
  94. package/src/tools/jira-tool.ts +373 -0
  95. package/src/tools/notion-tool.ts +322 -0
  96. package/src/tools/openai-tool.ts +236 -0
  97. package/src/tools/registry.ts +131 -0
  98. package/src/tools/serpapi-tool.ts +234 -0
  99. package/src/tools/shell-tool.ts +118 -0
  100. package/src/tools/slack-tool.ts +327 -0
  101. package/src/tools/telegram-tool.ts +127 -0
  102. package/src/tools/types.ts +229 -0
  103. package/src/tools/websearch-tool.ts +335 -0
  104. package/src/tools/wikipedia-tool.ts +177 -0
  105. package/src/tools/yfinance-tool.ts +33 -0
  106. package/src/voice/index.ts +17 -0
  107. package/src/voice/voice-provider.ts +228 -0
  108. package/tests/artifact.test.ts +241 -0
  109. package/tests/circuit-breaker.test.ts +171 -0
  110. package/tests/health.test.ts +192 -0
  111. package/tests/llm-cache.test.ts +186 -0
  112. package/tests/rate-limiter.test.ts +161 -0
  113. package/tsconfig.json +29 -0
  114. package/vitest.config.ts +47 -0
@@ -0,0 +1,315 @@
1
+ /**
2
+ * SQL-backed session store. Works with any DB via SessionDbDriver.
3
+ */
4
+
5
+ import type {
6
+ SessionStore,
7
+ Session,
8
+ SessionRun,
9
+ SessionId,
10
+ SessionQuery,
11
+ SessionStoreConfig,
12
+ } from './types.js';
13
+ import { SessionState } from './types.js';
14
+ import type { SessionDbDriver, SessionRow, SessionRunRow } from './db-driver.js';
15
+ import type { Message } from '../llm/types.js';
16
+
17
+ const DEFAULT_CONFIG: Required<SessionStoreConfig> = {
18
+ defaultTtlMs: 24 * 60 * 60 * 1000,
19
+ maxSessionsPerAgent: 100,
20
+ maxMessagesPerSession: 1000,
21
+ };
22
+
23
+ function toSession(row: SessionRow): Session {
24
+ return {
25
+ id: row.id,
26
+ agentId: row.agent_id,
27
+ userId: row.user_id ?? undefined,
28
+ state: row.state as SessionState,
29
+ messages: JSON.parse(row.messages || '[]') as Message[],
30
+ metadata: (JSON.parse(row.metadata || '{}') as Session['metadata']) ?? {},
31
+ context: (JSON.parse(row.context || '{}') as Record<string, unknown>) ?? {},
32
+ createdAt: new Date(row.created_at),
33
+ updatedAt: new Date(row.updated_at),
34
+ expiresAt: row.expires_at ? new Date(row.expires_at) : undefined,
35
+ };
36
+ }
37
+
38
+ function toSessionRun(row: SessionRunRow): SessionRun {
39
+ return {
40
+ id: row.id,
41
+ sessionId: row.session_id,
42
+ agentId: row.agent_id,
43
+ startTime: new Date(row.start_time),
44
+ endTime: row.end_time ? new Date(row.end_time) : undefined,
45
+ status: row.status as SessionRun['status'],
46
+ steps: row.steps,
47
+ result: row.result != null ? JSON.parse(row.result) : undefined,
48
+ error: row.error ?? undefined,
49
+ };
50
+ }
51
+
52
+ function genId(prefix: string): string {
53
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
54
+ }
55
+
56
+ /**
57
+ * SQL session store. Use with SessionDbDriver (SQLite, PostgreSQL, etc.).
58
+ */
59
+ export class SqlSessionStore implements SessionStore {
60
+ private driver: SessionDbDriver;
61
+ private config: Required<SessionStoreConfig>;
62
+ private tableSessions: string;
63
+ private tableRuns: string;
64
+
65
+ constructor(
66
+ driver: SessionDbDriver,
67
+ config: SessionStoreConfig & { tablePrefix?: string } = {}
68
+ ) {
69
+ this.driver = driver;
70
+ this.config = { ...DEFAULT_CONFIG, ...config };
71
+ const prefix = config.tablePrefix ?? 'agent';
72
+ this.tableSessions = `${prefix}_sessions`;
73
+ this.tableRuns = `${prefix}_session_runs`;
74
+ }
75
+
76
+ /** Create tables if they don't exist. Call once at startup. */
77
+ async migrate(): Promise<void> {
78
+ const exec = this.driver.exec ?? ((sql: string) => this.driver.run(sql));
79
+ await exec(
80
+ `CREATE TABLE IF NOT EXISTS ${this.tableSessions} (
81
+ id TEXT PRIMARY KEY,
82
+ agent_id TEXT NOT NULL,
83
+ user_id TEXT,
84
+ state TEXT NOT NULL,
85
+ messages TEXT NOT NULL DEFAULT '[]',
86
+ metadata TEXT NOT NULL DEFAULT '{}',
87
+ context TEXT NOT NULL DEFAULT '{}',
88
+ created_at TEXT NOT NULL,
89
+ updated_at TEXT NOT NULL,
90
+ expires_at TEXT
91
+ )`
92
+ );
93
+ await exec(
94
+ `CREATE TABLE IF NOT EXISTS ${this.tableRuns} (
95
+ id TEXT PRIMARY KEY,
96
+ session_id TEXT NOT NULL,
97
+ agent_id TEXT NOT NULL,
98
+ start_time TEXT NOT NULL,
99
+ end_time TEXT,
100
+ status TEXT NOT NULL,
101
+ steps INTEGER NOT NULL DEFAULT 0,
102
+ result TEXT,
103
+ error TEXT
104
+ )`
105
+ );
106
+ }
107
+
108
+ async create(session: Omit<Session, 'id' | 'createdAt' | 'updatedAt'>): Promise<Session> {
109
+ const id = genId('session');
110
+ const now = new Date().toISOString();
111
+ const messages = JSON.stringify(session.messages ?? []);
112
+ const metadata = JSON.stringify(session.metadata ?? {});
113
+ const context = JSON.stringify(session.context ?? {});
114
+ const expiresAt = session.expiresAt?.toISOString() ?? null;
115
+
116
+ await this.driver.run(
117
+ `INSERT INTO ${this.tableSessions} (id, agent_id, user_id, state, messages, metadata, context, created_at, updated_at, expires_at)
118
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
119
+ [
120
+ id,
121
+ session.agentId,
122
+ session.userId ?? null,
123
+ session.state,
124
+ messages,
125
+ metadata,
126
+ context,
127
+ now,
128
+ now,
129
+ expiresAt,
130
+ ]
131
+ );
132
+
133
+ await this.enforceMaxSessions(session.agentId);
134
+
135
+ return this.get(id) as Promise<Session>;
136
+ }
137
+
138
+ async get(sessionId: SessionId): Promise<Session | null> {
139
+ const rows = await this.driver.query<SessionRow>(
140
+ `SELECT * FROM ${this.tableSessions} WHERE id = ?`,
141
+ [sessionId]
142
+ );
143
+ const row = rows[0];
144
+ if (!row) return null;
145
+
146
+ if (row.expires_at && new Date(row.expires_at) < new Date()) {
147
+ await this.delete(sessionId);
148
+ return null;
149
+ }
150
+
151
+ return toSession(row);
152
+ }
153
+
154
+ async update(sessionId: SessionId, updates: Partial<Omit<Session, 'id' | 'createdAt'>>): Promise<Session> {
155
+ const existing = await this.get(sessionId);
156
+ if (!existing) throw new Error(`Session not found: ${sessionId}`);
157
+
158
+ const updated: Session = { ...existing, ...updates, updatedAt: new Date() };
159
+ const messages = JSON.stringify(updated.messages);
160
+ const metadata = JSON.stringify(updated.metadata);
161
+ const context = JSON.stringify(updated.context);
162
+ const expiresAt = updated.expiresAt?.toISOString() ?? null;
163
+
164
+ await this.driver.run(
165
+ `UPDATE ${this.tableSessions} SET agent_id = ?, user_id = ?, state = ?, messages = ?, metadata = ?, context = ?, updated_at = ?, expires_at = ?
166
+ WHERE id = ?`,
167
+ [
168
+ updated.agentId,
169
+ updated.userId ?? null,
170
+ updated.state,
171
+ messages,
172
+ metadata,
173
+ context,
174
+ updated.updatedAt.toISOString(),
175
+ expiresAt,
176
+ sessionId,
177
+ ]
178
+ );
179
+
180
+ return this.get(sessionId) as Promise<Session>;
181
+ }
182
+
183
+ async delete(sessionId: SessionId): Promise<boolean> {
184
+ await this.driver.run(`DELETE FROM ${this.tableRuns} WHERE session_id = ?`, [sessionId]);
185
+ await this.driver.run(`DELETE FROM ${this.tableSessions} WHERE id = ?`, [sessionId]);
186
+ return true;
187
+ }
188
+
189
+ async list(query?: SessionQuery): Promise<Session[]> {
190
+ let sql = `SELECT * FROM ${this.tableSessions} WHERE 1=1`;
191
+ const params: unknown[] = [];
192
+
193
+ if (query?.agentId) {
194
+ sql += ' AND agent_id = ?';
195
+ params.push(query.agentId);
196
+ }
197
+ if (query?.userId) {
198
+ sql += ' AND user_id = ?';
199
+ params.push(query.userId);
200
+ }
201
+ if (query?.state) {
202
+ sql += ' AND state = ?';
203
+ params.push(query.state);
204
+ }
205
+ if (query?.before) {
206
+ sql += ' AND created_at < ?';
207
+ params.push(query.before.toISOString());
208
+ }
209
+ if (query?.after) {
210
+ sql += ' AND created_at > ?';
211
+ params.push(query.after.toISOString());
212
+ }
213
+
214
+ sql += ' ORDER BY updated_at DESC';
215
+ if (query?.limit) {
216
+ sql += ' LIMIT ?';
217
+ params.push(query.limit);
218
+ }
219
+
220
+ const rows = await this.driver.query<SessionRow>(sql, params);
221
+ return rows.map(toSession);
222
+ }
223
+
224
+ async addMessage(sessionId: SessionId, message: Message): Promise<Session> {
225
+ const session = await this.get(sessionId);
226
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
227
+
228
+ const messages = [...session.messages, message];
229
+ if (messages.length > this.config.maxMessagesPerSession) {
230
+ messages.shift();
231
+ }
232
+
233
+ return this.update(sessionId, { messages, state: SessionState.ACTIVE });
234
+ }
235
+
236
+ async getMessages(sessionId: SessionId): Promise<Message[]> {
237
+ const session = await this.get(sessionId);
238
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
239
+ return [...session.messages];
240
+ }
241
+
242
+ async clearMessages(sessionId: SessionId): Promise<Session> {
243
+ return this.update(sessionId, { messages: [] });
244
+ }
245
+
246
+ async setContext(sessionId: SessionId, key: string, value: unknown): Promise<Session> {
247
+ const session = await this.get(sessionId);
248
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
249
+ return this.update(sessionId, { context: { ...session.context, [key]: value } });
250
+ }
251
+
252
+ async getContext(sessionId: SessionId, key: string): Promise<unknown> {
253
+ const session = await this.get(sessionId);
254
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
255
+ return session.context[key];
256
+ }
257
+
258
+ async recordRun(run: Omit<SessionRun, 'id'>): Promise<SessionRun> {
259
+ const session = await this.get(run.sessionId);
260
+ if (!session) throw new Error(`Session not found: ${run.sessionId}`);
261
+
262
+ const id = genId('run');
263
+ await this.driver.run(
264
+ `INSERT INTO ${this.tableRuns} (id, session_id, agent_id, start_time, end_time, status, steps, result, error)
265
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
266
+ [
267
+ id,
268
+ run.sessionId,
269
+ run.agentId,
270
+ run.startTime.toISOString(),
271
+ run.endTime?.toISOString() ?? null,
272
+ run.status,
273
+ run.steps,
274
+ run.result != null ? JSON.stringify(run.result) : null,
275
+ run.error ?? null,
276
+ ]
277
+ );
278
+
279
+ const rows = await this.driver.query<SessionRunRow>(`SELECT * FROM ${this.tableRuns} WHERE id = ?`, [id]);
280
+ return toSessionRun(rows[0]!);
281
+ }
282
+
283
+ async getRuns(sessionId: SessionId): Promise<SessionRun[]> {
284
+ const rows = await this.driver.query<SessionRunRow>(
285
+ `SELECT * FROM ${this.tableRuns} WHERE session_id = ? ORDER BY start_time DESC`,
286
+ [sessionId]
287
+ );
288
+ return rows.map(toSessionRun);
289
+ }
290
+
291
+ async cleanup(): Promise<number> {
292
+ const now = new Date().toISOString();
293
+ const rows = await this.driver.query<{ id: string }>(
294
+ `SELECT id FROM ${this.tableSessions} WHERE expires_at IS NOT NULL AND expires_at < ?`,
295
+ [now]
296
+ );
297
+ for (const r of rows) {
298
+ await this.delete(r.id);
299
+ }
300
+ return rows.length;
301
+ }
302
+
303
+ private async enforceMaxSessions(agentId: string): Promise<void> {
304
+ const rows = await this.driver.query<{ id: string; created_at: string }>(
305
+ `SELECT id, created_at FROM ${this.tableSessions} WHERE agent_id = ? ORDER BY created_at ASC`,
306
+ [agentId]
307
+ );
308
+ const excess = rows.length - this.config.maxSessionsPerAgent;
309
+ if (excess > 0) {
310
+ for (let i = 0; i < excess; i++) {
311
+ await this.delete(rows[i]!.id);
312
+ }
313
+ }
314
+ }
315
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * SQLite session store. Requires optional peer dependency: better-sqlite3.
3
+ *
4
+ * Install: pnpm add better-sqlite3
5
+ * Then: import { createSqliteSessionStore } from '@confused-ai/core/session';
6
+ */
7
+
8
+ import type { SessionStore } from './types.js';
9
+ import type { SessionStoreConfig } from './types.js';
10
+ import type { SessionDbDriver } from './db-driver.js';
11
+ import { SqlSessionStore } from './sql-store.js';
12
+
13
+ /**
14
+ * Create a SQLite-backed session store.
15
+ * Requires better-sqlite3: npm install better-sqlite3
16
+ *
17
+ * @param filePath - Path to SQLite database file (e.g. ./data/sessions.db)
18
+ * @param config - Optional store config (defaultTtlMs, maxSessionsPerAgent, maxMessagesPerSession, tablePrefix)
19
+ */
20
+ export async function createSqliteSessionStore(
21
+ filePath: string,
22
+ config?: SessionStoreConfig & { tablePrefix?: string }
23
+ ): Promise<SessionStore> {
24
+ let Database: (path: string) => {
25
+ exec: (sql: string) => void;
26
+ prepare: (sql: string) => {
27
+ run: (...params: unknown[]) => { lastInsertRowid: number };
28
+ all: (...params: unknown[]) => unknown[];
29
+ };
30
+ close: () => void;
31
+ };
32
+ try {
33
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
34
+ Database = require('better-sqlite3') as typeof Database;
35
+ } catch {
36
+ throw new Error(
37
+ 'createSqliteSessionStore requires better-sqlite3. Install it: npm install better-sqlite3'
38
+ );
39
+ }
40
+
41
+ const db = Database(filePath);
42
+
43
+ const driver: SessionDbDriver = {
44
+ async query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T[]> {
45
+ const stmt = db.prepare(sql);
46
+ const rows = stmt.all(...params) as T[];
47
+ return rows;
48
+ },
49
+ async run(sql: string, params: unknown[] = []): Promise<void> {
50
+ const stmt = db.prepare(sql);
51
+ stmt.run(...params);
52
+ },
53
+ async exec(sql: string): Promise<void> {
54
+ db.exec(sql);
55
+ },
56
+ };
57
+
58
+ const store = new SqlSessionStore(driver, config);
59
+ await store.migrate();
60
+ return store;
61
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Session management types and interfaces
3
+ */
4
+
5
+ import type { EntityId } from '../core/types.js';
6
+ import type { Message } from '../llm/types.js';
7
+
8
+ /**
9
+ * Unique session identifier
10
+ */
11
+ export type SessionId = string;
12
+
13
+ /**
14
+ * Session state
15
+ */
16
+ export enum SessionState {
17
+ ACTIVE = 'active',
18
+ PAUSED = 'paused',
19
+ COMPLETED = 'completed',
20
+ EXPIRED = 'expired',
21
+ }
22
+
23
+ /**
24
+ * Session metadata
25
+ */
26
+ export interface SessionMetadata {
27
+ readonly title?: string;
28
+ readonly description?: string;
29
+ readonly tags?: string[];
30
+ readonly custom?: Record<string, unknown>;
31
+ }
32
+
33
+ /**
34
+ * Session entry representing a conversation session
35
+ */
36
+ export interface Session {
37
+ readonly id: SessionId;
38
+ readonly agentId: EntityId;
39
+ readonly userId?: string;
40
+ readonly state: SessionState;
41
+ readonly messages: Message[];
42
+ readonly metadata: SessionMetadata;
43
+ readonly context: Record<string, unknown>;
44
+ readonly createdAt: Date;
45
+ readonly updatedAt: Date;
46
+ readonly expiresAt?: Date;
47
+ }
48
+
49
+ /**
50
+ * Run/execution entry within a session
51
+ */
52
+ export interface SessionRun {
53
+ readonly id: string;
54
+ readonly sessionId: SessionId;
55
+ readonly agentId: EntityId;
56
+ readonly startTime: Date;
57
+ readonly endTime?: Date;
58
+ readonly status: 'running' | 'completed' | 'failed' | 'interrupted';
59
+ readonly steps: number;
60
+ readonly result?: unknown;
61
+ readonly error?: string;
62
+ }
63
+
64
+ /**
65
+ * Configuration for session store
66
+ */
67
+ export interface SessionStoreConfig {
68
+ readonly defaultTtlMs?: number;
69
+ readonly maxSessionsPerAgent?: number;
70
+ readonly maxMessagesPerSession?: number;
71
+ }
72
+
73
+ /**
74
+ * Query options for session retrieval
75
+ */
76
+ export interface SessionQuery {
77
+ readonly agentId?: EntityId;
78
+ readonly userId?: string;
79
+ readonly state?: SessionState;
80
+ readonly limit?: number;
81
+ readonly before?: Date;
82
+ readonly after?: Date;
83
+ }
84
+
85
+ /**
86
+ * Session store interface for persisting conversation and run state
87
+ */
88
+ export interface SessionStore {
89
+ /**
90
+ * Create a new session
91
+ */
92
+ create(session: Omit<Session, 'id' | 'createdAt' | 'updatedAt'>): Promise<Session>;
93
+
94
+ /**
95
+ * Get a session by ID
96
+ */
97
+ get(sessionId: SessionId): Promise<Session | null>;
98
+
99
+ /**
100
+ * Update an existing session
101
+ */
102
+ update(sessionId: SessionId, updates: Partial<Omit<Session, 'id' | 'createdAt'>>): Promise<Session>;
103
+
104
+ /**
105
+ * Delete a session
106
+ */
107
+ delete(sessionId: SessionId): Promise<boolean>;
108
+
109
+ /**
110
+ * List sessions matching query
111
+ */
112
+ list(query?: SessionQuery): Promise<Session[]>;
113
+
114
+ /**
115
+ * Add a message to a session
116
+ */
117
+ addMessage(sessionId: SessionId, message: Message): Promise<Session>;
118
+
119
+ /**
120
+ * Get messages from a session
121
+ */
122
+ getMessages(sessionId: SessionId): Promise<Message[]>;
123
+
124
+ /**
125
+ * Clear messages from a session
126
+ */
127
+ clearMessages(sessionId: SessionId): Promise<Session>;
128
+
129
+ /**
130
+ * Set session context data
131
+ */
132
+ setContext(sessionId: SessionId, key: string, value: unknown): Promise<Session>;
133
+
134
+ /**
135
+ * Get session context data
136
+ */
137
+ getContext(sessionId: SessionId, key: string): Promise<unknown>;
138
+
139
+ /**
140
+ * Record a run within a session
141
+ */
142
+ recordRun(run: Omit<SessionRun, 'id'>): Promise<SessionRun>;
143
+
144
+ /**
145
+ * Get runs for a session
146
+ */
147
+ getRuns(sessionId: SessionId): Promise<SessionRun[]>;
148
+
149
+ /**
150
+ * Clean up expired sessions
151
+ */
152
+ cleanup(): Promise<number>;
153
+ }