@avee1234/agent-kit 0.1.0 → 0.3.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/dist/index.js CHANGED
@@ -237,6 +237,9 @@ var Agent = class {
237
237
  isModelAdapter(obj) {
238
238
  return typeof obj.chat === "function";
239
239
  }
240
+ getModel() {
241
+ return this.model;
242
+ }
240
243
  on(type, handler) {
241
244
  this.emitter.on(type, handler);
242
245
  }
@@ -392,6 +395,144 @@ var Agent = class {
392
395
  }
393
396
  };
394
397
 
398
+ // src/strategy/sequential.ts
399
+ var SequentialStrategy = class {
400
+ async execute(agents, task, _options, emitter) {
401
+ const responses = [];
402
+ let previousOutput;
403
+ for (const agent of agents) {
404
+ const input = previousOutput !== void 0 ? `${task}
405
+
406
+ Previous agent output:
407
+ ${previousOutput}` : task;
408
+ emitter.emit({
409
+ type: "team:agent:start",
410
+ timestamp: Date.now(),
411
+ agentId: "team",
412
+ data: { agentName: agent.name, input }
413
+ });
414
+ const startTime = Date.now();
415
+ const result = await agent.chat(input);
416
+ const latencyMs = Date.now() - startTime;
417
+ emitter.emit({
418
+ type: "team:agent:end",
419
+ timestamp: Date.now(),
420
+ agentId: "team",
421
+ data: { agentName: agent.name, output: result.content },
422
+ latencyMs
423
+ });
424
+ responses.push({ agent: agent.name, content: result.content });
425
+ previousOutput = result.content;
426
+ }
427
+ return {
428
+ content: responses[responses.length - 1]?.content ?? "",
429
+ responses
430
+ };
431
+ }
432
+ };
433
+
434
+ // src/strategy/parallel.ts
435
+ var ParallelStrategy = class {
436
+ async execute(agents, task, _options, emitter) {
437
+ const agentPromises = agents.map(async (agent) => {
438
+ emitter.emit({
439
+ type: "team:agent:start",
440
+ timestamp: Date.now(),
441
+ agentId: "team",
442
+ data: { agentName: agent.name, input: task }
443
+ });
444
+ const startTime = Date.now();
445
+ const result = await agent.chat(task);
446
+ const latencyMs = Date.now() - startTime;
447
+ emitter.emit({
448
+ type: "team:agent:end",
449
+ timestamp: Date.now(),
450
+ agentId: "team",
451
+ data: { agentName: agent.name, output: result.content },
452
+ latencyMs
453
+ });
454
+ return { agent: agent.name, content: result.content };
455
+ });
456
+ const responses = await Promise.all(agentPromises);
457
+ const content = responses.map((r) => `[${r.agent}]: ${r.content}`).join("\n\n");
458
+ return { content, responses };
459
+ }
460
+ };
461
+
462
+ // src/strategy/debate.ts
463
+ var DebateStrategy = class {
464
+ async execute(agents, task, options, emitter) {
465
+ const maxRounds = options.maxRounds ?? 3;
466
+ const responses = [];
467
+ const priorOutputs = [];
468
+ for (let round = 1; round <= maxRounds; round++) {
469
+ emitter.emit({
470
+ type: "team:round",
471
+ timestamp: Date.now(),
472
+ agentId: "team",
473
+ data: { round, totalRounds: maxRounds }
474
+ });
475
+ for (const agent of agents) {
476
+ const context = priorOutputs.length > 0 ? `${task}
477
+
478
+ Debate so far:
479
+ ${priorOutputs.join("\n\n")}
480
+
481
+ Your turn (Round ${round}):` : `${task}
482
+
483
+ (Round ${round}):`;
484
+ emitter.emit({
485
+ type: "team:agent:start",
486
+ timestamp: Date.now(),
487
+ agentId: "team",
488
+ data: { agentName: agent.name, round }
489
+ });
490
+ const startTime = Date.now();
491
+ const result = await agent.chat(context);
492
+ const latencyMs = Date.now() - startTime;
493
+ emitter.emit({
494
+ type: "team:agent:end",
495
+ timestamp: Date.now(),
496
+ agentId: "team",
497
+ data: { agentName: agent.name, output: result.content, round },
498
+ latencyMs
499
+ });
500
+ const agentResponse = {
501
+ agent: agent.name,
502
+ content: result.content,
503
+ round
504
+ };
505
+ responses.push(agentResponse);
506
+ priorOutputs.push(`[${agent.name}, Round ${round}]: ${result.content}`);
507
+ }
508
+ }
509
+ const firstAgent = agents[0];
510
+ const synthesisInput = `${task}
511
+
512
+ Debate summary:
513
+ ${priorOutputs.join("\n\n")}
514
+
515
+ Provide your final answer:`;
516
+ emitter.emit({
517
+ type: "team:agent:start",
518
+ timestamp: Date.now(),
519
+ agentId: "team",
520
+ data: { agentName: firstAgent.name, phase: "final" }
521
+ });
522
+ const finalResult = await firstAgent.chat(synthesisInput);
523
+ emitter.emit({
524
+ type: "team:agent:end",
525
+ timestamp: Date.now(),
526
+ agentId: "team",
527
+ data: { agentName: firstAgent.name, output: finalResult.content, phase: "final" }
528
+ });
529
+ return {
530
+ content: finalResult.content,
531
+ responses
532
+ };
533
+ }
534
+ };
535
+
395
536
  // src/tool.ts
