test news page
This commit is contained in:
parent
e43431a725
commit
5bf0623327
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,4 +18,4 @@ resources/service
|
|||||||
stats.html
|
stats.html
|
||||||
.openmcp
|
.openmcp
|
||||||
test-vsix
|
test-vsix
|
||||||
resources/changelog/index.html
|
resources/changelog/**
|
1
news/.gitignore
vendored
1
news/.gitignore
vendored
@ -28,3 +28,4 @@ coverage
|
|||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
./src/data.json
|
5
news/env.d.ts
vendored
5
news/env.d.ts
vendored
@ -1 +1,6 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
declare module '*.vue' {
|
||||||
|
import { DefineComponent } from 'vue'
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
<link rel="stylesheet" href="/default-dark.css">
|
<link rel="stylesheet" href="/default-dark.css">
|
||||||
<link rel="stylesheet" href="/vscode.css">
|
<link rel="stylesheet" href="/vscode.css">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Vite App</title>
|
<title>OpenMCP News Feature</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
7
news/package-lock.json
generated
7
news/package-lock.json
generated
@ -8,6 +8,7 @@
|
|||||||
"name": "news",
|
"name": "news",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"vanilla-tilt": "^1.8.1",
|
||||||
"vue": "^3.5.17"
|
"vue": "^3.5.17"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -2983,6 +2984,12 @@
|
|||||||
"browserslist": ">= 4.21.0"
|
"browserslist": ">= 4.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vanilla-tilt": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vanilla-tilt/-/vanilla-tilt-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-hPB1XUsnh+SIeVSW2beb5RnuFxz4ZNgxjGD78o52F49gS4xaoLeEMh9qrQnJrnEn/vjjBI7IlxrrXmz4tGV0Kw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"type-check": "vue-tsc --build"
|
"type-check": "vue-tsc --build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"vanilla-tilt": "^1.8.1",
|
||||||
"vue": "^3.5.17"
|
"vue": "^3.5.17"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -5,9 +5,10 @@ import OmMoreFeature from './components/MoreFeature.vue';
|
|||||||
import OmCoreFeature from './components/CoreFeature.vue';
|
import OmCoreFeature from './components/CoreFeature.vue';
|
||||||
import OmSponsor from './components/Sponsor.vue';
|
import OmSponsor from './components/Sponsor.vue';
|
||||||
import OmResource from './components/Resource.vue';
|
import OmResource from './components/Resource.vue';
|
||||||
import OmTroubleshoot from './components/Trouble.vue';
|
import OmTroubleshoot from './components/Troubleshoot.vue';
|
||||||
|
import OmContributor from './components/Contributor.vue';
|
||||||
|
|
||||||
import data from './data.json';
|
import data from './data.json';``
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -32,6 +33,9 @@ import data from './data.json';
|
|||||||
|
|
||||||
<!-- 6. 🔧 Troubleshooting -->
|
<!-- 6. 🔧 Troubleshooting -->
|
||||||
<om-troubleshoot />
|
<om-troubleshoot />
|
||||||
|
|
||||||
|
<!-- 7. 👥 Contributors -->
|
||||||
|
<om-contributor :contributors="data.contributors" />
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -95,15 +99,20 @@ body {
|
|||||||
gap: 24px;
|
gap: 24px;
|
||||||
margin: 0 0 32px 0;
|
margin: 0 0 32px 0;
|
||||||
padding: 0 0 16px 0;
|
padding: 0 0 16px 0;
|
||||||
border-bottom: 1px solid #B988D1;
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.openmcp-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.openmcp-logo {
|
.openmcp-logo {
|
||||||
width: 84px;
|
width: 84px;
|
||||||
height: 84px;
|
height: 84px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: var(--vscode-sideBar-background);
|
|
||||||
box-shadow: 0 2px 8px 0 rgba(185, 136, 209, 0.08);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.margin-bottom {
|
.margin-bottom {
|
||||||
|
98
news/src/components/Contributor.vue
Normal file
98
news/src/components/Contributor.vue
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, reactive } from 'vue';
|
||||||
|
import VanillaTilt from 'vanilla-tilt';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
contributors: {
|
||||||
|
username: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
homeUrl: string;
|
||||||
|
}[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const tiltElements = reactive<any[]>([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 为每个元素应用Tilt效果
|
||||||
|
tiltElements.forEach(el => {
|
||||||
|
VanillaTilt.init(el, {
|
||||||
|
max: 35,
|
||||||
|
speed: 400,
|
||||||
|
glare: true,
|
||||||
|
'max-glare': 0.2
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="troubleshoot-section">
|
||||||
|
<div class="section-title">👥 Contributors</div>
|
||||||
|
<div class="contributors-grid">
|
||||||
|
<div v-for="(contributor, idx) in props.contributors"
|
||||||
|
:key="contributor.username" class="contributor-tilt"
|
||||||
|
:ref="el => tiltElements[idx] = el"
|
||||||
|
>
|
||||||
|
<a :href="contributor.homeUrl" target="_blank">
|
||||||
|
<img :src="contributor.avatarUrl" :alt="contributor.username" class="contributor-avatar" />
|
||||||
|
<span class="contributor-name">{{ contributor.username }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.contributors-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributors-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributor-tilt {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1rem;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributor-tilt a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributor-avatar {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto 0.5rem;
|
||||||
|
border: 3px solid #fff;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contributor-name {
|
||||||
|
display: block;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #B988D1;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tilt.js 生成的眩光效果自定义 */
|
||||||
|
.tilt-glare {
|
||||||
|
border-radius: 12px !important;
|
||||||
|
}
|
||||||
|
</style>
|
@ -64,9 +64,18 @@ const props = defineProps({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<hr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1.5px solid #B988D1;
|
||||||
|
height: 0;
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.openmcp-header h1 {
|
.openmcp-header h1 {
|
||||||
font-size: 2.1rem;
|
font-size: 2.1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@ -74,7 +83,6 @@ const props = defineProps({
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: #B988D1;
|
color: #B988D1;
|
||||||
letter-spacing: 1px;
|
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +90,7 @@ const props = defineProps({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
justify-content: center;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
news/src/components/Hello.vue
Normal file
5
news/src/components/Hello.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -42,8 +42,4 @@
|
|||||||
.resource-list a:hover {
|
.resource-list a:hover {
|
||||||
color: #8e5bbf;
|
color: #8e5bbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
.troubleshoot-section {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
@ -13,7 +13,7 @@
|
|||||||
Github
|
Github
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<a class="sponsor-item" href="sponsor-item" target="_blank">
|
<a class="sponsor-item" href="https://afdian.com/a/kirigaya" target="_blank">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path
|
<path
|
||||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm.31-8.86c-1.77-.45-2.34-.94-2.34-1.67 0-.84.79-1.43 2.1-1.43 1.38 0 1.9.66 1.94 1.64h1.71c-.05-1.34-.87-2.57-2.49-2.97V5H10.9v1.69c-1.51.32-2.72 1.3-2.72 2.81 0 1.79 1.49 2.69 3.66 3.21 1.95.46 2.34 1.15 2.34 1.87 0 .53-.39 1.39-2.1 1.39-1.6 0-2.23-.72-2.32-1.64H8.04c.1 1.7 1.36 2.66 2.86 2.97V19h2.34v-1.67c1.52-.29 2.72-1.16 2.73-2.77-.01-2.2-1.9-2.96-3.66-3.42z">
|
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm.31-8.86c-1.77-.45-2.34-.94-2.34-1.67 0-.84.79-1.43 2.1-1.43 1.38 0 1.9.66 1.94 1.64h1.71c-.05-1.34-.87-2.57-2.49-2.97V5H10.9v1.69c-1.51.32-2.72 1.3-2.72 2.81 0 1.79 1.49 2.69 3.66 3.21 1.95.46 2.34 1.15 2.34 1.87 0 .53-.39 1.39-2.1 1.39-1.6 0-2.23-.72-2.32-1.64H8.04c.1 1.7 1.36 2.66 2.86 2.97V19h2.34v-1.67c1.52-.29 2.72-1.16 2.73-2.77-.01-2.2-1.9-2.96-3.66-3.42z">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<script>
|
<script setup lang="ts">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -18,6 +18,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.troubleshoot-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.troubleshoot-list {
|
.troubleshoot-list {
|
||||||
list-style: disc inside;
|
list-style: disc inside;
|
||||||
padding-left: 18px;
|
padding-left: 18px;
|
@ -1,11 +1,48 @@
|
|||||||
{
|
{
|
||||||
"version": "0.1.9",
|
"version": "0.1.9",
|
||||||
"changelogs": [
|
"changelogs": [
|
||||||
"Add mook feature: Automatically fill test tool form data using random seeds or AI generation.",
|
"Add mook feature: Automatically fill in test tool form data using random seeds or AI generation",
|
||||||
"Add tool self-check feature: In OpenMCP's tool section, click 'Tool Self-Check' on the right of 'Tool Module' to enter self-check mode, where users can define the execution topology order of tools and perform automatic detection in one go.",
|
"Add tool self-check feature: Under openmcp's tool, click 'Tool Self-Check' on the right side of 'Tool Module' to enter self-check mode. In this mode, users can define the topological order of tool execution and perform automatic detection in one go.",
|
||||||
"Fix issue #44: Complete platform adaptation for link redirection.",
|
"Fix issue #44: Complete platform adaptation for link redirection",
|
||||||
"Fix issue #36: Successful startup when not opening a folder.",
|
"Fix issue #36: Successful startup when not opening a folder",
|
||||||
"Fix issue #45: Support for array-type parameters.",
|
"Fix issue #45: Array type parameters not supported",
|
||||||
"Fix abnormal style when pasting multi-line conversations into the dialog box."
|
"Fix abnormal dialog style when pasting multi-line conversations into the dialog box"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"username": "LSTM-Kirigaya",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/59416203?v=4",
|
||||||
|
"homeUrl": "https://github.com/LSTM-Kirigaya"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "li1553770945",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/55867654?v=4",
|
||||||
|
"homeUrl": "https://github.com/li1553770945"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "STUzhy",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/129645384?v=4",
|
||||||
|
"homeUrl": "https://github.com/STUzhy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "appli456",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/8943691?v=4",
|
||||||
|
"homeUrl": "https://github.com/appli456"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "cybermanhao",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/37235140?v=4",
|
||||||
|
"homeUrl": "https://github.com/cybermanhao"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "ArcStellar2025",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/115577936?v=4",
|
||||||
|
"homeUrl": "https://github.com/ArcStellar2025"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "ZYD045692",
|
||||||
|
"avatarUrl": "https://avatars.githubusercontent.com/u/206822796?v=4",
|
||||||
|
"homeUrl": "https://github.com/ZYD045692"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -107,6 +107,12 @@
|
|||||||
"title": "%openmcp.hook.test-ocr.title%",
|
"title": "%openmcp.hook.test-ocr.title%",
|
||||||
"category": "openmcp",
|
"category": "openmcp",
|
||||||
"icon": "$(test)"
|
"icon": "$(test)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "openmcp.hook.test-news",
|
||||||
|
"title": "%openmcp.hook.test-news.title%",
|
||||||
|
"category": "openmcp",
|
||||||
|
"icon": "$(test)"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
|
@ -13,5 +13,6 @@
|
|||||||
"openmcp.hook.test-ocr.title": "OCR をテスト",
|
"openmcp.hook.test-ocr.title": "OCR をテスト",
|
||||||
"openmcp.sidebar.workspace-connection.view.title": "MCP 接続(ワークスペース)",
|
"openmcp.sidebar.workspace-connection.view.title": "MCP 接続(ワークスペース)",
|
||||||
"openmcp.sidebar.installed-connection.view.title": "インストール済み MCP サーバー",
|
"openmcp.sidebar.installed-connection.view.title": "インストール済み MCP サーバー",
|
||||||
"openmcp.sidebar.help.view.title": "はじめに・ヘルプ"
|
"openmcp.sidebar.help.view.title": "はじめに・ヘルプ",
|
||||||
|
"openmcp.hook.test-news.title": "テストニュースレポート"
|
||||||
}
|
}
|
@ -13,5 +13,6 @@
|
|||||||
"openmcp.hook.test-ocr.title": "Test OCR",
|
"openmcp.hook.test-ocr.title": "Test OCR",
|
||||||
"openmcp.sidebar.workspace-connection.view.title": "MCP Connections (Workspace)",
|
"openmcp.sidebar.workspace-connection.view.title": "MCP Connections (Workspace)",
|
||||||
"openmcp.sidebar.installed-connection.view.title": "Installed MCP Servers",
|
"openmcp.sidebar.installed-connection.view.title": "Installed MCP Servers",
|
||||||
"openmcp.sidebar.help.view.title": "Getting Started & Help"
|
"openmcp.sidebar.help.view.title": "Getting Started & Help",
|
||||||
|
"openmcp.hook.test-news.title": "test news report"
|
||||||
}
|
}
|
@ -13,5 +13,6 @@
|
|||||||
"openmcp.hook.test-ocr.title": "测试 OCR",
|
"openmcp.hook.test-ocr.title": "测试 OCR",
|
||||||
"openmcp.sidebar.workspace-connection.view.title": "MCP 连接 (工作区)",
|
"openmcp.sidebar.workspace-connection.view.title": "MCP 连接 (工作区)",
|
||||||
"openmcp.sidebar.installed-connection.view.title": "安装的 MCP 服务器",
|
"openmcp.sidebar.installed-connection.view.title": "安装的 MCP 服务器",
|
||||||
"openmcp.sidebar.help.view.title": "入门与帮助"
|
"openmcp.sidebar.help.view.title": "入门与帮助",
|
||||||
|
"openmcp.hook.test-news.title": "测试新闻报告"
|
||||||
}
|
}
|
167
scripts/update-news-data.mts
Normal file
167
scripts/update-news-data.mts
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import path from 'path';
|
||||||
|
import { OpenAI } from 'openai';
|
||||||
|
|
||||||
|
const client = new OpenAI({
|
||||||
|
baseURL: 'https://api.deepseek.com',
|
||||||
|
apiKey: process.env.DEEPSEEK_API_TOKEN,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetchContributorsFromRepo(owner: string, repo: string) {
|
||||||
|
let page = 1;
|
||||||
|
const per_page = 100;
|
||||||
|
let contributors: any[] = [];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const res = await fetch(
|
||||||
|
`https://api.github.com/repos/${owner}/${repo}/contributors?per_page=${per_page}&page=${page}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'openmcp-client-script'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`GitHub API error: ${res.status} ${res.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await res.json();
|
||||||
|
if (data.length === 0) break;
|
||||||
|
contributors = contributors.concat(data);
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contributors;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchAndMergeContributors() {
|
||||||
|
const repos = [
|
||||||
|
{ owner: 'LSTM-Kirigaya', repo: 'openmcp-client' },
|
||||||
|
{ owner: 'LSTM-Kirigaya', repo: 'openmcp-document' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const allContributors: Record<string, { username: string, avatarUrl: string, homeUrl: string, contributions: number }> = {};
|
||||||
|
|
||||||
|
for (const { owner, repo } of repos) {
|
||||||
|
const contributors = await fetchContributorsFromRepo(owner, repo);
|
||||||
|
for (const c of contributors) {
|
||||||
|
const username = c.login;
|
||||||
|
if (!allContributors[username]) {
|
||||||
|
allContributors[username] = {
|
||||||
|
username,
|
||||||
|
avatarUrl: c.avatar_url,
|
||||||
|
homeUrl: c.html_url,
|
||||||
|
contributions: c.contributions
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
allContributors[username].contributions += c.contributions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按贡献次数排序
|
||||||
|
const result = Object.values(allContributors)
|
||||||
|
.sort((a, b) => b.contributions - a.contributions)
|
||||||
|
.map(({ contributions, ...rest }) => rest); // 去掉contributions字段
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRJ_PATH = path.join(path.dirname(import.meta.dirname));
|
||||||
|
|
||||||
|
async function getVersionAndContent() {
|
||||||
|
const changelog = readFileSync( path.join(PRJ_PATH, 'CHANGELOG.md'), { encoding: 'utf-8' });
|
||||||
|
const newContent = changelog.split('## [main]')[1];
|
||||||
|
const version = newContent.split('\n')[0].trim();
|
||||||
|
|
||||||
|
// 提取 main 版本下的 markdown 列表内容
|
||||||
|
const contentLines = newContent.split('\n').slice(1);
|
||||||
|
const content = contentLines
|
||||||
|
.filter(line => line.trim().startsWith('- ') || line.trim().startsWith('* '))
|
||||||
|
.map(line => line.replace(/^[-*]\s*/, '').trim())
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
// 让大模型翻译并输出 json
|
||||||
|
const prompt = `
|
||||||
|
Translate the following markdown list to English and return a JSON array of strings (do not include any markdown or extra text, only valid JSON array):
|
||||||
|
|
||||||
|
${content}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const completion = await client.chat.completions.create({
|
||||||
|
model: 'deepseek-chat',
|
||||||
|
messages: [
|
||||||
|
{ role: 'system', content: 'You are a helpful assistant for translation and JSON formatting.' },
|
||||||
|
{ role: 'user', content: prompt }
|
||||||
|
],
|
||||||
|
temperature: 0.2,
|
||||||
|
max_tokens: 1024
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解析大模型返回的 JSON
|
||||||
|
let changelogs: string[] = [];
|
||||||
|
try {
|
||||||
|
const choices = completion.choices;
|
||||||
|
if (!choices || choices.length === 0 || !choices[0].message || !choices[0].message.content) {
|
||||||
|
throw new Error('Invalid response from LLM');
|
||||||
|
}
|
||||||
|
const text = choices[0].message.content.trim();
|
||||||
|
// 按行过滤:只保留非 ``` 开头的行
|
||||||
|
const clearText = text.split('\n').filter(line => !line.startsWith('```')).join('\n')
|
||||||
|
changelogs = JSON.parse(clearText);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Failed to parse LLM output as JSON: ' + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { version, changelogs };
|
||||||
|
}
|
||||||
|
|
||||||
|
const contributors = await fetchAndMergeContributors();
|
||||||
|
const { version, changelogs } = await getVersionAndContent();
|
||||||
|
const newsData = {
|
||||||
|
version,
|
||||||
|
changelogs,
|
||||||
|
contributors
|
||||||
|
};
|
||||||
|
const newsDataPath = path.join(PRJ_PATH, 'news', 'src', 'data.json');
|
||||||
|
writeFileSync(newsDataPath, JSON.stringify(newsData, null, 2), { encoding: 'utf-8' });
|
||||||
|
console.log('News data updated successfully:', newsDataPath);
|
||||||
|
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
|
// ...前面的代码...
|
||||||
|
|
||||||
|
// 写入 news/src/data.json
|
||||||
|
writeFileSync(newsDataPath, JSON.stringify(newsData, null, 2), { encoding: 'utf-8' });
|
||||||
|
console.log('News data updated successfully:', newsDataPath);
|
||||||
|
|
||||||
|
// 1. 进入 news 目录并编译
|
||||||
|
const newsDir = path.join(PRJ_PATH, 'news');
|
||||||
|
console.log('Building news SPA...');
|
||||||
|
execSync('npm run build', { cwd: newsDir, stdio: 'inherit' });
|
||||||
|
|
||||||
|
// 2. 拷贝编译产物到 resources/changelog
|
||||||
|
const buildOutputDir = path.join(newsDir, 'dist');
|
||||||
|
const targetDir = path.join(PRJ_PATH, 'resources', 'changelog');
|
||||||
|
|
||||||
|
// 简单递归复制函数
|
||||||
|
import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
|
||||||
|
|
||||||
|
function copyDir(src: string, dest: string) {
|
||||||
|
if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
|
||||||
|
for (const file of readdirSync(src)) {
|
||||||
|
const srcFile = path.join(src, file);
|
||||||
|
const destFile = path.join(dest, file);
|
||||||
|
if (file.endsWith('.css')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (statSync(srcFile).isDirectory()) {
|
||||||
|
copyDir(srcFile, destFile);
|
||||||
|
} else {
|
||||||
|
copyFileSync(srcFile, destFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copyDir(buildOutputDir, targetDir);
|
||||||
|
console.log('Build output copied to:', targetDir);
|
@ -2,7 +2,7 @@ import { RegisterCommand } from "../common/index.js";
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import Tesseract from 'tesseract.js';
|
import Tesseract from 'tesseract.js';
|
||||||
|
import { revealOpenMcpNewsWebviewPanel } from "../webview/webview.service.js";
|
||||||
|
|
||||||
export class HookController {
|
export class HookController {
|
||||||
|
|
||||||
@ -40,7 +40,8 @@ export class HookController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterCommand('openmcp.hook.test-news')
|
||||||
|
async testNews(context: vscode.ExtensionContext) {
|
||||||
|
revealOpenMcpNewsWebviewPanel(context);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user