@dainprotocol/cli 1.1.21 → 1.1.27
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/dev.js +70 -21
- package/dist/index.js +1 -1
- package/dist/templates/default/package.json +3 -3
- package/dist/templates/default/src/index.ts +90 -68
- package/dist/utils.js +16 -7
- package/package.json +1 -1
- package/templates/default/package.json +3 -3
- package/templates/default/src/index.ts +90 -68
package/dist/commands/dev.js
CHANGED
|
@@ -59,18 +59,35 @@ var path_1 = __importDefault(require("path"));
|
|
|
59
59
|
var miniflare_1 = require("miniflare");
|
|
60
60
|
var build_1 = __importDefault(require("./build"));
|
|
61
61
|
var fs_extra_1 = __importDefault(require("fs-extra"));
|
|
62
|
+
var net_1 = require("net");
|
|
62
63
|
var childProcess = null;
|
|
63
64
|
var watcher = null;
|
|
64
65
|
var mf = null;
|
|
65
|
-
|
|
66
|
+
var tunnelUrl = null;
|
|
67
|
+
function isPortAvailable(port) {
|
|
68
|
+
return new Promise(function (resolve) {
|
|
69
|
+
var server = (0, net_1.createServer)()
|
|
70
|
+
.listen(port, function () {
|
|
71
|
+
server.close();
|
|
72
|
+
resolve(true);
|
|
73
|
+
})
|
|
74
|
+
.on('error', function () {
|
|
75
|
+
resolve(false);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function startProcess(command, options) {
|
|
66
80
|
var _a, _b;
|
|
67
81
|
if (childProcess) {
|
|
68
82
|
childProcess.kill();
|
|
69
83
|
}
|
|
70
84
|
var spinner = (0, ora_1.default)('Starting development server...').start();
|
|
71
|
-
childProcess = (0, child_process_1.exec)(command,
|
|
85
|
+
childProcess = (0, child_process_1.exec)(command, options);
|
|
72
86
|
(_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', function (data) {
|
|
73
87
|
spinner.succeed('Development server started.');
|
|
88
|
+
if (tunnelUrl) {
|
|
89
|
+
(0, utils_1.displayTunnelUrl)(tunnelUrl);
|
|
90
|
+
}
|
|
74
91
|
console.log(data);
|
|
75
92
|
});
|
|
76
93
|
(_b = childProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', function (data) {
|
|
@@ -101,11 +118,33 @@ function cleanup() {
|
|
|
101
118
|
}
|
|
102
119
|
function dev(options) {
|
|
103
120
|
return __awaiter(this, void 0, void 0, function () {
|
|
104
|
-
var config, runtime, tsNodePath, command, envVars, proxyServer, watchPaths, dainDir, outFile, MFconfig_1, debounceTimer_1, watchDirs, error_1;
|
|
121
|
+
var config, portSource, port, portNumber, runtime, tsNodePath, command, envVars, proxyServer, portNumber_1, proxySetup, watchPaths, dainDir, outFile, MFconfig_1, debounceTimer_1, watchDirs, error_1;
|
|
105
122
|
return __generator(this, function (_a) {
|
|
106
123
|
switch (_a.label) {
|
|
107
124
|
case 0:
|
|
108
125
|
config = (0, utils_1.getDainConfig)(options.config);
|
|
126
|
+
if (process.env.PORT) {
|
|
127
|
+
port = process.env.PORT;
|
|
128
|
+
portSource = '.env file';
|
|
129
|
+
}
|
|
130
|
+
else if (options.port) {
|
|
131
|
+
port = options.port;
|
|
132
|
+
portSource = 'command line argument';
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
port = '2022';
|
|
136
|
+
portSource = 'default value';
|
|
137
|
+
}
|
|
138
|
+
portNumber = parseInt(port);
|
|
139
|
+
if (isNaN(portNumber) || portNumber < 0 || portNumber > 65535) {
|
|
140
|
+
(0, utils_1.logError)('Invalid port number. Using default port 2022');
|
|
141
|
+
options.port = '2022';
|
|
142
|
+
portSource = 'default value (after invalid port)';
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
options.port = port;
|
|
146
|
+
}
|
|
147
|
+
(0, utils_1.logInfo)("Using port ".concat(options.port, " (from ").concat(portSource, ")"));
|
|
109
148
|
console.log('Config: ' + JSON.stringify(config));
|
|
110
149
|
runtime = options.runtime || config.runtime || 'node';
|
|
111
150
|
console.log('Runtime: ' + runtime);
|
|
@@ -121,19 +160,29 @@ function dev(options) {
|
|
|
121
160
|
proxyServer = null;
|
|
122
161
|
_a.label = 1;
|
|
123
162
|
case 1:
|
|
124
|
-
_a.trys.push([1,
|
|
125
|
-
|
|
163
|
+
_a.trys.push([1, 9, , 10]);
|
|
164
|
+
portNumber_1 = parseInt(options.port);
|
|
165
|
+
return [4 /*yield*/, isPortAvailable(portNumber_1)];
|
|
166
|
+
case 2:
|
|
167
|
+
if (!(_a.sent())) {
|
|
168
|
+
(0, utils_1.logError)("Port ".concat(portNumber_1, " is already in use. Please use a different port with --port option."));
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
process.env.PORT = portNumber_1.toString();
|
|
172
|
+
if (!!options.noproxy) return [3 /*break*/, 4];
|
|
126
173
|
if (!config['api-key']) {
|
|
127
174
|
throw new Error("'api-key' is required when using development proxy");
|
|
128
175
|
}
|
|
129
176
|
return [4 /*yield*/, (0, utils_1.setupProxy)(options.port, config['api-key'], config)];
|
|
130
|
-
case 2:
|
|
131
|
-
proxyServer = _a.sent();
|
|
132
|
-
_a.label = 3;
|
|
133
177
|
case 3:
|
|
134
|
-
|
|
178
|
+
proxySetup = _a.sent();
|
|
179
|
+
proxyServer = proxySetup.client;
|
|
180
|
+
tunnelUrl = proxySetup.tunnelUrl;
|
|
181
|
+
_a.label = 4;
|
|
182
|
+
case 4:
|
|
183
|
+
if (!(runtime === 'node')) return [3 /*break*/, 5];
|
|
135
184
|
// Existing Node.js development process
|
|
136
|
-
startProcess(command, envVars);
|
|
185
|
+
startProcess(command, { env: __assign(__assign({}, process.env), envVars) });
|
|
137
186
|
watchPaths = [
|
|
138
187
|
path_1.default.dirname(config['main-file']),
|
|
139
188
|
config['static-dir']
|
|
@@ -146,7 +195,7 @@ function dev(options) {
|
|
|
146
195
|
});
|
|
147
196
|
watcher.on('change', function (path) {
|
|
148
197
|
(0, utils_1.logInfo)("File ".concat(path, " has been changed. Restarting..."));
|
|
149
|
-
startProcess(command, envVars);
|
|
198
|
+
startProcess(command, { env: __assign(__assign({}, process.env), envVars) });
|
|
150
199
|
});
|
|
151
200
|
(0, utils_1.logInfo)('Watching for file changes...');
|
|
152
201
|
// Add signal handlers for graceful shutdown
|
|
@@ -201,14 +250,14 @@ function dev(options) {
|
|
|
201
250
|
process.exit(1);
|
|
202
251
|
}, 500);
|
|
203
252
|
});
|
|
204
|
-
return [3 /*break*/,
|
|
205
|
-
case
|
|
206
|
-
if (!(runtime === 'workers')) return [3 /*break*/,
|
|
253
|
+
return [3 /*break*/, 8];
|
|
254
|
+
case 5:
|
|
255
|
+
if (!(runtime === 'workers')) return [3 /*break*/, 7];
|
|
207
256
|
dainDir = path_1.default.join(process.cwd(), '.dain');
|
|
208
257
|
outFile = path_1.default.join(dainDir, path_1.default.basename(config['main-file'], '.ts') + '.mjs');
|
|
209
258
|
// Start the build process in watch mode
|
|
210
259
|
return [4 /*yield*/, (0, build_1.default)({ config: options.config, runtime: 'workers', watch: true })];
|
|
211
|
-
case
|
|
260
|
+
case 6:
|
|
212
261
|
// Start the build process in watch mode
|
|
213
262
|
_a.sent();
|
|
214
263
|
MFconfig_1 = {
|
|
@@ -234,10 +283,10 @@ function dev(options) {
|
|
|
234
283
|
});
|
|
235
284
|
});
|
|
236
285
|
(0, utils_1.logInfo)('Watching for file changes in source and build directories...');
|
|
237
|
-
return [3 /*break*/,
|
|
238
|
-
case
|
|
239
|
-
case
|
|
240
|
-
case
|
|
286
|
+
return [3 /*break*/, 8];
|
|
287
|
+
case 7: throw new Error("Unsupported runtime: ".concat(runtime));
|
|
288
|
+
case 8: return [3 /*break*/, 10];
|
|
289
|
+
case 9:
|
|
241
290
|
error_1 = _a.sent();
|
|
242
291
|
(0, utils_1.logError)("Error in dev process for ".concat(runtime, " runtime:"), error_1);
|
|
243
292
|
cleanup();
|
|
@@ -246,8 +295,8 @@ function dev(options) {
|
|
|
246
295
|
setTimeout(function () {
|
|
247
296
|
process.exit(1);
|
|
248
297
|
}, 500);
|
|
249
|
-
return [3 /*break*/,
|
|
250
|
-
case
|
|
298
|
+
return [3 /*break*/, 10];
|
|
299
|
+
case 10: return [2 /*return*/];
|
|
251
300
|
}
|
|
252
301
|
});
|
|
253
302
|
});
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ program
|
|
|
33
33
|
program
|
|
34
34
|
.command('dev')
|
|
35
35
|
.description('Run the project in development mode')
|
|
36
|
-
.option('--port <port>', 'Set the port number'
|
|
36
|
+
.option('--port <port>', 'Set the port number')
|
|
37
37
|
.option('--noproxy', 'Disable localtunnel proxy')
|
|
38
38
|
.option('-c, --config <path>', 'Path to custom configuration file')
|
|
39
39
|
.option('--runtime <runtime>', 'Specify the runtime (node or workers)')
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"deploy": "dain deploy"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dainprotocol/service-sdk": "^1.0.
|
|
14
|
-
"@dainprotocol/utils": "^0.0.
|
|
13
|
+
"@dainprotocol/service-sdk": "^1.0.95",
|
|
14
|
+
"@dainprotocol/utils": "^0.0.49",
|
|
15
15
|
"zod": "^3.23.8",
|
|
16
16
|
"hono": "^4.6.3",
|
|
17
17
|
"ts-node": "^10.4.0",
|
|
@@ -19,6 +19,6 @@
|
|
|
19
19
|
"@types/express": "^4.17.13",
|
|
20
20
|
"@types/node": "^22.5.4",
|
|
21
21
|
"axios": "^1.7.5",
|
|
22
|
-
"@dainprotocol/cli": "^1.
|
|
22
|
+
"@dainprotocol/cli": "^1.1.26"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -3,20 +3,22 @@
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import axios from "axios";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
defineDAINService,
|
|
8
|
-
ToolConfig,
|
|
9
|
-
} from "@dainprotocol/service-sdk";
|
|
6
|
+
import { defineDAINService, ToolConfig } from "@dainprotocol/service-sdk";
|
|
10
7
|
|
|
11
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CardUIBuilder,
|
|
10
|
+
TableUIBuilder,
|
|
11
|
+
MapUIBuilder,
|
|
12
|
+
LayoutUIBuilder,
|
|
13
|
+
} from "@dainprotocol/utils";
|
|
12
14
|
|
|
13
15
|
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
|
|
16
|
+
if (temperature <= 0) return "🥶";
|
|
17
|
+
if (temperature <= 10) return "❄️";
|
|
18
|
+
if (temperature <= 20) return "⛅";
|
|
19
|
+
if (temperature <= 25) return "☀️";
|
|
20
|
+
if (temperature <= 30) return "🌞";
|
|
21
|
+
return "🔥";
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const getWeatherConfig: ToolConfig = {
|
|
@@ -37,12 +39,15 @@ const getWeatherConfig: ToolConfig = {
|
|
|
37
39
|
})
|
|
38
40
|
.describe("Current weather information"),
|
|
39
41
|
pricing: { pricePerUse: 0, currency: "USD" },
|
|
40
|
-
handler: async (
|
|
42
|
+
handler: async (
|
|
43
|
+
{ locationName, latitude, longitude },
|
|
44
|
+
agentInfo,
|
|
45
|
+
context
|
|
46
|
+
) => {
|
|
41
47
|
console.log(
|
|
42
48
|
`User / Agent ${agentInfo.id} requested weather at ${locationName} (${latitude},${longitude})`
|
|
43
49
|
);
|
|
44
50
|
|
|
45
|
-
|
|
46
51
|
const response = await axios.get(
|
|
47
52
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m`
|
|
48
53
|
);
|
|
@@ -59,20 +64,24 @@ const getWeatherConfig: ToolConfig = {
|
|
|
59
64
|
ui: new CardUIBuilder()
|
|
60
65
|
.setRenderMode("page")
|
|
61
66
|
.title(`Current Weather in ${locationName} ${weatherEmoji}`)
|
|
62
|
-
.addChild(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
.addChild(
|
|
68
|
+
new MapUIBuilder()
|
|
69
|
+
.setInitialView(latitude, longitude, 10)
|
|
70
|
+
.setMapStyle("mapbox://styles/mapbox/streets-v12")
|
|
71
|
+
.addMarkers([
|
|
72
|
+
{
|
|
73
|
+
latitude,
|
|
74
|
+
longitude,
|
|
75
|
+
title: locationName,
|
|
76
|
+
description: `Temperature: ${temperature_2m}°C\nWind: ${wind_speed_10m} km/h`,
|
|
77
|
+
text: `${locationName} ${weatherEmoji}`,
|
|
78
|
+
},
|
|
79
|
+
])
|
|
80
|
+
.build()
|
|
81
|
+
)
|
|
82
|
+
.content(
|
|
83
|
+
`Temperature: ${temperature_2m}°C\nWind Speed: ${wind_speed_10m} km/h`
|
|
84
|
+
)
|
|
76
85
|
.build(),
|
|
77
86
|
};
|
|
78
87
|
},
|
|
@@ -102,12 +111,15 @@ const getWeatherForecastConfig: ToolConfig = {
|
|
|
102
111
|
})
|
|
103
112
|
.describe("Hourly weather forecast"),
|
|
104
113
|
pricing: { pricePerUse: 0, currency: "USD" },
|
|
105
|
-
handler: async (
|
|
114
|
+
handler: async (
|
|
115
|
+
{ locationName, latitude, longitude },
|
|
116
|
+
agentInfo,
|
|
117
|
+
context
|
|
118
|
+
) => {
|
|
106
119
|
console.log(
|
|
107
120
|
`User / Agent ${agentInfo.id} requested forecast at ${locationName} (${latitude},${longitude})`
|
|
108
121
|
);
|
|
109
122
|
|
|
110
|
-
|
|
111
123
|
const response = await axios.get(
|
|
112
124
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
|
|
113
125
|
);
|
|
@@ -131,36 +143,46 @@ const getWeatherForecastConfig: ToolConfig = {
|
|
|
131
143
|
windSpeeds: limitedWind,
|
|
132
144
|
humidity: limitedHumidity,
|
|
133
145
|
},
|
|
134
|
-
ui: new
|
|
146
|
+
ui: new LayoutUIBuilder()
|
|
135
147
|
.setRenderMode("page")
|
|
136
|
-
.
|
|
137
|
-
.addChild(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
148
|
+
.setLayoutType("column")
|
|
149
|
+
.addChild(
|
|
150
|
+
new MapUIBuilder()
|
|
151
|
+
.setInitialView(latitude, longitude, 10)
|
|
152
|
+
.setMapStyle("mapbox://styles/mapbox/streets-v12")
|
|
153
|
+
.addMarkers([
|
|
154
|
+
{
|
|
155
|
+
latitude,
|
|
156
|
+
longitude,
|
|
157
|
+
title: locationName,
|
|
158
|
+
description: `Temperature: ${limitedTemp[0]}°C\nWind: ${limitedWind[0]} km/h`,
|
|
159
|
+
text: `${locationName} ${weatherEmoji}`,
|
|
160
|
+
},
|
|
161
|
+
])
|
|
162
|
+
.build()
|
|
163
|
+
)
|
|
164
|
+
.addChild(
|
|
165
|
+
new TableUIBuilder()
|
|
166
|
+
.addColumns([
|
|
167
|
+
{ key: "time", header: "Time", type: "string" },
|
|
168
|
+
{
|
|
169
|
+
key: "temperature",
|
|
170
|
+
header: "Temperature (°C)",
|
|
171
|
+
type: "number",
|
|
172
|
+
},
|
|
173
|
+
{ key: "windSpeed", header: "Wind Speed (km/h)", type: "number" },
|
|
174
|
+
{ key: "humidity", header: "Humidity (%)", type: "number" },
|
|
175
|
+
])
|
|
176
|
+
.rows(
|
|
177
|
+
limitedTime.map((t: string, i: number) => ({
|
|
178
|
+
time: new Date(t).toLocaleString(),
|
|
179
|
+
temperature: limitedTemp[i],
|
|
180
|
+
windSpeed: limitedWind[i],
|
|
181
|
+
humidity: limitedHumidity[i],
|
|
182
|
+
}))
|
|
183
|
+
)
|
|
184
|
+
.build()
|
|
185
|
+
)
|
|
164
186
|
.build(),
|
|
165
187
|
};
|
|
166
188
|
},
|
|
@@ -177,14 +199,14 @@ const dainService = defineDAINService({
|
|
|
177
199
|
logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png",
|
|
178
200
|
},
|
|
179
201
|
exampleQueries: [
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
202
|
+
{
|
|
203
|
+
category: "Weather",
|
|
204
|
+
queries: [
|
|
205
|
+
"What is the weather in Tokyo?",
|
|
206
|
+
"What is the weather in San Francisco?",
|
|
207
|
+
"What is the weather in London?",
|
|
208
|
+
],
|
|
209
|
+
},
|
|
188
210
|
],
|
|
189
211
|
identity: {
|
|
190
212
|
apiKey: process.env.DAIN_API_KEY,
|
|
@@ -192,6 +214,6 @@ const dainService = defineDAINService({
|
|
|
192
214
|
tools: [getWeatherConfig, getWeatherForecastConfig],
|
|
193
215
|
});
|
|
194
216
|
|
|
195
|
-
dainService.startNode(
|
|
196
|
-
console.log("Weather DAIN Service is running
|
|
217
|
+
dainService.startNode().then(({ address }) => {
|
|
218
|
+
console.log("Weather DAIN Service is running at :" + address().port);
|
|
197
219
|
});
|
package/dist/utils.js
CHANGED
|
@@ -40,6 +40,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
40
40
|
};
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.getDainConfig = getDainConfig;
|
|
43
|
+
exports.displayTunnelUrl = displayTunnelUrl;
|
|
43
44
|
exports.setupProxy = setupProxy;
|
|
44
45
|
exports.logError = logError;
|
|
45
46
|
exports.logSuccess = logSuccess;
|
|
@@ -62,7 +63,7 @@ function loadEnvFiles() {
|
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
function getDainConfig(configFile) {
|
|
65
|
-
loadEnvFiles(); //
|
|
66
|
+
loadEnvFiles(); // Loads all env files first
|
|
66
67
|
var defaultConfigPath = path_1.default.join(process.cwd(), 'dain.json');
|
|
67
68
|
var configPath = configFile
|
|
68
69
|
? path_1.default.join(process.cwd(), configFile)
|
|
@@ -101,6 +102,15 @@ function getDainConfig(configFile) {
|
|
|
101
102
|
throw new Error("Error reading or parsing configuration file: ".concat(error));
|
|
102
103
|
}
|
|
103
104
|
}
|
|
105
|
+
function displayTunnelUrl(tunnelUrl) {
|
|
106
|
+
var divider = chalk_1.default.green('------------------------------------------------------------');
|
|
107
|
+
var header = chalk_1.default.green('Your service is available publicly at:');
|
|
108
|
+
var url = chalk_1.default.cyan.underline(tunnelUrl);
|
|
109
|
+
var info = chalk_1.default.yellow('This service URL can be connected to by a DAIN client or assistant');
|
|
110
|
+
var subInfo = chalk_1.default.yellow('(such as butterfly in development mode)');
|
|
111
|
+
var warning = chalk_1.default.red('You should not visit this URL directly');
|
|
112
|
+
console.log("\n".concat(divider, "\n").concat(header, "\n").concat(url, "\n\n").concat(info, "\n").concat(subInfo, "\n\n").concat(warning, "\n").concat(divider, "\n"));
|
|
113
|
+
}
|
|
104
114
|
function setupProxy(port, apiKey, config) {
|
|
105
115
|
return __awaiter(this, void 0, void 0, function () {
|
|
106
116
|
var spinner, client, tunnelUrl, error_1;
|
|
@@ -115,15 +125,14 @@ function setupProxy(port, apiKey, config) {
|
|
|
115
125
|
return [4 /*yield*/, client.start(parseInt(port))];
|
|
116
126
|
case 2:
|
|
117
127
|
tunnelUrl = _a.sent();
|
|
118
|
-
spinner.succeed(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return [2 /*return*/, client];
|
|
128
|
+
spinner.succeed('Proxy setup complete');
|
|
129
|
+
displayTunnelUrl(tunnelUrl);
|
|
130
|
+
return [2 /*return*/, { client: client, tunnelUrl: tunnelUrl }];
|
|
122
131
|
case 3:
|
|
123
132
|
error_1 = _a.sent();
|
|
124
|
-
spinner.fail(chalk_1.default.red('
|
|
133
|
+
spinner.fail(chalk_1.default.red('Error setting up proxy'));
|
|
125
134
|
console.error(chalk_1.default.red(error_1));
|
|
126
|
-
|
|
135
|
+
throw error_1;
|
|
127
136
|
case 4: return [2 /*return*/];
|
|
128
137
|
}
|
|
129
138
|
});
|
package/package.json
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"deploy": "dain deploy"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dainprotocol/service-sdk": "^1.0.
|
|
14
|
-
"@dainprotocol/utils": "^0.0.
|
|
13
|
+
"@dainprotocol/service-sdk": "^1.0.95",
|
|
14
|
+
"@dainprotocol/utils": "^0.0.49",
|
|
15
15
|
"zod": "^3.23.8",
|
|
16
16
|
"hono": "^4.6.3",
|
|
17
17
|
"ts-node": "^10.4.0",
|
|
@@ -19,6 +19,6 @@
|
|
|
19
19
|
"@types/express": "^4.17.13",
|
|
20
20
|
"@types/node": "^22.5.4",
|
|
21
21
|
"axios": "^1.7.5",
|
|
22
|
-
"@dainprotocol/cli": "^1.
|
|
22
|
+
"@dainprotocol/cli": "^1.1.26"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -3,20 +3,22 @@
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import axios from "axios";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
defineDAINService,
|
|
8
|
-
ToolConfig,
|
|
9
|
-
} from "@dainprotocol/service-sdk";
|
|
6
|
+
import { defineDAINService, ToolConfig } from "@dainprotocol/service-sdk";
|
|
10
7
|
|
|
11
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CardUIBuilder,
|
|
10
|
+
TableUIBuilder,
|
|
11
|
+
MapUIBuilder,
|
|
12
|
+
LayoutUIBuilder,
|
|
13
|
+
} from "@dainprotocol/utils";
|
|
12
14
|
|
|
13
15
|
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
|
|
16
|
+
if (temperature <= 0) return "🥶";
|
|
17
|
+
if (temperature <= 10) return "❄️";
|
|
18
|
+
if (temperature <= 20) return "⛅";
|
|
19
|
+
if (temperature <= 25) return "☀️";
|
|
20
|
+
if (temperature <= 30) return "🌞";
|
|
21
|
+
return "🔥";
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const getWeatherConfig: ToolConfig = {
|
|
@@ -37,12 +39,15 @@ const getWeatherConfig: ToolConfig = {
|
|
|
37
39
|
})
|
|
38
40
|
.describe("Current weather information"),
|
|
39
41
|
pricing: { pricePerUse: 0, currency: "USD" },
|
|
40
|
-
handler: async (
|
|
42
|
+
handler: async (
|
|
43
|
+
{ locationName, latitude, longitude },
|
|
44
|
+
agentInfo,
|
|
45
|
+
context
|
|
46
|
+
) => {
|
|
41
47
|
console.log(
|
|
42
48
|
`User / Agent ${agentInfo.id} requested weather at ${locationName} (${latitude},${longitude})`
|
|
43
49
|
);
|
|
44
50
|
|
|
45
|
-
|
|
46
51
|
const response = await axios.get(
|
|
47
52
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m`
|
|
48
53
|
);
|
|
@@ -59,20 +64,24 @@ const getWeatherConfig: ToolConfig = {
|
|
|
59
64
|
ui: new CardUIBuilder()
|
|
60
65
|
.setRenderMode("page")
|
|
61
66
|
.title(`Current Weather in ${locationName} ${weatherEmoji}`)
|
|
62
|
-
.addChild(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
.addChild(
|
|
68
|
+
new MapUIBuilder()
|
|
69
|
+
.setInitialView(latitude, longitude, 10)
|
|
70
|
+
.setMapStyle("mapbox://styles/mapbox/streets-v12")
|
|
71
|
+
.addMarkers([
|
|
72
|
+
{
|
|
73
|
+
latitude,
|
|
74
|
+
longitude,
|
|
75
|
+
title: locationName,
|
|
76
|
+
description: `Temperature: ${temperature_2m}°C\nWind: ${wind_speed_10m} km/h`,
|
|
77
|
+
text: `${locationName} ${weatherEmoji}`,
|
|
78
|
+
},
|
|
79
|
+
])
|
|
80
|
+
.build()
|
|
81
|
+
)
|
|
82
|
+
.content(
|
|
83
|
+
`Temperature: ${temperature_2m}°C\nWind Speed: ${wind_speed_10m} km/h`
|
|
84
|
+
)
|
|
76
85
|
.build(),
|
|
77
86
|
};
|
|
78
87
|
},
|
|
@@ -102,12 +111,15 @@ const getWeatherForecastConfig: ToolConfig = {
|
|
|
102
111
|
})
|
|
103
112
|
.describe("Hourly weather forecast"),
|
|
104
113
|
pricing: { pricePerUse: 0, currency: "USD" },
|
|
105
|
-
handler: async (
|
|
114
|
+
handler: async (
|
|
115
|
+
{ locationName, latitude, longitude },
|
|
116
|
+
agentInfo,
|
|
117
|
+
context
|
|
118
|
+
) => {
|
|
106
119
|
console.log(
|
|
107
120
|
`User / Agent ${agentInfo.id} requested forecast at ${locationName} (${latitude},${longitude})`
|
|
108
121
|
);
|
|
109
122
|
|
|
110
|
-
|
|
111
123
|
const response = await axios.get(
|
|
112
124
|
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`
|
|
113
125
|
);
|
|
@@ -131,36 +143,46 @@ const getWeatherForecastConfig: ToolConfig = {
|
|
|
131
143
|
windSpeeds: limitedWind,
|
|
132
144
|
humidity: limitedHumidity,
|
|
133
145
|
},
|
|
134
|
-
ui: new
|
|
146
|
+
ui: new LayoutUIBuilder()
|
|
135
147
|
.setRenderMode("page")
|
|
136
|
-
.
|
|
137
|
-
.addChild(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
148
|
+
.setLayoutType("column")
|
|
149
|
+
.addChild(
|
|
150
|
+
new MapUIBuilder()
|
|
151
|
+
.setInitialView(latitude, longitude, 10)
|
|
152
|
+
.setMapStyle("mapbox://styles/mapbox/streets-v12")
|
|
153
|
+
.addMarkers([
|
|
154
|
+
{
|
|
155
|
+
latitude,
|
|
156
|
+
longitude,
|
|
157
|
+
title: locationName,
|
|
158
|
+
description: `Temperature: ${limitedTemp[0]}°C\nWind: ${limitedWind[0]} km/h`,
|
|
159
|
+
text: `${locationName} ${weatherEmoji}`,
|
|
160
|
+
},
|
|
161
|
+
])
|
|
162
|
+
.build()
|
|
163
|
+
)
|
|
164
|
+
.addChild(
|
|
165
|
+
new TableUIBuilder()
|
|
166
|
+
.addColumns([
|
|
167
|
+
{ key: "time", header: "Time", type: "string" },
|
|
168
|
+
{
|
|
169
|
+
key: "temperature",
|
|
170
|
+
header: "Temperature (°C)",
|
|
171
|
+
type: "number",
|
|
172
|
+
},
|
|
173
|
+
{ key: "windSpeed", header: "Wind Speed (km/h)", type: "number" },
|
|
174
|
+
{ key: "humidity", header: "Humidity (%)", type: "number" },
|
|
175
|
+
])
|
|
176
|
+
.rows(
|
|
177
|
+
limitedTime.map((t: string, i: number) => ({
|
|
178
|
+
time: new Date(t).toLocaleString(),
|
|
179
|
+
temperature: limitedTemp[i],
|
|
180
|
+
windSpeed: limitedWind[i],
|
|
181
|
+
humidity: limitedHumidity[i],
|
|
182
|
+
}))
|
|
183
|
+
)
|
|
184
|
+
.build()
|
|
185
|
+
)
|
|
164
186
|
.build(),
|
|
165
187
|
};
|
|
166
188
|
},
|
|
@@ -177,14 +199,14 @@ const dainService = defineDAINService({
|
|
|
177
199
|
logo: "https://cdn-icons-png.flaticon.com/512/252/252035.png",
|
|
178
200
|
},
|
|
179
201
|
exampleQueries: [
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
202
|
+
{
|
|
203
|
+
category: "Weather",
|
|
204
|
+
queries: [
|
|
205
|
+
"What is the weather in Tokyo?",
|
|
206
|
+
"What is the weather in San Francisco?",
|
|
207
|
+
"What is the weather in London?",
|
|
208
|
+
],
|
|
209
|
+
},
|
|
188
210
|
],
|
|
189
211
|
identity: {
|
|
190
212
|
apiKey: process.env.DAIN_API_KEY,
|
|
@@ -192,6 +214,6 @@ const dainService = defineDAINService({
|
|
|
192
214
|
tools: [getWeatherConfig, getWeatherForecastConfig],
|
|
193
215
|
});
|
|
194
216
|
|
|
195
|
-
dainService.startNode(
|
|
196
|
-
console.log("Weather DAIN Service is running
|
|
217
|
+
dainService.startNode().then(({ address }) => {
|
|
218
|
+
console.log("Weather DAIN Service is running at :" + address().port);
|
|
197
219
|
});
|