@opentiny/tiny-robot-cli 0.5.2-alpha.13 → 0.5.2-alpha.14
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 +32 -5
- package/bin/commands/add.js +589 -198
- package/bin/utils.js +139 -47
- package/package.json +4 -3
- package/templates/basic/.env.example +8 -0
- package/templates/basic/README.md +53 -22
- package/templates/basic/index.html +2 -2
- package/templates/basic/package.json +12 -16
- package/templates/basic/public/favicon.svg +1 -0
- package/templates/basic/public/icons.svg +24 -0
- package/templates/basic/src/App.vue +112 -119
- package/templates/basic/src/main.ts +2 -2
- package/templates/basic/tsconfig.app.json +2 -5
- package/templates/basic/tsconfig.node.json +3 -6
- package/templates/basic/vite.config.ts +6 -1
- package/templates/chat/.env.example +8 -0
- package/templates/chat/README.md +21 -13
- package/templates/chat/package.json +5 -5
- package/templates/chat/src/TinyRobotChat.vue +52 -132
- package/templates/chat/src/components/ComposerTools.vue +99 -0
- package/templates/chat/src/{tiny-robot-chat/components → components}/WindowHeader.vue +1 -1
- package/templates/chat/src/{tiny-robot-chat/composables → composables}/useWindow.ts +8 -18
- package/templates/chat/src/config/chat-runtime.ts +82 -0
- package/templates/chat/src/{tiny-robot-chat/config → config}/chat-ui.ts +22 -4
- package/templates/chat/src/index.css +116 -0
- package/templates/chat/src/main.ts +3 -0
- package/templates/basic/public/modelcontextprotocol.png +0 -0
- package/templates/basic/src/components/ChatList.vue +0 -82
- package/templates/basic/src/components/ChatSender.vue +0 -125
- package/templates/basic/src/components/ConversationHistory.vue +0 -136
- package/templates/basic/src/components/HistoryDrawerButton.vue +0 -43
- package/templates/basic/src/components/McpServerPickerButton.vue +0 -278
- package/templates/basic/src/components/ThemeToggleButton.vue +0 -44
- package/templates/basic/src/components/icons/IconDeepThink.vue +0 -29
- package/templates/basic/src/components/icons/IconModelAliyunBailian.vue +0 -51
- package/templates/basic/src/components/icons/IconModelDeepseek.vue +0 -29
- package/templates/basic/src/components/icons/IconMoon.vue +0 -29
- package/templates/basic/src/components/icons/IconPlugin.vue +0 -29
- package/templates/basic/src/components/icons/IconSun.vue +0 -35
- package/templates/basic/src/components/icons/IconWebSearch.vue +0 -36
- package/templates/basic/src/components/icons/index.ts +0 -7
- package/templates/basic/src/composables/useChat.ts +0 -129
- package/templates/basic/src/composables/useMcp.ts +0 -170
- package/templates/basic/src/composables/useModel.ts +0 -82
- package/templates/basic/src/mcpServers.ts +0 -40
- package/templates/basic/src/models.ts +0 -81
- package/templates/chat/src/tiny-robot-chat/components/ComposerTools.vue +0 -72
- package/templates/chat/src/tiny-robot-chat/config/chat-runtime.ts +0 -26
package/bin/utils.js
CHANGED
|
@@ -36,10 +36,7 @@ export function logError(message) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export function invariant(condition, message) {
|
|
39
|
-
if (!condition)
|
|
40
|
-
console.error(`Error: ${message}`)
|
|
41
|
-
process.exit(1)
|
|
42
|
-
}
|
|
39
|
+
if (!condition) throw new Error(message)
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
export function exists(file) {
|
|
@@ -114,7 +111,7 @@ function renameSpecialFiles(targetDir) {
|
|
|
114
111
|
}
|
|
115
112
|
|
|
116
113
|
function replaceTemplateVariables(targetDir, variables) {
|
|
117
|
-
const replaceFiles = ['package.json', 'README.md']
|
|
114
|
+
const replaceFiles = ['package.json', 'README.md', 'index.html']
|
|
118
115
|
|
|
119
116
|
for (const relativePath of replaceFiles) {
|
|
120
117
|
const file = path.join(targetDir, relativePath)
|
|
@@ -170,20 +167,24 @@ export function findProjectRoot(cwd) {
|
|
|
170
167
|
}
|
|
171
168
|
|
|
172
169
|
export function findSubPackageRoot(cwd, workspaceRoot) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return false
|
|
176
|
-
}
|
|
170
|
+
let dir = path.resolve(cwd)
|
|
171
|
+
const root = path.resolve(workspaceRoot)
|
|
177
172
|
|
|
178
|
-
|
|
179
|
-
|
|
173
|
+
for (;;) {
|
|
174
|
+
if (dir === root) return null
|
|
175
|
+
if (isPackageDir(dir)) return dir
|
|
176
|
+
|
|
177
|
+
const parent = path.dirname(dir)
|
|
178
|
+
if (parent === dir) return null
|
|
179
|
+
dir = parent
|
|
180
|
+
}
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
export function findWorkspacePackages(workspaceRoot) {
|
|
183
184
|
const workspaceFile = resolveWorkspaceFile(workspaceRoot)
|
|
184
185
|
|
|
185
186
|
if (!workspaceFile) {
|
|
186
|
-
return
|
|
187
|
+
return undefined
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
try {
|
|
@@ -191,60 +192,139 @@ export function findWorkspacePackages(workspaceRoot) {
|
|
|
191
192
|
|
|
192
193
|
const config = yaml.parse(content)
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
)
|
|
198
|
-
: []
|
|
199
|
-
} catch (error) {
|
|
200
|
-
const reason = error instanceof Error ? error.message : String(error)
|
|
195
|
+
if (config === null || typeof config !== 'object' || Array.isArray(config)) {
|
|
196
|
+
throw new Error('workspace configuration must be a YAML mapping')
|
|
197
|
+
}
|
|
201
198
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
199
|
+
if (!Object.prototype.hasOwnProperty.call(config, 'packages')) {
|
|
200
|
+
return undefined
|
|
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}`)
|
|
205
215
|
}
|
|
206
216
|
}
|
|
207
217
|
|
|
218
|
+
const WORKSPACE_SCAN_IGNORES = new Set(['.git', 'node_modules'])
|
|
219
|
+
|
|
208
220
|
function normalizeWorkspacePattern(pattern) {
|
|
209
|
-
|
|
221
|
+
let normalized = pattern.replaceAll('\\', '/').trim()
|
|
222
|
+
if (normalized.startsWith('./')) normalized = normalized.slice(2)
|
|
223
|
+
return normalized.replace(/\/$/, '')
|
|
210
224
|
}
|
|
211
225
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const addPackage = (dir) => {
|
|
216
|
-
if (isPackageDir(dir)) {
|
|
217
|
-
packageDirs.push(dir)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
226
|
+
function globSource(pattern) {
|
|
227
|
+
let source = ''
|
|
220
228
|
|
|
221
|
-
for (
|
|
222
|
-
const
|
|
229
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
230
|
+
const char = pattern[index]
|
|
223
231
|
|
|
224
|
-
|
|
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
|
+
}
|
|
225
246
|
|
|
226
|
-
if (
|
|
247
|
+
if (char === '?') {
|
|
248
|
+
source += '[^/]'
|
|
227
249
|
continue
|
|
228
250
|
}
|
|
229
251
|
|
|
230
|
-
if (
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
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
|
+
}
|
|
234
264
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
265
|
+
if (char === '[') {
|
|
266
|
+
const close = pattern.indexOf(']', index + 1)
|
|
267
|
+
if (close !== -1) {
|
|
268
|
+
source += pattern.slice(index, close + 1)
|
|
269
|
+
index = close
|
|
270
|
+
continue
|
|
239
271
|
}
|
|
240
|
-
}
|
|
241
|
-
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
source += char.replace(/[\\.^$+()|]/g, '\\$&')
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return source
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function matchesWorkspacePattern(relativePath, pattern) {
|
|
281
|
+
const normalized = normalizeWorkspacePattern(pattern)
|
|
282
|
+
if (normalized === '.') return relativePath === ''
|
|
283
|
+
return new RegExp(`^${globSource(normalized)}$`).test(relativePath)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function collectPackageDirs(workspaceRoot) {
|
|
287
|
+
const packageDirs = []
|
|
288
|
+
|
|
289
|
+
const visit = (dir) => {
|
|
290
|
+
if (isPackageDir(dir)) packageDirs.push(dir)
|
|
291
|
+
|
|
292
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
293
|
+
if (!entry.isDirectory() || WORKSPACE_SCAN_IGNORES.has(entry.name)) continue
|
|
294
|
+
visit(path.join(dir, entry.name))
|
|
242
295
|
}
|
|
243
296
|
}
|
|
244
297
|
|
|
298
|
+
visit(workspaceRoot)
|
|
245
299
|
return packageDirs
|
|
246
300
|
}
|
|
247
301
|
|
|
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
|
+
|
|
248
328
|
function ensureDir(file) {
|
|
249
329
|
fs.mkdirSync(path.dirname(file), {
|
|
250
330
|
recursive: true,
|
|
@@ -294,6 +374,19 @@ export function mergeEnvFile(templateFile, targetFile) {
|
|
|
294
374
|
|
|
295
375
|
const targetContent = fs.readFileSync(targetFile, 'utf-8')
|
|
296
376
|
|
|
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) {
|
|
297
390
|
const templateEnv = parseEnv(templateContent)
|
|
298
391
|
|
|
299
392
|
const targetEnv = parseEnv(targetContent)
|
|
@@ -316,10 +409,9 @@ export function mergeEnvFile(templateFile, targetFile) {
|
|
|
316
409
|
|
|
317
410
|
const nextContent = targetTrimmed ? `${targetTrimmed}\n${appendLines.join('\n')}\n` : `${appendLines.join('\n')}\n`
|
|
318
411
|
|
|
319
|
-
fs.writeFileSync(targetFile, nextContent)
|
|
320
|
-
|
|
321
412
|
return {
|
|
322
413
|
type: 'merged',
|
|
323
414
|
added: appendLines.length,
|
|
415
|
+
content: nextContent,
|
|
324
416
|
}
|
|
325
417
|
}
|
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.14",
|
|
4
4
|
"description": "CLI to scaffold TinyRobot product projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"start": "node ./bin/cli.js",
|
|
23
|
-
"test": "node --test
|
|
23
|
+
"test": "node --test test/*.test.js"
|
|
24
24
|
},
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"engines": {
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@inquirer/prompts": "^8.3.2",
|
|
31
|
+
"@vue/compiler-sfc": "^3.5.40",
|
|
31
32
|
"commander": "^14.0.3",
|
|
32
33
|
"picocolors": "^1.1.1",
|
|
33
34
|
"semver": "^7.8.1",
|
|
34
35
|
"yaml": "^2.9.0"
|
|
35
36
|
},
|
|
36
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "28e62a60d81f851ff6f07fb8fd9869a37fe6f097"
|
|
37
38
|
}
|
|
@@ -1,2 +1,10 @@
|
|
|
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.
|
|
1
9
|
VITE_ALIYUN_DASHSCOPE_KEY=
|
|
2
10
|
VITE_DEEPSEEK_API_KEY=
|
|
@@ -1,39 +1,71 @@
|
|
|
1
|
-
#
|
|
1
|
+
# **PROJECT_NAME**
|
|
2
2
|
|
|
3
|
-
TinyRobot
|
|
3
|
+
This project is generated from the TinyRobot Chat Basic template. It covers conversations, streaming responses, cancellation, Markdown rendering, responsive history, themes, model capabilities, and MCP Server/Tool management.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## MCP support
|
|
6
6
|
|
|
7
|
-
|
|
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
|
|
7
|
+
The demo declares MCP Servers through `mcpServers`:
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
```ts
|
|
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
|
+
```
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
`installed: true` means initially installed only. The Server remains disabled and does not connect or discover Tools until enabled.
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
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.
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
MCP follows the same three modes: the official endpoint with an optional API Key, a custom `baseUrl` with optional headers, or a proxy `baseUrl` without headers.
|
|
41
|
+
|
|
42
|
+
The basic template already includes the Model Context MCP proxy in `vite.config.ts`. If you use `add chat` in an existing project, the CLI does not modify that project's Vite configuration; add the same `/modelcontextprotocol-mcp` proxy under `server.proxy` manually and restart Vite.
|
|
43
|
+
|
|
44
|
+
## Model capabilities
|
|
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
|
|
51
|
+
|
|
52
|
+
Copy `.env.example` to `.env.local`. Leave endpoint variables blank for official Provider/MCP defaults, or set them for custom services and backend proxies:
|
|
25
53
|
|
|
26
54
|
```env
|
|
27
|
-
|
|
28
|
-
|
|
55
|
+
VITE_QWEN_API_URL=
|
|
56
|
+
VITE_DEEPSEEK_API_URL=
|
|
57
|
+
VITE_AMAP_MCP_URL=
|
|
58
|
+
VITE_ALIYUN_DASHSCOPE_KEY=
|
|
59
|
+
VITE_DEEPSEEK_API_KEY=
|
|
29
60
|
```
|
|
30
61
|
|
|
31
|
-
`
|
|
62
|
+
For a proxy setup, set for example `VITE_QWEN_API_URL=/api/chat/qwen`, `VITE_DEEPSEEK_API_URL=/api/chat/deepseek`, and `VITE_AMAP_MCP_URL=/api/mcp/amap-maps`, then leave the API Key variables blank.
|
|
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.
|
|
32
65
|
|
|
33
66
|
## Development
|
|
34
67
|
|
|
35
68
|
```bash
|
|
36
|
-
pnpm install
|
|
37
69
|
pnpm dev
|
|
38
70
|
```
|
|
39
71
|
|
|
@@ -41,5 +73,4 @@ pnpm dev
|
|
|
41
73
|
|
|
42
74
|
```bash
|
|
43
75
|
pnpm build
|
|
44
|
-
pnpm preview
|
|
45
76
|
```
|
|
@@ -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/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>__PROJECT_NAME__</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<div id="app"></div>
|
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "__PROJECT_NAME__",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "vue-tsc -b && vite build",
|
|
9
|
-
"preview": "vite preview"
|
|
10
|
-
"type-check": "vue-tsc --noEmit"
|
|
9
|
+
"preview": "vite preview"
|
|
11
10
|
},
|
|
12
11
|
"dependencies": {
|
|
13
|
-
"@
|
|
14
|
-
"@opentiny/tiny-robot": "
|
|
15
|
-
"@opentiny/tiny-robot-
|
|
16
|
-
"
|
|
17
|
-
"dompurify": "^3.3.1",
|
|
18
|
-
"markdown-it": "^14.1.0",
|
|
19
|
-
"vue": "^3.5.30"
|
|
12
|
+
"@opentiny/tiny-robot-chat": "0.5.2-alpha.14",
|
|
13
|
+
"@opentiny/tiny-robot": "0.5.2-alpha.14",
|
|
14
|
+
"@opentiny/tiny-robot-svgs": "0.5.2-alpha.14",
|
|
15
|
+
"vue": "^3.5.40"
|
|
20
16
|
},
|
|
21
17
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^24.
|
|
23
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
24
|
-
"@vue/tsconfig": "^0.9.
|
|
25
|
-
"typescript": "~
|
|
26
|
-
"vite": "^8.0
|
|
27
|
-
"vue-tsc": "^3.
|
|
18
|
+
"@types/node": "^24.13.3",
|
|
19
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
20
|
+
"@vue/tsconfig": "^0.9.1",
|
|
21
|
+
"typescript": "~6.0.2",
|
|
22
|
+
"vite": "^8.2.0",
|
|
23
|
+
"vue-tsc": "^3.3.8"
|
|
28
24
|
}
|
|
29
25
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="46" fill="none" viewBox="0 0 48 46"><path fill="#863bff" d="M25.946 44.938c-.664.845-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.287c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.497 0-3.578-1.842-3.578H1.237c-.92 0-1.456-1.04-.92-1.788L10.013.474c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.579 1.842 3.579h11.377c.943 0 1.473 1.088.89 1.83L25.947 44.94z" style="fill:#863bff;fill:color(display-p3 .5252 .23 1);fill-opacity:1"/><mask id="a" width="48" height="46" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M25.842 44.938c-.664.844-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.183c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.498 0-3.579-1.842-3.579H1.133c-.92 0-1.456-1.04-.92-1.787L9.91.473c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.578 1.842 3.578h11.377c.943 0 1.473 1.088.89 1.832L25.843 44.94z" style="fill:#000;fill-opacity:1"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#ede6ff" rx="5.508" ry="14.704" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -4.47 31.516)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#ede6ff" rx="10.399" ry="29.851" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -39.328 7.883)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#7e14ff" rx="5.508" ry="30.487" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -25.913 -14.639)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -32.644 -3.334)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -34.34 30.47)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#ede6ff" rx="14.072" ry="22.078" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="rotate(93.35 24.506 48.493)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx=".387" cy="8.972" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(39.51 .387 8.972)"/></g><g filter="url(#k)"><ellipse cx="47.523" cy="-6.092" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 47.523 -6.092)"/></g><g filter="url(#l)"><ellipse cx="41.412" cy="6.333" fill="#47bfff" rx="5.971" ry="9.665" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 41.412 6.333)"/></g><g filter="url(#m)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#n)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#o)"><ellipse cx="35.651" cy="29.907" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 35.651 29.907)"/></g><g filter="url(#p)"><ellipse cx="38.418" cy="32.4" fill="#47bfff" rx="5.971" ry="15.297" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 38.418 32.4)"/></g></g><defs><filter id="b" width="60.045" height="41.654" x="-19.77" y="16.149" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-54.613" y="-7.533" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-49.64" y="2.03" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-45.045" y="20.029" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-43.513" y="21.178" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="15.756" y="-17.901" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-27.636" y="-22.853" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="20.116" y="-38.415" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="24.641" y="-11.323" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="8.244" y="-2.416" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="18.713" y="10.588" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter></defs></svg>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
|
3
|
+
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
|
4
|
+
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
|
5
|
+
</symbol>
|
|
6
|
+
<symbol id="discord-icon" viewBox="0 0 20 19">
|
|
7
|
+
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
|
8
|
+
</symbol>
|
|
9
|
+
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
|
10
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
|
11
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
|
12
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
|
13
|
+
</symbol>
|
|
14
|
+
<symbol id="github-icon" viewBox="0 0 19 19">
|
|
15
|
+
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
|
16
|
+
</symbol>
|
|
17
|
+
<symbol id="social-icon" viewBox="0 0 20 20">
|
|
18
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
|
19
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
|
20
|
+
</symbol>
|
|
21
|
+
<symbol id="x-icon" viewBox="0 0 19 19">
|
|
22
|
+
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
|
23
|
+
</symbol>
|
|
24
|
+
</svg>
|