@dainprotocol/cli 1.1.12 → 1.1.13

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.
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@dainprotocol/service-sdk": "^1.0.85",
14
+ "@dainprotocol/utils": "^0.0.43",
14
15
  "zod": "^3.23.8",
15
16
  "hono": "^4.6.3",
16
17
  "ts-node": "^10.4.0",
@@ -6,17 +6,26 @@ import axios from "axios";
6
6
  import {
7
7
  defineDAINService,
8
8
  ToolConfig,
9
- ServiceConfig,
10
- ToolboxConfig,
11
- ServiceContext,
12
9
  } from "@dainprotocol/service-sdk";
13
10
 
11
+ import { CardUIBuilder, TableUIBuilder, MapUIBuilder } from "@dainprotocol/utils";
12
+
13
+ const getWeatherEmoji = (temperature: number): string => {
14
+ if (temperature <= 0) return '🥶';
15
+ if (temperature <= 10) return '❄️';
16
+ if (temperature <= 20) return '⛅';
17
+ if (temperature <= 25) return '☀️';
18
+ if (temperature <= 30) return '🌞';
19
+ return '🔥';
20
+ };
21
+
14
22
  const getWeatherConfig: ToolConfig = {
15
23
  id: "get-weather",
16
24
  name: "Get Weather",
17
25
  description: "Fetches current weather for a city",
18
26
  input: z
19
27
  .object({
28
+ locationName: z.string().describe("Location name"),
20
29
  latitude: z.number().describe("Latitude coordinate"),
21
30
  longitude: z.number().describe("Longitude coordinate"),
22
31
  })
@@ -28,24 +37,43 @@ const getWeatherConfig: ToolConfig = {
28
37
  })
29
38
  .describe("Current weather information"),
30
39
  pricing: { pricePerUse: 0, currency: "USD" },
31
- handler: async ({ latitude, longitude }, agentInfo) => {
40
+ handler: async ({ locationName, latitude, longitude }, agentInfo, context) => {
32
41
  console.log(
33
- `User / Agent ${agentInfo.id} requested weather at ${latitude},${longitude}`
42
+ `User / Agent ${agentInfo.id} requested weather at ${locationName} (${latitude},${longitude})`
34
43
  );
35
44
 
45
+
36
46
  const response = await axios.get(
37
47
  `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m`
38
48
  );
39
49
 
40
50
  const { temperature_2m, wind_speed_10m } = response.data.current;
51
+ const weatherEmoji = getWeatherEmoji(temperature_2m);
41
52
 
42
53
  return {
43
- text: `The current temperature is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
54
+ text: `The current temperature in ${locationName} is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
44
55
  data: {
45
56
  temperature: temperature_2m,
46
57
  windSpeed: wind_speed_10m,
47
58
  },
48
- ui: {},
59
+ ui: new CardUIBuilder()
60
+ .setRenderMode("page")
61
+ .title(`Current Weather in ${locationName} ${weatherEmoji}`)
62
+ .addChild(new MapUIBuilder()
63
+ .setInitialView(latitude, longitude, 10)
64
+ .setMapStyle('streets')
65
+ .addMarkers([
66
+ {
67
+ latitude,
68
+ longitude,
69
+ title: locationName,
70
+ description: `Temperature: ${temperature_2m}°C\nWind: ${wind_speed_10m} km/h`,
71
+ text: `${locationName} ${weatherEmoji}`,
72
+ }
73
+ ])
74
+ .build())
75
+ .content(`Temperature: ${temperature_2m}°C\nWind Speed: ${wind_speed_10m} km/h`)
76
+ .build(),
49
77
  };
50
78
  },
51
79
  };
@@ -56,6 +84,7 @@ const getWeatherForecastConfig: ToolConfig = {
56
84
  description: "Fetches hourly weather forecast",
57
85
  input: z
58
86
  .object({
87
+ locationName: z.string().describe("Location name"),
59
88
  latitude: z.number().describe("Latitude coordinate"),
60
89
  longitude: z.number().describe("Longitude coordinate"),
61
90
  })
@@ -73,11 +102,35 @@ const getWeatherForecastConfig: ToolConfig = {
73
102
  })
74
103
  .describe("Hourly weather forecast"),
75
104
  pricing: { pricePerUse: 0, currency: "USD" },
