agentnet 0.0.1 → 0.0.3

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.
@@ -0,0 +1,547 @@
1
+ import { AgentLoaderFile, Message, Bindings, NatsIO, MemoryStore, AgentClient } from "../../src/index.js";
2
+ import { v4 as uuidv4 } from 'uuid';
3
+
4
+ // Mock database of events
5
+ const mockDatabase = {
6
+ events: {
7
+ "evt-001": {
8
+ id: "evt-001",
9
+ title: "Weekly Team Meeting",
10
+ startDateTime: "2023-10-10T10:00:00",
11
+ endDateTime: "2023-10-10T11:00:00",
12
+ description: "Regular team sync to discuss project progress",
13
+ location: "Conference Room A",
14
+ participants: ["alice@example.com", "bob@example.com", "carol@example.com"],
15
+ createdBy: "alice@example.com",
16
+ createdAt: "2023-10-01T08:30:00"
17
+ },
18
+ "evt-002": {
19
+ id: "evt-002",
20
+ title: "Product Launch Planning",
21
+ startDateTime: "2023-10-12T14:00:00",
22
+ endDateTime: "2023-10-12T16:00:00",
23
+ description: "Finalize details for the upcoming product launch",
24
+ location: "Marketing Department",
25
+ participants: ["bob@example.com", "dave@example.com", "eve@example.com"],
26
+ createdBy: "bob@example.com",
27
+ createdAt: "2023-10-02T09:15:00"
28
+ },
29
+ "evt-003": {
30
+ id: "evt-003",
31
+ title: "Client Meeting - Acme Corp",
32
+ startDateTime: "2023-10-11T09:30:00",
33
+ endDateTime: "2023-10-11T10:30:00",
34
+ description: "Presentation of the new proposal",
35
+ location: "Virtual - Zoom",
36
+ participants: ["alice@example.com", "carol@example.com", "client@acmecorp.com"],
37
+ createdBy: "alice@example.com",
38
+ createdAt: "2023-10-03T14:20:00"
39
+ },
40
+ "evt-004": {
41
+ id: "evt-004",
42
+ title: "Quarterly Budget Review",
43
+ startDateTime: "2023-10-15T11:00:00",
44
+ endDateTime: "2023-10-15T12:30:00",
45
+ description: "Review of Q3 expenses and planning for Q4",
46
+ location: "Finance Conference Room",
47
+ participants: ["alice@example.com", "dave@example.com", "finance@example.com"],
48
+ createdBy: "dave@example.com",
49
+ createdAt: "2023-10-05T11:45:00"
50
+ }
51
+ },
52
+ users: {
53
+ "alice@example.com": {
54
+ name: "Alice Smith",
55
+ workingHours: { start: "09:00", end: "17:00" },
56
+ timezone: "America/New_York"
57
+ },
58
+ "bob@example.com": {
59
+ name: "Bob Johnson",
60
+ workingHours: { start: "08:00", end: "16:00" },
61
+ timezone: "America/Chicago"
62
+ },
63
+ "carol@example.com": {
64
+ name: "Carol Williams",
65
+ workingHours: { start: "10:00", end: "18:00" },
66
+ timezone: "America/Los_Angeles"
67
+ },
68
+ "dave@example.com": {
69
+ name: "Dave Brown",
70
+ workingHours: { start: "09:00", end: "17:00" },
71
+ timezone: "America/New_York"
72
+ },
73
+ "eve@example.com": {
74
+ name: "Eve Davis",
75
+ workingHours: { start: "08:30", end: "16:30" },
76
+ timezone: "America/Chicago"
77
+ }
78
+ }
79
+ };
80
+
81
+ // Helper functions for event management
82
+ function generateEventId() {
83
+ return `evt-${uuidv4().substring(0, 6)}`;
84
+ }
85
+
86
+ function formatDate(dateString) {
87
+ return new Date(dateString).toISOString().split('T')[0];
88
+ }
89
+
90
+ function parseDate(dateString) {
91
+ return new Date(dateString);
92
+ }
93
+
94
+ function isOverlapping(event1, event2) {
95
+ const start1 = new Date(event1.startDateTime);
96
+ const end1 = new Date(event1.endDateTime);
97
+ const start2 = new Date(event2.startDateTime);
98
+ const end2 = new Date(event2.endDateTime);
99
+
100
+ return (start1 < end2 && start2 < end1);
101
+ }
102
+
103
+ function getEventsInDateRange(startDate, endDate) {
104
+ const start = parseDate(startDate);
105
+ const end = parseDate(endDate);
106
+
107
+ return Object.values(mockDatabase.events).filter(event => {
108
+ const eventStart = parseDate(event.startDateTime);
109
+ return eventStart >= start && eventStart <= end;
110
+ });
111
+ }
112
+
113
+ // Set up the NATS instance for inter-agent communication
114
+ const natsIO = NatsIO();
115
+
116
+ // Main function to set up and demonstrate the event planner system
117
+ async function main() {
118
+ console.log("Loading event planner agents...");
119
+
120
+ // Load all agents from the YAML file
121
+ const agents = await AgentLoaderFile('./examples/event-planner/agents.yaml', {
122
+ bindings: { [Bindings.NatsIO]: natsIO, [Bindings.Memory]: MemoryStore() }
123
+ });
124
+
125
+ // Bind tool implementations for Planner Agent
126
+ agents.plannerAgent.tools.createEvent.bind(async (state, input) => {
127
+ const { title, startDateTime, endDateTime, description, location, participants, reminders } = input;
128
+
129
+ // Generate a new unique event ID
130
+ const eventId = generateEventId();
131
+
132
+ // Create the new event
133
+ const newEvent = {
134
+ id: eventId,
135
+ title,
136
+ startDateTime,
137
+ endDateTime,
138
+ description: description || "",
139
+ location: location || "Not specified",
140
+ participants: participants || [],
141
+ reminders: reminders || [],
142
+ createdBy: state.session?.userId || "system",
143
+ createdAt: new Date().toISOString()
144
+ };
145
+
146
+ // Add the event to the database
147
+ mockDatabase.events[eventId] = newEvent;
148
+
149
+ return {
150
+ success: true,
151
+ eventId,
152
+ message: `Event "${title}" has been created successfully.`,
153
+ event: newEvent
154
+ };
155
+ });
156
+
157
+ agents.plannerAgent.tools.listEvents.bind(async (state, input) => {
158
+ const { startDate, endDate, maxResults } = input;
159
+
160
+ // Get events in the specified date range
161
+ let events = getEventsInDateRange(startDate, endDate);
162
+
163
+ // Limit the number of results if specified
164
+ if (maxResults && events.length > maxResults) {
165
+ events = events.slice(0, maxResults);
166
+ }
167
+
168
+ return {
169
+ success: true,
170
+ count: events.length,
171
+ events: events.map(event => ({
172
+ id: event.id,
173
+ title: event.title,
174
+ startDateTime: event.startDateTime,
175
+ endDateTime: event.endDateTime,
176
+ location: event.location
177
+ }))
178
+ };
179
+ });
180
+
181
+ agents.plannerAgent.tools.getEventDetails.bind(async (state, input) => {
182
+ const { eventId } = input;
183
+ const event = mockDatabase.events[eventId];
184
+
185
+ if (!event) {
186
+ return {
187
+ success: false,
188
+ message: `Event with ID ${eventId} not found.`
189
+ };
190
+ }
191
+
192
+ return {
193
+ success: true,
194
+ event
195
+ };
196
+ });
197
+
198
+ agents.plannerAgent.tools.updateEvent.bind(async (state, input) => {
199
+ const { eventId, updates } = input;
200
+ const event = mockDatabase.events[eventId];
201
+
202
+ if (!event) {
203
+ return {
204
+ success: false,
205
+ message: `Event with ID ${eventId} not found.`
206
+ };
207
+ }
208
+
209
+ // Apply updates to the event
210
+ Object.keys(updates).forEach(key => {
211
+ if (key in event) {
212
+ event[key] = updates[key];
213
+ }
214
+ });
215
+
216
+ // Update the last modified information
217
+ event.lastModifiedBy = state.session?.userId || "system";
218
+ event.lastModifiedAt = new Date().toISOString();
219
+
220
+ return {
221
+ success: true,
222
+ message: `Event "${event.title}" has been updated successfully.`,
223
+ event
224
+ };
225
+ });
226
+
227
+ agents.plannerAgent.tools.deleteEvent.bind(async (state, input) => {
228
+ const { eventId, notifyParticipants } = input;
229
+
230
+ if (!mockDatabase.events[eventId]) {
231
+ return {
232
+ success: false,
233
+ message: `Event with ID ${eventId} not found.`
234
+ };
235
+ }
236
+
237
+ const eventTitle = mockDatabase.events[eventId].title;
238
+
239
+ // Remove the event from the database
240
+ delete mockDatabase.events[eventId];
241
+
242
+ return {
243
+ success: true,
244
+ message: `Event "${eventTitle}" has been deleted successfully.`,
245
+ notificationSent: notifyParticipants === true
246
+ };
247
+ });
248
+
249
+ agents.plannerAgent.tools.checkAvailability.bind(async (state, input) => {
250
+ const { startDateTime, endDateTime, participants } = input;
251
+
252
+ const potentialEvent = {
253
+ startDateTime,
254
+ endDateTime
255
+ };
256
+
257
+ // Find conflicts with existing events
258
+ const conflicts = Object.values(mockDatabase.events).filter(event => {
259
+ // If no participants specified, check for all events
260
+ if (!participants || participants.length === 0) {
261
+ return isOverlapping(event, potentialEvent);
262
+ }
263
+
264
+ // If participants specified, only check events with overlapping participants
265
+ const hasOverlappingParticipants = participants.some(participant =>
266
+ event.participants.includes(participant)
267
+ );
268
+
269
+ return hasOverlappingParticipants && isOverlapping(event, potentialEvent);
270
+ });
271
+
272
+ return {
273
+ available: conflicts.length === 0,
274
+ conflicts: conflicts.map(event => ({
275
+ id: event.id,
276
+ title: event.title,
277
+ startDateTime: event.startDateTime,
278
+ endDateTime: event.endDateTime,
279
+ participants: event.participants
280
+ }))
281
+ };
282
+ });
283
+
284
+ // Bind tool implementations for Event Finder Agent
285
+ agents.eventFinderAgent.tools.searchEvents.bind(async (state, input) => {
286
+ const { query, startDate, endDate, participants, locations, maxResults } = input;
287
+
288
+ // Start with all events
289
+ let filteredEvents = Object.values(mockDatabase.events);
290
+
291
+ // Filter by date range if specified
292
+ if (startDate && endDate) {
293
+ const start = parseDate(startDate);
294
+ const end = parseDate(endDate);
295
+
296
+ filteredEvents = filteredEvents.filter(event => {
297
+ const eventStart = parseDate(event.startDateTime);
298
+ return eventStart >= start && eventStart <= end;
299
+ });
300
+ }
301
+
302
+ // Filter by participants if specified
303
+ if (participants && participants.length > 0) {
304
+ filteredEvents = filteredEvents.filter(event =>
305
+ participants.some(participant => event.participants.includes(participant))
306
+ );
307
+ }
308
+
309
+ // Filter by locations if specified
310
+ if (locations && locations.length > 0) {
311
+ filteredEvents = filteredEvents.filter(event =>
312
+ locations.some(location =>
313
+ event.location.toLowerCase().includes(location.toLowerCase())
314
+ )
315
+ );
316
+ }
317
+
318
+ // Filter by text query
319
+ if (query) {
320
+ const lowerQuery = query.toLowerCase();
321
+ filteredEvents = filteredEvents.filter(event =>
322
+ event.title.toLowerCase().includes(lowerQuery) ||
323
+ (event.description && event.description.toLowerCase().includes(lowerQuery))
324
+ );
325
+ }
326
+
327
+ // Limit results if specified
328
+ if (maxResults && filteredEvents.length > maxResults) {
329
+ filteredEvents = filteredEvents.slice(0, maxResults);
330
+ }
331
+
332
+ return {
333
+ success: true,
334
+ count: filteredEvents.length,
335
+ events: filteredEvents.map(event => ({
336
+ id: event.id,
337
+ title: event.title,
338
+ startDateTime: event.startDateTime,
339
+ endDateTime: event.endDateTime,
340
+ location: event.location,
341
+ participants: event.participants
342
+ }))
343
+ };
344
+ });
345
+
346
+ agents.eventFinderAgent.tools.findConflicts.bind(async (state, input) => {
347
+ const { startDate, endDate, participants } = input;
348
+
349
+ // Get all events in the date range
350
+ const events = getEventsInDateRange(startDate, endDate);
351
+
352
+ // Find events with overlapping times
353
+ const conflicts = [];
354
+
355
+ for (let i = 0; i < events.length; i++) {
356
+ for (let j = i + 1; j < events.length; j++) {
357
+ if (isOverlapping(events[i], events[j])) {
358
+ // If participants specified, check if any are involved in both events
359
+ if (participants && participants.length > 0) {
360
+ const participantOverlap = participants.some(participant =>
361
+ events[i].participants.includes(participant) &&
362
+ events[j].participants.includes(participant)
363
+ );
364
+
365
+ if (!participantOverlap) continue;
366
+ }
367
+
368
+ conflicts.push({
369
+ event1: {
370
+ id: events[i].id,
371
+ title: events[i].title,
372
+ startDateTime: events[i].startDateTime,
373
+ endDateTime: events[i].endDateTime,
374
+ participants: events[i].participants
375
+ },
376
+ event2: {
377
+ id: events[j].id,
378
+ title: events[j].title,
379
+ startDateTime: events[j].startDateTime,
380
+ endDateTime: events[j].endDateTime,
381
+ participants: events[j].participants
382
+ }
383
+ });
384
+ }
385
+ }
386
+ }
387
+
388
+ return {
389
+ success: true,
390
+ conflictsFound: conflicts.length > 0,
391
+ conflicts
392
+ };
393
+ });
394
+
395
+ agents.eventFinderAgent.tools.suggestMeetingTimes.bind(async (state, input) => {
396
+ const { participants, duration, earliestDate, latestDate, workingHoursStart, workingHoursEnd } = input;
397
+
398
+ // This is a simplified version - in a real implementation, this would be much more complex
399
+ // and would account for working hours, timezones, and existing events
400
+
401
+ // Get working hours for all participants if none specified
402
+ const defaultStart = workingHoursStart || "09:00";
403
+ const defaultEnd = workingHoursEnd || "17:00";
404
+
405
+ // Get all events for the participants in the date range
406
+ const events = getEventsInDateRange(earliestDate, latestDate).filter(event =>
407
+ participants.some(participant => event.participants.includes(participant))
408
+ );
409
+
410
+ // For this mock implementation, just suggest a few time slots
411
+ const suggestedTimes = [
412
+ {
413
+ startDateTime: `${formatDate(earliestDate)}T${defaultStart}:00`,
414
+ endDateTime: `${formatDate(earliestDate)}T${defaultEnd}:00`,
415
+ participants: participants,
416
+ conflictCount: 0
417
+ },
418
+ {
419
+ startDateTime: `${formatDate(new Date(parseDate(earliestDate).getTime() + 86400000))}T${defaultStart}:00`,
420
+ endDateTime: `${formatDate(new Date(parseDate(earliestDate).getTime() + 86400000))}T${defaultEnd}:00`,
421
+ participants: participants,
422
+ conflictCount: 0
423
+ },
424
+ {
425
+ startDateTime: `${formatDate(new Date(parseDate(earliestDate).getTime() + 172800000))}T${defaultStart}:00`,
426
+ endDateTime: `${formatDate(new Date(parseDate(earliestDate).getTime() + 172800000))}T${defaultEnd}:00`,
427
+ participants: participants,
428
+ conflictCount: 0
429
+ }
430
+ ];
431
+
432
+ return {
433
+ success: true,
434
+ suggestedTimes
435
+ };
436
+ });
437
+
438
+ agents.eventFinderAgent.tools.getFreeBusy.bind(async (state, input) => {
439
+ const { participants, startDate, endDate } = input;
440
+
441
+ // Get all events for the participants in the date range
442
+ const events = getEventsInDateRange(startDate, endDate).filter(event =>
443
+ participants.some(participant => event.participants.includes(participant))
444
+ );
445
+
446
+ // Create a map of busy times for each participant
447
+ const busyTimes = {};
448
+
449
+ participants.forEach(participant => {
450
+ busyTimes[participant] = events
451
+ .filter(event => event.participants.includes(participant))
452
+ .map(event => ({
453
+ startDateTime: event.startDateTime,
454
+ endDateTime: event.endDateTime,
455
+ eventId: event.id,
456
+ title: event.title
457
+ }));
458
+ });
459
+
460
+ return {
461
+ success: true,
462
+ busyTimes
463
+ };
464
+ });
465
+
466
+ // Compile all agents
467
+ console.log("Compiling agents...");
468
+ await Promise.all(Object.values(agents).map(agent => agent.compile()));
469
+
470
+ // Wait for agent discovery to complete
471
+ console.log("Waiting for agent discovery...");
472
+ await new Promise(resolve => setTimeout(resolve, 2000));
473
+
474
+ console.log("Event planner system ready!");
475
+
476
+ // Example usage scenario 1: Creating a new event
477
+ const client = AgentClient();
478
+ console.log("\nExample 1: Creating a new event");
479
+ const createRequest = "I need to schedule a design review meeting next Monday at 2pm for 1 hour with the design team. Today is 11th May 2025.";
480
+
481
+ console.log(`User request: "${createRequest}"`);
482
+ const createResponse = await client.queryIo(natsIO, 'plannerAgent', new Message({
483
+ content: createRequest,
484
+ session: {
485
+ id: uuidv4(),
486
+ userId: "alice@example.com"
487
+ }
488
+ }));
489
+
490
+ console.log("Planner Agent Response:");
491
+ console.log(createResponse.getContent());
492
+
493
+ // Example usage scenario 2: Finding events with specific criteria
494
+ console.log("\nExample 2: Searching for events");
495
+ const searchRequest = "Show me all meetings with Bob next month. Today is october 2023.";
496
+
497
+ console.log(`User request: "${searchRequest}"`);
498
+ const searchResponse = await client.queryIo(natsIO, 'eventFinderAgent', new Message({
499
+ content: searchRequest,
500
+ session: {
501
+ id: uuidv4(),
502
+ userId: "alice@example.com"
503
+ }
504
+ }));
505
+
506
+ console.log("Event Finder Agent Response:");
507
+ console.log(searchResponse.getContent());
508
+
509
+ // Example usage scenario 3: Updating an event
510
+ console.log("\nExample 3: Updating an event");
511
+ const updateRequest = "Change the Weekly Team Meeting to start at 9:30am instead of 10am.";
512
+
513
+ console.log(`User request: "${updateRequest}"`);
514
+ const updateResponse = await client.queryIo(natsIO, 'plannerAgent', new Message({
515
+ content: updateRequest,
516
+ session: {
517
+ id: uuidv4(),
518
+ userId: "alice@example.com"
519
+ }
520
+ }));
521
+
522
+ console.log("Planner Agent Response:");
523
+ console.log(updateResponse.getContent());
524
+
525
+ // Example usage scenario 4: Finding scheduling conflicts
526
+ console.log("\nExample 4: Finding scheduling conflicts");
527
+ const conflictRequest = "Do I have any scheduling conflicts next week?";
528
+
529
+ console.log(`User request: "${conflictRequest}"`);
530
+ const conflictResponse = await client.queryIo(natsIO, 'eventFinderAgent', new Message({
531
+ content: conflictRequest,
532
+ session: {
533
+ id: uuidv4(),
534
+ userId: "alice@example.com"
535
+ }
536
+ }));
537
+
538
+ console.log("Event Finder Agent Response:");
539
+ console.log(conflictResponse.getContent());
540
+
541
+ console.log("\nEvent planner workflow complete!");
542
+ }
543
+
544
+ // Execute the demo
545
+ main().catch(error => {
546
+ console.error("Error running event planner demo:", error);
547
+ });
@@ -1,7 +1,7 @@
1
- import { AgentLoaderJSON, Message, Bindings, PostgresStore } from "../index.js"
1
+ import { AgentLoaderJSON, Message, Bindings, PostgresStore } from "../../src/index.js"
2
2
 
