@wwkit/freetoken 1.0.1

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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/cli/helpers/args.js +48 -0
  4. package/cli/index.js +374 -0
  5. package/cli/pid-manager.js +87 -0
  6. package/client/index.html +25 -0
  7. package/client/public/favicon.svg +1 -0
  8. package/client/public/icons.svg +24 -0
  9. package/client/src/App.vue +136 -0
  10. package/client/src/assets/vite.svg +1 -0
  11. package/client/src/assets/vue.svg +1 -0
  12. package/client/src/components/ChatBox.vue +320 -0
  13. package/client/src/components/CheckList.vue +52 -0
  14. package/client/src/components/CodeBlock.vue +99 -0
  15. package/client/src/components/DetailBlock.vue +47 -0
  16. package/client/src/components/HelloWorld.vue +95 -0
  17. package/client/src/components/LangSwitch.vue +32 -0
  18. package/client/src/components/LinkList.vue +32 -0
  19. package/client/src/components/OsSwitch.vue +42 -0
  20. package/client/src/components/OsToggle.vue +15 -0
  21. package/client/src/components/PageHeader.vue +31 -0
  22. package/client/src/components/StepList.vue +92 -0
  23. package/client/src/composables/useClipboard.js +26 -0
  24. package/client/src/composables/useOs.js +22 -0
  25. package/client/src/data/docs/agent.js +1002 -0
  26. package/client/src/data/docs/auth.js +631 -0
  27. package/client/src/data/docs/builtin-tools.js +322 -0
  28. package/client/src/data/docs/chat.js +181 -0
  29. package/client/src/data/docs/index.js +9 -0
  30. package/client/src/data/docs/skills.js +396 -0
  31. package/client/src/data/docs/spec-conversion.js +1042 -0
  32. package/client/src/data/freeModels/bluesliu.js +97 -0
  33. package/client/src/data/freeModels/index.js +11 -0
  34. package/client/src/data/freeModels/nvidia.js +126 -0
  35. package/client/src/data/freeModels/openrouter.js +116 -0
  36. package/client/src/data/harness/claude.js +89 -0
  37. package/client/src/data/harness/codex.js +66 -0
  38. package/client/src/data/harness/dsh.js +86 -0
  39. package/client/src/data/harness/hermes.js +56 -0
  40. package/client/src/data/harness/index.js +22 -0
  41. package/client/src/data/harness/opencode.js +77 -0
  42. package/client/src/data/proxy/api-relay.js +53 -0
  43. package/client/src/data/proxy/builtin-proxy.js +54 -0
  44. package/client/src/data/proxy/cf-workers.js +67 -0
  45. package/client/src/data/proxy/ecs-forward.js +75 -0
  46. package/client/src/data/proxy/ecs-reverse.js +89 -0
  47. package/client/src/data/proxy/index.js +15 -0
  48. package/client/src/docs/claudecode.md +44 -0
  49. package/client/src/docs/codex.md +90 -0
  50. package/client/src/docs/hermesagent.md +42 -0
  51. package/client/src/docs/opencode.md +103 -0
  52. package/client/src/locales/en.js +436 -0
  53. package/client/src/locales/index.js +31 -0
  54. package/client/src/locales/zh-CN.js +461 -0
  55. package/client/src/main.js +16 -0
  56. package/client/src/router/index.js +76 -0
  57. package/client/src/style.css +15 -0
  58. package/client/src/views/AdminModelsView.vue +214 -0
  59. package/client/src/views/DocsView.vue +1604 -0
  60. package/client/src/views/FreeModelsView.vue +518 -0
  61. package/client/src/views/HarnessView.vue +314 -0
  62. package/client/src/views/HomeView.vue +147 -0
  63. package/client/src/views/ProxyView.vue +112 -0
  64. package/client/src/views/TokenMarketView.vue +26 -0
  65. package/client/vite.config.js +41 -0
  66. package/package.json +85 -0
  67. package/scripts/build-zip.sh +61 -0
  68. package/scripts/postinstall.js +7 -0
  69. package/server/src/config/targets.json +1 -0
  70. package/server/src/index.js +52 -0
  71. package/server/src/lib/coding-test.js +215 -0
  72. package/server/src/lib/database.js +353 -0
  73. package/server/src/lib/run-test.js +15 -0
  74. package/server/src/lib/scheduler.js +21 -0
  75. package/server/src/lib/tester.js +310 -0
  76. package/server/src/routes/admin.js +48 -0
  77. package/server/src/routes/proxy.js +64 -0
  78. package/server/src/routes/speed.js +87 -0
  79. package/src/config.js +45 -0
  80. package/src/config.json5 +27 -0
  81. package/src/index.js +10 -0