76
- handler: async ({ latitude, longitude }, agentInfo) => {
105
+ handler: async ({ locationName, latitude, longitude }, agentInfo, context) => {
77
106
  console.log(
78
- `User / Agent ${agentInfo.id} requested forecast at ${latitude},${longitude}`
107
+ `User / Agent ${agentInfo.id} requested forecast at ${locationName} (${latitude},${longitude})`
79
108
  );
80
109
 
110
+ // Send early UI with map and loading state
111
+ if (context.updateUI) {
112
+ await context.updateUI({
113
+ ui: new CardUIBuilder()
114
+ .setRenderMode("page")
115
+ .title(`Weather Forecast for ${locationName} ⏳`)
116
+ .addChild(new MapUIBuilder()
117
+ .setInitialView(latitude, longitude, 10)
118
+ .setMapStyle('streets')
119
+ .addMarkers([
120
+ {
121
+ latitude,
122
+ longitude,
123
+ title: locationName,
124
+ description: 'Loading forecast data...',
125
+ text: `${locationName} ⏳`,
126
+ }
127
+ ])
128
+ .build())
129
+ .content('Fetching weather forecast data...')
130
+ .build()
131
+ });
132
+ }
133
+
81
134
  const response = await axios.get(
82
135
  `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
83
136
  );
@@ -85,15 +138,53 @@ const getWeatherForecastConfig: ToolConfig = {
85
138
  const { time, temperature_2m, wind_speed_10m, relative_humidity_2m } =
86
139
  response.data.hourly;
87
140
 
141
+ // Limit to first 24 hours of forecast data
142
+ const limitedTime = time.slice(0, 24);
143
+ const limitedTemp = temperature_2m.slice(0, 24);
144
+ const limitedWind = wind_speed_10m.slice(0, 24);
145
+ const limitedHumidity = relative_humidity_2m.slice(0, 24);
146
+
147
+ const weatherEmoji = getWeatherEmoji(limitedTemp[0]);
148
+
88
149
  return {
89
- text: `Weather forecast available for the next ${time.length} hours`,
150
+ text: `Weather forecast for ${locationName} available for the next 24 hours`,
90
151
  data: {
91
- times: time,
92
- temperatures: temperature_2m,
93
- windSpeeds: wind_speed_10m,
94
- humidity: relative_humidity_2m,
152
+ times: limitedTime,
153
+ temperatures: limitedTemp,
154
+ windSpeeds: limitedWind,
155
+ humidity: limitedHumidity,
95
156
  },
96
- ui: {},
157
+ ui: new CardUIBuilder()
158
+ .setRenderMode("page")
159
+ .title(`Weather Forecast for ${locationName} ${weatherEmoji}`)
160
+ .addChild(new MapUIBuilder()
161
+ .setInitialView(latitude, longitude, 10)
162
+ .setMapStyle('streets')
163
+ .addMarkers([
164
+ {
165
+ latitude,
166
+ longitude,
167
+ title: locationName,
168
+ description: `Temperature: ${limitedTemp[0]}°C\nWind: ${limitedWind[0]} km/h`,
169
+ text: `${locationName} ${weatherEmoji}`,
170
+ }
171
+ ])
172
+ .build())
173
+ .addChild(new TableUIBuilder()
174
+ .addColumns([
175
+ { key: 'time', header: 'Time', type: 'string' },
176
+ { key: 'temperature', header: 'Temperature (°C)', type: 'number' },
177
+ { key: 'windSpeed', header: 'Wind Speed (km/h)', type: 'number' },
178
+ { key: 'humidity', header: 'Humidity (%)', type: 'number' },
179
+ ])
180
+ .rows(limitedTime.map((t: string, i: number) => ({
181
+ time: new Date(t).toLocaleString(),
182
+ temperature: limitedTemp[i],
183
+ windSpeed: limitedWind[i],
184
+ humidity: limitedHumidity[i],
185
+ })))
186
+ .build())
187
+ .build(),
97
188
  };
98
189
  },
99
190
  };
@@ -106,8 +197,18 @@ const dainService = defineDAINService({
106
197
  version: "1.0.0",
107
198
  author: "Your Name",
108
199
  tags: ["weather", "forecast", "dain"],
109
- logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png"
200
+ logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png",
110
201
  },
202
+ exampleQueries: [
203
+ {
204
+ category: "Weather",
205
+ queries: [
206
+ "What is the weather in Tokyo?",
207
+ "What is the weather in San Francisco?",
208
+ "What is the weather in London?",
209
+ ],
210
+ }
211
+ ],
111
212
  identity: {
112
213
  apiKey: process.env.DAIN_API_KEY,
113
214
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dainprotocol/cli",
3
- "version": "1.1.12",
3
+ "version": "1.1.13",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@dainprotocol/service-sdk": "^1.0.85",
14
+ "@dainprotocol/utils": "^0.0.43",
14
15
  "zod": "^3.23.8",
15
16
  "hono": "^4.6.3",
16
17
  "ts-node": "^10.4.0",
@@ -6,17 +6,26 @@ import axios from "axios";
6
6
  import {
7
7
  defineDAINService,
8
8
  ToolConfig,
9
- ServiceConfig,
10
- ToolboxConfig,
11
- ServiceContext,
12
9
  } from "@dainprotocol/service-sdk";
13
10
 
11
+ import { CardUIBuilder, TableUIBuilder, MapUIBuilder } from "@dainprotocol/utils";
12
+
13
+ const getWeatherEmoji = (temperature: number): string => {
14
+ if (temperature <= 0) return '🥶';
15
+ if (temperature <= 10) return '❄️';
16
+ if (temperature <= 20) return '⛅';
17
+ if (temperature <= 25) return '☀️';
18
+ if (temperature <= 30) return '🌞';
19
+ return '🔥';
20
+ };
21
+
14
22
  const getWeatherConfig: ToolConfig = {
15
23
  id: "get-weather",
16
24
  name: "Get Weather",
17
25
  description: "Fetches current weather for a city",
18
26
  input: z
19
27
  .object({
28
+ locationName: z.string().describe("Location name"),
20
29
  latitude: z.number().describe("Latitude coordinate"),
21
30
  longitude: z.number().describe("Longitude coordinate"),
22
31
  })
@@ -28,24 +37,43 @@ const getWeatherConfig: ToolConfig = {
28
37
  })
29
38
  .describe("Current weather information"),
30
39
  pricing: { pricePerUse: 0, currency: "USD" },
31
- handler: async ({ latitude, longitude }, agentInfo) => {
40
+ handler: async ({ locationName, latitude, longitude }, agentInfo, context) => {
32
41
  console.log(
33
- `User / Agent ${agentInfo.id} requested weather at ${latitude},${longitude}`
42
+ `User / Agent ${agentInfo.id} requested weather at ${locationName} (${latitude},${longitude})`
34
43
  );
35
44
 
45
+
36
46
  const response = await axios.get(
37
47
  `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m`
38
48
  );
39
49
 
40
50
  const { temperature_2m, wind_speed_10m } = response.data.current;
51
+ const weatherEmoji = getWeatherEmoji(temperature_2m);
41
52
 
42
53
  return {
43
- text: `The current temperature is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
54
+ text: `The current temperature in ${locationName} is ${temperature_2m}°C with wind speed of ${wind_speed_10m} km/h`,
44
55
  data: {
45
56
  temperature: temperature_2m,
46
57
  windSpeed: wind_speed_10m,
47
58
  },
48
- ui: {},
59
+ ui: new CardUIBuilder()
60
+ .setRenderMode("page")
61
+ .title(`Current Weather in ${locationName} ${weatherEmoji}`)
62
+ .addChild(new MapUIBuilder()
63
+ .setInitialView(latitude, longitude, 10)
64
+ .setMapStyle('streets')
65
+ .addMarkers([
66
+ {
67
+ latitude,
68
+ longitude,
69
+ title: locationName,
70
+ description: `Temperature: ${temperature_2m}°C\nWind: ${wind_speed_10m} km/h`,
71
+ text: `${locationName} ${weatherEmoji}`,
72
+ }
73
+ ])
74
+ .build())
75
+ .content(`Temperature: ${temperature_2m}°C\nWind Speed: ${wind_speed_10m} km/h`)
76
+ .build(),
49
77
  };
50
78
  },
51
79
  };
