@projectaria/cf-agents 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.
package/README.md ADDED
@@ -0,0 +1,345 @@
1
+ # @projectaria/cf-agents
2
+
3
+ ARIA integration for Cloudflare Workers with Durable Objects. Build stateful AI agents with persistent memory, session management, and multi-turn conversations.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @projectaria/cf-agents agents @cloudflare/ai-chat ai
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Create Your Agent
14
+
15
+ ```typescript
16
+ // src/agent.ts
17
+ import { AriaAgent } from "@projectaria/cf-agents";
18
+ import { createAgent } from "@projectaria/aria-agents";
19
+ import { openai } from "@ai-sdk/openai";
20
+
21
+ export class MyAssistant extends AriaAgent {
22
+ // Create an ARIA agent with your configuration
23
+ private ariaAgent = createAgent({
24
+ id: "assistant",
25
+ name: "My Assistant",
26
+ instructions: "You are a helpful assistant that remembers user preferences.",
27
+ model: openai("gpt-4o"),
28
+ });
29
+
30
+ // Handle incoming chat messages
31
+ async onChatMessage(onFinish: () => void) {
32
+ // Get the current session with message history
33
+ const session = this.getSession();
34
+ const lastMessage = session.messages[session.messages.length - 1];
35
+
36
+ if (!lastMessage) {
37
+ return;
38
+ }
39
+
40
+ // Run the ARIA agent with automatic memory persistence
41
+ const result = await this.runAriaAgent(this.ariaAgent, lastMessage.content);
42
+
43
+ // Call onFinish to signal completion
44
+ onFinish();
45
+
46
+ // Return response (for HTTP) or it's already sent via WebSocket
47
+ return new Response(result.text);
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### 2. Configure Your Worker
53
+
54
+ ```typescript
55
+ // src/index.ts
56
+ import { routeAgentRequest } from "agents";
57
+ import { MyAssistant } from "./agent";
58
+
59
+ export { MyAssistant };
60
+
61
+ export default {
62
+ async fetch(request: Request, env: Env): Promise<Response> {
63
+ // Route requests to your agent
64
+ return (
65
+ (await routeAgentRequest(request, env)) ||
66
+ new Response("Not found", { status: 404 })
67
+ );
68
+ },
69
+ };
70
+ ```
71
+
72
+ ### 3. Configure Wrangler
73
+
74
+ ```jsonc
75
+ // wrangler.jsonc
76
+ {
77
+ "name": "my-assistant",
78
+ "main": "src/index.ts",
79
+ "compatibility_date": "2025-02-11",
80
+ "compatibility_flags": ["nodejs_compat"],
81
+ "durable_objects": {
82
+ "bindings": [
83
+ {
84
+ "name": "MyAssistant",
85
+ "class_name": "MyAssistant"
86
+ }
87
+ ]
88
+ },
89
+ "migrations": [
90
+ {
91
+ "tag": "v1",
92
+ "new_sqlite_classes": ["MyAssistant"]
93
+ }
94
+ ]
95
+ }
96
+ ```
97
+
98
+ ### 4. Deploy
99
+
100
+ ```bash
101
+ npx wrangler deploy
102
+ ```
103
+
104
+ ## Features
105
+
106
+ ### Memory Primitives
107
+
108
+ AriaAgent provides three levels of memory:
109
+
110
+ | Memory Type | Scope | Use Case |
111
+ |-------------|-------|----------|
112
+ | **Session** | Current conversation | Message history, flow state |
113
+ | **State** | Working memory | Shopping cart, form data |
114
+ | **Memory** | Cross-session | User preferences, learned facts |
115
+
116
+ ### Working Memory (Session-scoped)
117
+
118
+ ```typescript
119
+ class MyAgent extends AriaAgent {
120
+ async onChatMessage(onFinish) {
121
+ // Store data for current session
122
+ this.setWorkingMemory("cart", { items: ["item1", "item2"] });
123
+
124
+ // Retrieve working memory
125
+ const memory = this.getWorkingMemory();
126
+ console.log(memory.cart); // { items: ["item1", "item2"] }
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### Cross-Session Memory
132
+
133
+ ```typescript
134
+ class MyAgent extends AriaAgent {
135
+ async onChatMessage(onFinish) {
136
+ // Store a preference that persists across sessions
137
+ this.storeMemory({
138
+ key: "user:theme",
139
+ value: { theme: "dark", fontSize: "large" },
140
+ type: "preference",
141
+ });
142
+
143
+ // Search memories
144
+ const results = this.searchMemories({
145
+ query: "theme",
146
+ types: ["preference"],
147
+ limit: 5,
148
+ });
149
+ }
150
+ }
151
+ ```
152
+
153
+ ### Flow Orchestration
154
+
155
+ ```typescript
156
+ import { createFlow } from "@projectaria/aria-agents";
157
+
158
+ class MyAgent extends AriaAgent {
159
+ private orderFlow = createFlow({
160
+ id: "order-flow",
161
+ nodes: [
162
+ { id: "collect-items", ... },
163
+ { id: "confirm-order", ... },
164
+ { id: "payment", ... },
165
+ ],
166
+ });
167
+
168
+ constructor(ctx, env) {
169
+ super(ctx, env);
170
+ this.registerFlow(this.orderFlow);
171
+ }
172
+ }
173
+ ```
174
+
175
+ ## API Reference
176
+
177
+ ### AriaAgent Class
178
+
179
+ ```typescript
180
+ class AriaAgent extends AIChatAgent<AriaEnv, AriaSessionState> {
181
+ // Session Management
182
+ getSession(): AriaSession
183
+
184
+ // Working Memory
185
+ getWorkingMemory(): WorkingMemory
186
+ setWorkingMemory(key: string, value: unknown): void
187
+ clearWorkingMemory(): void
188
+
189
+ // Cross-Session Memory
190
+ storeMemory(memory: Omit<AriaMemory, "id" | ...>): string
191
+ searchMemories(query: MemorySearchQuery): MemorySearchResult[]
192
+
193
+ // ARIA Integration
194
+ runAriaAgent(agent, input, options?): Promise<{ text: string; session: AgentSession }>
195
+ streamAriaAgent(agent, input, options?): AsyncIterable<string>
196
+
197
+ // Flow Orchestration
198
+ registerFlow(flow: FlowDefinition): void
199
+ transitionFlow(flowId: string, toNodeId: string): void
200
+ }
201
+ ```
202
+
203
+ ## Connecting from Client
204
+
205
+ ### Using React
206
+
207
+ ```tsx
208
+ import { useAgentChat } from "@cloudflare/ai-chat/react";
209
+
210
+ function Chat() {
211
+ const { messages, input, handleInputChange, handleSubmit } = useAgentChat({
212
+ agent: "my-assistant",
213
+ });
214
+
215
+ return (
216
+ <div>
217
+ {messages.map((m) => (
218
+ <div key={m.id}>{m.content}</div>
219
+ ))}
220
+ <form onSubmit={handleSubmit}>
221
+ <input value={input} onChange={handleInputChange} />
222
+ <button type="submit">Send</button>
223
+ </form>
224
+ </div>
225
+ );
226
+ }
227
+ ```
228
+
229
+ ### Using WebSocket
230
+
231
+ ```typescript
232
+ const ws = new WebSocket("wss://your-worker.workers.dev/agents/my-assistant/session-123");
233
+
234
+ ws.onopen = () => {
235
+ ws.send(JSON.stringify({
236
+ type: "cf.agent.chat.request",
237
+ init: {
238
+ method: "POST",
239
+ body: JSON.stringify({
240
+ messages: [{ role: "user", content: "Hello!" }]
241
+ })
242
+ }
243
+ }));
244
+ };
245
+
246
+ ws.onmessage = (event) => {
247
+ const data = JSON.parse(event.data);
248
+ console.log("Response:", data);
249
+ };
250
+ ```
251
+
252
+ ### Using HTTP
253
+
254
+ ```typescript
255
+ const response = await fetch("https://your-worker.workers.dev/agents/my-assistant/session-123", {
256
+ method: "POST",
257
+ headers: { "Content-Type": "application/json" },
258
+ body: JSON.stringify({
259
+ messages: [{ role: "user", content: "Hello!" }]
260
+ })
261
+ });
262
+ ```
263
+
264
+ ## Environment Configuration
265
+
266
+ ```typescript
267
+ // src/types.ts
268
+ interface Env {
269
+ MyAssistant: DurableObjectNamespace;
270
+ OPENAI_API_KEY: string;
271
+ }
272
+ ```
273
+
274
+ ```toml
275
+ # wrangler.toml (secrets)
276
+ [vars]
277
+ # Set via: npx wrangler secret put OPENAI_API_KEY
278
+ ```
279
+
280
+ ## Complete Example
281
+
282
+ ```typescript
283
+ // src/shopping-assistant.ts
284
+ import { AriaAgent } from "@projectaria/cf-agents";
285
+ import { createAgent } from "@projectaria/aria-agents";
286
+ import { openai } from "@ai-sdk/openai";
287
+ import { tool } from "ai";
288
+ import { z } from "zod";
289
+
290
+ export class ShoppingAssistant extends AriaAgent {
291
+ private agent = createAgent({
292
+ id: "shopping-assistant",
293
+ name: "Shopping Assistant",
294
+ instructions: `You are a helpful shopping assistant.
295
+ You remember user preferences and can help them find products.
296
+ Use the cart tools to manage their shopping cart.`,
297
+ model: openai("gpt-4o"),
298
+ tools: {
299
+ addToCart: tool({
300
+ description: "Add an item to the cart",
301
+ parameters: z.object({
302
+ item: z.string(),
303
+ quantity: z.number().default(1),
304
+ }),
305
+ execute: async ({ item, quantity }) => {
306
+ const cart = this.getWorkingMemory().cart || [];
307
+ cart.push({ item, quantity });
308
+ this.setWorkingMemory("cart", cart);
309
+ return { success: true, cart };
310
+ },
311
+ }),
312
+ viewCart: tool({
313
+ description: "View the current cart",
314
+ parameters: z.object({}),
315
+ execute: async () => {
316
+ return this.getWorkingMemory().cart || [];
317
+ },
318
+ }),
319
+ },
320
+ });
321
+
322
+ async onChatMessage(onFinish: () => void) {
323
+ const session = this.getSession();
324
+ const lastMessage = session.messages[session.messages.length - 1];
325
+
326
+ if (!lastMessage) return;
327
+
328
+ // Check for returning user preferences
329
+ const prefs = this.searchMemories({
330
+ types: ["preference"],
331
+ limit: 5,
332
+ });
333
+
334
+ // Run agent with context
335
+ const result = await this.runAriaAgent(this.agent, lastMessage.content);
336
+
337
+ onFinish();
338
+ return new Response(result.text);
339
+ }
340
+ }
341
+ ```
342
+
343
+ ## License
344
+
345
+ MIT
@@ -0,0 +1,173 @@
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 { type AgentContext } from "agents";
16
+ import type { StreamTextOnFinishCallback, ToolSet } from "ai";
17
+ import type { AriaEnv, AriaMemory, AriaSession, AriaSessionState, FlowTransition, MemorySearchQuery, MemorySearchResult, WorkingMemory } from "./types";
18
+ /**
19
+ * ARIA Agent extending AIChatAgent
20
+ *
21
+ * Provides:
22
+ * - Session management with conversation history
23
+ * - State management (working memory) for session-local data
24
+ * - Memory layer for cross-session knowledge
25
+ * - Flow orchestration integration
26
+ * - Multi-turn conversation support
27
+ */
28
+ export declare class AriaAgent extends AIChatAgent<AriaEnv, AriaSessionState> {
29
+ private config;
30
+ private flowDefinitions;
31
+ constructor(ctx: AgentContext, env: AriaEnv);
32
+ /**
33
+ * Initialize ARIA-specific database tables
34
+ */
35
+ private initializeTables;
36
+ /**
37
+ * Initial state when no session exists
38
+ */
39
+ initialState: AriaSessionState;
40
+ /**
41
+ * Get the current session
42
+ * Session = Current conversation thread with chronological messages
43
+ */
44
+ getSession(): AriaSession;
45
+ /**
46
+ * Get session creation time from storage
47
+ */
48
+ private getCreatedAt;
49
+ /**
50
+ * Record a session event for tracking
51
+ */
52
+ private recordSessionEvent;
53
+ /**
54
+ * Get working memory (state within current conversation)
55
+ * Examples: shopping cart items, user preferences mentioned in this session
56
+ */
57
+ getWorkingMemory(): WorkingMemory;
58
+ /**
59
+ * Set a value in working memory
60
+ */
61
+ setWorkingMemory(key: string, value: unknown): void;
62
+ /**
63
+ * Clear all working memory
64
+ */
65
+ clearWorkingMemory(): void;
66
+ /**
67
+ * Store a memory for cross-session retrieval
68
+ * Memory = Searchable, cross-session information (knowledge base)
69
+ */
70
+ storeMemory(memory: Omit<AriaMemory, "id" | "createdAt" | "lastAccessedAt" | "accessCount">): string;
71
+ /**
72
+ * Search memory by query
73
+ * Returns relevant memories across all sessions
74
+ */
75
+ searchMemories(query: MemorySearchQuery): MemorySearchResult[];
76
+ /**
77
+ * Get a specific memory by key
78
+ */
79
+ getMemory(key: string): AriaMemory | null;
80
+ /**
81
+ * Update memory access (increments access count and updates timestamp)
82
+ */
83
+ private updateMemoryAccess;
84
+ /**
85
+ * Clean up old memories based on retention policy
86
+ */
87
+ cleanupOldMemories(): void;
88
+ /**
89
+ * Register a flow definition
90
+ */
91
+ registerFlow(flow: import("@projectaria/aria-agents").FlowDefinition): void;
92
+ /**
93
+ * Record a flow transition
94
+ */
95
+ recordFlowTransition(flowId: string, fromNodeId: string | null, toNodeId: string, metadata?: Record<string, unknown>): void;
96
+ /**
97
+ * Get flow transition history
98
+ */
99
+ getFlowHistory(flowId?: string, limit?: number): FlowTransition[];
100
+ /**
101
+ * Handle incoming chat messages
102
+ * This is where ARIA's flow orchestration would be integrated
103
+ */
104
+ onChatMessage(onFinish: StreamTextOnFinishCallback<ToolSet>, options?: {
105
+ abortSignal?: AbortSignal;
106
+ clientTools?: Array<{
107
+ name: string;
108
+ description?: string;
109
+ parameters?: import("ai").JSONSchema7;
110
+ }>;
111
+ }): Promise<Response | undefined>;
112
+ /**
113
+ * Build system prompt with conversation context
114
+ */
115
+ private buildSystemPrompt;
116
+ /**
117
+ * Run an ARIA agent with persistence
118
+ * This method allows you to use ARIA's createAgent() with persistent memory
119
+ *
120
+ * @param agent - The ARIA agent created via createAgent()
121
+ * @param input - The user input
122
+ * @returns The agent response with persisted session state
123
+ */
124
+ runAriaAgent(agent: import("@projectaria/aria-agents").Agent, input: string): Promise<{
125
+ text: string;
126
+ session: import("@projectaria/aria-agents").AgentSession;
127
+ }>;
128
+ /**
129
+ * Stream an ARIA agent response with persistence
130
+ *
131
+ * @param agent - The ARIA agent created via createAgent()
132
+ * @param input - The user input
133
+ * @returns Stream result with session
134
+ */
135
+ streamAriaAgent(agent: import("@projectaria/aria-agents").Agent, input: string): Promise<{
136
+ fullStream: AsyncIterable<import("@projectaria/aria-agents").AriaStreamPart>;
137
+ textStream: AsyncIterable<string>;
138
+ usage?: Promise<import("ai").LanguageModelUsage | undefined>;
139
+ }>;
140
+ /**
141
+ * Build ARIA agent prompt with context from session and memories
142
+ */
143
+ private buildAriaAgentPrompt;
144
+ /**
145
+ * Extract and store memories from ARIA agent conversation
146
+ */
147
+ private extractAndStoreMemories;
148
+ /**
149
+ * Extract preference key from message content
150
+ */
151
+ private extractPreferenceKey;
152
+ /**
153
+ * Extract fact key from message content
154
+ */
155
+ private extractFactKey;
156
+ /**
157
+ * Called when agent starts
158
+ */
159
+ onStart(): Promise<void>;
160
+ /**
161
+ * Called when a client connects
162
+ */
163
+ onConnect(connection: import("agents").Connection, ctx: import("agents").ConnectionContext): Promise<void>;
164
+ /**
165
+ * Cleanup when destroyed
166
+ */
167
+ destroy(): Promise<void>;
168
+ /**
169
+ * Handle HTTP requests
170
+ */
171
+ onRequest(request: Request): Promise<Response>;
172
+ }
173
+ //# sourceMappingURL=AriaAgent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AriaAgent.d.ts","sourceRoot":"","sources":["../src/AriaAgent.ts"],"names":[],"mappings":"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"}