@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.cjs CHANGED
@@ -25,8 +25,10 @@ __export(index_exports, {
25
25
  InMemoryStore: () => InMemoryStore,
26
26
  Memory: () => Memory,
27
27
  MockAdapter: () => MockAdapter,
28
+ OllamaEmbeddingAdapter: () => OllamaEmbeddingAdapter,
28
29
  OpenAICompatibleAdapter: () => OpenAICompatibleAdapter,
29
30
  SQLiteStore: () => SQLiteStore,
31
+ Team: () => Team,
30
32
  Tool: () => Tool,
31
33
  createMessage: () => createMessage,
32
34
  createSummary: () => createSummary,
@@ -273,6 +275,9 @@ var Agent = class {
273
275
  isModelAdapter(obj) {
274
276
  return typeof obj.chat === "function";
275
277
  }
278
+ getModel() {
279
+ return this.model;
280
+ }
276
281
  on(type, handler) {
277
282
  this.emitter.on(type, handler);
278
283
  }
@@ -428,6 +433,144 @@ var Agent = class {
428
433
  }
429
434
  };
430
435
 
436
+ // src/strategy/sequential.ts
437
+ var SequentialStrategy = class {
438
+ async execute(agents, task, _options, emitter) {
439
+ const responses = [];
440
+ let previousOutput;
441
+ for (const agent of agents) {
442
+ const input = previousOutput !== void 0 ? `${task}
443
+
444
+ Previous agent output:
445
+ ${previousOutput}` : task;
446
+ emitter.emit({
447
+ type: "team:agent:start",
448
+ timestamp: Date.now(),
449
+ agentId: "team",
450
+ data: { agentName: agent.name, input }
451
+ });
452
+ const startTime = Date.now();
453
+ const result = await agent.chat(input);
454
+ const latencyMs = Date.now() - startTime;
455
+ emitter.emit({
456
+ type: "team:agent:end",
457
+ timestamp: Date.now(),
458
+ agentId: "team",
459
+ data: { agentName: agent.name, output: result.content },
460
+ latencyMs
461
+ });
462
+ responses.push({ agent: agent.name, content: result.content });
463
+ previousOutput = result.content;
464
+ }
465
+ return {
466
+ content: responses[responses.length - 1]?.content ?? "",
467
+ responses
468
+ };
469
+ }
470
+ };
471
+
472
+ // src/strategy/parallel.ts
473
+ var ParallelStrategy = class {
474
+ async execute(agents, task, _options, emitter) {
475
+ const agentPromises = agents.map(async (agent) => {
476
+ emitter.emit({
477
+ type: "team:agent:start",
478
+ timestamp: Date.now(),
479
+ agentId: "team",
480
+ data: { agentName: agent.name, input: task }
481
+ });
482
+ const startTime = Date.now();
483
+ const result = await agent.chat(task);
484
+ const latencyMs = Date.now() - startTime;
485
+ emitter.emit({
486
+ type: "team:agent:end",
487
+ timestamp: Date.now(),
488
+ agentId: "team",
489
+ data: { agentName: agent.name, output: result.content },
490
+ latencyMs
491
+ });
492
+ return { agent: agent.name, content: result.content };
493
+ });
494
+ const responses = await Promise.all(agentPromises);
495
+ const content = responses.map((r) => `[${r.agent}]: ${r.content}`).join("\n\n");
496
+ return { content, responses };
497
+ }
498
+ };
499
+
500
+ // src/strategy/debate.ts
501
+ var DebateStrategy = class {
502
+ async execute(agents, task, options, emitter) {
503
+ const maxRounds = options.maxRounds ?? 3;
504
+ const responses = [];
505
+ const priorOutputs = [];
506
+ for (let round = 1; round <= maxRounds; round++) {
507
+ emitter.emit({
508
+ type: "team:round",
509
+ timestamp: Date.now(),
510
+ agentId: "team",
511
+ data: { round, totalRounds: maxRounds }
512
+ });
513
+ for (const agent of agents) {
514
+ const context = priorOutputs.length > 0 ? `${task}
515
+
516
+ Debate so far:
517
+ ${priorOutputs.join("\n\n")}
518
+
519
+ Your turn (Round ${round}):` : `${task}
520
+
521
+ (Round ${round}):`;
522
+ emitter.emit({
523
+ type: "team:agent:start",
524
+ timestamp: Date.now(),
525
+ agentId: "team",
526
+ data: { agentName: agent.name, round }
527
+ });
528
+ const startTime = Date.now();
529
+ const result = await agent.chat(context);
530
+ const latencyMs = Date.now() - startTime;
531
+ emitter.emit({
532
+ type: "team:agent:end",
533
+ timestamp: Date.now(),
534
+ agentId: "team",
535
+ data: { agentName: agent.name, output: result.content, round },
536
+ latencyMs
537
+ });
538
+ const agentResponse = {
539
+ agent: agent.name,
540
+ content: result.content,
541
+ round
542
+ };
543
+ responses.push(agentResponse);
544
+ priorOutputs.push(`[${agent.name}, Round ${round}]: ${result.content}`);
545
+ }
546
+ }
547
+ const firstAgent = agents[0];
548
+ const synthesisInput = `${task}
549
+
550
+ Debate summary:
551
+ ${priorOutputs.join("\n\n")}
552
+
553
+ Provide your final answer:`;
554
+ emitter.emit({
555
+ type: "team:agent:start",
556
+ timestamp: Date.now(),
557
+ agentId: "team",
558
+ data: { agentName: firstAgent.name, phase: "final" }
559
+ });
560
+ const finalResult = await firstAgent.chat(synthesisInput);
561
+ emitter.emit({
562
+ type: "team:agent:end",
563
+ timestamp: Date.now(),
564
+ agentId: "team",
565
+ data: { agentName: firstAgent.name, output: finalResult.content, phase: "final" }
566
+ });
567
+ return {
568
+ content: finalResult.content,
569
+ responses
570
+ };
571
+ }
572
+ };
573
+
431
574
  // src/tool.ts
432
575
  var Tool = class _Tool {
433
576
  name;
@@ -452,10 +595,157 @@ var Tool = class _Tool {
452
595
  }
453
596
  };
454
597
 
598
+ // src/strategy/hierarchical.ts
599
+ var HierarchicalStrategy = class {
600
+ async execute(agents, task, options, emitter) {
601
+ const { manager, maxDelegations = 10 } = options;
602
+ if (!manager) {
603
+ throw new Error("HierarchicalStrategy requires a manager agent");
604
+ }
605
+ const agentMap = new Map(agents.map((a) => [a.name, a]));
606
+ const responses = [];
607
+ const delegateTool = Tool.create({
608
+ name: "delegate",
609
+ description: "Delegate a sub-task to a specialist agent. Use this to assign work to workers.",
610
+ parameters: {
611
+ agentName: {
612
+ type: "string",
613
+ description: "The name of the agent to delegate to",
614
+ required: true
615
+ },
616
+ task: {
617
+ type: "string",
618
+ description: "The task to assign to the agent",
619
+ required: true
620
+ }
621
+ },
622
+ execute: async (params) => {
623
+ const agentName = params.agentName;
624
+ const subTask = params.task;
625
+ const worker = agentMap.get(agentName);
626
+ if (!worker) {
627
+ return `Error: No agent named "${agentName}" found. Available agents: ${[...agentMap.keys()].join(", ")}`;
628
+ }
629
+ emitter.emit({
630
+ type: "team:delegate",
631
+ timestamp: Date.now(),
632
+ agentId: "team",
633
+ data: { agentName, task: subTask }
634
+ });
635
+ const result = await worker.chat(subTask);
636
+ const response = { agent: agentName, content: result.content };
637
+ responses.push(response);
638
+ return result.content;
639
+ }
640
+ });
641
+ const orchestratorAgent = new Agent({
642
+ name: manager.name,
643
+ model: manager.getModel(),
644
+ tools: [delegateTool],
645
+ 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.`,
646
+ maxToolRounds: maxDelegations
647
+ });
648
+ const finalResult = await orchestratorAgent.chat(task);
649
+ return {
650
+ content: finalResult.content,
651
+ responses
652
+ };
653
+ }
654
+ };
655
+
656
+ // src/team.ts
657
+ var Team = class {
658
+ agents;
659
+ strategyName;
660
+ manager;
661
+ maxRounds;
662
+ maxDelegations;
663
+ emitter;
664
+ constructor(config) {
665
+ this.agents = config.agents;
666
+ this.strategyName = config.strategy;
667
+ this.manager = config.manager;
668
+ this.maxRounds = config.maxRounds;
669
+ this.maxDelegations = config.maxDelegations;
670
+ this.emitter = new AgentEventEmitter();
671
+ }
672
+ on(type, handler) {
673
+ this.emitter.on(type, handler);
674
+ }
675
+ off(type, handler) {
676
+ this.emitter.off(type, handler);
677
+ }
678
+ async run(task) {
679
+ this.emitter.emit({
680
+ type: "team:start",
681
+ timestamp: Date.now(),
682
+ agentId: "team",
683
+ data: {
684
+ strategy: this.strategyName,
685
+ agentCount: this.agents.length,
686
+ task
687
+ }
688
+ });
689
+ const startTime = Date.now();
690
+ const strategy = this.resolveStrategy();
691
+ const result = await strategy.execute(
692
+ this.agents,
693
+ task,
694
+ {
695
+ maxRounds: this.maxRounds,
696
+ maxDelegations: this.maxDelegations,
697
+ manager: this.manager
698
+ },
699
+ this.emitter
700
+ );
701
+ const latencyMs = Date.now() - startTime;
702
+ this.emitter.emit({
703
+ type: "team:end",
704
+ timestamp: Date.now(),
705
+ agentId: "team",
706
+ data: {
707
+ strategy: this.strategyName,
708
+ responseCount: result.responses.length
709
+ },
710
+ latencyMs
711
+ });
712
+ return result;
713
+ }
714
+ resolveStrategy() {
715
+ switch (this.strategyName) {
716
+ case "sequential":
717
+ return new SequentialStrategy();
718
+ case "parallel":
719
+ return new ParallelStrategy();
720
+ case "debate":
721
+ return new DebateStrategy();
722
+ case "hierarchical":
723
+ return new HierarchicalStrategy();
724
+ }
725
+ }
726
+ };
727
+
728
+ // src/store/cosine.ts
729
+ function cosineSimilarity(a, b) {
730
+ let dot = 0;
731
+ let normA = 0;
732
+ let normB = 0;
733
+ for (let i = 0; i < a.length; i++) {
734
+ dot += a[i] * b[i];
735
+ normA += a[i] * a[i];
736
+ normB += b[i] * b[i];
737
+ }
738
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
739
+ if (denom === 0) return 0;
740
+ return dot / denom;
741
+ }
742
+
455
743
  // src/store/in-memory.ts
456
744
  var InMemoryStore = class {
457
745
  messages = /* @__PURE__ */ new Map();
458
746
  summaries = /* @__PURE__ */ new Map();
747
+ // agentId -> (summaryId -> embedding vector)
748
+ embeddings = /* @__PURE__ */ new Map();
459
749
  async saveMessages(agentId, messages) {
460
750
  const existing = this.messages.get(agentId) ?? [];
461
751
  existing.push(...messages);
@@ -476,6 +766,28 @@ var InMemoryStore = class {
476
766
  const matches = all.filter((s) => s.content.toLowerCase().includes(queryLower)).sort((a, b) => b.timestamp - a.timestamp).slice(0, limit);
477
767
  return matches;
478
768
  }
769
+ async saveEmbedding(agentId, summaryId, embedding) {
770
+ let agentMap = this.embeddings.get(agentId);
771
+ if (!agentMap) {
772
+ agentMap = /* @__PURE__ */ new Map();
773
+ this.embeddings.set(agentId, agentMap);
774
+ }
775
+ agentMap.set(summaryId, embedding);
776
+ }
777
+ async searchByEmbedding(agentId, embedding, limit) {
778
+ const agentMap = this.embeddings.get(agentId);
779
+ if (!agentMap || agentMap.size === 0) return [];
780
+ const summaries = this.summaries.get(agentId) ?? [];
781
+ const summaryById = new Map(summaries.map((s) => [s.id, s]));
782
+ const scored = [];
783
+ for (const [summaryId, storedEmbedding] of agentMap) {
784
+ const summary = summaryById.get(summaryId);
785
+ if (!summary) continue;
786
+ const score = cosineSimilarity(embedding, storedEmbedding);
787
+ scored.push({ summary, score });
788
+ }
789
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
790
+ }
479
791
  };
480
792
 
481
793
  // src/store/sqlite.ts
@@ -509,8 +821,14 @@ var SQLiteStore = class {
509
821
  message_range_from INTEGER NOT NULL,
510
822
  message_range_to INTEGER NOT NULL
511
823
  );
824
+ CREATE TABLE IF NOT EXISTS embeddings (
825
+ summary_id TEXT PRIMARY KEY,
826
+ agent_id TEXT NOT NULL,
827
+ embedding BLOB NOT NULL
828
+ );
512
829
  CREATE INDEX IF NOT EXISTS idx_messages_agent ON messages(agent_id);
513
830
  CREATE INDEX IF NOT EXISTS idx_summaries_agent ON summaries(agent_id);
831
+ CREATE INDEX IF NOT EXISTS idx_embeddings_agent ON embeddings(agent_id);
514
832
  `);
515
833
  }
516
834
  async saveMessages(agentId, messages) {
@@ -570,6 +888,34 @@ var SQLiteStore = class {
570
888
  messageRange: { from: row.message_range_from, to: row.message_range_to }
571
889
  }));
572
890
  }
891
+ async saveEmbedding(agentId, summaryId, embedding) {
892
+ this.db.prepare(
893
+ "INSERT OR REPLACE INTO embeddings (summary_id, agent_id, embedding) VALUES (?, ?, ?)"
894
+ ).run(summaryId, agentId, JSON.stringify(embedding));
895
+ }
896
+ async searchByEmbedding(agentId, embedding, limit) {
897
+ const rows = this.db.prepare(
898
+ `SELECT e.summary_id, s.content, s.timestamp, s.message_range_from, s.message_range_to, e.embedding
899
+ FROM embeddings e
900
+ JOIN summaries s ON e.summary_id = s.id
901
+ WHERE e.agent_id = ?`
902
+ ).all(agentId);
903
+ if (rows.length === 0) return [];
904
+ const scored = rows.map((row) => {
905
+ const storedEmbedding = JSON.parse(row.embedding);
906
+ const score = cosineSimilarity(embedding, storedEmbedding);
907
+ return {
908
+ summary: {
909
+ id: row.summary_id,
910
+ content: row.content,
911
+ timestamp: row.timestamp,
912
+ messageRange: { from: row.message_range_from, to: row.message_range_to }
913
+ },
914
+ score
915
+ };
916
+ });
917
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((entry) => entry.summary);
918
+ }
573
919
  close() {
574
920
  this.db.close();
575
921
  }
@@ -581,10 +927,12 @@ var Memory = class {
581
927
  windowSize;
582
928
  summarizeAfter;
583
929
  model;
930
+ embeddingAdapter;
584
931
  messageCount = /* @__PURE__ */ new Map();
585
932
  constructor(config = {}) {
586
933
  this.windowSize = config.windowSize ?? 20;
587
934
  this.summarizeAfter = config.summarizeAfter ?? 20;
935
+ this.embeddingAdapter = config.embedding;
588
936
  if (!config.store || config.store === "memory") {
589
937
  this.store = new InMemoryStore();
590
938
  } else if (config.store === "sqlite") {
@@ -610,7 +958,13 @@ var Memory = class {
610
958
  }
611
959
  async getContext(agentId, query) {
612
960
  const recentMessages = await this.store.getRecentMessages(agentId, this.windowSize);
613
- const relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
961
+ let relevantSummaries;
962
+ if (this.embeddingAdapter && this.store.searchByEmbedding) {
963
+ const queryEmbedding = await this.embeddingAdapter.embed(query);
964
+ relevantSummaries = await this.store.searchByEmbedding(agentId, queryEmbedding, 3);
965
+ } else {
966
+ relevantSummaries = await this.store.searchSummaries(agentId, query, 3);
967
+ }
614
968
  return { recentMessages, relevantSummaries };
615
969
  }
616
970
  async summarize(agentId) {
@@ -633,6 +987,10 @@ var Memory = class {
633
987
  }
634
988
  });
635
989
  await this.store.saveSummary(agentId, summary);
990
+ if (this.embeddingAdapter && this.store.saveEmbedding) {
991
+ const embedding = await this.embeddingAdapter.embed(summary.content);
992
+ await this.store.saveEmbedding(agentId, summary.id, embedding);
993
+ }
636
994
  }
637
995
  close() {
638
996
  if ("close" in this.store && typeof this.store.close === "function") {
@@ -640,6 +998,36 @@ var Memory = class {
640
998
  }
641
999
  }
642
1000
  };
1001
+
1002
+ // src/model/ollama-embedding.ts
1003
+ var OllamaEmbeddingAdapter = class {
1004
+ baseURL;
1005
+ model;
1006
+ constructor(config = {}) {
1007
+ this.baseURL = config.baseURL ?? "http://localhost:11434";
1008
+ this.model = config.model ?? "nomic-embed-text";
1009
+ }
1010
+ async embed(text) {
1011
+ const [vector] = await this.request(text);
1012
+ return vector;
1013
+ }
1014
+ async embedBatch(texts) {
1015
+ if (texts.length === 0) return [];
1016
+ return this.request(texts);
1017
+ }
1018
+ async request(input) {
1019
+ const response = await fetch(`${this.baseURL}/api/embed`, {
1020
+ method: "POST",
1021
+ headers: { "Content-Type": "application/json" },
1022
+ body: JSON.stringify({ model: this.model, input })
1023
+ });
1024
+ if (!response.ok) {
1025
+ throw new Error(`Ollama embedding request failed: ${response.status} ${response.statusText}`);
1026
+ }
1027
+ const data = await response.json();
1028
+ return data.embeddings;
1029
+ }
1030
+ };
643
1031
  // Annotate the CommonJS export names for ESM import in node:
644
1032
  0 && (module.exports = {
645
1033
  Agent,
@@ -647,8 +1035,10 @@ var Memory = class {
647
1035
  InMemoryStore,
648
1036
  Memory,
649
1037
  MockAdapter,
1038
+ OllamaEmbeddingAdapter,
650
1039
  OpenAICompatibleAdapter,
651
1040
  SQLiteStore,
1041
+ Team,
652
1042
  Tool,
653
1043
  createMessage,
654
1044
  createSummary,