@opentiny/tiny-robot-cli 0.5.2-alpha.15 → 0.5.2-alpha.17
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 +1 -38
- package/bin/commands/add.js +268 -552
- package/bin/utils.js +44 -144
- package/package.json +3 -5
- package/templates/basic/.env.example +0 -8
- package/templates/basic/README.md +22 -53
- package/templates/basic/index.html +2 -2
- package/templates/basic/package.json +16 -12
- package/templates/basic/public/modelcontextprotocol.png +0 -0
- package/templates/basic/src/App.vue +119 -112
- package/templates/basic/src/components/ChatList.vue +82 -0
- package/templates/basic/src/components/ChatSender.vue +125 -0
- package/templates/basic/src/components/ConversationHistory.vue +136 -0
- package/templates/basic/src/components/HistoryDrawerButton.vue +43 -0
- package/templates/basic/src/components/McpServerPickerButton.vue +278 -0
- package/templates/basic/src/components/ThemeToggleButton.vue +44 -0
- package/templates/basic/src/components/icons/IconDeepThink.vue +29 -0
- package/templates/basic/src/components/icons/IconModelAliyunBailian.vue +51 -0
- package/templates/basic/src/components/icons/IconModelDeepseek.vue +29 -0
- package/templates/basic/src/components/icons/IconMoon.vue +29 -0
- package/templates/basic/src/components/icons/IconPlugin.vue +29 -0
- package/templates/basic/src/components/icons/IconSun.vue +35 -0
- package/templates/basic/src/components/icons/IconWebSearch.vue +36 -0
- package/templates/basic/src/components/icons/index.ts +7 -0
- package/templates/basic/src/composables/useChat.ts +129 -0
- package/templates/basic/src/composables/useMcp.ts +170 -0
- package/templates/basic/src/composables/useModel.ts +82 -0
- package/templates/basic/src/main.ts +2 -2
- package/templates/basic/src/mcpServers.ts +40 -0
- package/templates/basic/src/models.ts +81 -0
- package/templates/basic/tsconfig.app.json +5 -2
- package/templates/basic/tsconfig.node.json +6 -3
- package/templates/basic/vite.config.ts +1 -6
- package/templates/chat/.env.example +0 -9
- package/templates/chat/src/TinyRobotChat.vue +27 -88
- package/templates/basic/public/favicon.svg +0 -1
- package/templates/basic/public/icons.svg +0 -24
- package/templates/chat/README.md +0 -46
- package/templates/chat/index.html +0 -12
- package/templates/chat/package.json +0 -28
- package/templates/chat/src/components/ComposerTools.vue +0 -99
- package/templates/chat/src/components/WindowHeader.vue +0 -192
- package/templates/chat/src/composables/useWindow.ts +0 -83
- package/templates/chat/src/config/chat-runtime.ts +0 -82
- package/templates/chat/src/config/chat-ui.ts +0 -290
- package/templates/chat/src/index.css +0 -116
- package/templates/chat/src/main.ts +0 -7
- package/templates/chat/tsconfig.app.json +0 -13
- package/templates/chat/tsconfig.json +0 -7
- package/templates/chat/tsconfig.node.json +0 -19
- package/templates/chat/vite.config.ts +0 -16
package/bin/utils.js
CHANGED
|
@@ -36,7 +36,10 @@ export function logError(message) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export function invariant(condition, message) {
|
|
39
|
-
if (!condition)
|
|
39
|
+
if (!condition) {
|
|
40
|
+
console.error(`Error: ${message}`)
|
|
41
|
+
process.exit(1)
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
export function exists(file) {
|
|
@@ -85,10 +88,6 @@ export function validateProjectName(name) {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
export function copyTemplate(sourceDir, targetDir) {
|
|
88
|
-
copyDirectory(sourceDir, targetDir)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function copyDirectory(sourceDir, targetDir) {
|
|
92
91
|
fs.cpSync(sourceDir, targetDir, {
|
|
93
92
|
recursive: true,
|
|
94
93
|
filter: (source) => {
|
|
@@ -111,7 +110,7 @@ function renameSpecialFiles(targetDir) {
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
function replaceTemplateVariables(targetDir, variables) {
|
|
114
|
-
const replaceFiles = ['package.json', 'README.md'
|
|
113
|
+
const replaceFiles = ['package.json', 'README.md']
|
|
115
114
|
|
|
116
115
|
for (const relativePath of replaceFiles) {
|
|
117
116
|
const file = path.join(targetDir, relativePath)
|
|
@@ -167,24 +166,20 @@ export function findProjectRoot(cwd) {
|
|
|
167
166
|
}
|
|
168
167
|
|
|
169
168
|
export function findSubPackageRoot(cwd, workspaceRoot) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (dir === root) return null
|
|
175
|
-
if (isPackageDir(dir)) return dir
|
|
169
|
+
return findUp(cwd, (dir) => {
|
|
170
|
+
if (dir === workspaceRoot) {
|
|
171
|
+
return false
|
|
172
|
+
}
|
|
176
173
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
dir = parent
|
|
180
|
-
}
|
|
174
|
+
return isPackageDir(dir)
|
|
175
|
+
})
|
|
181
176
|
}
|
|
182
177
|
|
|
183
178
|
export function findWorkspacePackages(workspaceRoot) {
|
|
184
179
|
const workspaceFile = resolveWorkspaceFile(workspaceRoot)
|
|
185
180
|
|
|
186
181
|
if (!workspaceFile) {
|
|
187
|
-
return
|
|
182
|
+
return []
|
|
188
183
|
}
|
|
189
184
|
|
|
190
185
|
try {
|
|
@@ -192,139 +187,56 @@ export function findWorkspacePackages(workspaceRoot) {
|
|
|
192
187
|
|
|
193
188
|
const config = yaml.parse(content)
|
|
194
189
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (!Array.isArray(config.packages)) {
|
|
204
|
-
throw new Error('packages must be an array')
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (config.packages.some((pattern) => typeof pattern !== 'string' || pattern.trim().length === 0)) {
|
|
208
|
-
throw new Error('packages entries must be non-empty strings')
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return config.packages.map((pattern) => pattern.trim())
|
|
212
|
-
} catch (error) {
|
|
213
|
-
const detail = error instanceof Error ? `: ${error.message}` : ''
|
|
214
|
-
throw new Error(`Failed to read ${path.basename(workspaceFile)}${detail}`)
|
|
190
|
+
return Array.isArray(config?.packages)
|
|
191
|
+
? config.packages.filter(
|
|
192
|
+
(pattern) => typeof pattern === 'string' && pattern.length > 0 && !pattern.startsWith('!'),
|
|
193
|
+
)
|
|
194
|
+
: []
|
|
195
|
+
} catch {
|
|
196
|
+
return []
|
|
215
197
|
}
|
|
216
198
|
}
|
|
217
199
|
|
|
218
|
-
const WORKSPACE_SCAN_IGNORES = new Set(['.git', 'node_modules'])
|
|
219
|
-
|
|
220
200
|
function normalizeWorkspacePattern(pattern) {
|
|
221
|
-
|
|
222
|
-
if (normalized.startsWith('./')) normalized = normalized.slice(2)
|
|
223
|
-
return normalized.replace(/\/$/, '')
|
|
201
|
+
return pattern.replace(/\*\*?/g, '').replace(/\/$/, '')
|
|
224
202
|
}
|
|
225
203
|
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
for (let index = 0; index < pattern.length; index += 1) {
|
|
230
|
-
const char = pattern[index]
|
|
231
|
-
|
|
232
|
-
if (char === '*') {
|
|
233
|
-
if (pattern[index + 1] === '*') {
|
|
234
|
-
while (pattern[index + 1] === '*') index += 1
|
|
235
|
-
if (pattern[index + 1] === '/') {
|
|
236
|
-
source += '(?:.*/)?'
|
|
237
|
-
index += 1
|
|
238
|
-
} else {
|
|
239
|
-
source += '.*'
|
|
240
|
-
}
|
|
241
|
-
} else {
|
|
242
|
-
source += '[^/]*'
|
|
243
|
-
}
|
|
244
|
-
continue
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (char === '?') {
|
|
248
|
-
source += '[^/]'
|
|
249
|
-
continue
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (char === '{') {
|
|
253
|
-
const close = pattern.indexOf('}', index + 1)
|
|
254
|
-
if (close !== -1) {
|
|
255
|
-
const alternatives = pattern
|
|
256
|
-
.slice(index + 1, close)
|
|
257
|
-
.split(',')
|
|
258
|
-
.map((item) => globSource(item))
|
|
259
|
-
source += `(?:${alternatives.join('|')})`
|
|
260
|
-
index = close
|
|
261
|
-
continue
|
|
262
|
-
}
|
|
263
|
-
}
|
|
204
|
+
export function listPackages(workspaceRoot, patterns) {
|
|
205
|
+
const packageDirs = []
|
|
264
206
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
source += pattern.slice(index, close + 1)
|
|
269
|
-
index = close
|
|
270
|
-
continue
|
|
271
|
-
}
|
|
207
|
+
const addPackage = (dir) => {
|
|
208
|
+
if (isPackageDir(dir)) {
|
|
209
|
+
packageDirs.push(dir)
|
|
272
210
|
}
|
|
273
|
-
|
|
274
|
-
source += char.replace(/[\\.^$+()|]/g, '\\$&')
|
|
275
211
|
}
|
|
276
212
|
|
|
277
|
-
|
|
278
|
-
|
|
213
|
+
for (const pattern of patterns) {
|
|
214
|
+
const base = normalizeWorkspacePattern(pattern)
|
|
279
215
|
|
|
280
|
-
|
|
281
|
-
const normalized = normalizeWorkspacePattern(pattern)
|
|
282
|
-
if (normalized === '.') return relativePath === ''
|
|
283
|
-
return new RegExp(`^${globSource(normalized)}$`).test(relativePath)
|
|
284
|
-
}
|
|
216
|
+
const fullPath = path.join(workspaceRoot, base)
|
|
285
217
|
|
|
286
|
-
|
|
287
|
-
|
|
218
|
+
if (!exists(fullPath)) {
|
|
219
|
+
continue
|
|
220
|
+
}
|
|
288
221
|
|
|
289
|
-
|
|
290
|
-
|
|
222
|
+
if (pattern.includes('*')) {
|
|
223
|
+
const entries = fs.readdirSync(fullPath, {
|
|
224
|
+
withFileTypes: true,
|
|
225
|
+
})
|
|
291
226
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
227
|
+
for (const entry of entries) {
|
|
228
|
+
if (entry.isDirectory()) {
|
|
229
|
+
addPackage(path.join(fullPath, entry.name))
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
addPackage(fullPath)
|
|
295
234
|
}
|
|
296
235
|
}
|
|
297
236
|
|
|
298
|
-
visit(workspaceRoot)
|
|
299
237
|
return packageDirs
|
|
300
238
|
}
|
|
301
239
|
|
|
302
|
-
export function listPackages(workspaceRoot, patterns = undefined) {
|
|
303
|
-
const configuredPatterns = patterns ?? ['**']
|
|
304
|
-
const includePatterns = configuredPatterns.filter((pattern) => !pattern.startsWith('!'))
|
|
305
|
-
const excludePatterns = configuredPatterns
|
|
306
|
-
.filter((pattern) => pattern.startsWith('!'))
|
|
307
|
-
.map((pattern) => pattern.slice(1))
|
|
308
|
-
|
|
309
|
-
if (includePatterns.length === 0) return []
|
|
310
|
-
|
|
311
|
-
const root = path.resolve(workspaceRoot)
|
|
312
|
-
const packageDirs = collectPackageDirs(root)
|
|
313
|
-
const matched = packageDirs.filter((dir) => {
|
|
314
|
-
const relativePath = path.relative(root, dir).replaceAll('\\', '/')
|
|
315
|
-
return (
|
|
316
|
-
includePatterns.some((pattern) => matchesWorkspacePattern(relativePath, pattern)) &&
|
|
317
|
-
!excludePatterns.some((pattern) => matchesWorkspacePattern(relativePath, pattern))
|
|
318
|
-
)
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
return [...new Set(matched)].sort((left, right) => {
|
|
322
|
-
const leftRelative = path.relative(root, left)
|
|
323
|
-
const rightRelative = path.relative(root, right)
|
|
324
|
-
return leftRelative.localeCompare(rightRelative)
|
|
325
|
-
})
|
|
326
|
-
}
|
|
327
|
-
|
|
328
240
|
function ensureDir(file) {
|
|
329
241
|
fs.mkdirSync(path.dirname(file), {
|
|
330
242
|
recursive: true,
|
|
@@ -374,19 +286,6 @@ export function mergeEnvFile(templateFile, targetFile) {
|
|
|
374
286
|
|
|
375
287
|
const targetContent = fs.readFileSync(targetFile, 'utf-8')
|
|
376
288
|
|
|
377
|
-
const result = mergeEnvContent(templateContent, targetContent)
|
|
378
|
-
|
|
379
|
-
if (result.type === 'merged') {
|
|
380
|
-
fs.writeFileSync(targetFile, result.content)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return {
|
|
384
|
-
type: result.type,
|
|
385
|
-
...(result.added === undefined ? {} : { added: result.added }),
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
export function mergeEnvContent(templateContent, targetContent) {
|
|
390
289
|
const templateEnv = parseEnv(templateContent)
|
|
391
290
|
|
|
392
291
|
const targetEnv = parseEnv(targetContent)
|
|
@@ -409,9 +308,10 @@ export function mergeEnvContent(templateContent, targetContent) {
|
|
|
409
308
|
|
|
410
309
|
const nextContent = targetTrimmed ? `${targetTrimmed}\n${appendLines.join('\n')}\n` : `${appendLines.join('\n')}\n`
|
|
411
310
|
|
|
311
|
+
fs.writeFileSync(targetFile, nextContent)
|
|
312
|
+
|
|
412
313
|
return {
|
|
413
314
|
type: 'merged',
|
|
414
315
|
added: appendLines.length,
|
|
415
|
-
content: nextContent,
|
|
416
316
|
}
|
|
417
317
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/tiny-robot-cli",
|
|
3
|
-
"version": "0.5.2-alpha.
|
|
3
|
+
"version": "0.5.2-alpha.17",
|
|
4
4
|
"description": "CLI to scaffold TinyRobot product projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
"README.md"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"start": "node ./bin/cli.js"
|
|
23
|
-
"test": "node --test test/*.test.js"
|
|
22
|
+
"start": "node ./bin/cli.js"
|
|
24
23
|
},
|
|
25
24
|
"license": "MIT",
|
|
26
25
|
"engines": {
|
|
@@ -28,11 +27,10 @@
|
|
|
28
27
|
},
|
|
29
28
|
"dependencies": {
|
|
30
29
|
"@inquirer/prompts": "^8.3.2",
|
|
31
|
-
"@vue/compiler-sfc": "^3.5.40",
|
|
32
30
|
"commander": "^14.0.3",
|
|
33
31
|
"picocolors": "^1.1.1",
|
|
34
32
|
"semver": "^7.8.1",
|
|
35
33
|
"yaml": "^2.9.0"
|
|
36
34
|
},
|
|
37
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "b98ac146f0d6f7deb0834cb5d0c1f53d144d2ba2"
|
|
38
36
|
}
|
|
@@ -1,10 +1,2 @@
|
|
|
1
|
-
# Optional custom model endpoints. Leave blank to use official Provider defaults.
|
|
2
|
-
VITE_QWEN_API_URL=
|
|
3
|
-
VITE_DEEPSEEK_API_URL=
|
|
4
|
-
|
|
5
|
-
# Optional custom MCP endpoint. Leave blank to use the official endpoint.
|
|
6
|
-
VITE_AMAP_MCP_URL=
|
|
7
|
-
|
|
8
|
-
# Optional local direct-connection credentials.
|
|
9
1
|
VITE_ALIYUN_DASHSCOPE_KEY=
|
|
10
2
|
VITE_DEEPSEEK_API_KEY=
|
|
@@ -1,71 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TinyRobot AI chat starter built with Vue 3 + Vite.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Vue 3 + Vite + TypeScript project scaffold
|
|
8
|
+
- TinyRobot chat UI with `TrBubbleList`, `TrSender`, and markdown rendering
|
|
9
|
+
- Conversation management via `useConversation`
|
|
10
|
+
- Model switch with thinking/search capability toggles
|
|
11
|
+
- MCP server picker for add/toggle/delete server usage
|
|
12
|
+
- MCP transport support for both `sse` and `streamableHttp`
|
|
13
|
+
- Tool calling pipeline through `toolPlugin` + MCP `listTools` / `callTool`
|
|
14
|
+
- Theme toggle and responsive layout for desktop/mobile
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
const mcpServers = [
|
|
11
|
-
{ id: 'amap-maps', name: '高德地图', baseUrl: 'https://...' },
|
|
12
|
-
{
|
|
13
|
-
id: 'model-context-protocol-mcp',
|
|
14
|
-
name: 'Model Context Protocol MCP',
|
|
15
|
-
baseUrl: '/modelcontextprotocol-mcp',
|
|
16
|
-
installed: true,
|
|
17
|
-
},
|
|
18
|
-
]
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
`installed: true` means initially installed only. The Server remains disabled and does not connect or discover Tools until enabled.
|
|
22
|
-
|
|
23
|
-
| Server | Transport | Authentication |
|
|
24
|
-
| -------------------------- | --------------- | ---------------- |
|
|
25
|
-
| 高德地图 | Streamable HTTP | Optional API Key |
|
|
26
|
-
| Model Context Protocol MCP | Streamable HTTP | None |
|
|
27
|
-
|
|
28
|
-
Tools are discovered dynamically with `client.listTools()`. Tool choices are stored in the next user message's `runConfig` metadata snapshot, so changing a Tool affects subsequent turns without modifying a request already in progress.
|
|
29
|
-
|
|
30
|
-
Server installation, enabling, Tool loading, retry, de-duplication, and Tool calls are handled by the default adapter in `@opentiny/tiny-robot-chat`. If a Server cannot load its Tools, it remains installed but is automatically disabled. Other enabled Servers and normal chat remain available.
|
|
31
|
-
|
|
32
|
-
## Model connection modes
|
|
33
|
-
|
|
34
|
-
- API Key only: connects directly to the official Qwen or DeepSeek endpoint.
|
|
35
|
-
- `apiUrl` + API Key: connects to a custom service with frontend authentication.
|
|
36
|
-
- `apiUrl` only: connects to a backend proxy without frontend authentication.
|
|
37
|
-
|
|
38
|
-
The Chat package does not prompt for or validate missing API Keys. The upstream service or backend proxy decides whether authentication is required.
|
|
16
|
+
## Setup
|
|
39
17
|
|
|
40
|
-
|
|
18
|
+
1. Copy environment variables:
|
|
41
19
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Qwen models support deep thinking and web search. DeepSeek models support deep thinking. Unsupported capabilities remain visible as disabled buttons so the available model capabilities are clear.
|
|
47
|
-
|
|
48
|
-
DeepSeek models inherit the provider's thinking effort options: `low`, `high`, and `max`, with `high` as the default. The effort selector appears only after `深度思考` is enabled. To customize a model, set `efforts` and `defaultEffort` on that model in `src/App.vue`; use `thinkingRequired: true` only for models that cannot disable thinking.
|
|
49
|
-
|
|
50
|
-
## Environment variables
|
|
20
|
+
```bash
|
|
21
|
+
cp .env.example .env
|
|
22
|
+
```
|
|
51
23
|
|
|
52
|
-
|
|
24
|
+
2. Fill your provider keys in `.env`:
|
|
53
25
|
|
|
54
26
|
```env
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
VITE_AMAP_MCP_URL=
|
|
58
|
-
VITE_ALIYUN_DASHSCOPE_KEY=
|
|
59
|
-
VITE_DEEPSEEK_API_KEY=
|
|
27
|
+
VITE_ALIYUN_DASHSCOPE_KEY=your_dashscope_key
|
|
28
|
+
VITE_DEEPSEEK_API_KEY=your_deepseek_key
|
|
60
29
|
```
|
|
61
30
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
Variables prefixed with `VITE_` are exposed to browser code. Direct browser connections are intended only for servers without secrets and with CORS enabled. Production applications should keep credentials behind a backend or BFF proxy.
|
|
31
|
+
`VITE_ALIYUN_DASHSCOPE_KEY` is also used by configured MCP servers that require DashScope authorization.
|
|
65
32
|
|
|
66
33
|
## Development
|
|
67
34
|
|
|
68
35
|
```bash
|
|
36
|
+
pnpm install
|
|
69
37
|
pnpm dev
|
|
70
38
|
```
|
|
71
39
|
|
|
@@ -73,4 +41,5 @@ pnpm dev
|
|
|
73
41
|
|
|
74
42
|
```bash
|
|
75
43
|
pnpm build
|
|
44
|
+
pnpm preview
|
|
76
45
|
```
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/
|
|
5
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>TinyRobot AI Chat</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<div id="app"></div>
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "__PROJECT_NAME__",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "vue-tsc -b && vite build",
|
|
9
|
-
"preview": "vite preview"
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"type-check": "vue-tsc --noEmit"
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
|
-
"@
|
|
13
|
-
"@opentiny/tiny-robot": "0.5.
|
|
14
|
-
"@opentiny/tiny-robot-
|
|
15
|
-
"
|
|
13
|
+
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
14
|
+
"@opentiny/tiny-robot": "^0.5.0",
|
|
15
|
+
"@opentiny/tiny-robot-kit": "^0.5.0",
|
|
16
|
+
"@opentiny/tiny-robot-svgs": "^0.5.0",
|
|
17
|
+
"dompurify": "^3.3.1",
|
|
18
|
+
"markdown-it": "^14.1.0",
|
|
19
|
+
"vue": "^3.5.30"
|
|
16
20
|
},
|
|
17
21
|
"devDependencies": {
|
|
18
|
-
"@types/node": "^24.
|
|
19
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
20
|
-
"@vue/tsconfig": "^0.9.
|
|
21
|
-
"typescript": "~
|
|
22
|
-
"vite": "^8.
|
|
23
|
-
"vue-tsc": "^3.
|
|
22
|
+
"@types/node": "^24.12.0",
|
|
23
|
+
"@vitejs/plugin-vue": "^6.0.5",
|
|
24
|
+
"@vue/tsconfig": "^0.9.0",
|
|
25
|
+
"typescript": "~5.9.3",
|
|
26
|
+
"vite": "^8.0.1",
|
|
27
|
+
"vue-tsc": "^3.2.5"
|
|
24
28
|
}
|
|
25
29
|
}
|
|
Binary file
|