@dainprotocol/cli 1.0.11 → 1.0.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.
@@ -70,57 +70,92 @@ var fs_extra_1 = __importDefault(require("fs-extra"));
70
70
  var path_1 = __importDefault(require("path"));
71
71
  function build(options) {
72
72
  return __awaiter(this, void 0, void 0, function () {
73
- var spinner, config, outDir, staticDir, error_1;
73
+ var spinner, config, runtime, outDir, dainDir, buildOptions, context, staticDir, staticOutDir, error_1;
74
74
  return __generator(this, function (_a) {
75
75
  switch (_a.label) {
76
76
  case 0:
77
77
  spinner = (0, ora_1.default)('Building project...').start();
78
78
  config = (0, utils_1.getDainConfig)(options.config);
79
+ runtime = options.runtime || config.runtime || 'node';
79
80
  outDir = config['out-dir'] || 'build';
81
+ dainDir = path_1.default.join(process.cwd(), '.dain');
80
82
  _a.label = 1;
81
83
  case 1:
82
- _a.trys.push([1, 7, , 8]);
84
+ _a.trys.push([1, 12, , 13]);
83
85
  // Ensure build directory exists
84
86
  return [4 /*yield*/, fs_extra_1.default.ensureDir(outDir)];
85
87
  case 2:
86
88
  // Ensure build directory exists
87
89
  _a.sent();
88
- // Build the main application
89
- return [4 /*yield*/, esbuild.build({
90
- entryPoints: [config['main-file']],
91
- bundle: true,
90
+ buildOptions = {
91
+ entryPoints: [config['main-file']],
92
+ bundle: true,
93
+ sourcemap: true,
94
+ outdir: options.watch ? dainDir : outDir,
95
+ };
96
+ if (runtime === 'node') {
97
+ // Node.js build process
98
+ Object.assign(buildOptions, {
92
99
  platform: 'node',
93
100
  target: 'node14',
94
- outfile: path_1.default.join(outDir, 'index.js'),
95
- minify: true,
96
- sourcemap: true,
97
- })];
101
+ minify: !options.watch,
102
+ });
103
+ }
104
+ else if (runtime === 'workers') {
105
+ // Cloudflare Workers build process
106
+ Object.assign(buildOptions, {
107
+ format: 'esm',
108
+ target: 'esnext',
109
+ conditions: ['worker', 'workerd', 'browser'],
110
+ outExtension: { '.js': '.mjs' },
111
+ });
112
+ }
113
+ else {
114
+ throw new Error("Unsupported runtime: ".concat(runtime));
115
+ }
116
+ if (!options.watch) return [3 /*break*/, 6];
117
+ // Ensure .dain directory exists for watch mode
118
+ return [4 /*yield*/, fs_extra_1.default.ensureDir(dainDir)];
98
119
  case 3:
99
- // Build the main application
120
+ // Ensure .dain directory exists for watch mode
100
121
  _a.sent();
122
+ return [4 /*yield*/, esbuild.context(buildOptions)];
123
+ case 4:
124
+ context = _a.sent();
125
+ return [4 /*yield*/, context.watch()];
126
+ case 5:
127
+ _a.sent();
128
+ (0, utils_1.logInfo)('Watching for file changes...');
129
+ return [3 /*break*/, 8];
130
+ case 6: return [4 /*yield*/, esbuild.build(buildOptions)];
131
+ case 7:
132
+ _a.sent();
133
+ _a.label = 8;
134
+ case 8:
101
135
  staticDir = config['static-dir']
102
136
  ? path_1.default.join(process.cwd(), config['static-dir'])
103
137
  : path_1.default.join(process.cwd(), 'static');
104
- if (!fs_extra_1.default.existsSync(staticDir)) return [3 /*break*/, 5];
105
- return [4 /*yield*/, fs_extra_1.default.copy(staticDir, path_1.default.join(outDir, 'static'))];
106
- case 4:
138
+ if (!fs_extra_1.default.existsSync(staticDir)) return [3 /*break*/, 10];
139
+ staticOutDir = path_1.default.join(options.watch ? dainDir : outDir, 'static');
140
+ return [4 /*yield*/, fs_extra_1.default.copy(staticDir, staticOutDir)];
141
+ case 9:
107
142
  _a.sent();
108
- (0, utils_1.logInfo)("Static files copied to ".concat(path_1.default.join(outDir, 'static')));
109
- return [3 /*break*/, 6];
110
- case 5:
143
+ (0, utils_1.logInfo)("Static files copied to ".concat(staticOutDir));
144
+ return [3 /*break*/, 11];
145
+ case 10:
111
146
  (0, utils_1.logInfo)('No static directory found. Skipping static file copy.');
112
- _a.label = 6;
113
- case 6:
147
+ _a.label = 11;
148
+ case 11:
114
149
  spinner.succeed('Build completed successfully.');
115
- (0, utils_1.logSuccess)("Project built and ready for deployment in ".concat(outDir, "."));
116
- return [3 /*break*/, 8];
117
- case 7:
150
+ (0, utils_1.logSuccess)("Project built and ready for ".concat(runtime, " runtime in ").concat(options.watch ? dainDir : outDir, "."));
151
+ return [3 /*break*/, 13];
152
+ case 12:
118
153
  error_1 = _a.sent();
119
154
  spinner.fail('Build failed.');
120
155
  (0, utils_1.logError)('Build process encountered an error', error_1);
121
156
  process.exit(1);
122
- return [3 /*break*/, 8];
123
- case 8: return [2 /*return*/];
157
+ return [3 /*break*/, 13];
158
+ case 13: return [2 /*return*/];
124
159
  }
125
160
  });
126
161
  });
@@ -66,6 +66,14 @@ function config(action, key, value) {
66
66
  return [3 /*break*/, 6];
67
67
  case 3:
68
68
  if (!(action === 'edit' && key && value)) return [3 /*break*/, 5];
69
+ if (key === 'runtime' && !['node', 'workers'].includes(value)) {
70
+ (0, utils_1.logError)('Invalid runtime. Use "node" or "workers"');
71
+ return [2 /*return*/];
72
+ }
73
+ if (key === 'platform-base-url' && !value.startsWith('http')) {
74
+ (0, utils_1.logError)('Invalid platform-base-url. It should start with http:// or https://');
75
+ return [2 /*return*/];
76
+ }
69
77
  config_1[key] = value;
70
78
  return [4 /*yield*/, fs_extra_1.default.writeJSON(configPath, config_1, { spaces: 2 })];
71
79
  case 4:
@@ -47,43 +47,85 @@ var fs_extra_1 = __importDefault(require("fs-extra"));
47
47
  var path_1 = __importDefault(require("path"));
48
48
  function deploy(options) {
49
49
  return __awaiter(this, void 0, void 0, function () {
50
- var config, spinner, outDir, staticFilesPath, error_1;
50
+ var config, spinner, outDir_1, platformBaseUrl, deployUrl, files, deployFiles, deployData, response, result, error_1;
51
+ var _this = this;
51
52
  return __generator(this, function (_a) {
52
53
  switch (_a.label) {
53
54
  case 0:
54
55
  config = (0, utils_1.getDainConfig)(options.config);
56
+ if (config.runtime !== 'workers') {
57
+ (0, utils_1.logError)("Deployment is only supported for 'workers' runtime.");
58
+ process.exit(1);
59
+ }
55
60
  spinner = (0, ora_1.default)("Deploying project...").start();
56
61
  _a.label = 1;
57
62
  case 1:
58
- _a.trys.push([1, 3, , 4]);
63
+ _a.trys.push([1, 7, , 8]);
59
64
  // First, build the project
60
65
  return [4 /*yield*/, (0, build_1.default)({ config: options.config })];
61
66
  case 2:
62
67
  // First, build the project
63
68
  _a.sent();
64
- outDir = config['out-dir'] || 'build';
65
- // Here you would add your deployment logic
66
- // For example, uploading the outDir/index.js file and static files to your server
67
- (0, utils_1.logInfo)("Deployment logic to be implemented");
68
- staticFilesPath = path_1.default.join(outDir, 'static');
69
- if (fs_extra_1.default.existsSync(staticFilesPath)) {
70
- (0, utils_1.logInfo)("Static files are available at: ".concat(staticFilesPath));
71
- // Here you would implement the logic to deploy these static files
72
- }
73
- else {
74
- (0, utils_1.logInfo)("No static files to deploy.");
69
+ outDir_1 = config['out-dir'] || 'build';
70
+ platformBaseUrl = config['platform-base-url'] || 'https://platform.dain.org';
71
+ deployUrl = "".concat(platformBaseUrl, "/api/platform-api/v1/service/deploy");
72
+ return [4 /*yield*/, fs_extra_1.default.readdir(outDir_1)];
73
+ case 3:
74
+ files = _a.sent();
75
+ return [4 /*yield*/, Promise.all(files.map(function (file) { return __awaiter(_this, void 0, void 0, function () {
76
+ var fileType, content;
77
+ return __generator(this, function (_a) {
78
+ switch (_a.label) {
79
+ case 0:
80
+ fileType = path_1.default.extname(file).slice(1);
81
+ if (!['js', 'mjs', 'wasm'].includes(fileType)) return [3 /*break*/, 2];
82
+ return [4 /*yield*/, fs_extra_1.default.readFile(path_1.default.join(outDir_1, file), 'utf-8')];
83
+ case 1:
84
+ content = _a.sent();
85
+ return [2 /*return*/, {
86
+ name: file,
87
+ content: content,
88
+ type: fileType,
89
+ }];
90
+ case 2: return [2 /*return*/, null];
91
+ }
92
+ });
93
+ }); })).then(function (files) { return files.filter(Boolean); })];
94
+ case 4:
95
+ deployFiles = _a.sent();
96
+ deployData = {
97
+ serviceIdentifer: config['project-id'],
98
+ files: deployFiles,
99
+ };
100
+ console.log(deployData);
101
+ return [4 /*yield*/, fetch(deployUrl, {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json',
105
+ "X-DAIN-SIGNATORY-ADDRESS": "TODO: X-DAIN-SIGNATORY-ADDRESS",
106
+ "X-DAIN-SIGNATURE": "TODO: X-DAIN-SIGNATORY-SIGNATURE",
107
+ },
108
+ body: JSON.stringify(deployData),
109
+ })];
110
+ case 5:
111
+ response = _a.sent();
112
+ if (!response.ok) {
113
+ throw new Error("Deployment failed: ".concat(response.statusText));
75
114
  }
76
- (0, utils_1.logSuccess)("Deployment completed successfully. (NO LOGIC HERE YET, JUST EXAMPLE)");
115
+ return [4 /*yield*/, response.json()];
116
+ case 6:
117
+ result = _a.sent();
118
+ (0, utils_1.logSuccess)("Deployment completed successfully.");
77
119
  spinner.succeed("Deployment completed successfully.");
78
- (0, utils_1.logSuccess)("Project deployed and running.");
79
- return [3 /*break*/, 4];
80
- case 3:
120
+ (0, utils_1.logInfo)("Deployment result: ".concat(JSON.stringify(result, null, 2)));
121
+ return [3 /*break*/, 8];
122
+ case 7:
81
123
  error_1 = _a.sent();
82
124
  spinner.fail("Deployment failed.");
83
125
  (0, utils_1.logError)("Error during deployment", error_1);
84
126
  process.exit(1);
85
- return [3 /*break*/, 4];
86
- case 4: return [2 /*return*/];
127
+ return [3 /*break*/, 8];
128
+ case 8: return [2 /*return*/];
87
129
  }
88
130
  });
89
131
  });
@@ -56,8 +56,12 @@ var utils_1 = require("../utils");
56
56
  var ora_1 = __importDefault(require("ora"));
57
57
  var chokidar_1 = __importDefault(require("chokidar"));
58
58
  var path_1 = __importDefault(require("path"));
59
+ var miniflare_1 = require("miniflare");
60
+ var build_1 = __importDefault(require("./build"));
61
+ var fs_extra_1 = __importDefault(require("fs-extra"));
59
62
  var childProcess = null;
60
63
  var watcher = null;
64
+ var mf = null;
61
65
  function startProcess(command, env) {
62
66
  var _a, _b;
63
67
  if (childProcess) {
@@ -88,16 +92,23 @@ function cleanup() {
88
92
  watcher.close();
89
93
  watcher = null;
90
94
  }
95
+ if (mf) {
96
+ mf.dispose();
97
+ mf = null;
98
+ }
91
99
  (0, utils_1.logInfo)('Development server and file watcher stopped.');
92
100
  process.exit(0);
93
101
  }
94
102
  function dev(options) {
95
103
  return __awaiter(this, void 0, void 0, function () {
96
- var config, command, envVars, proxyServer, watchPaths, error_1;
104
+ var config, runtime, command, envVars, proxyServer, watchPaths, dainDir, outFile, MFconfig_1, debounceTimer_1, watchDirs, error_1;
97
105
  return __generator(this, function (_a) {
98
106
  switch (_a.label) {
99
107
  case 0:
100
108
  config = (0, utils_1.getDainConfig)(options.config);
109
+ console.log("Config: " + JSON.stringify(config));
110
+ runtime = options.runtime || config.runtime || 'node';
111
+ console.log("Runtime: " + runtime);
101
112
  command = "ts-node ".concat(config['main-file']);
102
113
  envVars = {
103
114
  PORT: options.port,
@@ -109,7 +120,9 @@ function dev(options) {
109
120
  proxyServer = null;
110
121
  _a.label = 1;
111
122
  case 1:
112
- _a.trys.push([1, 4, , 5]);
123
+ _a.trys.push([1, 8, , 9]);
124
+ if (!(runtime === 'node')) return [3 /*break*/, 4];
125
+ // Existing Node.js development process
113
126
  startProcess(command, envVars);
114
127
  if (!!options.noproxy) return [3 /*break*/, 3];
115
128
  if (!config['api-key']) {
@@ -185,18 +198,53 @@ function dev(options) {
185
198
  process.exit(1);
186
199
  }, 500);
187
200
  });
188
- return [3 /*break*/, 5];
201
+ return [3 /*break*/, 7];
189
202
  case 4:
203
+ if (!(runtime === 'workers')) return [3 /*break*/, 6];
204
+ dainDir = path_1.default.join(process.cwd(), '.dain');
205
+ outFile = path_1.default.join(dainDir, path_1.default.basename(config['main-file'], '.ts') + '.mjs');
206
+ // Start the build process in watch mode
207
+ return [4 /*yield*/, (0, build_1.default)({ config: options.config, runtime: 'workers', watch: true, })];
208
+ case 5:
209
+ // Start the build process in watch mode
210
+ _a.sent();
211
+ MFconfig_1 = {
212
+ scriptPath: outFile,
213
+ modules: true,
214
+ port: parseInt(options.port),
215
+ log: new miniflare_1.Log(miniflare_1.LogLevel.DEBUG),
216
+ liveReload: true,
217
+ };
218
+ mf = new miniflare_1.Miniflare(MFconfig_1);
219
+ (0, utils_1.logSuccess)("Miniflare server started on port ".concat(options.port));
220
+ watchDirs = [dainDir];
221
+ watchDirs.forEach(function (dir) {
222
+ fs_extra_1.default.watch(dir, { recursive: true }, function (eventType, filename) {
223
+ clearTimeout(debounceTimer_1);
224
+ debounceTimer_1 = setTimeout(function () {
225
+ if (mf) {
226
+ // mf.setOptions({ scriptPath: outFile });
227
+ mf.setOptions(MFconfig_1);
228
+ (0, utils_1.logInfo)("Build updated (".concat(filename, ")"));
229
+ }
230
+ }, 300); // 300ms debounce time
231
+ });
232
+ });
233
+ (0, utils_1.logInfo)('Watching for file changes in source and build directories...');
234
+ return [3 /*break*/, 7];
235
+ case 6: throw new Error("Unsupported runtime: ".concat(runtime));
236
+ case 7: return [3 /*break*/, 9];
237
+ case 8:
190
238
  error_1 = _a.sent();
191
- (0, utils_1.logError)('Error in dev process:', error_1);
239
+ (0, utils_1.logError)("Error in dev process for ".concat(runtime, " runtime:"), error_1);
192
240
  cleanup();
193
241
  if (proxyServer)
194
242
  proxyServer.close();
195
243
  setTimeout(function () {
196
244
  process.exit(1);
197
245
  }, 500);
198
- return [3 /*break*/, 5];
199
- case 5: return [2 /*return*/];
246
+ return [3 /*break*/, 9];
247
+ case 9: return [2 /*return*/];
200
248
  }
201
249
  });
202
250
  });
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ program
31
31
  .option('--port <port>', 'Set the port number', '2022')
32
32
  .option('--noproxy', 'Disable localtunnel proxy')
33
33
  .option('-c, --config <path>', 'Path to custom configuration file')
34
+ .option('--runtime <runtime>', 'Specify the runtime (node or workers)')
34
35
  .action(function (options) {
35
36
  (0, dev_1.default)(options);
36
37
  });
@@ -45,6 +46,7 @@ program
45
46
  .command('build')
46
47
  .description('Build the project')
47
48
  .option('-c, --config <path>', 'Path to custom configuration file')
49
+ .option('--runtime <runtime>', 'Specify the runtime (node or workers)', 'node')
48
50
  .action(function (options) {
49
51
  (0, build_1.default)(options);
50
52
  });
@@ -6,5 +6,7 @@
6
6
  "out-dir": "dist",
7
7
  "environment": "development",
8
8
  "version": "1.0.0",
9
- "tunnel-base-url": "wss:///devtunnel.dain-local.com"
9
+ "tunnel-base-url": "wss:///devtunnel.dain-local.com",
10
+ "platform-base-url": "https://platform.dain.org",
11
+ "runtime": "workers"
10
12
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { z } from "zod";
4
4
 
5
- import {defineDAINService, ToolConfig, ServiceConfig, ToolboxConfig} from "@dainprotocol/service-sdk";
5
+ import { defineDAINService , ToolConfig, ServiceConfig, ToolboxConfig} from "@dainprotocol/service-sdk";
6
6
 
7
7
  const getWeatherConfig: ToolConfig = {
8
8
  id: "get-weather",
@@ -23,15 +23,10 @@ const getWeatherConfig: ToolConfig = {
23
23
  .describe("Weather information for the requested city"),
24
24
  pricing: { pricePerUse: 0.01, currency: "USD" },
25
25
  handler: async ({ city }, agentInfo) => {
26
-
27
-
28
26
  console.log(`Agent ${agentInfo.agentId} requested weather for ${city}`);
29
-
30
-
31
-
32
27
  return {
33
- text: `The current weather in ${city} is 22°C and Sunny`,
34
- data: { temperature: 22, condition: "Sunny" },
28
+ text: `The current weather in ${city} is 125c and Sunny`,
29
+ data: { temperature: 99, condition: "Sunny" },
35
30
  ui: {
36
31
  type: "h2",
37
32
  children: "Weather test",
@@ -40,7 +35,7 @@ const getWeatherConfig: ToolConfig = {
40
35
  },
41
36
  };
42
37
 
43
- const getWeatherForecastConfig: ToolConfig = {
38
+ const getWeatherForecastConfig: ToolConfig = {
44
39
  id: "get-weather-forecast",
45
40
  name: "Get Weather Forecast",
46
41
  description: "Fetches a 5-day weather forecast for a city",
@@ -188,7 +183,7 @@ const dainService = defineDAINService({
188
183
  },
189
184
  identity: {
190
185
  apiKey:
191
- process.env.DAIN_API_KEY,
186
+ process.env.DAIN_API_KEY,
192
187
  },
193
188
  services: [weatherServiceConfig],
194
189
  tools: [
@@ -200,6 +195,6 @@ const dainService = defineDAINService({
200
195
  toolboxes: [weatherToolboxConfig],
201
196
  });
202
197
 
203
- dainService.startNode({ port: 2022 }).then(() => {
204
- console.log("Comprehensive Weather DAIN Service is running on port 2022");
205
- });
198
+ export default {
199
+ fetch: dainService.startWorkers(),
200
+ };
package/dist/utils.js CHANGED
@@ -88,6 +88,7 @@ function getDainConfig(configFile) {
88
88
  config["out-dir"] = config["out-dir"] || "dist"; // Default to 'dist' if not specified
89
89
  config["tunnel-base-url"] =
90
90
  config["tunnel-base-url"] || "wss:///tunnel.dain-local.com"; // Default value if not specified
91
+ config["runtime"] = config["runtime"] || "node"; // Add this line
91
92
  // Handle API key
92
93
  if (!config["api-key"] || config["api-key"] === "env" || config["api-key"] === "MUST PUT IN .env.development as DAIN_API_KEY=YOUR_API_KEY") {
93
94
  config["api-key"] = process.env.DAIN_API_KEY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dainprotocol/cli",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "CLI for Dain Protocol",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -25,6 +25,7 @@
25
25
  "esbuild": "^0.23.1",
26
26
  "fs-extra": "^11.2.0",
27
27
  "localtunnel": "^2.0.2",
28
+ "miniflare": "^3.20240909.1",
28
29
  "ora": "^3.4.0"
29
30
  },
30
31
  "devDependencies": {
@@ -6,5 +6,7 @@
6
6
  "out-dir": "dist",
7
7
  "environment": "development",
8
8
  "version": "1.0.0",
9
- "tunnel-base-url": "wss:///devtunnel.dain-local.com"
9
+ "tunnel-base-url": "wss:///devtunnel.dain-local.com",
10
+ "platform-base-url": "https://platform.dain.org",
11
+ "runtime": "workers"
10
12
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { z } from "zod";
4
4
 
5
- import {defineDAINService, ToolConfig, ServiceConfig, ToolboxConfig} from "@dainprotocol/service-sdk";
5
+ import { defineDAINService , ToolConfig, ServiceConfig, ToolboxConfig} from "@dainprotocol/service-sdk";
6
6
 
7
7
  const getWeatherConfig: ToolConfig = {
8
8
  id: "get-weather",
@@ -23,15 +23,10 @@ const getWeatherConfig: ToolConfig = {
23
23
  .describe("Weather information for the requested city"),
24
24
  pricing: { pricePerUse: 0.01, currency: "USD" },
25
25
  handler: async ({ city }, agentInfo) => {
26
-
27
-
28
26
  console.log(`Agent ${agentInfo.agentId} requested weather for ${city}`);
29
-
30
-
31
-
32
27
  return {
33
- text: `The current weather in ${city} is 22°C and Sunny`,
34
- data: { temperature: 22, condition: "Sunny" },
28
+ text: `The current weather in ${city} is 125c and Sunny`,
29
+ data: { temperature: 99, condition: "Sunny" },
35
30
  ui: {
36
31
  type: "h2",
37
32
  children: "Weather test",
@@ -40,7 +35,7 @@ const getWeatherConfig: ToolConfig = {
40
35
  },
41
36
  };
42
37
 
43
- const getWeatherForecastConfig: ToolConfig = {
38
+ const getWeatherForecastConfig: ToolConfig = {
44
39
  id: "get-weather-forecast",
45
40
  name: "Get Weather Forecast",
46
41
  description: "Fetches a 5-day weather forecast for a city",
@@ -188,7 +183,7 @@ const dainService = defineDAINService({
188
183
  },
189
184
  identity: {
190
185
  apiKey:
191
- process.env.DAIN_API_KEY,
186
+ process.env.DAIN_API_KEY,
192
187
  },
193
188
  services: [weatherServiceConfig],
194
189
  tools: [
@@ -200,6 +195,6 @@ const dainService = defineDAINService({
200
195
  toolboxes: [weatherToolboxConfig],
201
196
  });
202
197
 
203
- dainService.startNode({ port: 2022 }).then(() => {
204
- console.log("Comprehensive Weather DAIN Service is running on port 2022");
205
- });
198
+ export default {
199
+ fetch: dainService.startWorkers(),
200
+ };