@dainprotocol/cli 1.0.27 → 1.0.28
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/commands/init.js +8 -0
- package/dist/commands/testchat.js +12 -12
- package/dist/templates/default/package.json +7 -9
- package/dist/templates/default/src/index.ts +66 -150
- package/dist/templates/default/tsconfig.json +5 -0
- package/package.json +2 -2
- package/templates/default/package.json +7 -9
- package/templates/default/src/index.ts +66 -150
- package/templates/default/tsconfig.json +5 -0
package/dist/commands/init.js
CHANGED
|
@@ -13,6 +13,11 @@ function init(projectName) {
|
|
|
13
13
|
var projectDir = path_1.default.join(process.cwd(), projectName);
|
|
14
14
|
var templateDir = path_1.default.join(__dirname, '..', '..', 'templates', 'default');
|
|
15
15
|
try {
|
|
16
|
+
// Check if directory already exists
|
|
17
|
+
if (fs_extra_1.default.existsSync(projectDir)) {
|
|
18
|
+
spinner.fail("Directory ".concat(projectName, " already exists"));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
16
21
|
// Create project directory
|
|
17
22
|
fs_extra_1.default.ensureDirSync(projectDir);
|
|
18
23
|
// Copy template files
|
|
@@ -28,9 +33,12 @@ function init(projectName) {
|
|
|
28
33
|
(0, utils_1.logInfo)(" cd ".concat(projectName));
|
|
29
34
|
(0, utils_1.logInfo)(' npm install');
|
|
30
35
|
(0, utils_1.logInfo)(' dain dev');
|
|
36
|
+
// Explicitly exit with success
|
|
37
|
+
process.exit(0);
|
|
31
38
|
}
|
|
32
39
|
catch (error) {
|
|
33
40
|
spinner.fail('Project initialization failed');
|
|
34
41
|
(0, utils_1.logError)('Error initializing project', error);
|
|
42
|
+
process.exit(1);
|
|
35
43
|
}
|
|
36
44
|
}
|
|
@@ -113,25 +113,25 @@ function chat(dainConnection) {
|
|
|
113
113
|
case 6:
|
|
114
114
|
if (!true) return [3 /*break*/, 12];
|
|
115
115
|
if (!!toolResponseAvailable) return [3 /*break*/, 8];
|
|
116
|
-
return [4 /*yield*/, terminal.question(
|
|
116
|
+
return [4 /*yield*/, terminal.question("You: ")];
|
|
117
117
|
case 7:
|
|
118
118
|
userInput = _f.sent();
|
|
119
|
-
if (userInput.toLowerCase() ===
|
|
120
|
-
console.log(
|
|
119
|
+
if (userInput.toLowerCase() === "exit") {
|
|
120
|
+
console.log("Goodbye!");
|
|
121
121
|
terminal.close();
|
|
122
122
|
return [2 /*return*/];
|
|
123
123
|
}
|
|
124
|
-
messages.push({ role:
|
|
124
|
+
messages.push({ role: "user", content: userInput });
|
|
125
125
|
_f.label = 8;
|
|
126
126
|
case 8:
|
|
127
127
|
_f.trys.push([8, 10, , 11]);
|
|
128
128
|
console.log("messages", messages);
|
|
129
129
|
return [4 /*yield*/, (0, ai_1.generateText)({
|
|
130
|
-
model: (0, anthropic_1.anthropic)(
|
|
130
|
+
model: (0, anthropic_1.anthropic)("claude-3-5-sonnet-20240620"),
|
|
131
131
|
system: " Keep your responses brief but insightful.\n use lots of emojis, to show your enthusiasm!\n Your name is Butterfly, Built by the team at Dain. \n You are given tools only use them if they ask for it or if it helps you accomplish the task.\n when explaining topics you can use diagrams to help visualize the concepts.\n if the user asks for a tool, you can use it to help them\n You always answer the with markdown formatting. use markdown when it would be possible.\n You support the following markdown headings, bold, italic, links, tables, lists, code blocks, and blockquotes.\n You do not support images and never include images. You can also use emojis to show enthusiasm!\n Tools often have UI components that directly display to the user, once they are displayed you dont need to repeat the tool name or what it does or what its supposed to output, assume the user can already see the output.\n",
|
|
132
132
|
tools: allTools,
|
|
133
133
|
messages: messages,
|
|
134
|
-
maxSteps: 5
|
|
134
|
+
maxSteps: 5,
|
|
135
135
|
})];
|
|
136
136
|
case 9:
|
|
137
137
|
_a = _f.sent(), text = _a.text, toolCalls = _a.toolCalls, toolResults = _a.toolResults, responseMessages = _a.responseMessages;
|
|
@@ -147,13 +147,13 @@ function chat(dainConnection) {
|
|
|
147
147
|
_e = toolResults_1[_d], toolName = _e.toolName, result = _e.result;
|
|
148
148
|
process.stdout.write("\nTool response: '".concat(toolName, "' ").concat(JSON.stringify(result)));
|
|
149
149
|
}
|
|
150
|
-
process.stdout.write(
|
|
150
|
+
process.stdout.write("\n\n");
|
|
151
151
|
messages.push.apply(messages, responseMessages);
|
|
152
152
|
toolResponseAvailable = toolCalls.length > 0;
|
|
153
153
|
return [3 /*break*/, 11];
|
|
154
154
|
case 10:
|
|
155
155
|
error_1 = _f.sent();
|
|
156
|
-
console.error(
|
|
156
|
+
console.error("Error generating response:", error_1);
|
|
157
157
|
return [3 /*break*/, 11];
|
|
158
158
|
case 11: return [3 /*break*/, 6];
|
|
159
159
|
case 12: return [2 /*return*/];
|
|
@@ -170,18 +170,18 @@ function testchat(options) {
|
|
|
170
170
|
config = (0, utils_1.getDainConfig)(options.config);
|
|
171
171
|
url = options.url || process.env.TEST_CHAT_URL;
|
|
172
172
|
if (!url) {
|
|
173
|
-
console.error(
|
|
173
|
+
console.error("Error: Please provide a URL using --url option or set TEST_CHAT_URL in your .env file");
|
|
174
174
|
process.exit(1);
|
|
175
175
|
}
|
|
176
176
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
177
|
-
console.error(
|
|
177
|
+
console.error("Error: ANTHROPIC_API_KEY is not set in your .env file");
|
|
178
178
|
process.exit(1);
|
|
179
179
|
}
|
|
180
|
-
if (!config[
|
|
180
|
+
if (!config["api-key"]) {
|
|
181
181
|
throw new Error("'api-key' is required when using development proxy");
|
|
182
182
|
}
|
|
183
183
|
agentAuth = new client_1.DainClientAuth({
|
|
184
|
-
apiKey: config[
|
|
184
|
+
apiKey: config["api-key"],
|
|
185
185
|
});
|
|
186
186
|
dainConnection = new client_1.DainServiceConnection(url, agentAuth);
|
|
187
187
|
console.log('Starting chat session. Type "exit" to end the conversation.');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "dain-project",
|
|
2
|
+
"name": "example-dain-project",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"description": "A Dain Protocol project",
|
|
5
5
|
"main": "src/index.ts",
|
|
@@ -10,15 +10,13 @@
|
|
|
10
10
|
"deploy": "dain deploy"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dainprotocol/service-sdk": "^1.0.
|
|
13
|
+
"@dainprotocol/service-sdk": "^1.0.41",
|
|
14
14
|
"zod": "^3.23.8",
|
|
15
|
-
"hono": "^4.6.3"
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/express": "^4.17.13",
|
|
15
|
+
"hono": "^4.6.3",
|
|
20
16
|
"ts-node": "^10.4.0",
|
|
21
|
-
"typescript": "^
|
|
22
|
-
"@types/
|
|
17
|
+
"typescript": "^5.5.4",
|
|
18
|
+
"@types/express": "^4.17.13",
|
|
19
|
+
"@types/node": "^22.5.4",
|
|
20
|
+
"axios": "^1.7.5"
|
|
23
21
|
}
|
|
24
22
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
//File: example/example-node.ts
|
|
2
2
|
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import axios from "axios";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
defineDAINService,
|
|
8
|
+
ToolConfig,
|
|
9
|
+
ServiceConfig,
|
|
10
|
+
ToolboxConfig,
|
|
11
|
+
ServiceContext,
|
|
12
|
+
} from "@dainprotocol/service-sdk";
|
|
6
13
|
|
|
7
14
|
const getWeatherConfig: ToolConfig = {
|
|
8
15
|
id: "get-weather",
|
|
@@ -10,27 +17,35 @@ const getWeatherConfig: ToolConfig = {
|
|
|
10
17
|
description: "Fetches current weather for a city",
|
|
11
18
|
input: z
|
|
12
19
|
.object({
|
|
13
|
-
|
|
20
|
+
latitude: z.number().describe("Latitude coordinate"),
|
|
21
|
+
longitude: z.number().describe("Longitude coordinate"),
|
|
14
22
|
})
|
|
15
23
|
.describe("Input parameters for the weather request"),
|
|
16
24
|
output: z
|
|
17
25
|
.object({
|
|
18
26
|
temperature: z.number().describe("Current temperature in Celsius"),
|
|
19
|
-
|
|
20
|
-
.string()
|
|
21
|
-
.describe("Weather condition (e.g., Sunny, Rainy, Cloudy)"),
|
|
27
|
+
windSpeed: z.number().describe("Current wind speed in km/h"),
|
|
22
28
|
})
|
|
23
|
-
.describe("
|
|
24
|
-
pricing: { pricePerUse: 0
|
|
25
|
-
handler: async ({
|
|
26
|
-
console.log(
|
|
29
|
+
.describe("Current weather information"),
|
|
30
|
+
pricing: { pricePerUse: 0, currency: "USD" },
|
|
31
|
+
handler: async ({ latitude, longitude }, agentInfo) => {
|
|
32
|
+
console.log(
|
|
33
|
+
`Agent ${agentInfo.agentId} requested weather at ${latitude},${longitude}`
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const response = await axios.get(
|
|
37
|
+
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const { temperature_2m, wind_speed_10m } = response.data.current;
|
|
41
|
+
|
|
27
42
|
return {
|
|
28
|
-
text: `The current
|
|
29
|
-
data: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
children: "Weather test",
|
|
43
|
+
text: `The current temperature is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
|
|
44
|
+
data: {
|
|
45
|
+
temperature: temperature_2m,
|
|
46
|
+
windSpeed: wind_speed_10m,
|
|
33
47
|
},
|
|
48
|
+
ui: {},
|
|
34
49
|
};
|
|
35
50
|
},
|
|
36
51
|
};
|
|
@@ -38,165 +53,66 @@ const getWeatherConfig: ToolConfig = {
|
|
|
38
53
|
const getWeatherForecastConfig: ToolConfig = {
|
|
39
54
|
id: "get-weather-forecast",
|
|
40
55
|
name: "Get Weather Forecast",
|
|
41
|
-
description: "Fetches
|
|
56
|
+
description: "Fetches hourly weather forecast",
|
|
42
57
|
input: z
|
|
43
58
|
.object({
|
|
44
|
-
|
|
59
|
+
latitude: z.number().describe("Latitude coordinate"),
|
|
60
|
+
longitude: z.number().describe("Longitude coordinate"),
|
|
45
61
|
})
|
|
46
62
|
.describe("Input parameters for the forecast request"),
|
|
47
63
|
output: z
|
|
48
|
-
.array(
|
|
49
|
-
z.object({
|
|
50
|
-
date: z.string().describe("Date of the forecast"),
|
|
51
|
-
temperature: z.number().describe("Forecasted temperature in Celsius"),
|
|
52
|
-
condition: z.string().describe("Forecasted weather condition"),
|
|
53
|
-
})
|
|
54
|
-
)
|
|
55
|
-
.describe("5-day weather forecast for the requested city"),
|
|
56
|
-
pricing: { pricePerUse: 0.02, currency: "USD" },
|
|
57
|
-
handler: async ({ city }, agentInfo) => {
|
|
58
|
-
console.log(
|
|
59
|
-
`Agent ${agentInfo.agentId} requested weather forecast for ${city}`
|
|
60
|
-
);
|
|
61
|
-
return {
|
|
62
|
-
text: `The 5-day weather forecast for ${city} is included in the attached data`,
|
|
63
|
-
data: [
|
|
64
|
-
{ date: "2021-09-01", temperature: 22, condition: "Sunny" },
|
|
65
|
-
{ date: "2021-09-02", temperature: 23, condition: "Partly Cloudy" },
|
|
66
|
-
{ date: "2021-09-03", temperature: 21, condition: "Rainy" },
|
|
67
|
-
{ date: "2021-09-04", temperature: 20, condition: "Cloudy" },
|
|
68
|
-
{ date: "2021-09-05", temperature: 22, condition: "Sunny" },
|
|
69
|
-
],
|
|
70
|
-
ui: {},
|
|
71
|
-
};
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const getAirQualityConfig: ToolConfig = {
|
|
76
|
-
id: "get-air-quality",
|
|
77
|
-
name: "Get Air Quality",
|
|
78
|
-
description: "Fetches air quality information for a city",
|
|
79
|
-
input: z
|
|
80
64
|
.object({
|
|
81
|
-
|
|
65
|
+
times: z.array(z.string()).describe("Forecast times"),
|
|
66
|
+
temperatures: z
|
|
67
|
+
.array(z.number())
|
|
68
|
+
.describe("Temperature forecasts in Celsius"),
|
|
69
|
+
windSpeeds: z.array(z.number()).describe("Wind speed forecasts in km/h"),
|
|
70
|
+
humidity: z
|
|
71
|
+
.array(z.number())
|
|
72
|
+
.describe("Relative humidity forecasts in %"),
|
|
82
73
|
})
|
|
83
|
-
.describe("
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
aqi: z.number().describe("Air Quality Index"),
|
|
87
|
-
pollutant: z.string().describe("Main pollutant"),
|
|
88
|
-
level: z
|
|
89
|
-
.string()
|
|
90
|
-
.describe("Air quality level (e.g., Good, Moderate, Unhealthy)"),
|
|
91
|
-
})
|
|
92
|
-
.describe("Air quality information for the requested city"),
|
|
93
|
-
pricing: { pricePerUse: 0.015, currency: "USD" },
|
|
94
|
-
handler: async ({ city }, agentInfo) => {
|
|
95
|
-
console.log(`Agent ${agentInfo.agentId} requested air quality for ${city}`);
|
|
96
|
-
return {
|
|
97
|
-
text: `The air quality in ${city} is good`,
|
|
98
|
-
data: { aqi: 50, pollutant: "PM2.5", level: "Good" },
|
|
99
|
-
ui: {},
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const getHistoricalWeatherConfig: ToolConfig = {
|
|
105
|
-
id: "get-historical-weather",
|
|
106
|
-
name: "Get Historical Weather",
|
|
107
|
-
description: "Retrieves historical weather data for a specific date and city",
|
|
108
|
-
input: z
|
|
109
|
-
.object({
|
|
110
|
-
city: z.string().describe("The name of the city"),
|
|
111
|
-
date: z.string().describe("The date in YYYY-MM-DD format"),
|
|
112
|
-
})
|
|
113
|
-
.describe("Input parameters for the historical weather request"),
|
|
114
|
-
output: z
|
|
115
|
-
.object({
|
|
116
|
-
temperature: z.number().describe("Temperature in Celsius"),
|
|
117
|
-
condition: z.string().describe("Weather condition"),
|
|
118
|
-
precipitation: z.number().describe("Precipitation in mm"),
|
|
119
|
-
})
|
|
120
|
-
.describe("Historical weather information for the requested city and date"),
|
|
121
|
-
pricing: { pricePerUse: 0.03, currency: "USD" },
|
|
122
|
-
handler: async ({ city, date }, agentInfo) => {
|
|
74
|
+
.describe("Hourly weather forecast"),
|
|
75
|
+
pricing: { pricePerUse: 0, currency: "USD" },
|
|
76
|
+
handler: async ({ latitude, longitude }, agentInfo) => {
|
|
123
77
|
console.log(
|
|
124
|
-
`Agent ${agentInfo.agentId} requested
|
|
78
|
+
`Agent ${agentInfo.agentId} requested forecast at ${latitude},${longitude}`
|
|
125
79
|
);
|
|
80
|
+
|
|
81
|
+
const response = await axios.get(
|
|
82
|
+
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const { time, temperature_2m, wind_speed_10m, relative_humidity_2m } =
|
|
86
|
+
response.data.hourly;
|
|
87
|
+
|
|
126
88
|
return {
|
|
127
|
-
text: `
|
|
128
|
-
data: {
|
|
89
|
+
text: `Weather forecast available for the next ${time.length} hours`,
|
|
90
|
+
data: {
|
|
91
|
+
times: time,
|
|
92
|
+
temperatures: temperature_2m,
|
|
93
|
+
windSpeeds: wind_speed_10m,
|
|
94
|
+
humidity: relative_humidity_2m,
|
|
95
|
+
},
|
|
129
96
|
ui: {},
|
|
130
97
|
};
|
|
131
98
|
},
|
|
132
99
|
};
|
|
133
100
|
|
|
134
|
-
const weatherServiceConfig: ServiceConfig = {
|
|
135
|
-
id: "weather-service",
|
|
136
|
-
name: "Weather Service",
|
|
137
|
-
description: "Provides comprehensive weather information",
|
|
138
|
-
metadata: {
|
|
139
|
-
capabilities: [
|
|
140
|
-
"current-weather",
|
|
141
|
-
"weather-forecast",
|
|
142
|
-
"air-quality",
|
|
143
|
-
"historical-weather",
|
|
144
|
-
],
|
|
145
|
-
languages: ["en"],
|
|
146
|
-
},
|
|
147
|
-
recommendedPrompt:
|
|
148
|
-
"Ask about weather, forecasts, air quality, or historical weather data",
|
|
149
|
-
recommendedTools: [
|
|
150
|
-
"get-weather",
|
|
151
|
-
"get-weather-forecast",
|
|
152
|
-
"get-air-quality",
|
|
153
|
-
"get-historical-weather",
|
|
154
|
-
],
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const weatherToolboxConfig: ToolboxConfig = {
|
|
158
|
-
id: "weather-toolbox",
|
|
159
|
-
name: "Weather Toolbox",
|
|
160
|
-
description: "Collection of weather-related tools",
|
|
161
|
-
tools: [
|
|
162
|
-
"get-weather",
|
|
163
|
-
"get-weather-forecast",
|
|
164
|
-
"get-air-quality",
|
|
165
|
-
"get-historical-weather",
|
|
166
|
-
],
|
|
167
|
-
metadata: {
|
|
168
|
-
complexity: "Medium",
|
|
169
|
-
applicableFields: ["Meteorology", "Travel", "Environmental Science"],
|
|
170
|
-
},
|
|
171
|
-
recommendedPrompt:
|
|
172
|
-
"Use these tools for various weather-related tasks and analyses",
|
|
173
|
-
};
|
|
174
|
-
|
|
175
101
|
const dainService = defineDAINService({
|
|
176
102
|
metadata: {
|
|
177
|
-
title: "
|
|
103
|
+
title: "Weather DAIN Service",
|
|
178
104
|
description:
|
|
179
|
-
"A DAIN service for
|
|
180
|
-
version: "1.
|
|
105
|
+
"A DAIN service for current weather and forecasts using Open-Meteo API",
|
|
106
|
+
version: "1.0.0",
|
|
181
107
|
author: "Your Name",
|
|
182
|
-
tags: ["weather", "forecast", "
|
|
108
|
+
tags: ["weather", "forecast", "dain"],
|
|
183
109
|
},
|
|
184
110
|
identity: {
|
|
185
|
-
apiKey:
|
|
186
|
-
process.env.DAIN_API_KEY,
|
|
111
|
+
apiKey: process.env.DAIN_API_KEY,
|
|
187
112
|
},
|
|
188
|
-
|
|
189
|
-
tools: [
|
|
190
|
-
getWeatherConfig,
|
|
191
|
-
getWeatherForecastConfig,
|
|
192
|
-
getAirQualityConfig,
|
|
193
|
-
getHistoricalWeatherConfig,
|
|
194
|
-
],
|
|
195
|
-
toolboxes: [weatherToolboxConfig],
|
|
196
|
-
contexts: []
|
|
113
|
+
tools: [getWeatherConfig, getWeatherForecastConfig],
|
|
197
114
|
});
|
|
198
115
|
|
|
199
116
|
dainService.startNode({ port: 2022 }).then(() => {
|
|
200
|
-
console.log("
|
|
117
|
+
console.log("Weather DAIN Service is running on port 2022");
|
|
201
118
|
});
|
|
202
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dainprotocol/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"description": "CLI for Dain Protocol",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@ai-sdk/anthropic": "^0.0.50",
|
|
19
|
-
"@dainprotocol/service-sdk": "^1.0.
|
|
19
|
+
"@dainprotocol/service-sdk": "^1.0.41",
|
|
20
20
|
"@dainprotocol/tunnel": "^1.0.2",
|
|
21
21
|
"@types/fs-extra": "^11.0.4",
|
|
22
22
|
"@types/localtunnel": "^2.0.4",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "dain-project",
|
|
2
|
+
"name": "example-dain-project",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"description": "A Dain Protocol project",
|
|
5
5
|
"main": "src/index.ts",
|
|
@@ -10,15 +10,13 @@
|
|
|
10
10
|
"deploy": "dain deploy"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dainprotocol/service-sdk": "^1.0.
|
|
13
|
+
"@dainprotocol/service-sdk": "^1.0.41",
|
|
14
14
|
"zod": "^3.23.8",
|
|
15
|
-
"hono": "^4.6.3"
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/express": "^4.17.13",
|
|
15
|
+
"hono": "^4.6.3",
|
|
20
16
|
"ts-node": "^10.4.0",
|
|
21
|
-
"typescript": "^
|
|
22
|
-
"@types/
|
|
17
|
+
"typescript": "^5.5.4",
|
|
18
|
+
"@types/express": "^4.17.13",
|
|
19
|
+
"@types/node": "^22.5.4",
|
|
20
|
+
"axios": "^1.7.5"
|
|
23
21
|
}
|
|
24
22
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
//File: example/example-node.ts
|
|
2
2
|
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import axios from "axios";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
defineDAINService,
|
|
8
|
+
ToolConfig,
|
|
9
|
+
ServiceConfig,
|
|
10
|
+
ToolboxConfig,
|
|
11
|
+
ServiceContext,
|
|
12
|
+
} from "@dainprotocol/service-sdk";
|
|
6
13
|
|
|
7
14
|
const getWeatherConfig: ToolConfig = {
|
|
8
15
|
id: "get-weather",
|
|
@@ -10,27 +17,35 @@ const getWeatherConfig: ToolConfig = {
|
|
|
10
17
|
description: "Fetches current weather for a city",
|
|
11
18
|
input: z
|
|
12
19
|
.object({
|
|
13
|
-
|
|
20
|
+
latitude: z.number().describe("Latitude coordinate"),
|
|
21
|
+
longitude: z.number().describe("Longitude coordinate"),
|
|
14
22
|
})
|
|
15
23
|
.describe("Input parameters for the weather request"),
|
|
16
24
|
output: z
|
|
17
25
|
.object({
|
|
18
26
|
temperature: z.number().describe("Current temperature in Celsius"),
|
|
19
|
-
|
|
20
|
-
.string()
|
|
21
|
-
.describe("Weather condition (e.g., Sunny, Rainy, Cloudy)"),
|
|
27
|
+
windSpeed: z.number().describe("Current wind speed in km/h"),
|
|
22
28
|
})
|
|
23
|
-
.describe("
|
|
24
|
-
pricing: { pricePerUse: 0
|
|
25
|
-
handler: async ({
|
|
26
|
-
console.log(
|
|
29
|
+
.describe("Current weather information"),
|
|
30
|
+
pricing: { pricePerUse: 0, currency: "USD" },
|
|
31
|
+
handler: async ({ latitude, longitude }, agentInfo) => {
|
|
32
|
+
console.log(
|
|
33
|
+
`Agent ${agentInfo.agentId} requested weather at ${latitude},${longitude}`
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const response = await axios.get(
|
|
37
|
+
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const { temperature_2m, wind_speed_10m } = response.data.current;
|
|
41
|
+
|
|
27
42
|
return {
|
|
28
|
-
text: `The current
|
|
29
|
-
data: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
children: "Weather test",
|
|
43
|
+
text: `The current temperature is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
|
|
44
|
+
data: {
|
|
45
|
+
temperature: temperature_2m,
|
|
46
|
+
windSpeed: wind_speed_10m,
|
|
33
47
|
},
|
|
48
|
+
ui: {},
|
|
34
49
|
};
|
|
35
50
|
},
|
|
36
51
|
};
|
|
@@ -38,165 +53,66 @@ const getWeatherConfig: ToolConfig = {
|
|
|
38
53
|
const getWeatherForecastConfig: ToolConfig = {
|
|
39
54
|
id: "get-weather-forecast",
|
|
40
55
|
name: "Get Weather Forecast",
|
|
41
|
-
description: "Fetches
|
|
56
|
+
description: "Fetches hourly weather forecast",
|
|
42
57
|
input: z
|
|
43
58
|
.object({
|
|
44
|
-
|
|
59
|
+
latitude: z.number().describe("Latitude coordinate"),
|
|
60
|
+
longitude: z.number().describe("Longitude coordinate"),
|
|
45
61
|
})
|
|
46
62
|
.describe("Input parameters for the forecast request"),
|
|
47
63
|
output: z
|
|
48
|
-
.array(
|
|
49
|
-
z.object({
|
|
50
|
-
date: z.string().describe("Date of the forecast"),
|
|
51
|
-
temperature: z.number().describe("Forecasted temperature in Celsius"),
|
|
52
|
-
condition: z.string().describe("Forecasted weather condition"),
|
|
53
|
-
})
|
|
54
|
-
)
|
|
55
|
-
.describe("5-day weather forecast for the requested city"),
|
|
56
|
-
pricing: { pricePerUse: 0.02, currency: "USD" },
|
|
57
|
-
handler: async ({ city }, agentInfo) => {
|
|
58
|
-
console.log(
|
|
59
|
-
`Agent ${agentInfo.agentId} requested weather forecast for ${city}`
|
|
60
|
-
);
|
|
61
|
-
return {
|
|
62
|
-
text: `The 5-day weather forecast for ${city} is included in the attached data`,
|
|
63
|
-
data: [
|
|
64
|
-
{ date: "2021-09-01", temperature: 22, condition: "Sunny" },
|
|
65
|
-
{ date: "2021-09-02", temperature: 23, condition: "Partly Cloudy" },
|
|
66
|
-
{ date: "2021-09-03", temperature: 21, condition: "Rainy" },
|
|
67
|
-
{ date: "2021-09-04", temperature: 20, condition: "Cloudy" },
|
|
68
|
-
{ date: "2021-09-05", temperature: 22, condition: "Sunny" },
|
|
69
|
-
],
|
|
70
|
-
ui: {},
|
|
71
|
-
};
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const getAirQualityConfig: ToolConfig = {
|
|
76
|
-
id: "get-air-quality",
|
|
77
|
-
name: "Get Air Quality",
|
|
78
|
-
description: "Fetches air quality information for a city",
|
|
79
|
-
input: z
|
|
80
64
|
.object({
|
|
81
|
-
|
|
65
|
+
times: z.array(z.string()).describe("Forecast times"),
|
|
66
|
+
temperatures: z
|
|
67
|
+
.array(z.number())
|
|
68
|
+
.describe("Temperature forecasts in Celsius"),
|
|
69
|
+
windSpeeds: z.array(z.number()).describe("Wind speed forecasts in km/h"),
|
|
70
|
+
humidity: z
|
|
71
|
+
.array(z.number())
|
|
72
|
+
.describe("Relative humidity forecasts in %"),
|
|
82
73
|
})
|
|
83
|
-
.describe("
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
aqi: z.number().describe("Air Quality Index"),
|
|
87
|
-
pollutant: z.string().describe("Main pollutant"),
|
|
88
|
-
level: z
|
|
89
|
-
.string()
|
|
90
|
-
.describe("Air quality level (e.g., Good, Moderate, Unhealthy)"),
|
|
91
|
-
})
|
|
92
|
-
.describe("Air quality information for the requested city"),
|
|
93
|
-
pricing: { pricePerUse: 0.015, currency: "USD" },
|
|
94
|
-
handler: async ({ city }, agentInfo) => {
|
|
95
|
-
console.log(`Agent ${agentInfo.agentId} requested air quality for ${city}`);
|
|
96
|
-
return {
|
|
97
|
-
text: `The air quality in ${city} is good`,
|
|
98
|
-
data: { aqi: 50, pollutant: "PM2.5", level: "Good" },
|
|
99
|
-
ui: {},
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const getHistoricalWeatherConfig: ToolConfig = {
|
|
105
|
-
id: "get-historical-weather",
|
|
106
|
-
name: "Get Historical Weather",
|
|
107
|
-
description: "Retrieves historical weather data for a specific date and city",
|
|
108
|
-
input: z
|
|
109
|
-
.object({
|
|
110
|
-
city: z.string().describe("The name of the city"),
|
|
111
|
-
date: z.string().describe("The date in YYYY-MM-DD format"),
|
|
112
|
-
})
|
|
113
|
-
.describe("Input parameters for the historical weather request"),
|
|
114
|
-
output: z
|
|
115
|
-
.object({
|
|
116
|
-
temperature: z.number().describe("Temperature in Celsius"),
|
|
117
|
-
condition: z.string().describe("Weather condition"),
|
|
118
|
-
precipitation: z.number().describe("Precipitation in mm"),
|
|
119
|
-
})
|
|
120
|
-
.describe("Historical weather information for the requested city and date"),
|
|
121
|
-
pricing: { pricePerUse: 0.03, currency: "USD" },
|
|
122
|
-
handler: async ({ city, date }, agentInfo) => {
|
|
74
|
+
.describe("Hourly weather forecast"),
|
|
75
|
+
pricing: { pricePerUse: 0, currency: "USD" },
|
|
76
|
+
handler: async ({ latitude, longitude }, agentInfo) => {
|
|
123
77
|
console.log(
|
|
124
|
-
`Agent ${agentInfo.agentId} requested
|
|
78
|
+
`Agent ${agentInfo.agentId} requested forecast at ${latitude},${longitude}`
|
|
125
79
|
);
|
|
80
|
+
|
|
81
|
+
const response = await axios.get(
|
|
82
|
+
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const { time, temperature_2m, wind_speed_10m, relative_humidity_2m } =
|
|
86
|
+
response.data.hourly;
|
|
87
|
+
|
|
126
88
|
return {
|
|
127
|
-
text: `
|
|
128
|
-
data: {
|
|
89
|
+
text: `Weather forecast available for the next ${time.length} hours`,
|
|
90
|
+
data: {
|
|
91
|
+
times: time,
|
|
92
|
+
temperatures: temperature_2m,
|
|
93
|
+
windSpeeds: wind_speed_10m,
|
|
94
|
+
humidity: relative_humidity_2m,
|
|
95
|
+
},
|
|
129
96
|
ui: {},
|
|
130
97
|
};
|
|
131
98
|
},
|
|
132
99
|
};
|
|
133
100
|
|
|
134
|
-
const weatherServiceConfig: ServiceConfig = {
|
|
135
|
-
id: "weather-service",
|
|
136
|
-
name: "Weather Service",
|
|
137
|
-
description: "Provides comprehensive weather information",
|
|
138
|
-
metadata: {
|
|
139
|
-
capabilities: [
|
|
140
|
-
"current-weather",
|
|
141
|
-
"weather-forecast",
|
|
142
|
-
"air-quality",
|
|
143
|
-
"historical-weather",
|
|
144
|
-
],
|
|
145
|
-
languages: ["en"],
|
|
146
|
-
},
|
|
147
|
-
recommendedPrompt:
|
|
148
|
-
"Ask about weather, forecasts, air quality, or historical weather data",
|
|
149
|
-
recommendedTools: [
|
|
150
|
-
"get-weather",
|
|
151
|
-
"get-weather-forecast",
|
|
152
|
-
"get-air-quality",
|
|
153
|
-
"get-historical-weather",
|
|
154
|
-
],
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const weatherToolboxConfig: ToolboxConfig = {
|
|
158
|
-
id: "weather-toolbox",
|
|
159
|
-
name: "Weather Toolbox",
|
|
160
|
-
description: "Collection of weather-related tools",
|
|
161
|
-
tools: [
|
|
162
|
-
"get-weather",
|
|
163
|
-
"get-weather-forecast",
|
|
164
|
-
"get-air-quality",
|
|
165
|
-
"get-historical-weather",
|
|
166
|
-
],
|
|
167
|
-
metadata: {
|
|
168
|
-
complexity: "Medium",
|
|
169
|
-
applicableFields: ["Meteorology", "Travel", "Environmental Science"],
|
|
170
|
-
},
|
|
171
|
-
recommendedPrompt:
|
|
172
|
-
"Use these tools for various weather-related tasks and analyses",
|
|
173
|
-
};
|
|
174
|
-
|
|
175
101
|
const dainService = defineDAINService({
|
|
176
102
|
metadata: {
|
|
177
|
-
title: "
|
|
103
|
+
title: "Weather DAIN Service",
|
|
178
104
|
description:
|
|
179
|
-
"A DAIN service for
|
|
180
|
-
version: "1.
|
|
105
|
+
"A DAIN service for current weather and forecasts using Open-Meteo API",
|
|
106
|
+
version: "1.0.0",
|
|
181
107
|
author: "Your Name",
|
|
182
|
-
tags: ["weather", "forecast", "
|
|
108
|
+
tags: ["weather", "forecast", "dain"],
|
|
183
109
|
},
|
|
184
110
|
identity: {
|
|
185
|
-
apiKey:
|
|
186
|
-
process.env.DAIN_API_KEY,
|
|
111
|
+
apiKey: process.env.DAIN_API_KEY,
|
|
187
112
|
},
|
|
188
|
-
|
|
189
|
-
tools: [
|
|
190
|
-
getWeatherConfig,
|
|
191
|
-
getWeatherForecastConfig,
|
|
192
|
-
getAirQualityConfig,
|
|
193
|
-
getHistoricalWeatherConfig,
|
|
194
|
-
],
|
|
195
|
-
toolboxes: [weatherToolboxConfig],
|
|
196
|
-
contexts: []
|
|
113
|
+
tools: [getWeatherConfig, getWeatherForecastConfig],
|
|
197
114
|
});
|
|
198
115
|
|
|
199
116
|
dainService.startNode({ port: 2022 }).then(() => {
|
|
200
|
-
console.log("
|
|
117
|
+
console.log("Weather DAIN Service is running on port 2022");
|
|
201
118
|
});
|
|
202
|
-
|