@isolo/trinity 1.0.2 → 1.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isolo/trinity",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A Bun-based MCP server framework with dynamic tool loading, hot reload, and stdio/HTTP modes",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/Config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import fs from "node:fs";
2
3
 
3
4
  export class Config {
4
5
  private static instance: Config | null = null;
@@ -50,13 +51,18 @@ export class Config {
50
51
 
51
52
  if (!this._targetFolder) {
52
53
  throw new Error(
53
- "Missing required argument: --target <path>. Specify the folder containing tool files."
54
+ "Missing required argument: --target <path>. Specify the folder containing tool files.",
54
55
  );
55
56
  }
56
57
 
57
58
  // Resolve to absolute path
58
59
  this._targetFolder = path.resolve(this._targetFolder);
59
60
 
61
+ // Create target folder if it doesn't exist
62
+ if (!fs.existsSync(this._targetFolder)) {
63
+ fs.mkdirSync(this._targetFolder, { recursive: true });
64
+ }
65
+
60
66
  // Default log file relative to target folder
61
67
  if (!this._logFile) {
62
68
  this._logFile = path.join(this._targetFolder, "debug.log");
package/src/Server.ts CHANGED
@@ -51,6 +51,8 @@ export class Server {
51
51
  port: this.config.port,
52
52
  });
53
53
 
54
+ await this.tools.loadTools();
55
+
54
56
  this.tools.startWatching();
55
57
 
56
58
  const transport = await this.createTransport();
package/src/Tools.ts CHANGED
@@ -27,7 +27,7 @@ export class Tools {
27
27
 
28
28
  private constructor(
29
29
  private logger = new Logger(Tools),
30
- private config = Config.getInstance()
30
+ private config = Config.getInstance(),
31
31
  ) {}
32
32
 
33
33
  async loadTools(): Promise<ToolDefinition[]> {
@@ -40,18 +40,22 @@ export class Tools {
40
40
  try {
41
41
  const tool = await this.loadToolFromFile(filePath);
42
42
  tools.push(tool);
43
- } catch (err) {
44
- this.logger.error(`Failed to load tool from ${filePath}`, err as Error);
43
+ } catch (err: any) {
44
+ this.logger.error(`Failed to load tool from ${filePath}`, {
45
+ err: err.message,
46
+ });
45
47
  }
46
48
  }
47
49
 
50
+ this.logger.debug(`Loaded ${tools.length} tools successfully`);
51
+
48
52
  return tools;
49
53
  }
50
54
 
51
55
  async loadTool(name: string): Promise<ToolDefinition> {
52
56
  const files = await this.resolveToolFiles();
53
57
  const filePath = files.find(
54
- (f) => path.basename(f, path.extname(f)) === name
58
+ (f) => path.basename(f, path.extname(f)) === name,
55
59
  );
56
60
 
57
61
  if (!filePath) {
@@ -76,7 +80,7 @@ export class Tools {
76
80
  if (filename) {
77
81
  this.onFileChange(event, filename);
78
82
  }
79
- }
83
+ },
80
84
  );
81
85
 
82
86
  this.watcher.on("error", (err: Error) => {
@@ -110,19 +114,19 @@ export class Tools {
110
114
 
111
115
  if (!mod.description || typeof mod.description !== "string") {
112
116
  throw new Error(
113
- `Tool file ${filePath} must export a 'description' string`
117
+ `Tool file ${filePath} must export a 'description' string`,
114
118
  );
115
119
  }
116
120
 
117
121
  if (!mod.inputSchema || typeof mod.inputSchema !== "object") {
118
122
  throw new Error(
119
- `Tool file ${filePath} must export an 'inputSchema' object`
123
+ `Tool file ${filePath} must export an 'inputSchema' object`,
120
124
  );
121
125
  }
122
126
 
123
127
  if (!mod.default || typeof mod.default !== "function") {
124
128
  throw new Error(
125
- `Tool file ${filePath} must have a default export function (execute)`
129
+ `Tool file ${filePath} must have a default export function (execute)`,
126
130
  );
127
131
  }
128
132
 
@@ -134,9 +138,20 @@ export class Tools {
134
138
  };
135
139
  }
136
140
 
137
- private async dynamicImport(filePath: string): Promise<Record<string, unknown>> {
138
- // Cache-busting with timestamp to always get fresh module
139
- return import(`${filePath}?t=${Date.now()}`);
141
+ private async dynamicImport(
142
+ filePath: string,
143
+ ): Promise<Record<string, unknown>> {
144
+ try {
145
+ // Cache-busting with timestamp to always get fresh module
146
+ return import(`${filePath}?t=${Date.now()}`);
147
+ } catch (err) {
148
+ this.logger.error(`Failed to import tool module`, {
149
+ err: (err as Error).message,
150
+ filePath,
151
+ });
152
+
153
+ throw err;
154
+ }
140
155
  }
141
156
 
142
157
  private buildDescription(description: string, filePath: string): string {
package/src/index.ts CHANGED
@@ -9,8 +9,10 @@ const logger = new Logger("main");
9
9
  try {
10
10
  Config.getInstance().parse(process.argv.slice(2));
11
11
  } catch (err) {
12
- console.error((err as Error).message);
13
- console.error("Usage: bun --hot src/index.ts --target <path> [--glob <pattern>] [--port <number>]");
12
+ logger.error((err as Error).message);
13
+ logger.error(
14
+ "Usage: bun --hot src/index.ts --target <path> [--glob <pattern>] [--port <number>]",
15
+ );
14
16
  process.exit(1);
15
17
  }
16
18