@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,47 @@
1
+ <script setup>
2
+ defineProps({
3
+ title: { type: String, default: '' },
4
+ description: { type: String, default: '' },
5
+ })
6
+ </script>
7
+
8
+ <template>
9
+ <div class="detail-block">
10
+ <div v-if="title || $slots.header" class="detail-block-header">
11
+ <slot name="header">
12
+ <h3 class="detail-block-title">{{ title }}</h3>
13
+ <p v-if="description" class="detail-block-desc">{{ description }}</p>
14
+ </slot>
15
+ </div>
16
+ <div class="detail-block-body">
17
+ <slot />
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <style scoped>
23
+ .detail-block {
24
+ border: 1px solid var(--el-border-color);
25
+ border-radius: 8px;
26
+ overflow: hidden;
27
+ }
28
+ .detail-block-header {
29
+ padding: 8px 16px;
30
+ border-bottom: 1px solid var(--el-border-color);
31
+ background: var(--el-fill-color-light);
32
+ }
33
+ .detail-block-title {
34
+ margin: 0;
35
+ font-size: 14px;
36
+ font-weight: 600;
37
+ color: var(--el-text-color-primary);
38
+ }
39
+ .detail-block-desc {
40
+ margin: 2px 0 0;
41
+ font-size: 12px;
42
+ color: var(--el-text-color-secondary);
43
+ }
44
+ .detail-block-body {
45
+ padding: 12px 16px;
46
+ }
47
+ </style>
@@ -0,0 +1,95 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+ import viteLogo from '../assets/vite.svg'
4
+ import heroImg from '../assets/vite.svg'
5
+ import vueLogo from '../assets/vue.svg'
6
+
7
+ const count = ref(0)
8
+ </script>
9
+
10
+ <template>
11
+ <section id="center">
12
+ <div class="hero">
13
+ <img :src="heroImg" class="base" width="170" height="179" alt="" />
14
+ <img :src="vueLogo" class="framework" alt="Vue logo" />
15
+ <img :src="viteLogo" class="vite" alt="Vite logo" />
16
+ </div>
17
+ <div>
18
+ <h1>Get started</h1>
19
+ <p>Edit <code>src/App.vue</code> and save to test <code>HMR</code></p>
20
+ </div>
21
+ <button type="button" class="counter" @click="count++">
22
+ Count is {{ count }}
23
+ </button>
24
+ </section>
25
+
26
+ <div class="ticks"></div>
27
+
28
+ <section id="next-steps">
29
+ <div id="docs">
30
+ <svg class="icon" role="presentation" aria-hidden="true">
31
+ <use href="/icons.svg#documentation-icon"></use>
32
+ </svg>
33
+ <h2>Documentation</h2>
34
+ <p>Your questions, answered</p>
35
+ <ul>
36
+ <li>
37
+ <a href="https://vite.dev/" target="_blank">
38
+ <img class="logo" :src="viteLogo" alt="" />
39
+ Explore Vite
40
+ </a>
41
+ </li>
42
+ <li>
43
+ <a href="https://vuejs.org/" target="_blank">
44
+ <img class="button-icon" :src="vueLogo" alt="" />
45
+ Learn more
46
+ </a>
47
+ </li>
48
+ </ul>
49
+ </div>
50
+ <div id="social">
51
+ <svg class="icon" role="presentation" aria-hidden="true">
52
+ <use href="/icons.svg#social-icon"></use>
53
+ </svg>
54
+ <h2>Connect with us</h2>
55
+ <p>Join the Vite community</p>
56
+ <ul>
57
+ <li>
58
+ <a href="https://github.com/vitejs/vite" target="_blank">
59
+ <svg class="button-icon" role="presentation" aria-hidden="true">
60
+ <use href="/icons.svg#github-icon"></use>
61
+ </svg>
62
+ GitHub
63
+ </a>
64
+ </li>
65
+ <li>
66
+ <a href="https://chat.vite.dev/" target="_blank">
67
+ <svg class="button-icon" role="presentation" aria-hidden="true">
68
+ <use href="/icons.svg#discord-icon"></use>
69
+ </svg>
70
+ Discord
71
+ </a>
72
+ </li>
73
+ <li>
74
+ <a href="https://x.com/vite_js" target="_blank">
75
+ <svg class="button-icon" role="presentation" aria-hidden="true">
76
+ <use href="/icons.svg#x-icon"></use>
77
+ </svg>
78
+ X.com
79
+ </a>
80
+ </li>
81
+ <li>
82
+ <a href="https://bsky.app/profile/vite.dev" target="_blank">
83
+ <svg class="button-icon" role="presentation" aria-hidden="true">
84
+ <use href="/icons.svg#bluesky-icon"></use>
85
+ </svg>
86
+ Bluesky
87
+ </a>
88
+ </li>
89
+ </ul>
90
+ </div>
91
+ </section>
92
+
93
+ <div class="ticks"></div>
94
+ <section id="spacer"></section>
95
+ </template>
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ import { computed } from 'vue'
3
+ import { useI18n } from 'vue-i18n'
4
+ import { setLocale } from '../locales/index.js'
5
+
6
+ const { locale } = useI18n()
7
+
8
+ const toggleLabel = computed(() => (locale.value === 'zh-CN' ? 'English' : '中文'))
9
+
10
+ function toggle() {
11
+ setLocale(locale.value === 'zh-CN' ? 'en' : 'zh-CN')
12
+ }
13
+ </script>
14
+
15
+ <template>
16
+ <span class="lang-toggle" @click="toggle">
17
+ {{ toggleLabel }}
18
+ </span>
19
+ </template>
20
+
21
+ <style scoped>
22
+ .lang-toggle {
23
+ cursor: pointer;
24
+ font-size: 14px;
25
+ color: var(--el-text-color-primary);
26
+ white-space: nowrap;
27
+ user-select: none;
28
+ }
29
+ .lang-toggle:hover {
30
+ color: var(--el-color-primary);
31
+ }
32
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ defineProps({
3
+ links: { type: Array, default: () => [] },
4
+ })
5
+ </script>
6
+
7
+ <template>
8
+ <div class="link-list">
9
+ <el-link
10
+ v-for="link in links"
11
+ :key="link.url"
12
+ :href="link.url"
13
+ target="_blank"
14
+ type="primary"
15
+ :underline="false"
16
+ class="link-item"
17
+ >
18
+ {{ link.labelKey ? $t(link.labelKey) : link.label }}
19
+ </el-link>
20
+ </div>
21
+ </template>
22
+
23
+ <style scoped>
24
+ .link-list {
25
+ display: flex;
26
+ flex-wrap: wrap;
27
+ gap: 16px;
28
+ }
29
+ .link-item {
30
+ font-size: 14px;
31
+ }
32
+ </style>
@@ -0,0 +1,42 @@
1
+ <script setup>
2
+ import { useI18n } from 'vue-i18n'
3
+ import { useOs } from '../composables/useOs'
4
+
5
+ const { t } = useI18n()
6
+ const { os, setOs } = useOs()
7
+ </script>
8
+
9
+ <template>
10
+ <el-dropdown trigger="click" @command="setOs">
11
+ <span class="os-switch">
12
+ <el-icon><Monitor /></el-icon>
13
+ <span class="os-label">{{ t(`os.${os}`) }}</span>
14
+ <el-icon class="el-icon--right"><ArrowDown /></el-icon>
15
+ </span>
16
+ <template #dropdown>
17
+ <el-dropdown-menu>
18
+ <el-dropdown-item command="unix" :disabled="os === 'unix'">{{ t('os.unix') }}</el-dropdown-item>
19
+ <el-dropdown-item command="windows" :disabled="os === 'windows'">{{ t('os.windows') }}</el-dropdown-item>
20
+ </el-dropdown-menu>
21
+ </template>
22
+ </el-dropdown>
23
+ </template>
24
+
25
+ <style scoped>
26
+ .os-switch {
27
+ display: flex;
28
+ align-items: center;
29
+ gap: 4px;
30
+ cursor: pointer;
31
+ font-size: 14px;
32
+ color: var(--el-text-color-primary);
33
+ white-space: nowrap;
34
+ user-select: none;
35
+ }
36
+ .os-switch:hover {
37
+ color: var(--el-color-primary);
38
+ }
39
+ .os-label {
40
+ margin: 0 2px;
41
+ }
42
+ </style>
@@ -0,0 +1,15 @@
1
+ <script setup>
2
+ import { useI18n } from 'vue-i18n'
3
+
4
+ const props = defineProps({
5
+ os: { type: String, default: 'unix' },
6
+ })
7
+
8
+ const { t } = useI18n()
9
+ </script>
10
+
11
+ <template>
12
+ <el-tag type="info" effect="plain" size="small">
13
+ {{ $t('os.currentSystem') }}:{{ t(`os.${props.os}`) }}
14
+ </el-tag>
15
+ </template>
@@ -0,0 +1,31 @@
1
+ <script setup>
2
+ defineProps({
3
+ title: { type: String, required: true },
4
+ description: { type: String, default: '' },
5
+ })
6
+ </script>
7
+
8
+ <template>
9
+ <div class="page-header">
10
+ <h1 class="page-title">{{ title }}</h1>
11
+ <p v-if="description" class="page-desc">{{ description }}</p>
12
+ </div>
13
+ </template>
14
+
15
+ <style scoped>
16
+ .page-header {
17
+ margin-bottom: 24px;
18
+ }
19
+ .page-title {
20
+ margin: 0;
21
+ font-size: 28px;
22
+ font-weight: 600;
23
+ color: var(--el-text-color-primary);
24
+ }
25
+ .page-desc {
26
+ margin: 8px 0 0;
27
+ font-size: 14px;
28
+ color: var(--el-text-color-secondary);
29
+ line-height: 1.6;
30
+ }
31
+ </style>
@@ -0,0 +1,92 @@
1
+ <script setup>
2
+ const props = defineProps({
3
+ steps: { type: Array, default: () => [] },
4
+ small: { type: Boolean, default: false },
5
+ linkable: { type: Boolean, default: false },
6
+ })
7
+
8
+ const URL_RE = /(https?:\/\/[^\s,。、]+)/g
9
+
10
+ function parseStep(text) {
11
+ if (!props.linkable) return [{ type: 'text', value: text }]
12
+ const parts = []
13
+ let last = 0
14
+ let m
15
+ const re = new RegExp(URL_RE.source, 'g')
16
+ while ((m = re.exec(text)) !== null) {
17
+ if (m.index > last) parts.push({ type: 'text', value: text.slice(last, m.index) })
18
+ parts.push({ type: 'url', value: m[0] })
19
+ last = m.index + m[0].length
20
+ }
21
+ if (last < text.length) parts.push({ type: 'text', value: text.slice(last) })
22
+ return parts
23
+ }
24
+ </script>
25
+
26
+ <template>
27
+ <ol class="step-list" :class="{ 'step-list--small': small }">
28
+ <li v-for="(step, i) in steps" :key="i" class="step-item">
29
+ <span class="step-num">{{ i + 1 }}</span>
30
+ <span class="step-text">
31
+ <template v-for="(seg, si) in parseStep(step)" :key="si">
32
+ <a v-if="seg.type === 'url'" :href="seg.value" target="_blank" rel="noopener noreferrer" class="step-link">{{ seg.value }}</a>
33
+ <template v-else>{{ seg.value }}</template>
34
+ </template>
35
+ </span>
36
+ </li>
37
+ </ol>
38
+ </template>
39
+
40
+ <style scoped>
41
+ .step-list {
42
+ margin: 0;
43
+ padding: 0;
44
+ list-style: none;
45
+ }
46
+ .step-item {
47
+ display: flex;
48
+ align-items: flex-start;
49
+ gap: 12px;
50
+ padding: 8px 0;
51
+ }
52
+ .step-num {
53
+ flex-shrink: 0;
54
+ width: 24px;
55
+ height: 24px;
56
+ border-radius: 50%;
57
+ background: var(--el-color-primary);
58
+ color: #fff;
59
+ font-size: 12px;
60
+ font-weight: 600;
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ }
65
+ .step-text {
66
+ line-height: 1.6;
67
+ color: var(--el-text-color-primary);
68
+ padding-top: 2px;
69
+ font-size: 14px;
70
+ }
71
+ .step-link {
72
+ color: var(--el-color-primary);
73
+ text-decoration: none;
74
+ }
75
+ .step-link:hover {
76
+ text-decoration: underline;
77
+ }
78
+
79
+ .step-list--small .step-item {
80
+ padding: 5px 0;
81
+ }
82
+ .step-list--small .step-num {
83
+ width: 20px;
84
+ height: 20px;
85
+ font-size: 11px;
86
+ }
87
+ .step-list--small .step-text {
88
+ font-size: 13px;
89
+ line-height: 1.5;
90
+ padding-top: 1px;
91
+ }
92
+ </style>
@@ -0,0 +1,26 @@
1
+ import { ElMessage } from 'element-plus'
2
+ import i18n from '../locales/index.js'
3
+
4
+ export function useClipboard() {
5
+ async function copy(text) {
6
+ try {
7
+ if (navigator.clipboard && window.isSecureContext) {
8
+ await navigator.clipboard.writeText(text)
9
+ } else {
10
+ const textarea = document.createElement('textarea')
11
+ textarea.value = text
12
+ textarea.style.position = 'fixed'
13
+ textarea.style.opacity = '0'
14
+ document.body.appendChild(textarea)
15
+ textarea.select()
16
+ document.execCommand('copy')
17
+ document.body.removeChild(textarea)
18
+ }
19
+ ElMessage.success(i18n.global.t('common.copiedToClipboard'))
20
+ } catch {
21
+ ElMessage.error(i18n.global.t('common.copyFailed'))
22
+ }
23
+ }
24
+
25
+ return { copy }
26
+ }
@@ -0,0 +1,22 @@
1
+ import { ref } from 'vue'
2
+
3
+ const STORAGE_KEY = 'os'
4
+
5
+ function getInitialOs() {
6
+ const saved = localStorage.getItem(STORAGE_KEY)
7
+ if (saved === 'unix' || saved === 'windows') {
8
+ return saved
9
+ }
10
+ return /Win/i.test(navigator.userAgent) ? 'windows' : 'unix'
11
+ }
12
+
13
+ const os = ref(getInitialOs())
14
+
15
+ export function useOs() {
16
+ function setOs(value) {
17
+ os.value = value
18
+ localStorage.setItem(STORAGE_KEY, value)
19
+ }
20
+
21
+ return { os, setOs }
22
+ }