@@ -0,0 +1,214 @@
1
+ <script setup>
2
+ import { ref, computed, onMounted } from 'vue'
3
+ import { ElMessage, ElMessageBox } from 'element-plus'
4
+ import PageHeader from '../components/PageHeader.vue'
5
+ import axios from 'axios'
6
+
7
+ const models = ref([])
8
+ const loading = ref(false)
9
+ const dialogVisible = ref(false)
10
+ const dialogTitle = ref('添加模型')
11
+ const formData = ref({
12
+ id: null,
13
+ provider: '',
14
+ model: '',
15
+ baseUrl: '',
16
+ apiKeyEnv: '',
17
+ enableFullTest: false,
18
+ contextWindow: '',
19
+ description: ''
20
+ })
21
+
22
+ const activeProvider = ref('')
23
+
24
+ const providers = computed(() => {
25
+ const set = new Set(models.value.map(m => m.provider))
26
+ return Array.from(set).sort()
27
+ })
28
+
29
+ const filteredModels = computed(() => {
30
+ if (!activeProvider.value) return models.value
31
+ return models.value.filter(m => m.provider === activeProvider.value)
32
+ })
33
+
34
+ async function fetchModels() {
35
+ loading.value = true
36
+ try {
37
+ const res = await axios.get('/api/admin/')
38
+ models.value = res.data.models || []
39
+ if (providers.value.length > 0 && !activeProvider.value) {
40
+ activeProvider.value = providers.value[0]
41
+ }
42
+ } catch (error) {
43
+ ElMessage.error('获取模型列表失败: ' + error.message)
44
+ } finally {
45
+ loading.value = false
46
+ }
47
+ }
48
+
49
+ function selectProvider(p) {
50
+ activeProvider.value = p
51
+ }
52
+
53
+ function openAddDialog() {
54
+ dialogTitle.value = '添加模型'
55
+ formData.value = {
56
+ id: null,
57
+ provider: activeProvider.value || '',
58
+ model: '',
59
+ baseUrl: '',
60
+ apiKeyEnv: '',
61
+ enableFullTest: false,
62
+ contextWindow: '',
63
+ description: ''
64
+ }
65
+ dialogVisible.value = true
66
+ }
67
+
68
+ function openEditDialog(row) {
69
+ dialogTitle.value = '编辑模型'
70
+ formData.value = { ...row }
71
+ dialogVisible.value = true
72
+ }
73
+
74
+ async function saveModel() {
75
+ try {
76
+ if (formData.value.id) {
77
+ await axios.put(`/api/admin/${formData.value.id}`, formData.value)
78
+ ElMessage.success('更新成功')
79
+ } else {
80
+ await axios.post('/api/admin/', formData.value)
81
+ ElMessage.success('添加成功')
82
+ }
83
+ dialogVisible.value = false
84
+ fetchModels()
85
+ } catch (error) {
86
+ ElMessage.error('保存失败: ' + error.message)
87
+ }
88
+ }
89
+
90
+ async function deleteModel(row) {
91
+ try {
92
+ await ElMessageBox.confirm(`确定删除模型 ${row.model}?`, '确认删除', {
93
+ type: 'warning'
94
+ })
95
+ await axios.delete(`/api/admin/${row.id}`)
96
+ ElMessage.success('删除成功')
97
+ fetchModels()
98
+ } catch (error) {
99
+ if (error !== 'cancel') {
100
+ ElMessage.error('删除失败: ' + error.message)
101
+ }
102
+ }
103
+ }
104
+
105
+ onMounted(() => {
106
+ fetchModels()
107
+ })
108
+ </script>
109
+
110
+ <template>
111
+ <div class="admin-page">
112
+ <PageHeader title="模型管理" description="配置测速系统的模型列表" />
113
+
114
+ <el-tabs v-model="activeProvider" @tab-change="selectProvider">
115
+ <el-tab-pane
116
+ v-for="p in providers"
117
+ :key="p"
118
+ :name="p"
119
+ :label="p"
120
+ />
121
+ </el-tabs>
122
+
123
+ <div class="toolbar">
124
+ <el-button type="primary" @click="openAddDialog">添加模型</el-button>
125
+ <el-button @click="fetchModels" :loading="loading">刷新</el-button>
126
+ </div>
127
+
128
+ <el-table :data="filteredModels" border stripe v-loading="loading">
129
+ <el-table-column prop="id" label="ID" width="60" />
130
+ <el-table-column prop="provider" label="供应商" width="120" />
131
+ <el-table-column prop="model" label="模型名称" min-width="200" />
132
+ <el-table-column prop="baseUrl" label="Base URL" min-width="250" />
133
+ <el-table-column prop="apiKeyEnv" label="环境变量" width="180">
134
+ <template #default="scope">
135
+ <code v-if="scope.row.apiKeyEnv" class="env-code">{{ scope.row.apiKeyEnv }}</code>
136
+ <span v-else class="text-muted">-</span>
137
+ </template>
138
+ </el-table-column>
139
+ <el-table-column prop="enableFullTest" label="完整测试" width="100">
140
+ <template #default="scope">
141
+ <el-tag :type="scope.row.enableFullTest ? 'success' : 'info'" size="small">
142
+ {{ scope.row.enableFullTest ? '开启' : '关闭' }}
143
+ </el-tag>
144
+ </template>
145
+ </el-table-column>
146
+ <el-table-column prop="contextWindow" label="上下文窗口" width="120">
147
+ <template #default="scope">{{ scope.row.contextWindow || '-' }}</template>
148
+ </el-table-column>
149
+ <el-table-column prop="description" label="描述" min-width="150">
150
+ <template #default="scope">{{ scope.row.description || '-' }}</template>
151
+ </el-table-column>
152
+ <el-table-column label="操作" width="140" fixed="right">
153
+ <template #default="scope">
154
+ <el-button size="small" @click="openEditDialog(scope.row)">编辑</el-button>
155
+ <el-button size="small" type="danger" @click="deleteModel(scope.row)">删除</el-button>
156
+ </template>
157
+ </el-table-column>
158
+ </el-table>
159
+
160
+ <el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
161
+ <el-form :model="formData" label-width="100px">
162
+ <el-form-item label="供应商">
163
+ <el-input v-model="formData.provider" placeholder="如: bluesliu" />
164
+ </el-form-item>
165
+ <el-form-item label="模型名称">
166
+ <el-input v-model="formData.model" placeholder="如: MiniMax-M2.7" />
167
+ </el-form-item>
168
+ <el-form-item label="Base URL">
169
+ <el-input v-model="formData.baseUrl" placeholder="如: http://7.237.94.74:32527/v1" />
170
+ </el-form-item>
171
+ <el-form-item label="环境变量">
172
+ <el-input v-model="formData.apiKeyEnv" placeholder="如: BLUESLIU_API_KEY" />
173
+ </el-form-item>
174
+ <el-form-item label="完整测试">
175
+ <el-switch v-model="formData.enableFullTest" />
176
+ <span class="form-tip">开启后执行响应速度、吞吐速度、编码能力测试</span>
177
+ </el-form-item>
178
+ <el-form-item label="上下文窗口">
179
+ <el-input v-model="formData.contextWindow" placeholder="如: 128K tokens" />
180
+ </el-form-item>
181
+ <el-form-item label="描述">
182
+ <el-input v-model="formData.description" type="textarea" :rows="2" />
183
+ </el-form-item>
184
+ </el-form>
185
+ <template #footer>
186
+ <el-button @click="dialogVisible = false">取消</el-button>
187
+ <el-button type="primary" @click="saveModel">保存</el-button>
188
+ </template>
189
+ </el-dialog>
190
+ </div>
191
+ </template>
192
+
193
+ <style scoped>
194
+ .toolbar {
195
+ margin-bottom: 16px;
196
+ display: flex;
197
+ gap: 12px;
198
+ }
199
+ .env-code {
200
+ padding: 2px 6px;
201
+ background: var(--el-fill-color-light);
202
+ border-radius: 4px;
203
+ font-family: 'Monaco', 'Menlo', monospace;
204
+ font-size: 11px;
205
+ }
206
+ .text-muted {
207
+ color: var(--el-text-color-secondary);
208
+ }
209
+ .form-tip {
210
+ margin-left: 12px;
211
+ font-size: 12px;
212
+ color: var(--el-text-color-secondary);
213
+ }
214
+ </style>