@projectaria/cf-agents 0.1.0 → 0.1.2

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 (38) hide show
  1. package/README.md +359 -202
  2. package/dist/AriaCFChatAgent.d.ts +37 -0
  3. package/dist/AriaCFChatAgent.d.ts.map +1 -0
  4. package/dist/AriaCFChatAgent.js +200 -0
  5. package/dist/AriaCFChatAgent.js.map +1 -0
  6. package/dist/CloudflareSessionStore.d.ts +37 -0
  7. package/dist/CloudflareSessionStore.d.ts.map +1 -0
  8. package/dist/CloudflareSessionStore.js +101 -0
  9. package/dist/CloudflareSessionStore.js.map +1 -0
  10. package/dist/aria-to-ui-stream.d.ts +21 -0
  11. package/dist/aria-to-ui-stream.d.ts.map +1 -0
  12. package/dist/aria-to-ui-stream.js +118 -0
  13. package/dist/aria-to-ui-stream.js.map +1 -0
  14. package/dist/index.d.ts +25 -22
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +21 -23
  17. package/dist/index.js.map +1 -1
  18. package/dist/message-format.d.ts +39 -0
  19. package/dist/message-format.d.ts.map +1 -0
  20. package/dist/message-format.js +124 -0
  21. package/dist/message-format.js.map +1 -0
  22. package/dist/types.d.ts +59 -146
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/types.js +8 -7
  25. package/dist/types.js.map +1 -1
  26. package/package.json +3 -2
  27. package/dist/AriaAgent.d.ts +0 -173
  28. package/dist/AriaAgent.d.ts.map +0 -1
  29. package/dist/AriaAgent.js +0 -735
  30. package/dist/AriaAgent.js.map +0 -1
  31. package/dist/aria-agent-integration.d.ts +0 -52
  32. package/dist/aria-agent-integration.d.ts.map +0 -1
  33. package/dist/aria-agent-integration.js +0 -186
  34. package/dist/aria-agent-integration.js.map +0 -1
  35. package/dist/message-converter.d.ts +0 -48
  36. package/dist/message-converter.d.ts.map +0 -1
  37. package/dist/message-converter.js +0 -138
  38. package/dist/message-converter.js.map +0 -1