396
537
  var Tool = class _Tool {
397
538
  name;
@@ -416,10 +557,157 @@ var Tool = class _Tool {
416
557
  }
417
558
  };
418
559
 
560
+ // src/strategy/hierarchical.ts
561
+ var HierarchicalStrategy = class {
562
+ async execute(agents, task, options, emitter) {
563
+ const { manager, maxDelegations = 10 } = options;
564
+ if (!manager) {
565
+ throw new Error("HierarchicalStrategy requires a manager agent");
566
+ }
567
+ const agentMap = new Map(agents.map((a) => [a.name, a]));
568
+ const responses = [];
569
+ const delegateTool = Tool.create({
570
+ name: "delegate",
571
+ description: "Delegate a sub-task to a specialist agent. Use this to assign work to workers.",
572
+ parameters: {
573
+ agentName: {
574
+ type: "string",
575
+ description: "The name of the agent to delegate to",
576
+ required: true
577
+ },
578
+ task: {
579
+ type: "string",
580
+ description: "The task to assign to the agent",
581
+ required: true
582
+ }
583
+ },
584
+ execute: async (params) => {
585
+ const agentName = params.agentName;
586
+ const subTask = params.task;
587
+ const worker = agentMap.get(agentName);
588
+ if (!worker) {
589
+ return `Error: No agent named "${agentName}" found. Available agents: ${[...agentMap.keys()].join(", ")}`;
590
+ }
591
+ emitter.emit({
592
+ type: "team:delegate",
593
+ timestamp: Date.now(),
594
+ agentId: "team",
595
+ data: { agentName, task: subTask }
596
+ });
597
+ const result = await worker.chat(subTask);
598
+ const response = { agent: agentName, content: result.content };
599
+ responses.push(response);
600
+ return result.content;
601
+ }
602
+ });
603
+ const orchestratorAgent = new Agent({
604
+ name: manager.name,
605
+ model: manager.getModel(),
606
+ tools: [delegateTool],
607
+ system: `You are an orchestrating manager. You have access to specialist agents: ${[...agentMap.keys()].join(", ")}. Use the delegate tool to assign sub-tasks to them.`,
608
+ maxToolRounds: maxDelegations
609
+ });
610
+ const finalResult = await orchestratorAgent.chat(task);
611
+ return {
612
+ content: finalResult.content,
613
+ responses
614
+ };
615
+ }
616
+ };
617
+
618
+ // src/team.ts
619
+ var Team = class {
620
+ agents;
621
+ strategyName;
622
+ manager;
623
+ maxRounds;
624
+ maxDelegations;
625
+ emitter;
626
+ constructor(config) {
627
+ this.agents = config.agents;
628
+ this.strategyName = config.strategy;
629
+ this.manager = config.manager;
630
+ this.maxRounds = config.maxRounds;
631
+ this.maxDelegations = config.maxDelegations;
632
+ this.emitter = new AgentEventEmitter();
633
+ }
634
+ on(type, handler) {
635
+ this.emitter.on(type, handler);
636
+ }
637
+ off(type, handler) {
638
+ this.emitter.off(type, handler);
639
+ }
640
+ async run(task) {
641
+ this.emitter.emit({
642
+ type: "team:start",
643
+ timestamp: Date.now(),
644
+ agentId: "team",
645
+ data: {
646
+ strategy: this.strategyName,
647
+ agentCount: this.agents.length,
648
+ task
649
+ }
650
+ });
651
+ const startTime = Date.now();
652
+ const strategy = this.resolveStrategy();
653
+ const result = await strategy.execute(
654
+ this.agents,
655
+ task,
656
+ {
657
+ maxRounds: this.maxRounds,
658
+ maxDelegations: this.maxDelegations,
659
+ manager: this.manager
660
+ },
661
+ this.emitter
662
+ );
663
+ const latencyMs = Date.now() - startTime;
664
+ this.emitter.emit({
665
+ type: "team:end",
666
+ timestamp: Date.now(),
667
+ agentId: "team",
668
+ data: {
669
+ strategy: this.strategyName,
670
+ responseCount: result.responses.length
671
+ },
672
+ latencyMs
673
+ });
674
+ return result;
675
+ }
676
+ resolveStrategy() {
677
+ switch (this.strategyName) {
678
+ case "sequential":
679
+ return new SequentialStrategy();
680
+ case "parallel":
681
+ return new ParallelStrategy();
682
+ case "debate":
683
+ return new DebateStrategy();
684
+ case "hierarchical":
685
+ return new HierarchicalStrategy();
686
+ }
687
+ }
688
+ };
689
+
690
+ // src/store/cosine.ts
691
+ function cosineSimilarity(a, b) {
692
+ let dot = 0;
693
+ let normA = 0;
694
+ let normB = 0;
695
+ for (let i = 0; i < a.length; i++) {
696
+ dot += a[i] * b[i];
697
+ normA += a[i] * a[i];
698
+ normB += b[i] * b[i];
699
+ }
700
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
701
+ if (denom === 0) return 0;
702
+ return dot / denom;
703
+ }
704
+
419
705
  // src/store/in-memory.ts
