@artinet/agent-relay-mcp 0.0.1 → 0.0.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/README.md +3 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +31 -1
- package/dist/src/server.d.ts +1 -1
- package/dist/src/server.js +2 -2
- package/package.json +9 -9
- package/dist/src/manager.d.ts +0 -19
- package/dist/src/manager.js +0 -56
- package/dist/src/relay.d.ts +0 -36
- package/dist/src/relay.js +0 -157
- package/dist/src/scan.d.ts +0 -7
- package/dist/src/scan.js +0 -30
- package/dist/src/sync.d.ts +0 -26
- package/dist/src/sync.js +0 -98
- package/dist/src/types/config.d.ts +0 -76
- package/dist/src/types/config.js +0 -12
- package/dist/src/types/index.d.ts +0 -4
- package/dist/src/types/index.js +0 -4
- package/dist/src/types/manager.d.ts +0 -14
- package/dist/src/types/manager.js +0 -1
- package/dist/src/types/relay.d.ts +0 -16
- package/dist/src/types/relay.js +0 -1
- package/dist/src/types/schema.d.ts +0 -19
- package/dist/src/types/schema.js +0 -16
package/README.md
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
# Agent Relay MCP Server
|
|
10
10
|
|
|
11
|
-
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that enables AI agents to discover and communicate with other [A2A (Agent-to-Agent)](https://github.com/a2aproject/A2A) enabled AI agents through the [@artinet/sdk](https://github.com/the-artinet-project/artinet-sdk).
|
|
11
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that enables AI agents to discover and communicate with other [A2A (Agent-to-Agent)](https://github.com/a2aproject/A2A) enabled AI agents through the [@artinet/sdk](https://github.com/the-artinet-project/artinet-sdk) and [@artinet/agent-relay](https://github.com/the-artinet-project/agent-relay).
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
15
|
- **Automatic Agent Discovery**: Scans network ports to discover available agents
|
|
16
|
+
- **Multi-Agent Orchestration**: Coordinate workflows across multiple specialized agents
|
|
16
17
|
- **Message Relay**: Send messages to agents and receive responses with full task context
|
|
17
18
|
- **Task Management**: Query task status and cancel running tasks
|
|
18
19
|
- **Agent Discovery**: View and search agents by name, description, or skills
|
|
19
|
-
- **Multi-Agent Orchestration**: Coordinate workflows across multiple specialized agents
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
@@ -38,7 +38,7 @@ Example:
|
|
|
38
38
|
npx @artinet/agent-relay-mcp my-assistant 3000 3100 10
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
\*
|
|
41
|
+
\*We recommend allocating a small port range because port scanning is resource intensive.
|
|
42
42
|
|
|
43
43
|
### As an MCP Server
|
|
44
44
|
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./server.js";
|
|
2
|
-
export * from "
|
|
2
|
+
export * from "@artinet/agent-relay";
|
package/dist/src/index.js
CHANGED
|
@@ -1,2 +1,32 @@
|
|
|
1
|
+
// import * as z from "zod";
|
|
2
|
+
// import { ScanConfigSchema } from "@artinet/agent-relay";
|
|
3
|
+
// import { RelayServer } from "./server.js";
|
|
4
|
+
//for smithery
|
|
5
|
+
// export const configSchema = z.object({
|
|
6
|
+
// callerId: z.string(),
|
|
7
|
+
// syncInterval: z.number().optional(),
|
|
8
|
+
// scanConfig: ScanConfigSchema.optional(),
|
|
9
|
+
// });
|
|
10
|
+
// type Config = z.infer<typeof configSchema>;
|
|
11
|
+
// export default async function createServer({ config }: { config: Config }) {
|
|
12
|
+
// const server = new RelayServer({
|
|
13
|
+
// name: "agent-relay-server",
|
|
14
|
+
// version: "0.0.1",
|
|
15
|
+
// });
|
|
16
|
+
// await server.init({
|
|
17
|
+
// callerId: config.callerId,
|
|
18
|
+
// syncInterval: config.syncInterval ?? 2500,
|
|
19
|
+
// scanConfig: {
|
|
20
|
+
// ...(config.scanConfig ?? {}),
|
|
21
|
+
// host: config.scanConfig?.host ?? "localhost",
|
|
22
|
+
// startPort: config.scanConfig?.startPort ?? 3000,
|
|
23
|
+
// endPort: config.scanConfig?.endPort ?? 3100,
|
|
24
|
+
// threads: config.scanConfig?.threads ?? 10,
|
|
25
|
+
// fallbackPath:
|
|
26
|
+
// config.scanConfig?.fallbackPath ?? "/.well-known/agent-card.json",
|
|
27
|
+
// },
|
|
28
|
+
// });
|
|
29
|
+
// return server.server;
|
|
30
|
+
// }
|
|
1
31
|
export * from "./server.js";
|
|
2
|
-
export * from "
|
|
32
|
+
export * from "@artinet/agent-relay";
|
package/dist/src/server.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
7
|
import { Implementation } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
-
import { AgentRelayConfig } from "
|
|
8
|
+
import { AgentRelayConfig } from "@artinet/agent-relay";
|
|
9
9
|
declare class RelayServer extends McpServer {
|
|
10
10
|
private relay;
|
|
11
11
|
constructor(info?: Implementation, options?: ServerOptions);
|
package/dist/src/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { AgentRelay } from "
|
|
2
|
+
import { AgentRelay } from "@artinet/agent-relay";
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
4
|
import { TaskSchema, AgentCardSchema, SendMessageSuccessResultSchema, getContent, } from "@artinet/sdk";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -138,7 +138,7 @@ The assistant should always return the result to the user in a clear and concise
|
|
|
138
138
|
});
|
|
139
139
|
this.registerTool("getAgentCard", {
|
|
140
140
|
title: "Get Agent Card",
|
|
141
|
-
description: "Get the
|
|
141
|
+
description: "Get the AgentCard that describes the capabilities and skills of an agent",
|
|
142
142
|
inputSchema: z.object({
|
|
143
143
|
agentId: z
|
|
144
144
|
.string()
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artinet/agent-relay-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A Model Context Protocol (MCP) server for relaying messages between A2A enabled AI agents.",
|
|
5
5
|
"author": "artinet",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/the-artinet-project/mcp
|
|
9
|
+
"url": "git+https://github.com/the-artinet-project/mcp.git#main"
|
|
10
10
|
},
|
|
11
11
|
"issues": {
|
|
12
12
|
"url": "https://github.com/the-artinet-project/mcp/issues"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"LICENSE"
|
|
19
19
|
],
|
|
20
20
|
"bin": {
|
|
21
|
-
"agent-relay-mcp": "
|
|
21
|
+
"agent-relay-mcp": "dist/bin/stdio.js"
|
|
22
22
|
},
|
|
23
23
|
"keywords": [
|
|
24
24
|
"artinet",
|
|
@@ -45,19 +45,19 @@
|
|
|
45
45
|
"build": "tsc --project tsconfig.json",
|
|
46
46
|
"clean": "rimraf dist",
|
|
47
47
|
"clean:all": "rimraf dist node_modules package-lock.json",
|
|
48
|
-
"dev": "tsc --watch",
|
|
49
48
|
"start": "node dist/bin/stdio.js",
|
|
50
49
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
51
50
|
"prepublishOnly": "npm run clean:all && npm i && npm run build && npm test"
|
|
52
51
|
},
|
|
53
52
|
"dependencies": {
|
|
54
|
-
"@artinet/sdk": "^0.5.
|
|
55
|
-
"@artinet/
|
|
56
|
-
"@
|
|
53
|
+
"@artinet/sdk": "^0.5.13",
|
|
54
|
+
"@artinet/agent-relay": "^0.0.3",
|
|
55
|
+
"@artinet/types": "^0.0.5",
|
|
56
|
+
"@modelcontextprotocol/sdk": "1.20.0",
|
|
57
57
|
"p-limit": "^7.2.0",
|
|
58
58
|
"portscanner": "^2.2.0",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
59
|
+
"uuid": "^11.1.0",
|
|
60
|
+
"zod": "^3.23.8"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/node": "^20.17.50",
|
package/dist/src/manager.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { AgentCard } from "@artinet/sdk";
|
|
6
|
-
import { IAgentManager, AgentType, ClientConfig } from "./types/index.js";
|
|
7
|
-
export declare function getAgentCard(agent: AgentType | ClientConfig): Promise<AgentCard | undefined>;
|
|
8
|
-
export declare class AgentManager implements IAgentManager {
|
|
9
|
-
private agents;
|
|
10
|
-
constructor(agents?: Map<string, AgentType>);
|
|
11
|
-
getAgent(id: string): AgentType | undefined;
|
|
12
|
-
setAgent(agent: AgentType): Promise<void>;
|
|
13
|
-
deleteAgent(id: string): void;
|
|
14
|
-
getAgents(): AgentType[];
|
|
15
|
-
getAgentCards(): Promise<AgentCard[]>;
|
|
16
|
-
getAgentCount(): number;
|
|
17
|
-
getAgentIds(): string[];
|
|
18
|
-
close(): Promise<void>;
|
|
19
|
-
}
|
package/dist/src/manager.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { A2AClient, A2AService } from "@artinet/sdk";
|
|
6
|
-
export async function getAgentCard(agent) {
|
|
7
|
-
if (agent instanceof A2AClient) {
|
|
8
|
-
return await agent.agentCard();
|
|
9
|
-
}
|
|
10
|
-
else if (agent instanceof A2AService) {
|
|
11
|
-
return agent.agentCard;
|
|
12
|
-
}
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
export class AgentManager {
|
|
16
|
-
agents = new Map();
|
|
17
|
-
constructor(agents = new Map()) {
|
|
18
|
-
this.agents = agents;
|
|
19
|
-
}
|
|
20
|
-
getAgent(id) {
|
|
21
|
-
return this.agents.get(id);
|
|
22
|
-
}
|
|
23
|
-
async setAgent(agent) {
|
|
24
|
-
if (agent instanceof A2AClient) {
|
|
25
|
-
const agentCard = await agent.agentCard();
|
|
26
|
-
this.agents.set(agentCard.name, agent);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
this.agents.set(agent.agentCard.name, agent);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
deleteAgent(id) {
|
|
33
|
-
this.agents.delete(id);
|
|
34
|
-
}
|
|
35
|
-
getAgents() {
|
|
36
|
-
return Array.from(this.agents.values());
|
|
37
|
-
}
|
|
38
|
-
async getAgentCards() {
|
|
39
|
-
const agents = this.getAgents();
|
|
40
|
-
const agentCards = await Promise.all(agents.map(async (agent) => await getAgentCard(agent)));
|
|
41
|
-
return agentCards.filter((agentCard) => agentCard !== undefined);
|
|
42
|
-
}
|
|
43
|
-
getAgentCount() {
|
|
44
|
-
return this.agents.size;
|
|
45
|
-
}
|
|
46
|
-
getAgentIds() {
|
|
47
|
-
return Array.from(this.agents.keys());
|
|
48
|
-
}
|
|
49
|
-
async close() {
|
|
50
|
-
await Promise.all(Array.from(this.agents.values()).map(async (agent) => {
|
|
51
|
-
if ("stop" in agent) {
|
|
52
|
-
await agent.stop();
|
|
53
|
-
}
|
|
54
|
-
}));
|
|
55
|
-
}
|
|
56
|
-
}
|
package/dist/src/relay.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { AgentCard, MessageSendParams, SendMessageSuccessResult, TaskQueryParams, Task, TaskIdParams } from "@artinet/sdk";
|
|
6
|
-
import { AgentType, IAgentRelay, ClientConfig, AgentRelayConfig } from "./types/index.js";
|
|
7
|
-
import { AgentManager } from "./manager.js";
|
|
8
|
-
export declare const DEFAULT_SYNC_INTERVAL: number;
|
|
9
|
-
/**
|
|
10
|
-
* @description AgentRelay is a class that manages the agents and their interactions.
|
|
11
|
-
* It scans for agents on the network and registers them.
|
|
12
|
-
* It also provides a way to send messages to the agents and get tasks from them.
|
|
13
|
-
* It also provides a way to get the agent card and search for agents.
|
|
14
|
-
*/
|
|
15
|
-
export declare class AgentRelay extends AgentManager implements IAgentRelay {
|
|
16
|
-
private config;
|
|
17
|
-
private timeoutId;
|
|
18
|
-
constructor(config: AgentRelayConfig);
|
|
19
|
-
/**
|
|
20
|
-
* @description Create a new AgentRelay instance and ensure its ready to use
|
|
21
|
-
* @param config - The configuration for the AgentRelay
|
|
22
|
-
* @returns The AgentRelay instance
|
|
23
|
-
*/
|
|
24
|
-
static create(config: AgentRelayConfig): Promise<AgentRelay>;
|
|
25
|
-
getAgent(agentId: string): AgentType | undefined;
|
|
26
|
-
close(): Promise<void>;
|
|
27
|
-
private startSync;
|
|
28
|
-
private findAgents;
|
|
29
|
-
registerAgent(agent: AgentType | ClientConfig): Promise<AgentCard>;
|
|
30
|
-
deregisterAgent(id: string): Promise<void>;
|
|
31
|
-
sendMessage(agentId: string, messageParams: MessageSendParams): Promise<SendMessageSuccessResult>;
|
|
32
|
-
getTask(agentId: string, taskQuery: TaskQueryParams): Promise<Task>;
|
|
33
|
-
cancelTask(agentId: string, taskId: TaskIdParams): Promise<Task>;
|
|
34
|
-
getAgentCard(agentId: string): Promise<AgentCard>;
|
|
35
|
-
searchAgents(query: string): Promise<AgentCard[]>;
|
|
36
|
-
}
|
package/dist/src/relay.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { A2AClient, } from "@artinet/sdk";
|
|
6
|
-
import { AgentManager, getAgentCard } from "./manager.js";
|
|
7
|
-
import { scanAgents, DEFAULT_MAX_THREADS } from "./scan.js";
|
|
8
|
-
import { getAgentRuntimePath } from "./sync.js";
|
|
9
|
-
export const DEFAULT_SYNC_INTERVAL = parseInt(process.env.ARTINET_RELAY_SYNC_INTERVAL || "30000");
|
|
10
|
-
/**
|
|
11
|
-
* @description AgentRelay is a class that manages the agents and their interactions.
|
|
12
|
-
* It scans for agents on the network and registers them.
|
|
13
|
-
* It also provides a way to send messages to the agents and get tasks from them.
|
|
14
|
-
* It also provides a way to get the agent card and search for agents.
|
|
15
|
-
*/
|
|
16
|
-
export class AgentRelay extends AgentManager {
|
|
17
|
-
config;
|
|
18
|
-
timeoutId = null;
|
|
19
|
-
constructor(config) {
|
|
20
|
-
super(config.agents);
|
|
21
|
-
this.config = {
|
|
22
|
-
...config,
|
|
23
|
-
abortSignal: config.abortSignal ?? new AbortController().signal,
|
|
24
|
-
syncInterval: config.syncInterval ?? DEFAULT_SYNC_INTERVAL,
|
|
25
|
-
configPath: config.configPath ?? getAgentRuntimePath(),
|
|
26
|
-
scanConfig: {
|
|
27
|
-
...(config.scanConfig ?? {}),
|
|
28
|
-
host: config.scanConfig?.host ?? "localhost",
|
|
29
|
-
startPort: config.scanConfig?.startPort ?? 3000,
|
|
30
|
-
endPort: config.scanConfig?.endPort ?? 5000,
|
|
31
|
-
threads: config.scanConfig?.threads ?? DEFAULT_MAX_THREADS,
|
|
32
|
-
},
|
|
33
|
-
agents: config.agents ?? new Map(),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* @description Create a new AgentRelay instance and ensure its ready to use
|
|
38
|
-
* @param config - The configuration for the AgentRelay
|
|
39
|
-
* @returns The AgentRelay instance
|
|
40
|
-
*/
|
|
41
|
-
static async create(config) {
|
|
42
|
-
const relay = new AgentRelay(config);
|
|
43
|
-
await relay.findAgents(relay.config.scanConfig);
|
|
44
|
-
relay.startSync().catch((error) => {
|
|
45
|
-
console.error("Error running sync: ", error);
|
|
46
|
-
throw error;
|
|
47
|
-
});
|
|
48
|
-
return relay;
|
|
49
|
-
}
|
|
50
|
-
getAgent(agentId) {
|
|
51
|
-
//to avoid recursive calls
|
|
52
|
-
if (agentId === this.config.callerId) {
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
return super.getAgent(agentId);
|
|
56
|
-
}
|
|
57
|
-
async close() {
|
|
58
|
-
if (this.timeoutId) {
|
|
59
|
-
clearTimeout(this.timeoutId);
|
|
60
|
-
}
|
|
61
|
-
await super.close();
|
|
62
|
-
}
|
|
63
|
-
async startSync() {
|
|
64
|
-
this.timeoutId = setInterval(async () => {
|
|
65
|
-
await this.findAgents(this.config.scanConfig);
|
|
66
|
-
}, this.config.syncInterval);
|
|
67
|
-
}
|
|
68
|
-
async findAgents(config) {
|
|
69
|
-
const configs = await scanAgents(config).catch((error) => {
|
|
70
|
-
console.error(`Error scanning agents: ${error}`);
|
|
71
|
-
return [];
|
|
72
|
-
});
|
|
73
|
-
for (const config of configs) {
|
|
74
|
-
await this.registerAgent(config).catch((error) => {
|
|
75
|
-
console.error(`Error registering agent: ${error}`);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
//todo if agent is not a server, serverfy it?
|
|
80
|
-
// I think we'll avoid this for now
|
|
81
|
-
// Because it will allow Relay's to have local environments that are unique to them
|
|
82
|
-
async registerAgent(agent) {
|
|
83
|
-
let agentCard = await getAgentCard(agent);
|
|
84
|
-
if (!agentCard &&
|
|
85
|
-
"url" in agent &&
|
|
86
|
-
"headers" in agent &&
|
|
87
|
-
"fallbackPath" in agent) {
|
|
88
|
-
try {
|
|
89
|
-
agent = new A2AClient(agent.url, agent.headers, agent.fallbackPath);
|
|
90
|
-
agentCard = await agent.agentCard();
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
console.error("error creating client for agent: ", error);
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else if (!agentCard) {
|
|
98
|
-
throw new Error("Invalid agent type");
|
|
99
|
-
}
|
|
100
|
-
await super.setAgent(agent);
|
|
101
|
-
return agentCard;
|
|
102
|
-
}
|
|
103
|
-
async deregisterAgent(id) {
|
|
104
|
-
super.deleteAgent(id);
|
|
105
|
-
}
|
|
106
|
-
async sendMessage(agentId, messageParams) {
|
|
107
|
-
const agent = this.getAgent(agentId);
|
|
108
|
-
if (!agent) {
|
|
109
|
-
throw new Error(`Agent ${agentId} not found`);
|
|
110
|
-
}
|
|
111
|
-
const sendMessageResult = await agent.sendMessage(messageParams);
|
|
112
|
-
if (!sendMessageResult) {
|
|
113
|
-
throw new Error(`Failed to send message to agent ${agentId}`);
|
|
114
|
-
}
|
|
115
|
-
return sendMessageResult;
|
|
116
|
-
}
|
|
117
|
-
async getTask(agentId, taskQuery) {
|
|
118
|
-
const agent = this.getAgent(agentId);
|
|
119
|
-
if (!agent) {
|
|
120
|
-
throw new Error(`Agent ${agentId} not found`);
|
|
121
|
-
}
|
|
122
|
-
const task = await agent.getTask(taskQuery);
|
|
123
|
-
if (!task) {
|
|
124
|
-
throw new Error(`Task ${agentId} not found`);
|
|
125
|
-
}
|
|
126
|
-
return task;
|
|
127
|
-
}
|
|
128
|
-
async cancelTask(agentId, taskId) {
|
|
129
|
-
const agent = this.getAgent(agentId);
|
|
130
|
-
if (!agent) {
|
|
131
|
-
throw new Error(`Agent ${agentId} not found`);
|
|
132
|
-
}
|
|
133
|
-
const task = await agent.cancelTask(taskId);
|
|
134
|
-
if (!task) {
|
|
135
|
-
throw new Error(`Task ${agentId} not found`);
|
|
136
|
-
}
|
|
137
|
-
return task;
|
|
138
|
-
}
|
|
139
|
-
async getAgentCard(agentId) {
|
|
140
|
-
const agent = this.getAgent(agentId);
|
|
141
|
-
if (!agent) {
|
|
142
|
-
throw new Error(`Agent ${agentId} not found`);
|
|
143
|
-
}
|
|
144
|
-
let agentCard = await getAgentCard(agent);
|
|
145
|
-
if (!agentCard) {
|
|
146
|
-
throw new Error(`Invalid agent type`);
|
|
147
|
-
}
|
|
148
|
-
return agentCard;
|
|
149
|
-
}
|
|
150
|
-
async searchAgents(query) {
|
|
151
|
-
const agents = this.getAgents();
|
|
152
|
-
return (await Promise.all(agents.map(async (agent) => agent instanceof A2AClient ? await agent.agentCard() : agent.agentCard))).filter((agentCard) => agentCard.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
153
|
-
agentCard.description.toLowerCase().includes(query.toLowerCase()) ||
|
|
154
|
-
agentCard.skills.some((skill) => skill.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
155
|
-
skill.description.toLowerCase().includes(query.toLowerCase())));
|
|
156
|
-
}
|
|
157
|
-
}
|
package/dist/src/scan.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { ClientConfig, ScanConfig } from "./types/index.js";
|
|
6
|
-
export declare const DEFAULT_MAX_THREADS = 250;
|
|
7
|
-
export declare function scanAgents(config: ScanConfig): Promise<ClientConfig[]>;
|
package/dist/src/scan.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as portscanner from "portscanner";
|
|
2
|
-
import pLimit from "p-limit";
|
|
3
|
-
export const DEFAULT_MAX_THREADS = 250;
|
|
4
|
-
export async function scanAgents(config) {
|
|
5
|
-
//avoid overwhelming the port scanner
|
|
6
|
-
const limit = pLimit(config.threads ?? DEFAULT_MAX_THREADS);
|
|
7
|
-
const portChecks = [];
|
|
8
|
-
for (let port = config.startPort; port <= config.endPort; port++) {
|
|
9
|
-
portChecks.push(limit(async () => await portscanner
|
|
10
|
-
.checkPortStatus(port, config.host)
|
|
11
|
-
.then((status) => ({ port, status }))));
|
|
12
|
-
}
|
|
13
|
-
const results = await Promise.all(portChecks);
|
|
14
|
-
const openPorts = results
|
|
15
|
-
.filter((r) => r.status === "open")
|
|
16
|
-
.map((r) => r.port);
|
|
17
|
-
if (!openPorts?.length) {
|
|
18
|
-
// console.log("No open ports found");
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
const configs = [];
|
|
22
|
-
for (const port of openPorts) {
|
|
23
|
-
configs.push({
|
|
24
|
-
url: `http://${config.host}:${port}`,
|
|
25
|
-
headers: config.headers,
|
|
26
|
-
fallbackPath: config.fallbackPath,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return configs;
|
|
30
|
-
}
|
package/dist/src/sync.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { IRuntimeSync, SyncConfig } from "./types/index.js";
|
|
6
|
-
import { AgentRuntime } from "./types/config.js";
|
|
7
|
-
export declare const DEFAULT_RELAY_CONFIG_PATH: string;
|
|
8
|
-
export declare function getAgentRuntimePath(configPath?: string): string;
|
|
9
|
-
export declare class RuntimeLoader {
|
|
10
|
-
private configPath;
|
|
11
|
-
constructor(configPath?: string);
|
|
12
|
-
loadAgentRuntime(): Promise<AgentRuntime>;
|
|
13
|
-
saveAgentRuntime(agentRuntime: AgentRuntime): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
export declare class Sync extends RuntimeLoader implements IRuntimeSync {
|
|
16
|
-
private syncInterval;
|
|
17
|
-
private runtime;
|
|
18
|
-
private abortSignal;
|
|
19
|
-
private _isRunning;
|
|
20
|
-
constructor(config: SyncConfig);
|
|
21
|
-
private initializeSync;
|
|
22
|
-
getRuntime(): Promise<AgentRuntime>;
|
|
23
|
-
updateRuntime(data: AgentRuntime): Promise<boolean>;
|
|
24
|
-
isRunning(): boolean;
|
|
25
|
-
close(): void;
|
|
26
|
-
}
|
package/dist/src/sync.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { AgentRuntimeSchema, } from "./types/index.js";
|
|
6
|
-
import { join } from "path";
|
|
7
|
-
import { homedir } from "os";
|
|
8
|
-
import fs from "fs/promises";
|
|
9
|
-
import { dirname } from "path";
|
|
10
|
-
export const DEFAULT_RELAY_CONFIG_PATH = process.env.ARTINET_RELAY_CONFIG_DIR ||
|
|
11
|
-
(process.env.XDG_CONFIG_HOME
|
|
12
|
-
? join(process.env.XDG_CONFIG_HOME, "symphony")
|
|
13
|
-
: join(homedir(), ".config", "symphony"));
|
|
14
|
-
export function getAgentRuntimePath(configPath = DEFAULT_RELAY_CONFIG_PATH) {
|
|
15
|
-
return join(configPath, "agent-runtime.json");
|
|
16
|
-
}
|
|
17
|
-
export class RuntimeLoader {
|
|
18
|
-
configPath;
|
|
19
|
-
constructor(configPath = DEFAULT_RELAY_CONFIG_PATH) {
|
|
20
|
-
this.configPath = configPath;
|
|
21
|
-
}
|
|
22
|
-
async loadAgentRuntime() {
|
|
23
|
-
const runtimeFilePath = getAgentRuntimePath(this.configPath);
|
|
24
|
-
const dir = dirname(runtimeFilePath);
|
|
25
|
-
try {
|
|
26
|
-
await fs.access(dir);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
await fs.mkdir(dir, { recursive: true });
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
await fs.access(runtimeFilePath);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
await fs.writeFile(runtimeFilePath, "{}", "utf8");
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
await fs.access(runtimeFilePath);
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
throw new Error(`agent runtime file does not exist or is not accessible: ${runtimeFilePath}`);
|
|
42
|
-
}
|
|
43
|
-
const agentRuntime = await fs.readFile(runtimeFilePath, "utf8");
|
|
44
|
-
if (agentRuntime.trim() === "") {
|
|
45
|
-
throw new Error("agent runtime file is empty");
|
|
46
|
-
}
|
|
47
|
-
const parsedRuntime = AgentRuntimeSchema.safeParse(JSON.parse(agentRuntime));
|
|
48
|
-
if (parsedRuntime.error) {
|
|
49
|
-
throw new Error("invalid agent runtime file: " + parsedRuntime.error.message);
|
|
50
|
-
}
|
|
51
|
-
// filter out removed agents
|
|
52
|
-
// we do this here so that all runtimes know not to add the removed agent to their runtime
|
|
53
|
-
const runtime = Object.fromEntries(Object.entries(parsedRuntime.data).filter(([_, value]) => value.removed === undefined ? true : value.removed !== true));
|
|
54
|
-
return runtime;
|
|
55
|
-
}
|
|
56
|
-
async saveAgentRuntime(agentRuntime) {
|
|
57
|
-
const runtimeFilePath = getAgentRuntimePath(this.configPath);
|
|
58
|
-
const currentRuntime = await this.loadAgentRuntime();
|
|
59
|
-
const newRuntime = { ...currentRuntime, ...agentRuntime };
|
|
60
|
-
await fs.writeFile(runtimeFilePath, JSON.stringify(newRuntime, null, 2), "utf8");
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
export class Sync extends RuntimeLoader {
|
|
64
|
-
syncInterval;
|
|
65
|
-
runtime = {};
|
|
66
|
-
abortSignal;
|
|
67
|
-
_isRunning = false;
|
|
68
|
-
constructor(config) {
|
|
69
|
-
super(config.configPath);
|
|
70
|
-
this.syncInterval = config.syncInterval;
|
|
71
|
-
this.abortSignal = config.abortSignal;
|
|
72
|
-
this.initializeSync().catch((error) => {
|
|
73
|
-
console.error("Error syncing runtime: ", error);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
async initializeSync() {
|
|
77
|
-
this._isRunning = true;
|
|
78
|
-
while (!this.abortSignal.aborted && this._isRunning) {
|
|
79
|
-
this.runtime = await this.loadAgentRuntime();
|
|
80
|
-
await new Promise((resolve) => setTimeout(resolve, this.syncInterval));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async getRuntime() {
|
|
84
|
-
this.runtime = await this.loadAgentRuntime();
|
|
85
|
-
return this.runtime;
|
|
86
|
-
}
|
|
87
|
-
async updateRuntime(data) {
|
|
88
|
-
this.runtime = { ...this.runtime, ...data };
|
|
89
|
-
await this.saveAgentRuntime(this.runtime);
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
isRunning() {
|
|
93
|
-
return this._isRunning;
|
|
94
|
-
}
|
|
95
|
-
close() {
|
|
96
|
-
this._isRunning = false;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { AgentType } from "./manager.js";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
export declare const RuntimeServerConfigSchema: z.ZodObject<{
|
|
4
|
-
id: z.ZodOptional<z.ZodString>;
|
|
5
|
-
url: z.ZodString;
|
|
6
|
-
} & {
|
|
7
|
-
blocklist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
8
|
-
} & {
|
|
9
|
-
removed: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
11
|
-
fallbackPath: z.ZodOptional<z.ZodString>;
|
|
12
|
-
}, "strip", z.ZodTypeAny, {
|
|
13
|
-
url: string;
|
|
14
|
-
id?: string | undefined;
|
|
15
|
-
headers?: Record<string, string> | undefined;
|
|
16
|
-
blocklist?: string[] | undefined;
|
|
17
|
-
removed?: boolean | undefined;
|
|
18
|
-
fallbackPath?: string | undefined;
|
|
19
|
-
}, {
|
|
20
|
-
url: string;
|
|
21
|
-
id?: string | undefined;
|
|
22
|
-
headers?: Record<string, string> | undefined;
|
|
23
|
-
blocklist?: string[] | undefined;
|
|
24
|
-
removed?: boolean | undefined;
|
|
25
|
-
fallbackPath?: string | undefined;
|
|
26
|
-
}>;
|
|
27
|
-
export type RuntimeServerConfig = z.infer<typeof RuntimeServerConfigSchema>;
|
|
28
|
-
export declare const AgentRuntimeSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
29
|
-
id: z.ZodOptional<z.ZodString>;
|
|
30
|
-
url: z.ZodString;
|
|
31
|
-
} & {
|
|
32
|
-
blocklist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
33
|
-
} & {
|
|
34
|
-
removed: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
36
|
-
fallbackPath: z.ZodOptional<z.ZodString>;
|
|
37
|
-
}, "strip", z.ZodTypeAny, {
|
|
38
|
-
url: string;
|
|
39
|
-
id?: string | undefined;
|
|
40
|
-
headers?: Record<string, string> | undefined;
|
|
41
|
-
blocklist?: string[] | undefined;
|
|
42
|
-
removed?: boolean | undefined;
|
|
43
|
-
fallbackPath?: string | undefined;
|
|
44
|
-
}, {
|
|
45
|
-
url: string;
|
|
46
|
-
id?: string | undefined;
|
|
47
|
-
headers?: Record<string, string> | undefined;
|
|
48
|
-
blocklist?: string[] | undefined;
|
|
49
|
-
removed?: boolean | undefined;
|
|
50
|
-
fallbackPath?: string | undefined;
|
|
51
|
-
}>>;
|
|
52
|
-
export type AgentRuntime = z.infer<typeof AgentRuntimeSchema>;
|
|
53
|
-
export interface IRuntimeSync {
|
|
54
|
-
getRuntime(): Promise<AgentRuntime>;
|
|
55
|
-
updateRuntime(data: AgentRuntime): Promise<boolean>;
|
|
56
|
-
}
|
|
57
|
-
export interface RuntimeLoaderConfig {
|
|
58
|
-
configPath: string;
|
|
59
|
-
}
|
|
60
|
-
export interface SyncConfig extends Partial<RuntimeLoaderConfig> {
|
|
61
|
-
abortSignal: AbortSignal;
|
|
62
|
-
syncInterval: number;
|
|
63
|
-
}
|
|
64
|
-
export interface ScanConfig {
|
|
65
|
-
host: string;
|
|
66
|
-
startPort: number;
|
|
67
|
-
endPort: number;
|
|
68
|
-
headers?: Record<string, string>;
|
|
69
|
-
fallbackPath?: string;
|
|
70
|
-
threads?: number;
|
|
71
|
-
}
|
|
72
|
-
export interface AgentRelayConfig extends Partial<SyncConfig> {
|
|
73
|
-
callerId: string;
|
|
74
|
-
scanConfig?: ScanConfig;
|
|
75
|
-
agents?: Map<string, AgentType>;
|
|
76
|
-
}
|
package/dist/src/types/config.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { RemoteServerConfigSchema } from "@artinet/types";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
export const RuntimeServerConfigSchema = RemoteServerConfigSchema.extend({
|
|
8
|
-
removed: z.boolean().optional(),
|
|
9
|
-
headers: z.record(z.string(), z.string()).optional(),
|
|
10
|
-
fallbackPath: z.string().optional(),
|
|
11
|
-
});
|
|
12
|
-
export const AgentRuntimeSchema = z.record(z.string(), RuntimeServerConfigSchema);
|
package/dist/src/types/index.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { Agent, A2AClient } from "@artinet/sdk";
|
|
6
|
-
export type AgentType = Agent | A2AClient;
|
|
7
|
-
export interface IAgentManager {
|
|
8
|
-
getAgent(id: string): AgentType | undefined;
|
|
9
|
-
setAgent(agent: AgentType): Promise<void>;
|
|
10
|
-
deleteAgent(id: string): void;
|
|
11
|
-
getAgents(): AgentType[];
|
|
12
|
-
getAgentCount(): number;
|
|
13
|
-
getAgentIds(): string[];
|
|
14
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { AgentType, IAgentManager } from "./manager.js";
|
|
6
|
-
import { ClientConfig } from "./schema.js";
|
|
7
|
-
import { AgentCard, TaskQueryParams, Task, TaskIdParams, MessageSendParams, SendMessageSuccessResult } from "@artinet/sdk";
|
|
8
|
-
export interface IAgentRelay extends IAgentManager {
|
|
9
|
-
registerAgent(agent: AgentType | ClientConfig): Promise<AgentCard>;
|
|
10
|
-
deregisterAgent(agentId: string): Promise<void>;
|
|
11
|
-
sendMessage(agentId: string, messageParams: MessageSendParams): Promise<SendMessageSuccessResult>;
|
|
12
|
-
getTask(agentId: string, taskQuery: TaskQueryParams): Promise<Task>;
|
|
13
|
-
cancelTask(agentId: string, taskId: TaskIdParams): Promise<Task>;
|
|
14
|
-
getAgentCard(agentId: string): Promise<AgentCard | undefined>;
|
|
15
|
-
searchAgents(query: string): Promise<AgentCard[]>;
|
|
16
|
-
}
|
package/dist/src/types/relay.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import z from "zod";
|
|
6
|
-
export declare const ClientConfigSchema: z.ZodObject<{
|
|
7
|
-
url: z.ZodString;
|
|
8
|
-
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
9
|
-
fallbackPath: z.ZodOptional<z.ZodString>;
|
|
10
|
-
}, "strip", z.ZodTypeAny, {
|
|
11
|
-
url: string;
|
|
12
|
-
headers?: Record<string, string> | undefined;
|
|
13
|
-
fallbackPath?: string | undefined;
|
|
14
|
-
}, {
|
|
15
|
-
url: string;
|
|
16
|
-
headers?: Record<string, string> | undefined;
|
|
17
|
-
fallbackPath?: string | undefined;
|
|
18
|
-
}>;
|
|
19
|
-
export type ClientConfig = z.infer<typeof ClientConfigSchema>;
|
package/dist/src/types/schema.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 The Artinet Project
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import z from "zod";
|
|
6
|
-
export const ClientConfigSchema = z.object({
|
|
7
|
-
url: z.string().url().describe("The URL of the agent to register."),
|
|
8
|
-
headers: z
|
|
9
|
-
.record(z.string(), z.string())
|
|
10
|
-
.optional()
|
|
11
|
-
.describe("The headers to send to the agent."),
|
|
12
|
-
fallbackPath: z
|
|
13
|
-
.string()
|
|
14
|
-
.optional()
|
|
15
|
-
.describe("The fallback path to use if the agent does not support the request."),
|
|
16
|
-
});
|