nitrostack 1.0.69 → 1.0.71
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/README.md +5 -7
- package/dist/core/builders.d.ts +1 -1
- package/dist/core/builders.d.ts.map +1 -1
- package/dist/core/builders.js +6 -3
- package/dist/core/builders.js.map +1 -1
- package/dist/core/decorators.d.ts +21 -0
- package/dist/core/decorators.d.ts.map +1 -1
- package/dist/core/decorators.js +28 -0
- package/dist/core/decorators.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/tool.d.ts +2 -0
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +6 -0
- package/dist/core/tool.js.map +1 -1
- package/package.json +1 -1
- package/src/studio/app/api/chat/route.ts +30 -14
- package/src/studio/app/chat/page.tsx +128 -34
- package/src/studio/lib/llm-service.ts +104 -1
- package/src/studio/lib/store.ts +21 -21
- package/src/studio/lib/types.ts +1 -1
- package/templates/typescript-starter/package-lock.json +4112 -0
- package/templates/typescript-starter/package.json +2 -3
- package/templates/typescript-starter/src/modules/calculator/calculator.tools.ts +100 -5
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
"widget": "npm --prefix src/widgets"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"dotenv": "^16.3.1",
|
|
14
15
|
"nitrostack": "^1",
|
|
15
|
-
"zod": "^3.22.4"
|
|
16
|
-
"dotenv": "^16.3.1"
|
|
16
|
+
"zod": "^3.22.4"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"typescript": "^5.3.3"
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ToolDecorator as Tool, Widget, ExecutionContext, z } from 'nitrostack';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
2
4
|
|
|
3
5
|
export class CalculatorTools {
|
|
4
6
|
@Tool({
|
|
@@ -26,10 +28,10 @@ export class CalculatorTools {
|
|
|
26
28
|
})
|
|
27
29
|
@Widget('calculator-result')
|
|
28
30
|
async calculate(input: any, ctx: ExecutionContext) {
|
|
29
|
-
ctx.logger.info('Performing calculation', {
|
|
30
|
-
operation: input.operation,
|
|
31
|
-
a: input.a,
|
|
32
|
-
b: input.b
|
|
31
|
+
ctx.logger.info('Performing calculation', {
|
|
32
|
+
operation: input.operation,
|
|
33
|
+
a: input.a,
|
|
34
|
+
b: input.b
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
let result: number;
|
|
@@ -67,5 +69,98 @@ export class CalculatorTools {
|
|
|
67
69
|
expression: `${input.a} ${symbol} ${input.b} = ${result}`
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
|
-
}
|
|
71
72
|
|
|
73
|
+
@Tool({
|
|
74
|
+
name: 'convert_temperature',
|
|
75
|
+
description: 'Convert temperature units based on file content or direct input. Supports Celsius (C) and Fahrenheit (F).',
|
|
76
|
+
inputSchema: z.object({
|
|
77
|
+
file_name: z.string().describe('Name of the uploaded file'),
|
|
78
|
+
file_type: z.string().describe('MIME type of the uploaded file'),
|
|
79
|
+
file_content: z.string().describe('Base64 encoded file content. Will be injected by system.'),
|
|
80
|
+
value: z.number().optional().describe('Temperature value to convert'),
|
|
81
|
+
from_unit: z.enum(['C', 'F']).optional().describe('Unit to convert from (C or F)'),
|
|
82
|
+
to_unit: z.enum(['C', 'F']).optional().describe('Unit to convert to (C or F)')
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
async convertTemperature(input: any, ctx: ExecutionContext) {
|
|
86
|
+
ctx.logger.info('Processing temperature file', {
|
|
87
|
+
name: input.file_name,
|
|
88
|
+
type: input.file_type,
|
|
89
|
+
value: input.value,
|
|
90
|
+
from: input.from_unit,
|
|
91
|
+
to: input.to_unit
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Save file to uploads directory
|
|
95
|
+
const uploadsDir = path.join(process.cwd(), 'uploads');
|
|
96
|
+
if (!fs.existsSync(uploadsDir)) {
|
|
97
|
+
fs.mkdirSync(uploadsDir, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const filePath = path.join(uploadsDir, input.file_name);
|
|
101
|
+
|
|
102
|
+
// Decode base64
|
|
103
|
+
if (input.file_content) {
|
|
104
|
+
try {
|
|
105
|
+
const matches = input.file_content.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
|
|
106
|
+
let buffer;
|
|
107
|
+
|
|
108
|
+
if (matches && matches.length === 3) {
|
|
109
|
+
buffer = Buffer.from(matches[2], 'base64');
|
|
110
|
+
} else {
|
|
111
|
+
buffer = Buffer.from(input.file_content, 'base64');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fs.writeFileSync(filePath, buffer);
|
|
115
|
+
ctx.logger.info(`Saved file to ${filePath}`);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
ctx.logger.error('Failed to save file', e);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const fileStats = {
|
|
122
|
+
name: input.file_name,
|
|
123
|
+
type: input.file_type,
|
|
124
|
+
saved_path: filePath,
|
|
125
|
+
status: 'saved'
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
let result: number | null = null;
|
|
129
|
+
let message = `Successfully processed and saved file ${input.file_name}`;
|
|
130
|
+
|
|
131
|
+
// Perform conversion logic
|
|
132
|
+
if (input.value !== undefined && input.from_unit && input.to_unit) {
|
|
133
|
+
try {
|
|
134
|
+
message += `. Converting ${input.value}°${input.from_unit} to ${input.to_unit}`;
|
|
135
|
+
|
|
136
|
+
if (input.from_unit === input.to_unit) {
|
|
137
|
+
result = input.value;
|
|
138
|
+
} else if (input.from_unit === 'C' && input.to_unit === 'F') {
|
|
139
|
+
result = (input.value * 9 / 5) + 32;
|
|
140
|
+
} else if (input.from_unit === 'F' && input.to_unit === 'C') {
|
|
141
|
+
result = (input.value - 32) * 5 / 9;
|
|
142
|
+
} else {
|
|
143
|
+
throw new Error('Unsupported unit conversion');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Round to 2 decimal places
|
|
147
|
+
if (result !== null) {
|
|
148
|
+
result = Math.round(result * 100) / 100;
|
|
149
|
+
message += `. Result: ${result}°${input.to_unit}`;
|
|
150
|
+
}
|
|
151
|
+
} catch (e: any) {
|
|
152
|
+
message += `. Conversion failed: ${e.message}`;
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
message += `. No valid conversion parameters detected from manual input or file extraction.`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
status: 'success',
|
|
160
|
+
message,
|
|
161
|
+
file_info: fileStats,
|
|
162
|
+
conversion_result: result !== null ? { value: result, unit: input.to_unit } : null,
|
|
163
|
+
original_value: input.value !== undefined ? { value: input.value, unit: input.from_unit } : null
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|