420
706
  var InMemoryStore = class {
421
707
  messages = /* @__PURE__ */ new Map();
422
708
  summaries = /* @__PURE__ */ new Map();
709
+ // agentId -> (summaryId -> embedding vector)
710
+ embeddings = /* @__PURE__ */ new Map();
423
711
  async saveMessages(agentId, messages) {
424
712
  const existing = this.messages.get(agentId) ?? [];
425
713
  existing.push(...messages);
@@ -440,6 +728,28 @@ var InMemoryStore = class {
440
728
  const matches = all.filter((s) => s.content.toLowerCase().includes(queryLower)).sort((a, b) => b.timestamp - a.timestamp).slice(0, limit);
441
729
  return matches;
442
730
  }
731
+ async saveEmbedding(agentId, summaryId, embedding) {
732
+ let agentMap = this.embeddings.get(agentId);
733
+ if (!agentMap) {
734
+ agentMap = /* @__PURE__ */ new Map();
735
+ this.embeddings.set(agentId, agentMap);
736
+ }
737
+ agentMap.set(summaryId, embedding);
738
+ }
739
+ async searchByEmbedding(agentId, embedding, limit) {
740
+ const agentMap = this.embeddings.get(agentId);
741
+ if (!agentMap || agentMap.size === 0) return [];
742
+ const summaries = this.summaries.get(agentId) ?? [];
743
+ const summaryById = new Map(summaries.map((s) => [s.id, s]));
744
+ const scored = [];
745
+ for (const [summaryId, storedEmbedding] of agentMap) {
746
+ const summary = summaryById.get(summaryId);
747
+ if (!summary) continue;
748
+ const score = cosineSimilarity(embedding, storedEmbedding);
749
+ scored.push({ summary, score });
750
+ }
751
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
752
+ }
443
753
  };
444
754
 
445
755
  // src/store/sqlite.ts
@@ -472,8 +782,14 @@ var SQLiteStore = class {
472
782
  message_range_from INTEGER NOT NULL,
473
783
  message_range_to INTEGER NOT NULL
474
784
  );
785
+ CREATE TABLE IF NOT EXISTS embeddings (
786
+ summary_id TEXT PRIMARY KEY,
787
+ agent_id TEXT NOT NULL,
788
+ embedding BLOB NOT NULL
789
+ );
475
790
  CREATE INDEX IF NOT EXISTS idx_messages_agent ON messages(agent_id);
476
791
  CREATE INDEX IF NOT EXISTS idx_summaries_agent ON summaries(agent_id);
792
+ CREATE INDEX IF NOT EXISTS idx_embeddings_agent ON embeddings(agent_id);
477
793
  `);
478
794
  }
479
795
  async saveMessages(agentId, messages) {
@@ -533,6 +849,34 @@ var SQLiteStore = class {
533
849
  messageRange: { from: row.message_range_from, to: row.message_range_to }
534
850
  }));
535
851
  }
852
+ async saveEmbedding(agentId, summaryId, embedding) {
853
+ this.db.prepare(
854
+ "INSERT OR REPLACE INTO embeddings (summary_id, agent_id, embedding) VALUES (?, ?, ?)"
855
+ ).run(summaryId, agentId, JSON.stringify(embedding));
856
+ }
857
+ async searchByEmbedding(agentId, embedding, limit) {
858
+ const rows = this.db.prepare(
859
+ `SELECT e.summary_id, s.content, s.timestamp, s.message_range_from, s.message_range_to, e.embedding
860
+ FROM embeddings e
861
+ JOIN summaries s ON e.summary_id = s.id
862
+ WHERE e.agent_id = ?`
863
+ ).all(agentId);
864
+ if (rows.length === 0) return [];
865
+ const scored = rows.map((row) => {
866
+ const storedEmbedding = JSON.parse(row.embedding);
867
+ const score = cosineSimilarity(embedding, storedEmbedding);
868
+ return {
869
+ summary: {
870
+ id: row.summary_id,
871
+ content: row.content,
872
+ timestamp: row.timestamp,
873
+ messageRange: { from: row.message_range_from, to: row.message_range_to }
874
+ },
875
+ score
876
+ };
877
+ });
878
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
879
+ }
536
880
  close() {
537
881
  this.db.close();
538
882
  }
@@ -544,10 +888,12 @@ var Memory = class {
544
888
  windowSize;
545
889
  summarizeAfter;
546
890
  model;
891
+ embeddingAdapter;
547
892
  messageCount = /* @__PURE__ */ new Map();
548
893
  constructor(config = {}) {
549
894
  this.windowSize = config.windowSize ?? 20;
550
895
  this.summarizeAfter = config.summarizeAfter ?? 20;
896
+ this.embeddingAdapter = config.embedding;
551
897
  if (!config.store || config.store === "memory") {
552
898
  this.store = new InMemoryStore();
553
899
  } else if (config.store === "sqlite") {
@@ -573,7 +919,13 @@ var Memory = class {
573
919
  }
574
920
  async getContext(agentId, query) {
575
921
  const recentMessages = await this.store.getRecentMessages(agentId, this.windowSize);
576
- const relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
922
+ let relevantSummaries;
923
+ if (this.embeddingAdapter && this.store.searchByEmbedding) {
924
+ const queryEmbedding = await this.embeddingAdapter.embed(query);
925
+ relevantSummaries = await this.store.searchByEmbedding(agentId, queryEmbedding, 3);
926
+ } else {
927
+ relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
928
+ }
577
929
  return { recentMessages, relevantSummaries };
578
930
  }
579
931
  async summarize(agentId) {
@@ -596,6 +948,10 @@ var Memory = class {
596
948
  }
597
949
  });
598
950
  await this.store.saveSummary(agentId, summary);
951
+ if (this.embeddingAdapter && this.store.saveEmbedding) {
952
+ const embedding = await this.embeddingAdapter.embed(summary.content);
953
+ await this.store.saveEmbedding(agentId, summary.id, embedding);
954
+ }
599
955
  }
600
956
  close() {
601
957
  if ("close" in this.store && typeof this.store.close === "function") {
@@ -603,14 +959,46 @@ var Memory = class {
603
959
  }
604
960
  }
605
961
  };
962
+
963
+ // src/model/ollama-embedding.ts
964
+ var OllamaEmbeddingAdapter = class {
965
+ baseURL;
966
+ model;
967
+ constructor(config = {}) {
968
+ this.baseURL = config.baseURL ?? "http://localhost:11434";
969
+ this.model = config.model ?? "nomic-embed-text";
970
+ }
971
+ async embed(text) {
972
+ const [vector] = await this.request(text);
973
+ return vector;
974
+ }
975
+ async embedBatch(texts) {
976
+ if (texts.length === 0) return [];
977
+ return this.request(texts);
978
+ }
979
+ async request(input) {
980
+ const response = await fetch(`${this.baseURL}/api/embed`, {
981
+ method: "POST",
982
+ headers: { "Content-Type": "application/json" },
983
+ body: JSON.stringify({ model: this.model, input })
984
+ });
985
+ if (!response.ok) {
986
+ throw new Error(`Ollama embedding request failed: ${response.status} ${response.statusText}`);
987
+ }
988
+ const data = await response.json();
989
+ return data.embeddings;
990
+ }
991
+ };
606
992
  export {
607
993
  Agent,
608
994
  AgentEventEmitter,
609
995
  InMemoryStore,
610
996
  Memory,
611
997
  MockAdapter,
998
+ OllamaEmbeddingAdapter,
612
999
  OpenAICompatibleAdapter,
613
1000
  SQLiteStore,
1001
+ Team,
614
1002
  Tool,
615
1003
  createMessage,
616
1004
  createSummary,