sillyspec 3.7.14 → 3.7.16
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/.claude/skills/sillyspec-archive/SKILL.md +77 -0
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +591 -0
- package/.claude/skills/sillyspec-continue/SKILL.md +44 -0
- package/.claude/skills/sillyspec-execute/SKILL.md +233 -0
- package/.claude/skills/sillyspec-explore/SKILL.md +96 -0
- package/.claude/skills/sillyspec-export/SKILL.md +53 -0
- package/.claude/skills/sillyspec-init/SKILL.md +171 -0
- package/.claude/skills/sillyspec-plan/SKILL.md +263 -0
- package/.claude/skills/sillyspec-propose/SKILL.md +248 -0
- package/.claude/skills/sillyspec-quick/SKILL.md +102 -0
- package/.claude/skills/sillyspec-resume/SKILL.md +111 -0
- package/{templates/scan.md → .claude/skills/sillyspec-scan/SKILL.md} +22 -60
- package/.claude/skills/sillyspec-state/SKILL.md +54 -0
- package/.claude/skills/sillyspec-status/SKILL.md +131 -0
- package/.claude/skills/sillyspec-verify/SKILL.md +146 -0
- package/.claude/skills/sillyspec-workspace/SKILL.md +149 -0
- package/.sillyspec/changes/run-command-design/design.md +1230 -0
- package/.sillyspec/docs/sillyspec/scan/.gitkeep +0 -0
- package/.sillyspec/knowledge/INDEX.md +8 -0
- package/.sillyspec/knowledge/uncategorized.md +3 -0
- package/.sillyspec/projects/sillyspec.yaml +3 -0
- package/package.json +1 -1
- package/packages/dashboard/dist/assets/index-Bx0cgoK_.js +7446 -0
- package/packages/dashboard/dist/assets/index-DbkUSsNO.css +1 -0
- package/packages/dashboard/dist/index.html +2 -2
- package/packages/dashboard/package-lock.json +220 -0
- package/packages/dashboard/package.json +8 -5
- package/packages/dashboard/server/index.js +91 -3
- package/packages/dashboard/server/parser.js +252 -28
- package/packages/dashboard/src/App.vue +54 -8
- package/packages/dashboard/src/components/ActionBar.vue +23 -39
- package/packages/dashboard/src/components/CommandPalette.vue +40 -65
- package/packages/dashboard/src/components/DetailPanel.vue +68 -53
- package/packages/dashboard/src/components/DocPreview.vue +137 -20
- package/packages/dashboard/src/components/DocTree.vue +48 -26
- package/packages/dashboard/src/components/LogStream.vue +12 -32
- package/packages/dashboard/src/components/PipelineStage.vue +8 -8
- package/packages/dashboard/src/components/PipelineView.vue +35 -43
- package/packages/dashboard/src/components/ProjectList.vue +51 -77
- package/packages/dashboard/src/components/ProjectOverview.vue +178 -0
- package/packages/dashboard/src/components/StageBadge.vue +13 -13
- package/packages/dashboard/src/components/StepCard.vue +11 -11
- package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -0
- package/packages/dashboard/src/components/detail/GitDetail.vue +61 -0
- package/packages/dashboard/src/components/detail/TechDetail.vue +43 -0
- package/packages/dashboard/src/main.js +4 -1
- package/packages/dashboard/src/style.css +14 -14
- package/src/index.js +55 -8
- package/src/init.js +69 -196
- package/src/migrate.js +1 -18
- package/src/progress.js +279 -281
- package/src/run.js +320 -0
- package/src/setup.js +1 -9
- package/src/stages/brainstorm.js +210 -0
- package/src/stages/execute.js +190 -0
- package/src/stages/index.js +22 -0
- package/src/stages/plan.js +118 -0
- package/src/stages/propose.js +115 -0
- package/src/stages/verify.js +98 -0
- package/packages/dashboard/dist/assets/index-hNnQCobe.css +0 -1
- package/packages/dashboard/dist/assets/index-qgPzQGjk.js +0 -17
- package/templates/archive.md +0 -121
- package/templates/brainstorm.md +0 -246
- package/templates/commit.md +0 -123
- package/templates/continue.md +0 -32
- package/templates/execute.md +0 -314
- package/templates/explore.md +0 -60
- package/templates/export.md +0 -21
- package/templates/init.md +0 -61
- package/templates/plan.md +0 -157
- package/templates/progress-format.md +0 -90
- package/templates/propose.md +0 -73
- package/templates/quick.md +0 -135
- package/templates/resume-dialog.md +0 -55
- package/templates/resume.md +0 -53
- package/templates/scan-quick.md +0 -49
- package/templates/skills/playwright-e2e/SKILL.md +0 -340
- package/templates/status.md +0 -72
- package/templates/verify.md +0 -253
- package/templates/workspace-sync.md +0 -89
- package/templates/workspace.md +0 -67
- /package/.sillyspec/{docs/sillyspec/brainstorm → changes/brainstorm-archive}/2026-04-05-dashboard-design.md +0 -0
- /package/.sillyspec/{docs/sillyspec/brainstorm → changes/brainstorm-archive}/2026-04-05-unified-docs-design.md +0 -0
- /package/.sillyspec/{specs/2026-04-05-dashboard-design.md → changes/dashboard/design.md.braindraft} +0 -0
- /package/.sillyspec/{specs/2026-04-05-unified-docs-design.md → changes/unified-docs-design/design.md} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="data?.length" class="px-4 py-3">
|
|
3
|
+
<div v-for="group in data" :key="group.key" class="mb-4">
|
|
4
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">
|
|
5
|
+
{{ group.icon }} {{ group.label }} ({{ group.files.length }})
|
|
6
|
+
</h4>
|
|
7
|
+
<div class="space-y-1">
|
|
8
|
+
<div
|
|
9
|
+
v-for="f in group.files"
|
|
10
|
+
:key="f.path"
|
|
11
|
+
class="flex items-center gap-2 px-2 py-1.5 rounded text-[11px] cursor-pointer hover:bg-[#FEF3C7] transition-colors"
|
|
12
|
+
@click="$emit('open-file', f)"
|
|
13
|
+
>
|
|
14
|
+
<svg class="w-3 h-3 flex-shrink-0" fill="none" stroke="#9CA3AF" viewBox="0 0 24 24">
|
|
15
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
|
16
|
+
</svg>
|
|
17
|
+
<span class="truncate" style="color: #1C1C1E;">{{ f.name }}</span>
|
|
18
|
+
<span class="ml-auto flex-shrink-0 font-mono text-[10px]" style="color: #9CA3AF;">{{ formatSize(f.size) }}</span>
|
|
19
|
+
<span class="flex-shrink-0 text-[10px]" style="color: #9CA3AF;">{{ relativeTime(f.mtime) }}</span>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<n-empty v-else description="无文档" style="padding: 48px 0;" />
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
defineProps({ data: { type: Array, default: () => [] } })
|
|
29
|
+
defineEmits(['open-file'])
|
|
30
|
+
|
|
31
|
+
function formatSize(bytes) {
|
|
32
|
+
if (!bytes) return '—'
|
|
33
|
+
if (bytes < 1024) return bytes + ' B'
|
|
34
|
+
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'
|
|
35
|
+
return (bytes / 1048576).toFixed(1) + ' MB'
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function relativeTime(iso) {
|
|
39
|
+
if (!iso) return ''
|
|
40
|
+
const d = new Date(iso)
|
|
41
|
+
const diff = Date.now() - d.getTime()
|
|
42
|
+
if (diff < 60000) return '刚刚'
|
|
43
|
+
if (diff < 3600000) return `${Math.floor(diff / 60000)} 分钟前`
|
|
44
|
+
if (diff < 86400000) return `${Math.floor(diff / 3600000)} 小时前`
|
|
45
|
+
if (diff < 604800000) return `${Math.floor(diff / 86400000)} 天前`
|
|
46
|
+
return `${d.getMonth() + 1}/${d.getDate()}`
|
|
47
|
+
}
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="data" class="px-4 py-3">
|
|
3
|
+
<!-- Branch -->
|
|
4
|
+
<div class="mb-4">
|
|
5
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-1.5 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">当前分支</h4>
|
|
6
|
+
<div class="text-[18px] font-bold font-[JetBrains_Mono,monospace]" style="color: #D97706;">{{ data.branch || '—' }}</div>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<!-- Commits -->
|
|
10
|
+
<div v-if="data.commits?.length" class="mb-4">
|
|
11
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">最近提交</h4>
|
|
12
|
+
<div class="space-y-2">
|
|
13
|
+
<div v-for="c in data.commits" :key="c.hash" class="px-3 py-2 rounded-md" style="background: #F5F5F7;">
|
|
14
|
+
<div class="flex items-center gap-2">
|
|
15
|
+
<span class="text-[11px] font-mono font-semibold" style="color: #D97706;">{{ c.hash }}</span>
|
|
16
|
+
<span class="text-[11px] flex-1 truncate" style="color: #1C1C1E;">{{ c.message }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="flex items-center gap-2 mt-1 text-[10px]" style="color: #6B7280;">
|
|
19
|
+
<span>{{ c.author }}</span>
|
|
20
|
+
<span>·</span>
|
|
21
|
+
<span>{{ relativeTime(c.date) }}</span>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<!-- Untracked -->
|
|
28
|
+
<div v-if="data.untracked?.length">
|
|
29
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">未提交文件</h4>
|
|
30
|
+
<div class="space-y-1">
|
|
31
|
+
<div v-for="f in data.untracked" :key="f.file" class="flex items-center gap-2 px-2 py-1 rounded text-[11px] font-[JetBrains_Mono,monospace]">
|
|
32
|
+
<span class="font-semibold w-5 text-center" :style="{ color: statusColor(f.status) }">{{ f.status }}</span>
|
|
33
|
+
<span class="truncate" style="color: #1C1C1E;">{{ f.file }}</span>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<n-empty v-else description="无 Git 信息" style="padding: 48px 0;" />
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script setup>
|
|
42
|
+
defineProps({ data: { type: Object, default: null } })
|
|
43
|
+
|
|
44
|
+
function statusColor(s) {
|
|
45
|
+
if (s.includes('M')) return '#F59E0B'
|
|
46
|
+
if (s.includes('A') || s === '?') return '#10B981'
|
|
47
|
+
if (s.includes('D')) return '#EF4444'
|
|
48
|
+
return '#9CA3AF'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function relativeTime(iso) {
|
|
52
|
+
if (!iso) return ''
|
|
53
|
+
const d = new Date(iso)
|
|
54
|
+
const diff = Date.now() - d.getTime()
|
|
55
|
+
if (diff < 60000) return '刚刚'
|
|
56
|
+
if (diff < 3600000) return `${Math.floor(diff / 60000)} 分钟前`
|
|
57
|
+
if (diff < 86400000) return `${Math.floor(diff / 3600000)} 小时前`
|
|
58
|
+
if (diff < 604800000) return `${Math.floor(diff / 86400000)} 天前`
|
|
59
|
+
return `${d.getMonth() + 1}/${d.getDate()}`
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="data" class="px-4 py-3">
|
|
3
|
+
<!-- Frameworks -->
|
|
4
|
+
<div v-if="data.frameworks?.length" class="mb-4">
|
|
5
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">识别框架</h4>
|
|
6
|
+
<div class="flex flex-wrap gap-2">
|
|
7
|
+
<n-tag v-for="f in data.frameworks" :key="f" type="warning" size="small" round>{{ f }}</n-tag>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<!-- Dependencies -->
|
|
12
|
+
<div v-if="depEntries.length" class="mb-4">
|
|
13
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">dependencies ({{ depEntries.length }})</h4>
|
|
14
|
+
<div class="space-y-1">
|
|
15
|
+
<div v-for="[name, ver] in depEntries" :key="name" class="flex items-center gap-2 px-2 py-1 rounded text-[11px]" style="background: #F5F5F7;">
|
|
16
|
+
<span class="font-mono font-medium truncate" style="color: #1C1C1E;">{{ name }}</span>
|
|
17
|
+
<span class="font-mono ml-auto flex-shrink-0" style="color: #9CA3AF;">{{ ver }}</span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Dev Dependencies -->
|
|
23
|
+
<div v-if="devDepEntries.length">
|
|
24
|
+
<h4 class="text-[9px] font-semibold uppercase tracking-[0.2em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">devDependencies ({{ devDepEntries.length }})</h4>
|
|
25
|
+
<div class="space-y-1">
|
|
26
|
+
<div v-for="[name, ver] in devDepEntries" :key="name" class="flex items-center gap-2 px-2 py-1 rounded text-[11px]" style="background: #F5F5F7;">
|
|
27
|
+
<span class="font-mono font-medium truncate" style="color: #1C1C1E;">{{ name }}</span>
|
|
28
|
+
<span class="font-mono ml-auto flex-shrink-0" style="color: #9CA3AF;">{{ ver }}</span>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<n-empty v-else description="无依赖信息" style="padding: 48px 0;" />
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup>
|
|
37
|
+
import { computed } from 'vue'
|
|
38
|
+
|
|
39
|
+
const props = defineProps({ data: { type: Object, default: null } })
|
|
40
|
+
|
|
41
|
+
const depEntries = computed(() => props.data ? Object.entries(props.data.dependencies || {}) : [])
|
|
42
|
+
const devDepEntries = computed(() => props.data ? Object.entries(props.data.devDependencies || {}) : [])
|
|
43
|
+
</script>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
|
|
3
3
|
@theme {
|
|
4
|
-
--color-bg: #
|
|
5
|
-
--color-primary: #
|
|
6
|
-
--color-primary-dim: #
|
|
7
|
-
--color-warning: #
|
|
8
|
-
--color-danger: #
|
|
9
|
-
--color-muted: #
|
|
10
|
-
--color-surface: #
|
|
11
|
-
--color-surface-2: #
|
|
12
|
-
--color-border: #
|
|
13
|
-
--color-border-light: #
|
|
14
|
-
--color-text: #
|
|
15
|
-
--color-text-secondary: #
|
|
16
|
-
--color-info: #
|
|
17
|
-
--color-success: #
|
|
4
|
+
--color-bg: #F5F5F7;
|
|
5
|
+
--color-primary: #D97706;
|
|
6
|
+
--color-primary-dim: #92400E;
|
|
7
|
+
--color-warning: #EA580C;
|
|
8
|
+
--color-danger: #DC2626;
|
|
9
|
+
--color-muted: #6B7280;
|
|
10
|
+
--color-surface: #FFFFFF;
|
|
11
|
+
--color-surface-2: #F0F0F3;
|
|
12
|
+
--color-border: #E5E5EA;
|
|
13
|
+
--color-border-light: #D1D1D6;
|
|
14
|
+
--color-text: #1C1C1E;
|
|
15
|
+
--color-text-secondary: #636366;
|
|
16
|
+
--color-info: #2563EB;
|
|
17
|
+
--color-success: #16A34A;
|
|
18
18
|
|
|
19
19
|
--font-display: 'JetBrains Mono', monospace;
|
|
20
20
|
--font-body: 'DM Sans', sans-serif;
|
package/src/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SillySpec CLI — 安装工具
|
|
5
5
|
*
|
|
6
6
|
* 只负责两件事:init(安装命令模板)和 setup(安装 MCP 工具)。
|
|
7
|
-
*
|
|
7
|
+
* 状态管理通过 progress.json 完成,使用 `sillyspec progress` 命令。
|
|
8
8
|
*/
|
|
9
9
|
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
10
10
|
import { join, resolve } from 'path';
|
|
@@ -25,11 +25,15 @@ SillySpec CLI — 规范驱动开发工具包
|
|
|
25
25
|
[--dir <path>] 指定目录
|
|
26
26
|
sillyspec setup [--list] 安装推荐 MCP 工具
|
|
27
27
|
[--list] 查看已安装状态
|
|
28
|
-
sillyspec progress <cmd>
|
|
29
|
-
init
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
sillyspec progress <cmd> 进度管理
|
|
29
|
+
init 初始化 progress.json
|
|
30
|
+
show 查看当前进度
|
|
31
|
+
set-stage <stage> 设置当前阶段
|
|
32
|
+
add-step <stage> <name> 添加步骤
|
|
33
|
+
update-step <s> <n> --status <st> [--output <t>]
|
|
34
|
+
complete-stage <stage> 完成阶段并推进
|
|
35
|
+
validate 校验并修复
|
|
36
|
+
reset [--stage X] 重置进度
|
|
33
37
|
complete --stage X 归档已完成阶段
|
|
34
38
|
sillyspec docs migrate 迁移旧文档到统一结构
|
|
35
39
|
sillyspec dashboard 启动 Dashboard Web UI
|
|
@@ -93,6 +97,11 @@ async function main() {
|
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
const command = filteredArgs[0];
|
|
100
|
+
// 支持 sillyspec init /path/to/project 语法:如果第二个参数看起来像路径,当作 targetDir
|
|
101
|
+
if (command === 'init' && filteredArgs[1] && !filteredArgs[1].startsWith('-')) {
|
|
102
|
+
targetDir = resolve(filteredArgs[1]);
|
|
103
|
+
filteredArgs.splice(1, 1);
|
|
104
|
+
}
|
|
96
105
|
const dir = targetDir;
|
|
97
106
|
|
|
98
107
|
if (!existsSync(dir)) {
|
|
@@ -119,7 +128,8 @@ async function main() {
|
|
|
119
128
|
pm.init(dir);
|
|
120
129
|
break;
|
|
121
130
|
case 'status':
|
|
122
|
-
|
|
131
|
+
case 'show':
|
|
132
|
+
pm.show(dir);
|
|
123
133
|
break;
|
|
124
134
|
case 'validate':
|
|
125
135
|
pm.validate(dir);
|
|
@@ -130,8 +140,40 @@ async function main() {
|
|
|
130
140
|
case 'complete':
|
|
131
141
|
pm.complete(dir, stage);
|
|
132
142
|
break;
|
|
143
|
+
case 'set-stage': {
|
|
144
|
+
const setStageName = filteredArgs[2];
|
|
145
|
+
if (!setStageName) { console.log('❌ 用法: sillyspec progress set-stage <stage>'); break; }
|
|
146
|
+
pm.setStage(dir, setStageName);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case 'add-step': {
|
|
150
|
+
const addStepStage = filteredArgs[2];
|
|
151
|
+
const addStepName = filteredArgs[3];
|
|
152
|
+
if (!addStepStage || !addStepName) { console.log('❌ 用法: sillyspec progress add-step <stage> <step-name>'); break; }
|
|
153
|
+
pm.addStep(dir, addStepStage, addStepName);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case 'update-step': {
|
|
157
|
+
const updStepStage = filteredArgs[2];
|
|
158
|
+
const updStepName = filteredArgs[3];
|
|
159
|
+
if (!updStepStage || !updStepName) { console.log('❌ 用法: sillyspec progress update-step <stage> <step-name> --status <status> [--output <text>]'); break; }
|
|
160
|
+
// Parse --status and --output from args
|
|
161
|
+
let updStatus = null, updOutput = undefined;
|
|
162
|
+
for (let ai = 0; ai < args.length; ai++) {
|
|
163
|
+
if (args[ai] === '--status' && args[ai + 1]) { updStatus = args[ai + 1]; ai++; }
|
|
164
|
+
if (args[ai] === '--output' && args[ai + 1]) { updOutput = args[ai + 1]; ai++; }
|
|
165
|
+
}
|
|
166
|
+
pm.updateStep(dir, updStepStage, updStepName, { status: updStatus, output: updOutput });
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case 'complete-stage': {
|
|
170
|
+
const compStageName = filteredArgs[2];
|
|
171
|
+
if (!compStageName) { console.log('❌ 用法: sillyspec progress complete-stage <stage>'); break; }
|
|
172
|
+
pm.completeStage(dir, compStageName);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
133
175
|
default:
|
|
134
|
-
console.log('用法: sillyspec progress <init|
|
|
176
|
+
console.log('用法: sillyspec progress <init|show|validate|reset|complete|set-stage|add-step|update-step|complete-stage>');
|
|
135
177
|
}
|
|
136
178
|
break;
|
|
137
179
|
}
|
|
@@ -145,6 +187,11 @@ async function main() {
|
|
|
145
187
|
}
|
|
146
188
|
break;
|
|
147
189
|
}
|
|
190
|
+
case 'run': {
|
|
191
|
+
const { runCommand } = await import('./run.js')
|
|
192
|
+
runCommand(filteredArgs.slice(1), dir)
|
|
193
|
+
break
|
|
194
|
+
}
|
|
148
195
|
case 'dashboard': {
|
|
149
196
|
// Parse dashboard options
|
|
150
197
|
let port = 3456;
|