@lupaflow/multi-agent 0.1.1 → 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.
package/dist/index.cjs ADDED
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ AgentCommunicator: () => AgentCommunicator,
24
+ Orchestrator: () => Orchestrator,
25
+ Team: () => Team
26
+ });
27
+ module.exports = __toCommonJS(src_exports);
28
+
29
+ // src/orchestrator.ts
30
+ var import_agent = require("@lupaflow/agent");
31
+
32
+ // src/communication.ts
33
+ var import_core = require("@lupaflow/core");
34
+ var AgentCommunicator = class {
35
+ messages = [];
36
+ listeners = /* @__PURE__ */ new Map();
37
+ send(from, to, content, metadata) {
38
+ const msg = {
39
+ id: (0, import_core.generateId)(),
40
+ from,
41
+ to,
42
+ content,
43
+ type: "request",
44
+ timestamp: Date.now(),
45
+ metadata
46
+ };
47
+ this.messages.push(msg);
48
+ const listeners = this.listeners.get(to);
49
+ if (listeners) {
50
+ for (const listener of listeners) {
51
+ listener(msg);
52
+ }
53
+ }
54
+ return msg;
55
+ }
56
+ broadcast(from, content) {
57
+ const msg = {
58
+ id: (0, import_core.generateId)(),
59
+ from,
60
+ to: "*",
61
+ content,
62
+ type: "broadcast",
63
+ timestamp: Date.now()
64
+ };
65
+ this.messages.push(msg);
66
+ for (const listeners of this.listeners.values()) {
67
+ for (const listener of listeners) {
68
+ listener(msg);
69
+ }
70
+ }
71
+ }
72
+ respond(to, originalId, content) {
73
+ const original = this.messages.find((m) => m.id === originalId);
74
+ const msg = {
75
+ id: (0, import_core.generateId)(),
76
+ from: to,
77
+ to: original?.from || to,
78
+ content,
79
+ type: "response",
80
+ timestamp: Date.now()
81
+ };
82
+ this.messages.push(msg);
83
+ const listeners = this.listeners.get(msg.to);
84
+ if (listeners) {
85
+ for (const listener of listeners) {
86
+ listener(msg);
87
+ }
88
+ }
89
+ return msg;
90
+ }
91
+ on(agentId, handler) {
92
+ if (!this.listeners.has(agentId)) {
93
+ this.listeners.set(agentId, /* @__PURE__ */ new Set());
94
+ }
95
+ this.listeners.get(agentId).add(handler);
96
+ return () => this.listeners.get(agentId)?.delete(handler);
97
+ }
98
+ getHistory() {
99
+ return [...this.messages];
100
+ }
101
+ clear() {
102
+ this.messages = [];
103
+ }
104
+ };
105
+
106
+ // src/orchestrator.ts
107
+ var import_core2 = require("@lupaflow/core");
108
+ var Orchestrator = class {
109
+ team;
110
+ communicator;
111
+ agents = /* @__PURE__ */ new Map();
112
+ agentsReady = /* @__PURE__ */ new Map();
113
+ constructor(team) {
114
+ this.team = team;
115
+ this.communicator = new AgentCommunicator();
116
+ for (const member of team.config.members) {
117
+ const agent = new import_agent.Agent(member.agentConfig);
118
+ this.agents.set(member.id, agent);
119
+ }
120
+ }
121
+ async runMember(member, task) {
122
+ const agent = this.agents.get(member.id);
123
+ const result = await agent.run(task);
124
+ return result.output;
125
+ }
126
+ async run(task) {
127
+ const start = Date.now();
128
+ const id = (0, import_core2.generateId)();
129
+ const memberOutputs = /* @__PURE__ */ new Map();
130
+ const leader = this.team.getLeader();
131
+ if (!leader) throw new Error("No leader found in team");
132
+ const leaderResult = await this.runMember(leader, `As the ${leader.role}, oversee this task: ${task}`);
133
+ memberOutputs.set(leader.id, leaderResult);
134
+ const otherMembers = this.team.config.members.filter((m) => m.id !== leader.id);
135
+ for (const member of otherMembers) {
136
+ const msg = this.communicator.send(
137
+ leader.id,
138
+ member.id,
139
+ `Task: ${task}
140
+ Leader's plan: ${leaderResult}
141
+ Your role: ${member.role}
142
+ Execute your part.`
143
+ );
144
+ const memberResult = await this.runMember(member, msg.content);
145
+ memberOutputs.set(member.id, memberResult);
146
+ this.communicator.respond(leader.id, msg.id, memberResult);
147
+ }
148
+ const allOutputs = Array.from(memberOutputs.values()).join("\n\n");
149
+ let finalOutput;
150
+ if (otherMembers.length > 0) {
151
+ const finalResult = await this.runMember(
152
+ leader,
153
+ `Original task: ${task}
154
+
155
+ Here are all the outputs from your team:
156
+ ${allOutputs}
157
+
158
+ Synthesize a final cohesive response.`
159
+ );
160
+ finalOutput = finalResult;
161
+ } else {
162
+ finalOutput = leaderResult;
163
+ }
164
+ return {
165
+ id,
166
+ output: finalOutput,
167
+ memberOutputs,
168
+ messages: this.communicator.getHistory(),
169
+ durationMs: Date.now() - start
170
+ };
171
+ }
172
+ getCommunicator() {
173
+ return this.communicator;
174
+ }
175
+ getTeam() {
176
+ return this.team;
177
+ }
178
+ };
179
+
180
+ // src/team.ts
181
+ var import_core3 = require("@lupaflow/core");
182
+ var Team = class {
183
+ config;
184
+ constructor(config) {
185
+ this.config = {
186
+ ...config,
187
+ members: config.members.map((m) => ({ ...m, id: m.id || (0, import_core3.generateId)() }))
188
+ };
189
+ }
190
+ getMember(idOrName) {
191
+ return this.config.members.find((m) => m.id === idOrName || m.name === idOrName);
192
+ }
193
+ getLeader() {
194
+ if (!this.config.leader) return this.config.members[0];
195
+ return this.getMember(this.config.leader);
196
+ }
197
+ getByRole(role) {
198
+ return this.config.members.filter((m) => m.role === role);
199
+ }
200
+ };
201
+ // Annotate the CommonJS export names for ESM import in node:
202
+ 0 && (module.exports = {
203
+ AgentCommunicator,
204
+ Orchestrator,
205
+ Team
206
+ });
207
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/orchestrator.ts","../src/communication.ts","../src/team.ts"],"sourcesContent":["export { Orchestrator } from \"./orchestrator\"\nexport { Team } from \"./team\"\nexport { AgentCommunicator } from \"./communication\"\nexport type { TeamMember, TeamConfig } from \"./team\"\nexport type { AgentMessage } from \"./communication\"\n","import { Agent } from \"@lupaflow/agent\"\nimport { AgentCommunicator, type AgentMessage } from \"./communication\"\nimport { Team, type TeamMember } from \"./team\"\nimport { generateId } from \"@lupaflow/core\"\n\nexport interface OrchestrationResult {\n id: string\n output: string\n memberOutputs: Map<string, string>\n messages: AgentMessage[]\n durationMs: number\n}\n\nexport class Orchestrator {\n private team: Team\n private communicator: AgentCommunicator\n private agents: Map<string, Agent> = new Map()\n private agentsReady: Map<string, Promise<void>> = new Map()\n\n constructor(team: Team) {\n this.team = team\n this.communicator = new AgentCommunicator()\n for (const member of team.config.members) {\n const agent = new Agent(member.agentConfig)\n this.agents.set(member.id, agent)\n }\n }\n\n private async runMember(member: TeamMember, task: string): Promise<string> {\n const agent = this.agents.get(member.id)!\n const result = await agent.run(task)\n return result.output\n }\n\n async run(task: string): Promise<OrchestrationResult> {\n const start = Date.now()\n const id = generateId()\n const memberOutputs = new Map<string, string>()\n\n const leader = this.team.getLeader()\n if (!leader) throw new Error(\"No leader found in team\")\n\n const leaderResult = await this.runMember(leader, `As the ${leader.role}, oversee this task: ${task}`)\n memberOutputs.set(leader.id, leaderResult)\n\n const otherMembers = this.team.config.members.filter((m) => m.id !== leader.id)\n for (const member of otherMembers) {\n const msg = this.communicator.send(\n leader.id,\n member.id,\n `Task: ${task}\\nLeader's plan: ${leaderResult}\\nYour role: ${member.role}\\nExecute your part.`\n )\n\n const memberResult = await this.runMember(member, msg.content)\n memberOutputs.set(member.id, memberResult)\n\n this.communicator.respond(leader.id, msg.id, memberResult)\n }\n\n const allOutputs = Array.from(memberOutputs.values()).join(\"\\n\\n\")\n let finalOutput: string\n\n if (otherMembers.length > 0) {\n const finalResult = await this.runMember(\n leader,\n `Original task: ${task}\\n\\nHere are all the outputs from your team:\\n${allOutputs}\\n\\nSynthesize a final cohesive response.`\n )\n finalOutput = finalResult\n } else {\n finalOutput = leaderResult\n }\n\n return {\n id,\n output: finalOutput,\n memberOutputs,\n messages: this.communicator.getHistory(),\n durationMs: Date.now() - start,\n }\n }\n\n getCommunicator(): AgentCommunicator {\n return this.communicator\n }\n\n getTeam(): Team {\n return this.team\n }\n}\n","import { generateId } from \"@lupaflow/core\"\n\nexport interface AgentMessage {\n id: string\n from: string\n to: string\n content: string\n type: \"request\" | \"response\" | \"broadcast\"\n timestamp: number\n metadata?: Record<string, unknown>\n}\n\nexport class AgentCommunicator {\n private messages: AgentMessage[] = []\n private listeners: Map<string, Set<(msg: AgentMessage) => void>> = new Map()\n\n send(from: string, to: string, content: string, metadata?: Record<string, unknown>): AgentMessage {\n const msg: AgentMessage = {\n id: generateId(),\n from,\n to,\n content,\n type: \"request\",\n timestamp: Date.now(),\n metadata,\n }\n this.messages.push(msg)\n const listeners = this.listeners.get(to)\n if (listeners) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n return msg\n }\n\n broadcast(from: string, content: string): void {\n const msg: AgentMessage = {\n id: generateId(),\n from,\n to: \"*\",\n content,\n type: \"broadcast\",\n timestamp: Date.now(),\n }\n this.messages.push(msg)\n for (const listeners of this.listeners.values()) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n }\n\n respond(to: string, originalId: string, content: string): AgentMessage {\n const original = this.messages.find((m) => m.id === originalId)\n const msg: AgentMessage = {\n id: generateId(),\n from: to,\n to: original?.from || to,\n content,\n type: \"response\",\n timestamp: Date.now(),\n }\n this.messages.push(msg)\n const listeners = this.listeners.get(msg.to)\n if (listeners) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n return msg\n }\n\n on(agentId: string, handler: (msg: AgentMessage) => void): () => void {\n if (!this.listeners.has(agentId)) {\n this.listeners.set(agentId, new Set())\n }\n this.listeners.get(agentId)!.add(handler)\n return () => this.listeners.get(agentId)?.delete(handler)\n }\n\n getHistory(): AgentMessage[] {\n return [...this.messages]\n }\n\n clear(): void {\n this.messages = []\n }\n}\n","import type { AgentConfig } from \"@lupaflow/types\"\nimport { generateId } from \"@lupaflow/core\"\n\nexport interface TeamMember {\n id: string\n name: string\n role: string\n agentConfig: AgentConfig\n}\n\nexport interface TeamConfig {\n name: string\n members: TeamMember[]\n leader?: string\n description?: string\n}\n\nexport class Team {\n public config: TeamConfig\n\n constructor(config: TeamConfig) {\n this.config = {\n ...config,\n members: config.members.map((m) => ({ ...m, id: m.id || generateId() })),\n }\n }\n\n getMember(idOrName: string): TeamMember | undefined {\n return this.config.members.find((m) => m.id === idOrName || m.name === idOrName)\n }\n\n getLeader(): TeamMember | undefined {\n if (!this.config.leader) return this.config.members[0]\n return this.getMember(this.config.leader)\n }\n\n getByRole(role: string): TeamMember[] {\n return this.config.members.filter((m) => m.role === role)\n }\n}\n"],"mappings":"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","names":["import_core","import_core"]}
@@ -0,0 +1,62 @@
1
+ import { AgentConfig } from '@lupaflow/types';
2
+
3
+ interface AgentMessage {
4
+ id: string;
5
+ from: string;
6
+ to: string;
7
+ content: string;
8
+ type: "request" | "response" | "broadcast";
9
+ timestamp: number;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ declare class AgentCommunicator {
13
+ private messages;
14
+ private listeners;
15
+ send(from: string, to: string, content: string, metadata?: Record<string, unknown>): AgentMessage;
16
+ broadcast(from: string, content: string): void;
17
+ respond(to: string, originalId: string, content: string): AgentMessage;
18
+ on(agentId: string, handler: (msg: AgentMessage) => void): () => void;
19
+ getHistory(): AgentMessage[];
20
+ clear(): void;
21
+ }
22
+
23
+ interface TeamMember {
24
+ id: string;
25
+ name: string;
26
+ role: string;
27
+ agentConfig: AgentConfig;
28
+ }
29
+ interface TeamConfig {
30
+ name: string;
31
+ members: TeamMember[];
32
+ leader?: string;
33
+ description?: string;
34
+ }
35
+ declare class Team {
36
+ config: TeamConfig;
37
+ constructor(config: TeamConfig);
38
+ getMember(idOrName: string): TeamMember | undefined;
39
+ getLeader(): TeamMember | undefined;
40
+ getByRole(role: string): TeamMember[];
41
+ }
42
+
43
+ interface OrchestrationResult {
44
+ id: string;
45
+ output: string;
46
+ memberOutputs: Map<string, string>;
47
+ messages: AgentMessage[];
48
+ durationMs: number;
49
+ }
50
+ declare class Orchestrator {
51
+ private team;
52
+ private communicator;
53
+ private agents;
54
+ private agentsReady;
55
+ constructor(team: Team);
56
+ private runMember;
57
+ run(task: string): Promise<OrchestrationResult>;
58
+ getCommunicator(): AgentCommunicator;
59
+ getTeam(): Team;
60
+ }
61
+
62
+ export { AgentCommunicator, type AgentMessage, Orchestrator, Team, type TeamConfig, type TeamMember };
@@ -0,0 +1,62 @@
1
+ import { AgentConfig } from '@lupaflow/types';
2
+
3
+ interface AgentMessage {
4
+ id: string;
5
+ from: string;
6
+ to: string;
7
+ content: string;
8
+ type: "request" | "response" | "broadcast";
9
+ timestamp: number;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ declare class AgentCommunicator {
13
+ private messages;
14
+ private listeners;
15
+ send(from: string, to: string, content: string, metadata?: Record<string, unknown>): AgentMessage;
16
+ broadcast(from: string, content: string): void;
17
+ respond(to: string, originalId: string, content: string): AgentMessage;
18
+ on(agentId: string, handler: (msg: AgentMessage) => void): () => void;
19
+ getHistory(): AgentMessage[];
20
+ clear(): void;
21
+ }
22
+
23
+ interface TeamMember {
24
+ id: string;
25
+ name: string;
26
+ role: string;
27
+ agentConfig: AgentConfig;
28
+ }
29
+ interface TeamConfig {
30
+ name: string;
31
+ members: TeamMember[];
32
+ leader?: string;
33
+ description?: string;
34
+ }
35
+ declare class Team {
36
+ config: TeamConfig;
37
+ constructor(config: TeamConfig);
38
+ getMember(idOrName: string): TeamMember | undefined;
39
+ getLeader(): TeamMember | undefined;
40
+ getByRole(role: string): TeamMember[];
41
+ }
42
+
43
+ interface OrchestrationResult {
44
+ id: string;
45
+ output: string;
46
+ memberOutputs: Map<string, string>;
47
+ messages: AgentMessage[];
48
+ durationMs: number;
49
+ }
50
+ declare class Orchestrator {
51
+ private team;
52
+ private communicator;
53
+ private agents;
54
+ private agentsReady;
55
+ constructor(team: Team);
56
+ private runMember;
57
+ run(task: string): Promise<OrchestrationResult>;
58
+ getCommunicator(): AgentCommunicator;
59
+ getTeam(): Team;
60
+ }
61
+
62
+ export { AgentCommunicator, type AgentMessage, Orchestrator, Team, type TeamConfig, type TeamMember };
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ // src/orchestrator.ts
2
+ import { Agent } from "@lupaflow/agent";
3
+
4
+ // src/communication.ts
5
+ import { generateId } from "@lupaflow/core";
6
+ var AgentCommunicator = class {
7
+ messages = [];
8
+ listeners = /* @__PURE__ */ new Map();
9
+ send(from, to, content, metadata) {
10
+ const msg = {
11
+ id: generateId(),
12
+ from,
13
+ to,
14
+ content,
15
+ type: "request",
16
+ timestamp: Date.now(),
17
+ metadata
18
+ };
19
+ this.messages.push(msg);
20
+ const listeners = this.listeners.get(to);
21
+ if (listeners) {
22
+ for (const listener of listeners) {
23
+ listener(msg);
24
+ }
25
+ }
26
+ return msg;
27
+ }
28
+ broadcast(from, content) {
29
+ const msg = {
30
+ id: generateId(),
31
+ from,
32
+ to: "*",
33
+ content,
34
+ type: "broadcast",
35
+ timestamp: Date.now()
36
+ };
37
+ this.messages.push(msg);
38
+ for (const listeners of this.listeners.values()) {
39
+ for (const listener of listeners) {
40
+ listener(msg);
41
+ }
42
+ }
43
+ }
44
+ respond(to, originalId, content) {
45
+ const original = this.messages.find((m) => m.id === originalId);
46
+ const msg = {
47
+ id: generateId(),
48
+ from: to,
49
+ to: original?.from || to,
50
+ content,
51
+ type: "response",
52
+ timestamp: Date.now()
53
+ };
54
+ this.messages.push(msg);
55
+ const listeners = this.listeners.get(msg.to);
56
+ if (listeners) {
57
+ for (const listener of listeners) {
58
+ listener(msg);
59
+ }
60
+ }
61
+ return msg;
62
+ }
63
+ on(agentId, handler) {
64
+ if (!this.listeners.has(agentId)) {
65
+ this.listeners.set(agentId, /* @__PURE__ */ new Set());
66
+ }
67
+ this.listeners.get(agentId).add(handler);
68
+ return () => this.listeners.get(agentId)?.delete(handler);
69
+ }
70
+ getHistory() {
71
+ return [...this.messages];
72
+ }
73
+ clear() {
74
+ this.messages = [];
75
+ }
76
+ };
77
+
78
+ // src/orchestrator.ts
79
+ import { generateId as generateId2 } from "@lupaflow/core";
80
+ var Orchestrator = class {
81
+ team;
82
+ communicator;
83
+ agents = /* @__PURE__ */ new Map();
84
+ agentsReady = /* @__PURE__ */ new Map();
85
+ constructor(team) {
86
+ this.team = team;
87
+ this.communicator = new AgentCommunicator();
88
+ for (const member of team.config.members) {
89
+ const agent = new Agent(member.agentConfig);
90
+ this.agents.set(member.id, agent);
91
+ }
92
+ }
93
+ async runMember(member, task) {
94
+ const agent = this.agents.get(member.id);
95
+ const result = await agent.run(task);
96
+ return result.output;
97
+ }
98
+ async run(task) {
99
+ const start = Date.now();
100
+ const id = generateId2();
101
+ const memberOutputs = /* @__PURE__ */ new Map();
102
+ const leader = this.team.getLeader();
103
+ if (!leader) throw new Error("No leader found in team");
104
+ const leaderResult = await this.runMember(leader, `As the ${leader.role}, oversee this task: ${task}`);
105
+ memberOutputs.set(leader.id, leaderResult);
106
+ const otherMembers = this.team.config.members.filter((m) => m.id !== leader.id);
107
+ for (const member of otherMembers) {
108
+ const msg = this.communicator.send(
109
+ leader.id,
110
+ member.id,
111
+ `Task: ${task}
112
+ Leader's plan: ${leaderResult}
113
+ Your role: ${member.role}
114
+ Execute your part.`
115
+ );
116
+ const memberResult = await this.runMember(member, msg.content);
117
+ memberOutputs.set(member.id, memberResult);
118
+ this.communicator.respond(leader.id, msg.id, memberResult);
119
+ }
120
+ const allOutputs = Array.from(memberOutputs.values()).join("\n\n");
121
+ let finalOutput;
122
+ if (otherMembers.length > 0) {
123
+ const finalResult = await this.runMember(
124
+ leader,
125
+ `Original task: ${task}
126
+
127
+ Here are all the outputs from your team:
128
+ ${allOutputs}
129
+
130
+ Synthesize a final cohesive response.`
131
+ );
132
+ finalOutput = finalResult;
133
+ } else {
134
+ finalOutput = leaderResult;
135
+ }
136
+ return {
137
+ id,
138
+ output: finalOutput,
139
+ memberOutputs,
140
+ messages: this.communicator.getHistory(),
141
+ durationMs: Date.now() - start
142
+ };
143
+ }
144
+ getCommunicator() {
145
+ return this.communicator;
146
+ }
147
+ getTeam() {
148
+ return this.team;
149
+ }
150
+ };
151
+
152
+ // src/team.ts
153
+ import { generateId as generateId3 } from "@lupaflow/core";
154
+ var Team = class {
155
+ config;
156
+ constructor(config) {
157
+ this.config = {
158
+ ...config,
159
+ members: config.members.map((m) => ({ ...m, id: m.id || generateId3() }))
160
+ };
161
+ }
162
+ getMember(idOrName) {
163
+ return this.config.members.find((m) => m.id === idOrName || m.name === idOrName);
164
+ }
165
+ getLeader() {
166
+ if (!this.config.leader) return this.config.members[0];
167
+ return this.getMember(this.config.leader);
168
+ }
169
+ getByRole(role) {
170
+ return this.config.members.filter((m) => m.role === role);
171
+ }
172
+ };
173
+ export {
174
+ AgentCommunicator,
175
+ Orchestrator,
176
+ Team
177
+ };
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/orchestrator.ts","../src/communication.ts","../src/team.ts"],"sourcesContent":["import { Agent } from \"@lupaflow/agent\"\nimport { AgentCommunicator, type AgentMessage } from \"./communication\"\nimport { Team, type TeamMember } from \"./team\"\nimport { generateId } from \"@lupaflow/core\"\n\nexport interface OrchestrationResult {\n id: string\n output: string\n memberOutputs: Map<string, string>\n messages: AgentMessage[]\n durationMs: number\n}\n\nexport class Orchestrator {\n private team: Team\n private communicator: AgentCommunicator\n private agents: Map<string, Agent> = new Map()\n private agentsReady: Map<string, Promise<void>> = new Map()\n\n constructor(team: Team) {\n this.team = team\n this.communicator = new AgentCommunicator()\n for (const member of team.config.members) {\n const agent = new Agent(member.agentConfig)\n this.agents.set(member.id, agent)\n }\n }\n\n private async runMember(member: TeamMember, task: string): Promise<string> {\n const agent = this.agents.get(member.id)!\n const result = await agent.run(task)\n return result.output\n }\n\n async run(task: string): Promise<OrchestrationResult> {\n const start = Date.now()\n const id = generateId()\n const memberOutputs = new Map<string, string>()\n\n const leader = this.team.getLeader()\n if (!leader) throw new Error(\"No leader found in team\")\n\n const leaderResult = await this.runMember(leader, `As the ${leader.role}, oversee this task: ${task}`)\n memberOutputs.set(leader.id, leaderResult)\n\n const otherMembers = this.team.config.members.filter((m) => m.id !== leader.id)\n for (const member of otherMembers) {\n const msg = this.communicator.send(\n leader.id,\n member.id,\n `Task: ${task}\\nLeader's plan: ${leaderResult}\\nYour role: ${member.role}\\nExecute your part.`\n )\n\n const memberResult = await this.runMember(member, msg.content)\n memberOutputs.set(member.id, memberResult)\n\n this.communicator.respond(leader.id, msg.id, memberResult)\n }\n\n const allOutputs = Array.from(memberOutputs.values()).join(\"\\n\\n\")\n let finalOutput: string\n\n if (otherMembers.length > 0) {\n const finalResult = await this.runMember(\n leader,\n `Original task: ${task}\\n\\nHere are all the outputs from your team:\\n${allOutputs}\\n\\nSynthesize a final cohesive response.`\n )\n finalOutput = finalResult\n } else {\n finalOutput = leaderResult\n }\n\n return {\n id,\n output: finalOutput,\n memberOutputs,\n messages: this.communicator.getHistory(),\n durationMs: Date.now() - start,\n }\n }\n\n getCommunicator(): AgentCommunicator {\n return this.communicator\n }\n\n getTeam(): Team {\n return this.team\n }\n}\n","import { generateId } from \"@lupaflow/core\"\n\nexport interface AgentMessage {\n id: string\n from: string\n to: string\n content: string\n type: \"request\" | \"response\" | \"broadcast\"\n timestamp: number\n metadata?: Record<string, unknown>\n}\n\nexport class AgentCommunicator {\n private messages: AgentMessage[] = []\n private listeners: Map<string, Set<(msg: AgentMessage) => void>> = new Map()\n\n send(from: string, to: string, content: string, metadata?: Record<string, unknown>): AgentMessage {\n const msg: AgentMessage = {\n id: generateId(),\n from,\n to,\n content,\n type: \"request\",\n timestamp: Date.now(),\n metadata,\n }\n this.messages.push(msg)\n const listeners = this.listeners.get(to)\n if (listeners) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n return msg\n }\n\n broadcast(from: string, content: string): void {\n const msg: AgentMessage = {\n id: generateId(),\n from,\n to: \"*\",\n content,\n type: \"broadcast\",\n timestamp: Date.now(),\n }\n this.messages.push(msg)\n for (const listeners of this.listeners.values()) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n }\n\n respond(to: string, originalId: string, content: string): AgentMessage {\n const original = this.messages.find((m) => m.id === originalId)\n const msg: AgentMessage = {\n id: generateId(),\n from: to,\n to: original?.from || to,\n content,\n type: \"response\",\n timestamp: Date.now(),\n }\n this.messages.push(msg)\n const listeners = this.listeners.get(msg.to)\n if (listeners) {\n for (const listener of listeners) {\n listener(msg)\n }\n }\n return msg\n }\n\n on(agentId: string, handler: (msg: AgentMessage) => void): () => void {\n if (!this.listeners.has(agentId)) {\n this.listeners.set(agentId, new Set())\n }\n this.listeners.get(agentId)!.add(handler)\n return () => this.listeners.get(agentId)?.delete(handler)\n }\n\n getHistory(): AgentMessage[] {\n return [...this.messages]\n }\n\n clear(): void {\n this.messages = []\n }\n}\n","import type { AgentConfig } from \"@lupaflow/types\"\nimport { generateId } from \"@lupaflow/core\"\n\nexport interface TeamMember {\n id: string\n name: string\n role: string\n agentConfig: AgentConfig\n}\n\nexport interface TeamConfig {\n name: string\n members: TeamMember[]\n leader?: string\n description?: string\n}\n\nexport class Team {\n public config: TeamConfig\n\n constructor(config: TeamConfig) {\n this.config = {\n ...config,\n members: config.members.map((m) => ({ ...m, id: m.id || generateId() })),\n }\n }\n\n getMember(idOrName: string): TeamMember | undefined {\n return this.config.members.find((m) => m.id === idOrName || m.name === idOrName)\n }\n\n getLeader(): TeamMember | undefined {\n if (!this.config.leader) return this.config.members[0]\n return this.getMember(this.config.leader)\n }\n\n getByRole(role: string): TeamMember[] {\n return this.config.members.filter((m) => m.role === role)\n }\n}\n"],"mappings":"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","names":["generateId","generateId"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lupaflow/multi-agent",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -16,7 +16,8 @@
16
16
  "import": "./dist/index.js"
17
17
  }
18
18
  },
19
- "scripts": {
19
+ "files": ["dist", "src", "package.json"],
20
+ "scripts": {
20
21
  "build": "tsup",
21
22
  "dev": "tsup --watch"
22
23
  },
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src"
6
- },
7
- "include": ["src"]
8
- }
package/tsup.config.ts DELETED
@@ -1,9 +0,0 @@
1
- import { defineConfig } from "tsup"
2
- export default defineConfig({
3
- entry: { index: "src/index.ts" },
4
- format: ["cjs", "esm"],
5
- dts: true,
6
- sourcemap: true,
7
- clean: true,
8
- external: [/node_modules/],
9
- })