3
3
  const agentDefinition = {
4
- "apiVersion": "smartagent.io/v1alpha1",
4
+ "apiVersion": "agentnet/v1alpha1",
5
5
  "kind": "AgentDefinition",
6
6
  "metadata": {
7
7
  "name": "accomodationAgent",
@@ -2,17 +2,17 @@
2
2
  apiVersion: smartagent.io/v1alpha1
3
3
  kind: AgentDefinition
4
4
  metadata:
5
- name: smartnessAgent
5
+ name: entrypoint
6
6
  namespace: smartchat
7
7
  spec:
8
8
  io:
9
9
  - type: NatsIO
10
10
  bindings:
11
11
  discoveryTopic: smartness.discovery
12
- doHandoffsTo:
13
- - "smartness.accomodation.*"
12
+ acceptedNetworks:
13
+ - "smartchat.*"
14
14
  store:
15
- type: Postgres
15
+ type: Memory
16
16
  llm:
17
17
  provider: Gemini
18
18
  model: gemini-2.0-flash
@@ -26,20 +26,17 @@ spec:
26
26
  functionCallingConfig:
27
27
  mode: 'auto'
28
28
 
29
-
30
29
  ---
31
30
  apiVersion: smartagent.io/v1alpha1
32
31
  kind: AgentDefinition
33
32
  metadata:
34
- name: accomodationAgent
33
+ name: accomodation
35
34
  namespace: smartchat
36
35
  spec:
37
36
  io:
38
37
  - type: NatsIO
39
38
  bindings:
40
39
  discoveryTopic: smartness.discovery
41
- doHandoffsTo:
42
- - "smartness.accomodation.*"
43
40
  store:
44
41
  type: Postgres
45
42
 
@@ -102,15 +99,13 @@ spec:
102
99
  apiVersion: smartagent.io/v1alpha1
103
100
  kind: AgentDefinition
104
101
  metadata:
105
- name: hotelReviewAgent
102
+ name: review
106
103
  namespace: smartchat
107
104
  spec:
108
105
  io:
109
106
  - type: NatsIO
110
107
  bindings:
111
108
  discoveryTopic: smartness.discovery
112
- doHandoffsTo:
113
- - "smartness.accomodation.*"
114
109
  store:
115
110
  type: Postgres
116
111
 
@@ -155,15 +150,13 @@ spec:
155
150
  apiVersion: smartagent.io/v1alpha1
156
151
  kind: AgentDefinition
157
152
  metadata:
158
- name: bookingAgent
153
+ name: booking
159
154
  namespace: smartchat
160
155
  spec:
161
156
  io:
162
157
  - type: NatsIO
163
158
  bindings:
164
159
  discoveryTopic: smartness.discovery
165
- doHandoffsTo:
166
- - "smartness.accomodation.*"
167
160
  store:
168
161
  type: Postgres
169
162
 
@@ -227,15 +220,13 @@ spec:
227
220
  apiVersion: smartagent.io/v1alpha1
228
221
  kind: AgentDefinition
229
222
  metadata:
230
- name: pricingAgent
223
+ name: pricing
231
224
  namespace: smartchat
232
225
  spec:
233
226
  io:
234
227
  - type: NatsIO
235
228
  bindings:
236
229
  discoveryTopic: smartness.discovery
237
- doHandoffsTo:
238
- - "smartness.accomodation.*"
239
230
  store:
240
231
  type: Postgres
241
232