@@ -56,6 +84,7 @@ const getWeatherForecastConfig: ToolConfig = {
56
84
  description: "Fetches hourly weather forecast",
57
85
  input: z
58
86
  .object({
87
+ locationName: z.string().describe("Location name"),
59
88
  latitude: z.number().describe("Latitude coordinate"),
60
89
  longitude: z.number().describe("Longitude coordinate"),
61
90
  })
@@ -73,11 +102,35 @@ const getWeatherForecastConfig: ToolConfig = {
73
102
  })
74
103
  .describe("Hourly weather forecast"),
75
104
  pricing: { pricePerUse: 0, currency: "USD" },
76
- handler: async ({ latitude, longitude }, agentInfo) => {
105
+ handler: async ({ locationName, latitude, longitude }, agentInfo, context) => {
77
106
  console.log(
78
- `User / Agent ${agentInfo.id} requested forecast at ${latitude},${longitude}`
107
+ `User / Agent ${agentInfo.id} requested forecast at ${locationName} (${latitude},${longitude})`
79
108
  );
80
109
 
110
+ // Send early UI with map and loading state
111
+ if (context.updateUI) {
112
+ await context.updateUI({
113
+ ui: new CardUIBuilder()
114
+ .setRenderMode("page")
115
+ .title(`Weather Forecast for ${locationName} ⏳`)
116
+ .addChild(new MapUIBuilder()
117
+ .setInitialView(latitude, longitude, 10)
118
+ .setMapStyle('streets')
119
+ .addMarkers([
120
+ {
121
+ latitude,
122
+ longitude,
123
+ title: locationName,
124
+ description: 'Loading forecast data...',
125
+ text: `${locationName} ⏳`,
126
+ }
127
+ ])
128
+ .build())
129
+ .content('Fetching weather forecast data...')
130
+ .build()
131
+ });
132
+ }
133
+
81
134
  const response = await axios.get(
82
135
  `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
83
136
  );
@@ -85,15 +138,53 @@ const getWeatherForecastConfig: ToolConfig = {
85
138
  const { time, temperature_2m, wind_speed_10m, relative_humidity_2m } =
86
139
  response.data.hourly;
87
140
 
141
+ // Limit to first 24 hours of forecast data
142
+ const limitedTime = time.slice(0, 24);
143
+ const limitedTemp = temperature_2m.slice(0, 24);
144
+ const limitedWind = wind_speed_10m.slice(0, 24);
145
+ const limitedHumidity = relative_humidity_2m.slice(0, 24);
146
+
147
+ const weatherEmoji = getWeatherEmoji(limitedTemp[0]);
148
+
88
149
  return {
89
- text: `Weather forecast available for the next ${time.length} hours`,
150
+ text: `Weather forecast for ${locationName} available for the next 24 hours`,
90
151
  data: {
91
- times: time,
92
- temperatures: temperature_2m,
93
- windSpeeds: wind_speed_10m,
94
- humidity: relative_humidity_2m,
152
+ times: limitedTime,
153
+ temperatures: limitedTemp,
154
+ windSpeeds: limitedWind,
155
+ humidity: limitedHumidity,
95
156
  },
96
- ui: {},
157
+ ui: new CardUIBuilder()
158
+ .setRenderMode("page")
159
+ .title(`Weather Forecast for ${locationName} ${weatherEmoji}`)
160
+ .addChild(new MapUIBuilder()
161
+ .setInitialView(latitude, longitude, 10)
162
+ .setMapStyle('streets')
163
+ .addMarkers([
164
+ {
165
+ latitude,
166
+ longitude,
167
+ title: locationName,
168
+ description: `Temperature: ${limitedTemp[0]}°C\nWind: ${limitedWind[0]} km/h`,
169
+ text: `${locationName} ${weatherEmoji}`,
170
+ }
171
+ ])
172
+ .build())
173
+ .addChild(new TableUIBuilder()
174
+ .addColumns([
175
+ { key: 'time', header: 'Time', type: 'string' },
176
+ { key: 'temperature', header: 'Temperature (°C)', type: 'number' },
177
+ { key: 'windSpeed', header: 'Wind Speed (km/h)', type: 'number' },
178
+ { key: 'humidity', header: 'Humidity (%)', type: 'number' },
179
+ ])
180
+ .rows(limitedTime.map((t: string, i: number) => ({
181
+ time: new Date(t).toLocaleString(),
182
+ temperature: limitedTemp[i],
183
+ windSpeed: limitedWind[i],
184
+ humidity: limitedHumidity[i],
185
+ })))
186
+ .build())
187
+ .build(),
97
188
  };
98
189
  },
99
190
  };
@@ -106,8 +197,18 @@ const dainService = defineDAINService({
106
197
  version: "1.0.0",
107
198
  author: "Your Name",
108
199
  tags: ["weather", "forecast", "dain"],
109
- logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png"
200
+ logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png",
110
201
  },
202
+ exampleQueries: [
203
+ {
204
+ category: "Weather",
205
+ queries: [
206
+ "What is the weather in Tokyo?",
207
+ "What is the weather in San Francisco?",
208
+ "What is the weather in London?",
209
+ ],
210
+ }
211
+ ],
111
212
  identity: {
112
213
  apiKey: process.env.DAIN_API_KEY,
113
214
  },