package/dist/AriaAgent.js DELETED
@@ -1,735 +0,0 @@
1
- /**
2
- * ARIA Agent - Cloudflare Agents integration with proper memory primitives
3
- *
4
- * Memory Architecture:
5
- * 1. Session: Current conversation thread with chronological messages
6
- * 2. State: Temporary data within the current conversation (working memory)
7
- * 3. Memory: Searchable, cross-session information (knowledge base)
8
- *
9
- * AI SDK 6.0 Message Types (matching agents@0.3.3):
10
- * - UIMessage: Format with UI metadata (id, role, parts)
11
- * - ModelMessage: Format expected by LLM models
12
- * - convertToModelMessages: Converts UIMessage[] to ModelMessage[]
13
- */
14
- import { AIChatAgent } from "agents/ai-chat-agent";
15
- import { nanoid } from "nanoid";
16
- import { batchAriaToChat, batchChatToAria, extractConversationSummary, } from "./message-converter";
17
- /**
18
- * Default configuration
19
- */
20
- const DEFAULT_CONFIG = {
21
- historyLimit: 50,
22
- enableMemory: true,
23
- memoryRetentionMs: 30 * 24 * 60 * 60 * 1000, // 30 days
24
- trackTransitions: true,
25
- generateSessionId: () => crypto.randomUUID(),
26
- };
27
- /**
28
- * ARIA Agent extending AIChatAgent
29
- *
30
- * Provides:
31
- * - Session management with conversation history
32
- * - State management (working memory) for session-local data
33
- * - Memory layer for cross-session knowledge
34
- * - Flow orchestration integration
35
- * - Multi-turn conversation support
36
- */
37
- export class AriaAgent extends AIChatAgent {
38
- config;
39
- flowDefinitions;
40
- constructor(ctx, env) {
41
- super(ctx, env);
42
- this.config = { ...DEFAULT_CONFIG };
43
- this.flowDefinitions = new Map();
44
- // Create ARIA-specific tables
45
- this.initializeTables();
46
- }
47
- /**
48
- * Initialize ARIA-specific database tables
49
- */
50
- initializeTables() {
51
- // Memory table for cross-session knowledge
52
- this.sql `
53
- create table if not exists aria_memory (
54
- id text primary key,
55
- session_id text,
56
- key text not null,
57
- value text not null,
58
- type text not null check(type in ('preference', 'fact', 'context', 'entity', 'custom')),
59
- created_at integer default (unixepoch()),
60
- last_accessed_at integer default (unixepoch()),
61
- access_count integer default 1,
62
- embedding text,
63
- metadata text
64
- )
65
- `;
66
- this.sql `create index if not exists idx_memory_session
67
- on aria_memory(session_id)`;
68
- this.sql `create index if not exists idx_memory_key
69
- on aria_memory(key)`;
70
- this.sql `create index if not exists idx_memory_type
71
- on aria_memory(type)`;
72
- // Flow transitions table for tracking execution history
73
- this.sql `
74
- create table if not exists aria_flow_transitions (
75
- id text primary key,
76
- flow_id text not null,
77
- from_node_id text,
78
- to_node_id text not null,
79
- transitioned_at integer default (unixepoch()),
80
- metadata text
81
- )
82
- `;
83
- this.sql `create index if not exists idx_flow_transitions_flow
84
- on aria_flow_transitions(flow_id, transitioned_at)`;
85
- // Session history table (in addition to AIChatAgent's messages)
86
- this.sql `
87
- create table if not exists aria_session_events (
88
- id text primary key,
89
- event_type text not null,
90
- event_data text,
91
- occurred_at integer default (unixepoch())
92
- )
93
- `;
94
- }
95
- /**
96
- * Initial state when no session exists
97
- */
98
- initialState = {
99
- workingMemory: {},
100
- activeFlowId: undefined,
101
- activeNodeId: undefined,
102
- historyLimit: DEFAULT_CONFIG.historyLimit,
103
- };
104
- // ============================================================
105
- // SESSION MANAGEMENT
106
- // ============================================================
107
- /**
108
- * Get the current session
109
- * Session = Current conversation thread with chronological messages
110
- */
111
- getSession() {
112
- const state = this.state;
113
- return {
114
- id: this.name,
115
- messages: batchChatToAria(this.messages),
116
- activeFlow: state.activeFlowId && state.activeNodeId
117
- ? {
118
- flowId: state.activeFlowId,
119
- currentNodeId: state.activeNodeId,
120
- enteredAt: Date.now(),
121
- }
122
- : undefined,
123
- historyLimit: state.historyLimit,
124
- createdAt: this.getCreatedAt(),
125
- updatedAt: Date.now(),
126
- };
127
- }
128
- /**
129
- * Get session creation time from storage
130
- */
131
- getCreatedAt() {
132
- const row = this.sql `
133
- select min(created_at) as created_at from aria_session_events
134
- `;
135
- return row?.[0]?.created_at || Date.now();
136
- }
137
- /**
138
- * Record a session event for tracking
139
- */
140
- recordSessionEvent(eventType, eventData) {
141
- this.sql `
142
- insert into aria_session_events (id, event_type, event_data)
143
- values (${nanoid()}, ${eventType}, ${JSON.stringify(eventData)})
144
- `;
145
- }
146
- // ============================================================
147
- // STATE MANAGEMENT (Session-Local Data)
148
- // ============================================================
149
- /**
150
- * Get working memory (state within current conversation)
151
- * Examples: shopping cart items, user preferences mentioned in this session
152
- */
153
- getWorkingMemory() {
154
- return this.state.workingMemory || {};
155
- }
156
- /**
157
- * Set a value in working memory
158
- */
159
- setWorkingMemory(key, value) {
160
- const current = this.getWorkingMemory();
161
- this.setState({
162
- ...this.state,
163
- workingMemory: {
164
- ...current,
165
- [key]: value,
166
- },
167
- });
168
- }
169
- /**
170
- * Clear all working memory
171
- */
172
- clearWorkingMemory() {
173
- this.setState({
174
- ...this.state,
175
- workingMemory: {},
176
- });
177
- }
178
- // ============================================================
179
- // MEMORY LAYER (Cross-Session Knowledge)
180
- // ============================================================
181
- /**
182
- * Store a memory for cross-session retrieval
183
- * Memory = Searchable, cross-session information (knowledge base)
184
- */
185
- storeMemory(memory) {
186
- const id = nanoid();
187
- const now = Date.now();
188
- this.sql `
189
- insert into aria_memory (
190
- id, session_id, key, value, type,
191
- created_at, last_accessed_at, access_count, metadata
192
- )
193
- values (
194
- ${id},
195
- ${memory.sessionId ?? null},
196
- ${memory.key},
197
- ${JSON.stringify(memory.value)},
198
- ${memory.type},
199
- ${Math.floor(now / 1000)},
200
- ${Math.floor(now / 1000)},
201
- 1,
202
- ${memory.metadata ? JSON.stringify(memory.metadata) : null}
203
- )
204
- `;
205
- return id;
206
- }
207
- /**
208
- * Search memory by query
209
- * Returns relevant memories across all sessions
210
- */
211
- searchMemories(query) {
212
- const limit = query.limit || 10;
213
- let rows = [];
214
- // Use different queries based on search criteria
215
- // Note: SQLite tagged template literals don't support dynamic queries
216
- if (query.query && query.types && query.types.length > 0) {
217
- // Search with text and type filter
218
- const typeList = query.types.join(",");
219
- const searchPattern = `%${query.query}%`;
220
- rows = this.sql `
221
- select * from aria_memory
222
- where key like ${searchPattern}
223
- and type in (${typeList})
224
- order by access_count desc, last_accessed_at desc
225
- limit ${limit}
226
- ` || [];
227
- }
228
- else if (query.query) {
229
- // Search with text only
230
- const searchPattern = `%${query.query}%`;
231
- rows = this.sql `
232
- select * from aria_memory
233
- where key like ${searchPattern}
234
- order by access_count desc, last_accessed_at desc
235
- limit ${limit}
236
- ` || [];
237
- }
238
- else if (query.types && query.types.length > 0) {
239
- // Search with type filter only
240
- const typeList = query.types.join(",");
241
- rows = this.sql `
242
- select * from aria_memory
243
- where type in (${typeList})
244
- order by access_count desc, last_accessed_at desc
245
- limit ${limit}
246
- ` || [];
247
- }
248
- else {
249
- // Get all memories
250
- rows = this.sql `
251
- select * from aria_memory
252
- order by access_count desc, last_accessed_at desc
253
- limit ${limit}
254
- ` || [];
255
- }
256
- return rows.map((row) => ({
257
- memory: {
258
- id: row.id,
259
- sessionId: row.session_id,
260
- key: row.key,
261
- value: JSON.parse(row.value),
262
- type: row.type,
263
- createdAt: row.created_at * 1000,
264
- lastAccessedAt: row.last_accessed_at * 1000,
265
- accessCount: row.access_count,
266
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
267
- },
268
- score: Math.min(1, row.access_count / 10), // Simple relevance score
269
- relevance: row.access_count > 5 ? "high" : row.access_count > 2 ? "medium" : "low",
270
- }));
271
- }
272
- /**
273
- * Get a specific memory by key
274
- */
275
- getMemory(key) {
276
- const rows = this.sql `
277
- select * from aria_memory where key = ${key} limit 1
278
- `;
279
- if (!rows || rows.length === 0) {
280
- return null;
281
- }
282
- return {
283
- id: key,
284
- sessionId: null,
285
- key,
286
- value: JSON.parse(rows[0].value),
287
- type: rows[0].type,
288
- createdAt: Date.now(),
289
- lastAccessedAt: Date.now(),
290
- accessCount: 1,
291
- };
292
- }
293
- /**
294
- * Update memory access (increments access count and updates timestamp)
295
- */
296
- updateMemoryAccess(key) {
297
- this.sql `
298
- update aria_memory
299
- set access_count = access_count + 1, last_accessed_at = ${Math.floor(Date.now() / 1000)}
300
- where key = ${key}
301
- `;
302
- }
303
- /**
304
- * Clean up old memories based on retention policy
305
- */
306
- cleanupOldMemories() {
307
- const cutoff = Math.floor((Date.now() - this.config.memoryRetentionMs) / 1000);
308
- this.sql `delete from aria_memory where created_at < ${cutoff}`;
309
- }
310
- // ============================================================
311
- // FLOW ORCHESTRATION
312
- // ============================================================
313
- /**
314
- * Register a flow definition
315
- */
316
- registerFlow(flow) {
317
- this.flowDefinitions.set(flow.id, flow);
318
- }
319
- /**
320
- * Record a flow transition
321
- */
322
- recordFlowTransition(flowId, fromNodeId, toNodeId, metadata) {
323
- if (!this.config.trackTransitions) {
324
- return;
325
- }
326
- this.sql `
327
- insert into aria_flow_transitions (id, flow_id, from_node_id, to_node_id, metadata)
328
- values (${nanoid()}, ${flowId}, ${fromNodeId}, ${toNodeId}, ${metadata ? JSON.stringify(metadata) : null})
329
- `;
330
- this.setState({
331
- ...this.state,
332
- activeFlowId: flowId,
333
- activeNodeId: toNodeId,
334
- });
335
- }
336
- /**
337
- * Get flow transition history
338
- */
339
- getFlowHistory(flowId, limit = 100) {
340
- let query = "select * from aria_flow_transitions";
341
- if (flowId) {
342
- query += ` where flow_id = ${flowId}`;
343
- }
344
- query += ` order by transitioned_at desc limit ${limit}`;
345
- const rows = this.sql `
346
- ${query}
347
- `;
348
- return (rows || []).map((row) => ({
349
- id: row.id,
350
- flowId: row.flow_id,
351
- fromNodeId: row.from_node_id,
352
- toNodeId: row.to_node_id,
353
- transitionedAt: row.transitioned_at * 1000,
354
- metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
355
- }));
356
- }
357
- // ============================================================
358
- // MESSAGE HANDLING
359
- // ============================================================
360
- /**
361
- * Handle incoming chat messages
362
- * This is where ARIA's flow orchestration would be integrated
363
- */
364
- async onChatMessage(onFinish, options) {
365
- // Record session event
366
- this.recordSessionEvent("message_received", {
367
- messageCount: this.messages.length,
368
- workingMemoryKeys: Object.keys(this.getWorkingMemory()),
369
- });
370
- // Get current session
371
- const session = this.getSession();
372
- // Get conversation context from memory
373
- const relevantMemories = this.searchMemories({
374
- query: session.messages[session.messages.length - 1]?.content || "",
375
- limit: 5,
376
- types: ["context", "entity", "preference"],
377
- });
378
- // Build system prompt with context
379
- const systemPrompt = this.buildSystemPrompt(session, relevantMemories);
380
- // Here you would integrate ARIA's flow orchestration
381
- // For now, return a basic response
382
- // TODO: Integrate with @projectaria/aria VoltRuntime
383
- // Example: Save learned facts to memory
384
- const summary = extractConversationSummary(session.messages);
385
- for (const topic of summary.topics.slice(0, 3)) {
386
- this.storeMemory({
387
- sessionId: session.id,
388
- key: topic,
389
- value: { mentioned: true, count: 1 },
390
- type: "context",
391
- });
392
- }
393
- // Call parent implementation
394
- return super.onChatMessage(onFinish, options);
395
- }
396
- /**
397
- * Build system prompt with conversation context
398
- */
399
- buildSystemPrompt(session, memories) {
400
- const parts = [
401
- "You are a helpful AI assistant.",
402
- "You have access to conversation history and can recall information from previous conversations.",
403
- ];
404
- // Add active flow context
405
- if (session.activeFlow) {
406
- parts.push(`\nCurrent flow: ${session.activeFlow.flowId} (node: ${session.activeFlow.currentNodeId})`);
407
- }
408
- // Add working memory context
409
- const workingMemory = this.getWorkingMemory();
410
- if (Object.keys(workingMemory).length > 0) {
411
- parts.push("\nCurrent session data:");
412
- for (const [key, value] of Object.entries(workingMemory)) {
413
- parts.push(` - ${key}: ${JSON.stringify(value)}`);
414
- }
415
- }
416
- // Add memory context
417
- if (memories.length > 0) {
418
- parts.push("\nRelevant information from previous conversations:");
419
- for (const memory of memories) {
420
- parts.push(` - ${memory.memory.key}: ${JSON.stringify(memory.memory.value)}`);
421
- this.updateMemoryAccess(memory.memory.key);
422
- }
423
- }
424
- return parts.join("\n");
425
- }
426
- // ============================================================
427
- // ARIA AGENT INTEGRATION
428
- // ============================================================
429
- /**
430
- * Run an ARIA agent with persistence
431
- * This method allows you to use ARIA's createAgent() with persistent memory
432
- *
433
- * @param agent - The ARIA agent created via createAgent()
434
- * @param input - The user input
435
- * @returns The agent response with persisted session state
436
- */
437
- async runAriaAgent(agent, input) {
438
- // Get current session from persistent storage
439
- const currentSession = this.getSession();
440
- // Convert to ARIA AgentSession format
441
- const ariaSession = {
442
- sessionId: currentSession.id,
443
- conversationId: currentSession.id,
444
- history: batchAriaToChat(currentSession.messages),
445
- workingMemory: this.getWorkingMemory(),
446
- context: new Map(),
447
- createdAt: new Date(currentSession.createdAt).toISOString(),
448
- updatedAt: new Date(currentSession.updatedAt).toISOString(),
449
- };
450
- // Search for relevant memories
451
- const relevantMemories = this.searchMemories({
452
- query: input,
453
- limit: 5,
454
- types: ["preference", "fact", "context", "entity"],
455
- });
456
- // Build enhanced prompt with context
457
- const prompt = this.buildAriaAgentPrompt(currentSession, relevantMemories, this.getWorkingMemory());
458
- // Run the ARIA agent
459
- // Note: systemPrompt should be passed via the agent config, not metadata
460
- const result = await agent.generateText({
461
- input,
462
- session: ariaSession,
463
- });
464
- // Persist working memory changes
465
- if (result.session) {
466
- const stateBefore = JSON.stringify(ariaSession.workingMemory);
467
- const stateAfter = JSON.stringify(result.session.workingMemory);
468
- if (stateBefore !== stateAfter) {
469
- // Merge the updated working memory into our persistent state
470
- const currentWorkingMemory = this.getWorkingMemory();
471
- const updatedWorkingMemory = {
472
- ...currentWorkingMemory,
473
- ...result.session.workingMemory,
474
- };
475
- this.setState({
476
- ...this.state,
477
- workingMemory: updatedWorkingMemory,
478
- });
479
- }
480
- // Extract and store memories from the conversation
481
- await this.extractAndStoreMemories(result.session);
482
- }
483
- return {
484
- text: result.text,
485
- session: result.session,
486
- };
487
- }
488
- /**
489
- * Stream an ARIA agent response with persistence
490
- *
491
- * @param agent - The ARIA agent created via createAgent()
492
- * @param input - The user input
493
- * @returns Stream result with session
494
- */
495
- async streamAriaAgent(agent, input) {
496
- // Get current session from persistent storage
497
- const currentSession = this.getSession();
498
- // Convert to ARIA AgentSession format
499
- const ariaSession = {
500
- sessionId: currentSession.id,
501
- conversationId: currentSession.id,
502
- history: batchAriaToChat(currentSession.messages),
503
- workingMemory: this.getWorkingMemory(),
504
- context: new Map(),
505
- createdAt: new Date(currentSession.createdAt).toISOString(),
506
- updatedAt: new Date(currentSession.updatedAt).toISOString(),
507
- };
508
- // Search for relevant memories
509
- const relevantMemories = this.searchMemories({
510
- query: input,
511
- limit: 5,
512
- types: ["preference", "fact", "context", "entity"],
513
- });
514
- // Build enhanced prompt with context
515
- const prompt = this.buildAriaAgentPrompt(currentSession, relevantMemories, this.getWorkingMemory());
516
- // Stream the ARIA agent response
517
- // Note: systemPrompt should be passed via the agent config, not metadata
518
- const result = await agent.streamText({
519
- input,
520
- session: ariaSession,
521
- });
522
- // Note: For streaming, we need to handle persistence after the stream completes
523
- // This is typically done in the onFinish callback
524
- if (result.usage) {
525
- result.usage.then(async () => {
526
- await this.extractAndStoreMemories(ariaSession);
527
- });
528
- }
529
- return {
530
- fullStream: result.fullStream,
531
- textStream: result.textStream,
532
- usage: result.usage,
533
- };
534
- }
535
- /**
536
- * Build ARIA agent prompt with context from session and memories
537
- */
538
- buildAriaAgentPrompt(session, memories, workingMemory) {
539
- const parts = ["You are a helpful AI assistant with memory."];
540
- // Add working memory/state context
541
- if (Object.keys(workingMemory).length > 0) {
542
- parts.push("\n📋 Current Session Data:");
543
- for (const [key, value] of Object.entries(workingMemory)) {
544
- parts.push(` ${key}: ${JSON.stringify(value)}`);
545
- }
546
- }
547
- // Add memories from past conversations
548
- if (memories.length > 0) {
549
- parts.push("\n💭 Relevant Information from Past Conversations:");
550
- for (const memoryResult of memories) {
551
- const { memory } = memoryResult;
552
- parts.push(` [${memory.type}] ${memory.key}: ${JSON.stringify(memory.value)}`);
553
- // Update access count for relevance tracking
554
- this.updateMemoryAccess(memory.key);
555
- }
556
- }
557
- return parts.join("\n");
558
- }
559
- /**
560
- * Extract and store memories from ARIA agent conversation
561
- */
562
- async extractAndStoreMemories(ariaSession) {
563
- const conversation = ariaSession.history;
564
- // Analyze each message for memory extraction
565
- for (const message of conversation) {
566
- if (message.role === "user") {
567
- // Extract text content
568
- const text = message.parts
569
- .filter((p) => p.type === "text")
570
- .map((p) => p.text)
571
- .join(" ");
572
- const content = text.toLowerCase();
573
- // Detect preferences
574
- if (content.includes("prefer") ||
575
- content.includes("like") ||
576
- content.includes("want")) {
577
- const prefKey = this.extractPreferenceKey(text);
578
- if (prefKey) {
579
- this.storeMemory({
580
- sessionId: ariaSession.sessionId,
581
- key: prefKey,
582
- value: { stated: text, timestamp: Date.now() },
583
- type: "preference",
584
- });
585
- }
586
- }
587
- // Detect facts
588
- if (content.includes("my name is") ||
589
- content.includes("i live in") ||
590
- content.includes("i am a")) {
591
- const factKey = this.extractFactKey(text);
592
- if (factKey) {
593
- this.storeMemory({
594
- sessionId: null, // Global memory
595
- key: factKey,
596
- value: { stated: text, timestamp: Date.now() },
597
- type: "fact",
598
- });
599
- }
600
- }
601
- }
602
- }
603
- }
604
- /**
605
- * Extract preference key from message content
606
- */
607
- extractPreferenceKey(content) {
608
- const lower = content.toLowerCase();
609
- if (lower.includes("dark mode"))
610
- return "pref:theme:dark";
611
- if (lower.includes("light mode"))
612
- return "pref:theme:light";
613
- if (lower.includes("email updates"))
614
- return "pref:email-updates";
615
- if (lower.includes("notifications"))
616
- return "pref:notifications";
617
- // Pattern matching
618
- const preferMatch = content.match(/i (?:prefer|like|want) (.+?)(?:\.|,|!|$)/i);
619
- if (preferMatch) {
620
- return `pref:custom:${preferMatch[1].trim().toLowerCase()}`;
621
- }
622
- return null;
623
- }
624
- /**
625
- * Extract fact key from message content
626
- */
627
- extractFactKey(content) {
628
- const lower = content.toLowerCase();
629
- if (lower.includes("my name is")) {
630
- const name = content.match(/name is (\w+)/i)?.[1];
631
- return name ? `fact:name:${name}` : null;
632
- }
633
- if (lower.includes("i live in")) {
634
- const location = content.match(/live in (\w+(?: \w+)*)/i)?.[1];
635
- return location ? `fact:location:${location}` : null;
636
- }
637
- if (lower.includes("i am a")) {
638
- const role = content.match(/i am a (\w+(?: \w+)*)/i)?.[1];
639
- return role ? `fact:role:${role}` : null;
640
- }
641
- return null;
642
- }
643
- // ============================================================
644
- // LIFECYCLE
645
- // ============================================================
646
- /**
647
- * Called when agent starts
648
- */
649
- async onStart() {
650
- this.recordSessionEvent("session_started", {
651
- agentName: this.name,
652
- timestamp: Date.now(),
653
- });
654
- // Cleanup old memories periodically
655
- this.cleanupOldMemories();
656
- }
657
- /**
658
- * Called when a client connects
659
- */
660
- async onConnect(connection, ctx) {
661
- this.recordSessionEvent("client_connected", {
662
- connectionId: connection.id,
663
- });
664
- return super.onConnect(connection, ctx);
665
- }
666
- /**
667
- * Cleanup when destroyed
668
- */
669
- async destroy() {
670
- // Record session end
671
- this.recordSessionEvent("session_ended", {
672
- messageCount: this.messages.length,
673
- finalWorkingMemory: this.getWorkingMemory(),
674
- });
675
- // Drop ARIA tables
676
- this.sql `drop table if exists aria_memory`;
677
- this.sql `drop table if exists aria_flow_transitions`;
678
- this.sql `drop table if exists aria_session_events`;
679
- await super.destroy();
680
- }
681
- // ============================================================
682
- // HTTP ENDPOINTS
683
- // ============================================================
684
- /**
685
- * Handle HTTP requests
686
- */
687
- async onRequest(request) {
688
- const url = new URL(request.url);
689
- // GET /session - Get current session
690
- if (url.pathname === "/session" && request.method === "GET") {
691
- return Response.json(this.getSession());
692
- }
693
- // GET /working-memory - Get working memory
694
- if (url.pathname === "/working-memory" && request.method === "GET") {
695
- return Response.json(this.getWorkingMemory());
696
- }
697
- // PUT /working-memory - Set working memory value
698
- if (url.pathname === "/working-memory" && request.method === "PUT") {
699
- const body = await request.json();
700
- this.setWorkingMemory(body.key, body.value);
701
- return Response.json({ success: true });
702
- }
703
- // GET /memory - Search memories
704
- if (url.pathname === "/memory" && request.method === "GET") {
705
- const query = url.searchParams.get("q");
706
- const type = url.searchParams.get("type");
707
- const limit = parseInt(url.searchParams.get("limit") || "10", 10);
708
- const results = this.searchMemories({
709
- query: query || undefined,
710
- types: type ? [type] : undefined,
711
- limit,
712
- });
713
- return Response.json(results);
714
- }
715
- // POST /memory - Store memory
716
- if (url.pathname === "/memory" && request.method === "POST") {
717
- const body = await request.json();
718
- const id = this.storeMemory(body);
719
- return Response.json({ id, success: true });
720
- }
721
- // GET /flow-history - Get flow transition history
722
- if (url.pathname === "/flow-history" && request.method === "GET") {
723
- const flowId = url.searchParams.get("flowId") || undefined;
724
- const limit = parseInt(url.searchParams.get("limit") || "100", 10);
725
- return Response.json(this.getFlowHistory(flowId, limit));
726
- }
727
- // GET /summary - Get conversation summary
728
- if (url.pathname === "/summary" && request.method === "GET") {
729
- const summary = extractConversationSummary(batchChatToAria(this.messages));
730
- return Response.json(summary);
731
- }
732
- return super.onRequest(request);
733
- }
734
- }
735
- //# sourceMappingURL=AriaAgent.js.map