Merge pull request #47 from LSTM-Kirigaya/dev

Dev
This commit is contained in:
Kirigaya Kazuto 2025-07-06 16:52:13 +08:00 committed by GitHub
commit 7263baf956
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 6545 additions and 2847 deletions

View File

@ -4,9 +4,6 @@ on:
push: push:
branches: branches:
- main - main
- dev
- hotfix
- hotfix/*
release: release:
types: types:
- published - published

View File

@ -4,9 +4,6 @@ on:
push: push:
branches: branches:
- main - main
- dev
- hotfix
- hotfix/*
release: release:
types: types:
- published - published

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ resources/service
stats.html stats.html
.openmcp .openmcp
test-vsix test-vsix
resources/changelog/**

View File

@ -14,6 +14,7 @@ vsc-extension-quickstart.md
**/.vscode-test.* **/.vscode-test.*
renderer/** renderer/**
service/** service/**
news/**
test/** test/**
servers/** servers/**
scripts/** scripts/**

31
news/.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo
./src/data.json

3
news/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

183
news/README.md Normal file
View File

@ -0,0 +1,183 @@
## OpenMCP News
Change when user update extension
## Context
You are a clever bot to write SPA page to display the changelog and news of my software OpenMCP.
### Some basic information you should know
- Release is: https://github.com/LSTM-Kirigaya/openmcp-client/releases
- OpenMCP website is: https://kirigaya.cn/openmcp/
- Github: https://github.com/LSTM-Kirigaya/openmcp-client
- Discord: https://discord.com/invite/SKTZRf6NzU
- QQ: https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD
### Design framework
You should obey the following order to make the page:
1. 📣 What is news in xxx
2. 🐳 Learn more features
3. ✨ Core Features
4. ❤️ How to sponsor
5. 📚 Resources
6. 🔧 Troubleshooting
### Some design requirements
- Theme color of openmcp is #B988D1, you should use it wisely and don't use light blue as default theme color, use #B988D1 instead.
- This is a website designed to be opened in vscode, so you should make vscode oriented design, where you should use following css macro to dev css class:
```css
:root {
--font-monospace-family: var(--vscode-editor-font-family);
--font-monospace-weight: var(--vscode-editor-font-weight);
--font-monospace-size: var(--vscode-editor-font-size);
--link-foreground: var(--vscode-textLink-foreground);
--link-active: var(--vscode-textLink-activeForeground);
/* UI & Control */
--input-active-background: var(--vscode-input-background);
--input-active-border: var(--vscode-focusBorder);
--input-active-foreground: var(--vscode-input-foreground);
--input-error-background: var(--vscode-inputValidation-errorBackground);
--input-error-border: var(--vscode-inputValidation-errorBorder);
--input-error-foreground: var(--vscode-inputValidation-errorForeground);
--input-foreground: var(--vscode-input-foreground);
--input-background: var(--vscode-input-background);
--input-border: var(--vscode-input-border);
--input-hover: var(--vscode-input-background);
--input-placeholder: var(--vscode-input-placeholderForeground);
--input-radius: 0px;
--scrollbar-background: var(--vscode-scrollbarSlider-background);
--scrollbar-hover: var(--vscode-scrollbarSlider-hoverBackground);
--scrollbar-active: var(--vscode-scrollbarSlider-activeBackground);
/* Window */
--title-bar: #1f1f1f;
--title-color: #fff;
--foreground: var(--vscode-editor-foreground);
--background: var(--vscode-editor-background);
--label: rgb(189, 189, 189);
--shadow: #000;
--border: var(--vscode-input-border);
--window-button-hover: rgba(255,255,255,0.1);
--window-button-active: rgba(255,255,255,0.2);
--window-blur-background: rgba(0,0,0,0.25);
--window-title-foreground: var(--foreground);
--window-background: var(--sidebar);
--window-border: transparent;
--window-radius: 0px;
/* Sidebar */
--sidebar: var(--vscode-sideBar-background);
--sidebar-border: var(--vscode-sideBar-border);
--sidebar-min-width: 280px;
--sidebar-item-text: var(--vscode-list-inactiveSelectionForeground);
--sidebar-item-border: var(--vscode-input-border);
--sidebar-item-background: var(--sidebar);
--sidebar-item-selected: var(--vscode-list-inactiveSelectionBackground);
--sidebar-item-hover: var(--vscode-list-hoverBackground);
--sidebar-item-max-height: 40px;
--sidebar-item-radix-background: var(--vscode-breadcrumb-background);
--sidebar-group-text: var(--vscode-sideBarSectionHeader-foreground);
--sidebar-group-border: var(--vscode-sideBarSectionHeader-border);
--sidebar-group-background: var(--vscode-sideBarSectionHeader-background);
/* Labels */
--signalSize-background: rgba(0,0,0,0.5);
--signalSize-border: rgba(255,255,255,0.2);
--signalSize-color: var(--foreground);
/* Color Picker */
--picker-swatch-size: 15px;
--picker-swatch-cols: 8;
--picker-background: var(--vscode-breadcrumbPicker-background);
--picker-border: var(--vscode-dropdown-border);
/* Search */
--search-background: var(--vscode-quickInput-background);
--search-border: var(--border);
--search-panel-background: transparent;
--search-panel-border: var(--vscode-pickerGroup-border);
--search-panel-text: var(--vscode-quickInput-foreground);
--search-label: var(--foreground);
--search-selected-background: var(--vscode-list-inactiveSelectionBackground);
/* Properties */
--properties-background: var(--vscode-breadcrumb-background);
--properties-border: var(--border);
/* Navbar */
--navBar-background: var(--sidebar);
--navBar-height: 32px;
--navBar-button: transparent;
--navBar-button-text: var(--foreground);
--navBar-group-background: var(--background);
--navBar-preview-background: var(--vscode-scrollbarSlider-background);
--navBar-slider-border: var(--foreground);
/* Buttons */
--button: var(--vscode-button-background);
--button-text: var(--vscode-button-foreground);
--button-hover: var(--vscode-button-hoverBackground);
--button-active: var(--vscode-button-hoverBackground);
--button-disabled: var(--vscode-activityBar-background);
--button-disabled-text: var(--vscode-activityBar-inactiveForeground);
/* Grid Lines */
--grid-dash: 2;
--grid-space: 4;
--grid-line: var(--vscode-editorIndentGuide-background);
--grid-tick: var(--vscode-editorIndentGuide-activeBackground);
/* Cursor */
--cursor: var(--vscode-editorCursor-foreground);
--cursor-ghost: rgba(255, 255, 255, 0.2);
--cursor-width: 2;
/* X-Axis */
--axis-height: 38px;
--axis-line: var(--border);
--axis-background: var(--vscode-sideBar-background);
--axis-foreground: var(--foreground);
/* Signals */
--signal-highlight: var(--vscode-list-inactiveSelectionBackground);
/* Colors */
--accent: var(--vscode-button-background);
--accent-dim: #234175;
--accent-bright: #24c5f7;
--accent-hover: var(--vscode-button-hoverBackground);
--color-red: #ff5252;
--color-pink: #ff4081;
--color-purple: #e040fb;
--color-deepPurple: #7c4dff;
--color-indigo: #536dfe;
--color-blue: #448aff;
--color-lightBlue: #40c4ff;
--color-cyan: #18ffff;
--color-teal: #64ffda;
--color-green: #69f0ae;
--color-lightGreen: #b2ff59;
--color-lime: #eeff41;
--color-yellow: #ffff00;
--color-amber: #ffd740;
--color-orange: #ffab40;
--color-deepOrange: #ff6e40;
/* Settings */
--settings-action-background: var(--background);
}
```

6
news/env.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

24
news/index.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/default-dark.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenMCP News Feature</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
<style>
.openmcp-icon {
display: inline-block;
vertical-align: middle;
background: url('https://kirigaya.cn/openmcp/images/favicon.svg') no-repeat center/contain;
}
</style>

3255
news/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

29
news/package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "news",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build"
},
"dependencies": {
"vanilla-tilt": "^1.8.1",
"vue": "^3.5.17"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.2",
"@types/node": "^22.15.32",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/tsconfig": "^0.7.0",
"npm-run-all2": "^8.0.4",
"typescript": "~5.8.0",
"vite": "^7.0.0",
"vite-plugin-singlefile": "^2.3.0",
"vite-plugin-vue-devtools": "^7.7.7",
"vue-tsc": "^2.2.10"
}
}

View File

@ -0,0 +1,772 @@
:root {
--vscode-foreground: #cccccc;
--vscode-disabledForeground: rgba(204, 204, 204, 0.5);
--vscode-errorForeground: #f48771;
--vscode-descriptionForeground: rgba(204, 204, 204, 0.7);
--vscode-icon-foreground: #c5c5c5;
--vscode-focusBorder: #007fd4;
--vscode-textLink-foreground: #3794ff;
--vscode-textLink-activeForeground: #3794ff;
--vscode-textSeparator-foreground: rgba(255, 255, 255, 0.18);
--vscode-textPreformat-foreground: #d7ba7d;
--vscode-textPreformat-background: rgba(255, 255, 255, 0.1);
--vscode-textBlockQuote-background: #222222;
--vscode-textBlockQuote-border: rgba(0, 122, 204, 0.5);
--vscode-textCodeBlock-background: rgba(10, 10, 10, 0.4);
--vscode-sash-hoverBorder: #007fd4;
--vscode-badge-background: #4d4d4d;
--vscode-badge-foreground: #ffffff;
--vscode-scrollbar-shadow: #000000;
--vscode-scrollbarSlider-background: rgba(121, 121, 121, 0.4);
--vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
--vscode-scrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4);
--vscode-progressBar-background: #0e70c0;
--vscode-editor-background: #1e1e1e;
--vscode-editor-foreground: #d4d4d4;
--vscode-editorStickyScroll-background: #1e1e1e;
--vscode-editorStickyScrollHover-background: #2a2d2e;
--vscode-editorStickyScroll-shadow: #000000;
--vscode-editorWidget-background: #252526;
--vscode-editorWidget-foreground: #cccccc;
--vscode-editorWidget-border: #454545;
--vscode-editorError-foreground: #f14c4c;
--vscode-editorWarning-foreground: #cca700;
--vscode-editorInfo-foreground: #3794ff;
--vscode-editorHint-foreground: rgba(238, 238, 238, 0.7);
--vscode-editorLink-activeForeground: #4e94ce;
--vscode-editor-selectionBackground: #264f78;
--vscode-editor-inactiveSelectionBackground: #3a3d41;
--vscode-editor-selectionHighlightBackground: rgba(173, 214, 255, 0.15);
--vscode-editor-findMatchBackground: #515c6a;
--vscode-editor-findMatchHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-editor-findRangeHighlightBackground: rgba(58, 61, 65, 0.4);
--vscode-editor-hoverHighlightBackground: rgba(38, 79, 120, 0.25);
--vscode-editorHoverWidget-background: #252526;
--vscode-editorHoverWidget-foreground: #cccccc;
--vscode-editorHoverWidget-border: #454545;
--vscode-editorHoverWidget-statusBarBackground: #2c2c2d;
--vscode-editorInlayHint-foreground: #969696;
--vscode-editorInlayHint-background: rgba(77, 77, 77, 0.1);
--vscode-editorInlayHint-typeForeground: #969696;
--vscode-editorInlayHint-typeBackground: rgba(77, 77, 77, 0.1);
--vscode-editorInlayHint-parameterForeground: #969696;
--vscode-editorInlayHint-parameterBackground: rgba(77, 77, 77, 0.1);
--vscode-editorLightBulb-foreground: #ffcc00;
--vscode-editorLightBulbAutoFix-foreground: #75beff;
--vscode-editorLightBulbAi-foreground: #ffcc00;
--vscode-editor-snippetTabstopHighlightBackground: rgba(124, 124, 124, 0.3);
--vscode-editor-snippetFinalTabstopHighlightBorder: #525252;
--vscode-diffEditor-insertedTextBackground: rgba(156, 204, 44, 0.2);
--vscode-diffEditor-removedTextBackground: rgba(255, 0, 0, 0.2);
--vscode-diffEditor-insertedLineBackground: rgba(155, 185, 85, 0.2);
--vscode-diffEditor-removedLineBackground: rgba(255, 0, 0, 0.2);
--vscode-diffEditor-diagonalFill: rgba(204, 204, 204, 0.2);
--vscode-diffEditor-unchangedRegionBackground: #252526;
--vscode-diffEditor-unchangedRegionForeground: #cccccc;
--vscode-diffEditor-unchangedCodeBackground: rgba(116, 116, 116, 0.16);
--vscode-widget-shadow: rgba(0, 0, 0, 0.36);
--vscode-widget-border: #303031;
--vscode-toolbar-hoverBackground: rgba(90, 93, 94, 0.31);
--vscode-toolbar-activeBackground: rgba(99, 102, 103, 0.31);
--vscode-breadcrumb-foreground: rgba(204, 204, 204, 0.8);
--vscode-breadcrumb-background: #1e1e1e;
--vscode-breadcrumb-focusForeground: #e0e0e0;
--vscode-breadcrumb-activeSelectionForeground: #e0e0e0;
--vscode-breadcrumbPicker-background: #252526;
--vscode-merge-currentHeaderBackground: rgba(64, 200, 174, 0.5);
--vscode-merge-currentContentBackground: rgba(64, 200, 174, 0.2);
--vscode-merge-incomingHeaderBackground: rgba(64, 166, 255, 0.5);
--vscode-merge-incomingContentBackground: rgba(64, 166, 255, 0.2);
--vscode-merge-commonHeaderBackground: rgba(96, 96, 96, 0.4);
--vscode-merge-commonContentBackground: rgba(96, 96, 96, 0.16);
--vscode-editorOverviewRuler-currentContentForeground: rgba(64, 200, 174, 0.5);
--vscode-editorOverviewRuler-incomingContentForeground: rgba(64, 166, 255, 0.5);
--vscode-editorOverviewRuler-commonContentForeground: rgba(96, 96, 96, 0.4);
--vscode-editorOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49);
--vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8);
--vscode-problemsErrorIcon-foreground: #f14c4c;
--vscode-problemsWarningIcon-foreground: #cca700;
--vscode-problemsInfoIcon-foreground: #3794ff;
--vscode-minimap-findMatchHighlight: #d18616;
--vscode-minimap-selectionOccurrenceHighlight: #676767;
--vscode-minimap-selectionHighlight: #264f78;
--vscode-minimap-infoHighlight: #3794ff;
--vscode-minimap-warningHighlight: #cca700;
--vscode-minimap-errorHighlight: rgba(255, 18, 18, 0.7);
--vscode-minimap-foregroundOpacity: #000000;
--vscode-minimapSlider-background: rgba(121, 121, 121, 0.2);
--vscode-minimapSlider-hoverBackground: rgba(100, 100, 100, 0.35);
--vscode-minimapSlider-activeBackground: rgba(191, 191, 191, 0.2);
--vscode-charts-foreground: #cccccc;
--vscode-charts-lines: rgba(204, 204, 204, 0.5);
--vscode-charts-red: #f14c4c;
--vscode-charts-blue: #3794ff;
--vscode-charts-yellow: #cca700;
--vscode-charts-orange: #d18616;
--vscode-charts-green: #89d185;
--vscode-charts-purple: #b180d7;
--vscode-input-background: #3c3c3c;
--vscode-input-foreground: #cccccc;
--vscode-inputOption-activeBorder: #007acc;
--vscode-inputOption-hoverBackground: rgba(90, 93, 94, 0.5);
--vscode-inputOption-activeBackground: rgba(0, 127, 212, 0.4);
--vscode-inputOption-activeForeground: #ffffff;
--vscode-input-placeholderForeground: #a6a6a6;
--vscode-inputValidation-infoBackground: #063b49;
--vscode-inputValidation-infoBorder: #007acc;
--vscode-inputValidation-warningBackground: #352a05;
--vscode-inputValidation-warningBorder: #b89500;
--vscode-inputValidation-errorBackground: #5a1d1d;
--vscode-inputValidation-errorBorder: #be1100;
--vscode-dropdown-background: #3c3c3c;
--vscode-dropdown-foreground: #f0f0f0;
--vscode-dropdown-border: #3c3c3c;
--vscode-button-foreground: #ffffff;
--vscode-button-separator: rgba(255, 255, 255, 0.4);
--vscode-button-background: #0e639c;
--vscode-button-hoverBackground: #1177bb;
--vscode-button-secondaryForeground: #ffffff;
--vscode-button-secondaryBackground: #3a3d41;
--vscode-button-secondaryHoverBackground: #45494e;
--vscode-radio-activeForeground: #ffffff;
--vscode-radio-activeBackground: rgba(0, 127, 212, 0.4);
--vscode-radio-activeBorder: #007acc;
--vscode-radio-inactiveBorder: rgba(255, 255, 255, 0.2);
--vscode-radio-inactiveHoverBackground: rgba(90, 93, 94, 0.5);
--vscode-checkbox-background: #3c3c3c;
--vscode-checkbox-selectBackground: #252526;
--vscode-checkbox-foreground: #f0f0f0;
--vscode-checkbox-border: #6b6b6b;
--vscode-checkbox-selectBorder: #c5c5c5;
--vscode-keybindingLabel-background: rgba(128, 128, 128, 0.17);
--vscode-keybindingLabel-foreground: #cccccc;
--vscode-keybindingLabel-border: rgba(51, 51, 51, 0.6);
--vscode-keybindingLabel-bottomBorder: rgba(68, 68, 68, 0.6);
--vscode-list-focusOutline: #007fd4;
--vscode-list-activeSelectionBackground: #04395e;
--vscode-list-activeSelectionForeground: #ffffff;
--vscode-list-activeSelectionIconForeground: #ffffff;
--vscode-list-inactiveSelectionBackground: #37373d;
--vscode-list-hoverBackground: #2a2d2e;
--vscode-list-dropBackground: #383b3d;
--vscode-list-dropBetweenBackground: #c5c5c5;
--vscode-list-highlightForeground: #2aaaff;
--vscode-list-focusHighlightForeground: #2aaaff;
--vscode-list-invalidItemForeground: #b89500;
--vscode-list-errorForeground: #f88070;
--vscode-list-warningForeground: #cca700;
--vscode-listFilterWidget-background: #252526;
--vscode-listFilterWidget-outline: rgba(0, 0, 0, 0);
--vscode-listFilterWidget-noMatchesOutline: #be1100;
--vscode-listFilterWidget-shadow: rgba(0, 0, 0, 0.36);
--vscode-list-filterMatchBackground: rgba(234, 92, 0, 0.33);
--vscode-list-deemphasizedForeground: #8c8c8c;
--vscode-tree-indentGuidesStroke: #585858;
--vscode-tree-inactiveIndentGuidesStroke: rgba(88, 88, 88, 0.4);
--vscode-tree-tableColumnsBorder: rgba(204, 204, 204, 0.13);
--vscode-tree-tableOddRowsBackground: rgba(204, 204, 204, 0.04);
--vscode-editorActionList-background: #252526;
--vscode-editorActionList-foreground: #cccccc;
--vscode-editorActionList-focusForeground: #ffffff;
--vscode-editorActionList-focusBackground: #04395e;
--vscode-menu-border: #454545;
--vscode-menu-foreground: #cccccc;
--vscode-menu-background: #252526;
--vscode-menu-selectionForeground: #ffffff;
--vscode-menu-selectionBackground: #0078d4;
--vscode-menu-separatorBackground: #454545;
--vscode-quickInput-background: #252526;
--vscode-quickInput-foreground: #cccccc;
--vscode-quickInputTitle-background: rgba(255, 255, 255, 0.1);
--vscode-pickerGroup-foreground: #3794ff;
--vscode-pickerGroup-border: #3f3f46;
--vscode-quickInputList-focusForeground: #ffffff;
--vscode-quickInputList-focusIconForeground: #ffffff;
--vscode-quickInputList-focusBackground: #04395e;
--vscode-search-resultsInfoForeground: rgba(204, 204, 204, 0.65);
--vscode-searchEditor-findMatchBackground: rgba(234, 92, 0, 0.22);
--vscode-editor-lineHighlightBorder: #282828;
--vscode-editor-rangeHighlightBackground: rgba(255, 255, 255, 0.04);
--vscode-editor-symbolHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-editorCursor-foreground: #aeafad;
--vscode-editorMultiCursor-primary-foreground: #aeafad;
--vscode-editorMultiCursor-secondary-foreground: #aeafad;
--vscode-editorWhitespace-foreground: rgba(227, 228, 226, 0.16);
--vscode-editorLineNumber-foreground: #858585;
--vscode-editorIndentGuide-background: rgba(227, 228, 226, 0.16);
--vscode-editorIndentGuide-activeBackground: rgba(227, 228, 226, 0.16);
--vscode-editorIndentGuide-background1: #404040;
--vscode-editorIndentGuide-background2: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-background3: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-background4: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-background5: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-background6: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-activeBackground1: #707070;
--vscode-editorIndentGuide-activeBackground2: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-activeBackground3: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-activeBackground4: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-activeBackground5: rgba(0, 0, 0, 0);
--vscode-editorIndentGuide-activeBackground6: rgba(0, 0, 0, 0);
--vscode-editorActiveLineNumber-foreground: #c6c6c6;
--vscode-editorLineNumber-activeForeground: #c6c6c6;
--vscode-editorRuler-foreground: #5a5a5a;
--vscode-editorCodeLens-foreground: #999999;
--vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1);
--vscode-editorBracketMatch-border: #888888;
--vscode-editorOverviewRuler-border: rgba(127, 127, 127, 0.3);
--vscode-editorGutter-background: #1e1e1e;
--vscode-editorUnnecessaryCode-opacity: rgba(0, 0, 0, 0.67);
--vscode-editorGhostText-foreground: rgba(255, 255, 255, 0.34);
--vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6);
--vscode-editorOverviewRuler-errorForeground: rgba(255, 18, 18, 0.7);
--vscode-editorOverviewRuler-warningForeground: #cca700;
--vscode-editorOverviewRuler-infoForeground: #3794ff;
--vscode-editorBracketHighlight-foreground1: #ffd700;
--vscode-editorBracketHighlight-foreground2: #da70d6;
--vscode-editorBracketHighlight-foreground3: #179fff;
--vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-unexpectedBracket-foreground: rgba(255, 18, 18, 0.8);
--vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0);
--vscode-editorUnicodeHighlight-border: #cca700;
--vscode-diffEditor-move-border: rgba(139, 139, 139, 0.61);
--vscode-diffEditor-moveActive-border: #ffa500;
--vscode-diffEditor-unchangedRegionShadow: #000000;
--vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0;
--vscode-symbolIcon-arrayForeground: #cccccc;
--vscode-symbolIcon-booleanForeground: #cccccc;
--vscode-symbolIcon-classForeground: #ee9d28;
--vscode-symbolIcon-colorForeground: #cccccc;
--vscode-symbolIcon-constantForeground: #cccccc;
--vscode-symbolIcon-constructorForeground: #b180d7;
--vscode-symbolIcon-enumeratorForeground: #ee9d28;
--vscode-symbolIcon-enumeratorMemberForeground: #75beff;
--vscode-symbolIcon-eventForeground: #ee9d28;
--vscode-symbolIcon-fieldForeground: #75beff;
--vscode-symbolIcon-fileForeground: #cccccc;
--vscode-symbolIcon-folderForeground: #cccccc;
--vscode-symbolIcon-functionForeground: #b180d7;
--vscode-symbolIcon-interfaceForeground: #75beff;
--vscode-symbolIcon-keyForeground: #cccccc;
--vscode-symbolIcon-keywordForeground: #cccccc;
--vscode-symbolIcon-methodForeground: #b180d7;
--vscode-symbolIcon-moduleForeground: #cccccc;
--vscode-symbolIcon-namespaceForeground: #cccccc;
--vscode-symbolIcon-nullForeground: #cccccc;
--vscode-symbolIcon-numberForeground: #cccccc;
--vscode-symbolIcon-objectForeground: #cccccc;
--vscode-symbolIcon-operatorForeground: #cccccc;
--vscode-symbolIcon-packageForeground: #cccccc;
--vscode-symbolIcon-propertyForeground: #cccccc;
--vscode-symbolIcon-referenceForeground: #cccccc;
--vscode-symbolIcon-snippetForeground: #cccccc;
--vscode-symbolIcon-stringForeground: #cccccc;
--vscode-symbolIcon-structForeground: #cccccc;
--vscode-symbolIcon-textForeground: #cccccc;
--vscode-symbolIcon-typeParameterForeground: #cccccc;
--vscode-symbolIcon-unitForeground: #cccccc;
--vscode-symbolIcon-variableForeground: #75beff;
--vscode-actionBar-toggledBackground: #383a49;
--vscode-peekViewTitle-background: #252526;
--vscode-peekViewTitleLabel-foreground: #ffffff;
--vscode-peekViewTitleDescription-foreground: rgba(204, 204, 204, 0.7);
--vscode-peekView-border: #3794ff;
--vscode-peekViewResult-background: #252526;
--vscode-peekViewResult-lineForeground: #bbbbbb;
--vscode-peekViewResult-fileForeground: #ffffff;
--vscode-peekViewResult-selectionBackground: rgba(51, 153, 255, 0.2);
--vscode-peekViewResult-selectionForeground: #ffffff;
--vscode-peekViewEditor-background: #001f33;
--vscode-peekViewEditorGutter-background: #001f33;
--vscode-peekViewEditorStickyScroll-background: #001f33;
--vscode-peekViewResult-matchHighlightBackground: rgba(234, 92, 0, 0.3);
--vscode-peekViewEditor-matchHighlightBackground: rgba(255, 143, 0, 0.6);
--vscode-editor-foldBackground: rgba(38, 79, 120, 0.3);
--vscode-editor-foldPlaceholderForeground: #808080;
--vscode-editorGutter-foldingControlForeground: #c5c5c5;
--vscode-editorSuggestWidget-background: #252526;
--vscode-editorSuggestWidget-border: #454545;
--vscode-editorSuggestWidget-foreground: #d4d4d4;
--vscode-editorSuggestWidget-selectedForeground: #ffffff;
--vscode-editorSuggestWidget-selectedIconForeground: #ffffff;
--vscode-editorSuggestWidget-selectedBackground: #04395e;
--vscode-editorSuggestWidget-highlightForeground: #2aaaff;
--vscode-editorSuggestWidget-focusHighlightForeground: #2aaaff;
--vscode-editorSuggestWidgetStatus-foreground: rgba(212, 212, 212, 0.5);
--vscode-editorMarkerNavigationError-background: #f14c4c;
--vscode-editorMarkerNavigationError-headerBackground: rgba(241, 76, 76, 0.1);
--vscode-editorMarkerNavigationWarning-background: #cca700;
--vscode-editorMarkerNavigationWarning-headerBackground: rgba(204, 167, 0, 0.1);
--vscode-editorMarkerNavigationInfo-background: #3794ff;
--vscode-editorMarkerNavigationInfo-headerBackground: rgba(55, 148, 255, 0.1);
--vscode-editorMarkerNavigation-background: #1e1e1e;
--vscode-editor-linkedEditingBackground: rgba(255, 0, 0, 0.3);
--vscode-editor-wordHighlightBackground: rgba(87, 87, 87, 0.72);
--vscode-editor-wordHighlightStrongBackground: rgba(0, 73, 114, 0.72);
--vscode-editor-wordHighlightTextBackground: rgba(87, 87, 87, 0.72);
--vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8);
--vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8);
--vscode-editorOverviewRuler-wordHighlightTextForeground: rgba(160, 160, 160, 0.8);
--vscode-editorHoverWidget-highlightForeground: #2aaaff;
--vscode-editor-placeholder-foreground: rgba(255, 255, 255, 0.34);
--vscode-tab-activeBackground: #1e1e1e;
--vscode-tab-unfocusedActiveBackground: #1e1e1e;
--vscode-tab-inactiveBackground: #2d2d2d;
--vscode-tab-unfocusedInactiveBackground: #2d2d2d;
--vscode-tab-activeForeground: #ffffff;
--vscode-tab-inactiveForeground: rgba(255, 255, 255, 0.5);
--vscode-tab-unfocusedActiveForeground: rgba(255, 255, 255, 0.5);
--vscode-tab-unfocusedInactiveForeground: rgba(255, 255, 255, 0.25);
--vscode-tab-border: #252526;
--vscode-tab-lastPinnedBorder: rgba(204, 204, 204, 0.2);
--vscode-tab-selectedBackground: #222222;
--vscode-tab-selectedForeground: rgba(255, 255, 255, 0.63);
--vscode-tab-dragAndDropBorder: #ffffff;
--vscode-tab-activeModifiedBorder: #3399cc;
--vscode-tab-inactiveModifiedBorder: rgba(51, 153, 204, 0.5);
--vscode-tab-unfocusedActiveModifiedBorder: rgba(51, 153, 204, 0.5);
--vscode-tab-unfocusedInactiveModifiedBorder: rgba(51, 153, 204, 0.25);
--vscode-editorPane-background: #1e1e1e;
--vscode-editorGroupHeader-tabsBackground: #252526;
--vscode-editorGroupHeader-noTabsBackground: #1e1e1e;
--vscode-editorGroup-border: #444444;
--vscode-editorGroup-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-editorGroup-dropIntoPromptForeground: #cccccc;
--vscode-editorGroup-dropIntoPromptBackground: #252526;
--vscode-sideBySideEditor-horizontalBorder: #444444;
--vscode-sideBySideEditor-verticalBorder: #444444;
--vscode-panel-background: #1e1e1e;
--vscode-panel-border: rgba(128, 128, 128, 0.35);
--vscode-panelTitle-activeForeground: #e7e7e7;
--vscode-panelTitle-inactiveForeground: rgba(231, 231, 231, 0.6);
--vscode-panelTitle-activeBorder: #e7e7e7;
--vscode-panel-dropBorder: #e7e7e7;
--vscode-panelSection-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-panelSectionHeader-background: rgba(128, 128, 128, 0.2);
--vscode-panelSection-border: rgba(128, 128, 128, 0.35);
--vscode-panelStickyScroll-background: #1e1e1e;
--vscode-panelStickyScroll-shadow: #000000;
--vscode-banner-background: #04395e;
--vscode-banner-foreground: #ffffff;
--vscode-banner-iconForeground: #3794ff;
--vscode-statusBar-foreground: #ffffff;
--vscode-statusBar-noFolderForeground: #ffffff;
--vscode-statusBar-background: #007acc;
--vscode-statusBar-noFolderBackground: #68217a;
--vscode-statusBar-focusBorder: #ffffff;
--vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18);
--vscode-statusBarItem-focusBorder: #ffffff;
--vscode-statusBarItem-hoverBackground: rgba(255, 255, 255, 0.12);
--vscode-statusBarItem-hoverForeground: #ffffff;
--vscode-statusBarItem-compactHoverBackground: rgba(255, 255, 255, 0.2);
--vscode-statusBarItem-prominentForeground: #ffffff;
--vscode-statusBarItem-prominentBackground: rgba(0, 0, 0, 0.5);
--vscode-statusBarItem-prominentHoverForeground: #ffffff;
--vscode-statusBarItem-prominentHoverBackground: rgba(0, 0, 0, 0.3);
--vscode-statusBarItem-errorBackground: #c72e0f;
--vscode-statusBarItem-errorForeground: #ffffff;
--vscode-statusBarItem-errorHoverForeground: #ffffff;
--vscode-statusBarItem-errorHoverBackground: rgba(255, 255, 255, 0.12);
--vscode-statusBarItem-warningBackground: #7a6400;
--vscode-statusBarItem-warningForeground: #ffffff;
--vscode-statusBarItem-warningHoverForeground: #ffffff;
--vscode-statusBarItem-warningHoverBackground: rgba(255, 255, 255, 0.12);
--vscode-activityBar-background: #333333;
--vscode-activityBar-foreground: #ffffff;
--vscode-activityBar-inactiveForeground: rgba(255, 255, 255, 0.4);
--vscode-activityBar-activeBorder: #ffffff;
--vscode-activityBar-dropBorder: #ffffff;
--vscode-activityBarBadge-background: #007acc;
--vscode-activityBarBadge-foreground: #ffffff;
--vscode-activityBarTop-foreground: #e7e7e7;
--vscode-activityBarTop-activeBorder: #e7e7e7;
--vscode-activityBarTop-inactiveForeground: rgba(231, 231, 231, 0.6);
--vscode-activityBarTop-dropBorder: #e7e7e7;
--vscode-profileBadge-background: #4d4d4d;
--vscode-profileBadge-foreground: #ffffff;
--vscode-statusBarItem-remoteBackground: #16825d;
--vscode-statusBarItem-remoteForeground: #ffffff;
--vscode-statusBarItem-remoteHoverForeground: #ffffff;
--vscode-statusBarItem-remoteHoverBackground: rgba(255, 255, 255, 0.12);
--vscode-statusBarItem-offlineBackground: #6c1717;
--vscode-statusBarItem-offlineForeground: #ffffff;
--vscode-statusBarItem-offlineHoverForeground: #ffffff;
--vscode-statusBarItem-offlineHoverBackground: rgba(255, 255, 255, 0.12);
--vscode-extensionBadge-remoteBackground: #007acc;
--vscode-extensionBadge-remoteForeground: #ffffff;
--vscode-sideBar-background: #252526;
--vscode-sideBarTitle-background: #252526;
--vscode-sideBarTitle-foreground: #bbbbbb;
--vscode-sideBar-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-sideBarSectionHeader-background: rgba(0, 0, 0, 0);
--vscode-sideBarSectionHeader-border: rgba(204, 204, 204, 0.2);
--vscode-sideBarActivityBarTop-border: rgba(204, 204, 204, 0.2);
--vscode-sideBarStickyScroll-background: #252526;
--vscode-sideBarStickyScroll-shadow: #000000;
--vscode-titleBar-activeForeground: #cccccc;
--vscode-titleBar-inactiveForeground: rgba(204, 204, 204, 0.6);
--vscode-titleBar-activeBackground: #3c3c3c;
--vscode-titleBar-inactiveBackground: rgba(60, 60, 60, 0.6);
--vscode-menubar-selectionForeground: #cccccc;
--vscode-menubar-selectionBackground: rgba(90, 93, 94, 0.31);
--vscode-commandCenter-foreground: #cccccc;
--vscode-commandCenter-activeForeground: #cccccc;
--vscode-commandCenter-inactiveForeground: rgba(204, 204, 204, 0.6);
--vscode-commandCenter-background: rgba(255, 255, 255, 0.05);
--vscode-commandCenter-activeBackground: rgba(255, 255, 255, 0.08);
--vscode-commandCenter-border: rgba(204, 204, 204, 0.2);
--vscode-commandCenter-activeBorder: rgba(204, 204, 204, 0.3);
--vscode-commandCenter-inactiveBorder: rgba(204, 204, 204, 0.15);
--vscode-notificationCenter-border: #303031;
--vscode-notificationToast-border: #303031;
--vscode-notifications-foreground: #cccccc;
--vscode-notifications-background: #252526;
--vscode-notificationLink-foreground: #3794ff;
--vscode-notificationCenterHeader-background: #303031;
--vscode-notifications-border: #303031;
--vscode-notificationsErrorIcon-foreground: #f14c4c;
--vscode-notificationsWarningIcon-foreground: #cca700;
--vscode-notificationsInfoIcon-foreground: #3794ff;
--vscode-inlineChat-foreground: #cccccc;
--vscode-inlineChat-background: #252526;
--vscode-inlineChat-border: #454545;
--vscode-inlineChat-shadow: rgba(0, 0, 0, 0.36);
--vscode-inlineChatInput-border: #454545;
--vscode-inlineChatInput-focusBorder: #007fd4;
--vscode-inlineChatInput-placeholderForeground: #a6a6a6;
--vscode-inlineChatInput-background: #3c3c3c;
--vscode-inlineChatDiff-inserted: rgba(156, 204, 44, 0.1);
--vscode-editorOverviewRuler-inlineChatInserted: rgba(156, 204, 44, 0.12);
--vscode-inlineChatDiff-removed: rgba(255, 0, 0, 0.1);
--vscode-editorOverviewRuler-inlineChatRemoved: rgba(255, 0, 0, 0.12);
--vscode-extensionButton-background: #0e639c;
--vscode-extensionButton-foreground: #ffffff;
--vscode-extensionButton-hoverBackground: #1177bb;
--vscode-extensionButton-separator: rgba(255, 255, 255, 0.4);
--vscode-extensionButton-prominentBackground: #0e639c;
--vscode-extensionButton-prominentForeground: #ffffff;
--vscode-extensionButton-prominentHoverBackground: #1177bb;
--vscode-chat-requestBorder: rgba(255, 255, 255, 0.1);
--vscode-chat-requestBackground: rgba(30, 30, 30, 0.62);
--vscode-chat-slashCommandBackground: rgba(52, 65, 75, 0.56);
--vscode-chat-slashCommandForeground: #40a6ff;
--vscode-chat-avatarBackground: #1f1f1f;
--vscode-chat-avatarForeground: #cccccc;
--vscode-terminal-foreground: #cccccc;
--vscode-terminal-selectionBackground: #264f78;
--vscode-terminal-inactiveSelectionBackground: #3a3d41;
--vscode-terminalCommandDecoration-defaultBackground: rgba(255, 255, 255, 0.25);
--vscode-terminalCommandDecoration-successBackground: #1b81a8;
--vscode-terminalCommandDecoration-errorBackground: #f14c4c;
--vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8);
--vscode-terminal-border: rgba(128, 128, 128, 0.35);
--vscode-terminalOverviewRuler-border: rgba(127, 127, 127, 0.3);
--vscode-terminal-findMatchBackground: #515c6a;
--vscode-terminal-hoverHighlightBackground: rgba(38, 79, 120, 0.13);
--vscode-terminal-findMatchHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-terminalOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49);
--vscode-terminal-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-terminal-initialHintForeground: rgba(255, 255, 255, 0.34);
--vscode-terminalStickyScrollHover-background: #2a2d2e;
--vscode-scmGraph-historyItemRefColor: #3794ff;
--vscode-scmGraph-historyItemRemoteRefColor: #b180d7;
--vscode-scmGraph-historyItemBaseRefColor: #ea5c00;
--vscode-scmGraph-historyItemHoverDefaultLabelForeground: #cccccc;
--vscode-scmGraph-historyItemHoverDefaultLabelBackground: #4d4d4d;
--vscode-scmGraph-historyItemHoverLabelForeground: #ffffff;
--vscode-scmGraph-historyItemHoverAdditionsForeground: #81b88b;
--vscode-scmGraph-historyItemHoverDeletionsForeground: #c74e39;
--vscode-scmGraph-foreground1: #ffb000;
--vscode-scmGraph-foreground2: #dc267f;
--vscode-scmGraph-foreground3: #994f00;
--vscode-scmGraph-foreground4: #40b0a6;
--vscode-scmGraph-foreground5: #b66dff;
--vscode-commentsView-resolvedIcon: rgba(204, 204, 204, 0.5);
--vscode-commentsView-unresolvedIcon: #007fd4;
--vscode-editorCommentsWidget-replyInputBackground: #252526;
--vscode-editorCommentsWidget-resolvedBorder: rgba(204, 204, 204, 0.5);
--vscode-editorCommentsWidget-unresolvedBorder: #007fd4;
--vscode-editorCommentsWidget-rangeBackground: rgba(0, 127, 212, 0.1);
--vscode-editorCommentsWidget-rangeActiveBackground: rgba(0, 127, 212, 0.1);
--vscode-editorGutter-commentRangeForeground: #37373d;
--vscode-editorOverviewRuler-commentForeground: #37373d;
--vscode-editorOverviewRuler-commentUnresolvedForeground: #37373d;
--vscode-editorGutter-commentGlyphForeground: #d4d4d4;
--vscode-editorGutter-commentUnresolvedGlyphForeground: #d4d4d4;
--vscode-activityWarningBadge-foreground: #000000;
--vscode-activityWarningBadge-background: #cca700;
--vscode-activityErrorBadge-foreground: #000000;
--vscode-activityErrorBadge-background: #f14c4c;
--vscode-ports-iconRunningProcessForeground: #369432;
--vscode-editorWatermark-foreground: rgba(212, 212, 212, 0.6);
--vscode-settings-headerForeground: #e7e7e7;
--vscode-settings-settingsHeaderHoverForeground: rgba(231, 231, 231, 0.7);
--vscode-settings-modifiedItemIndicator: #0c7d9d;
--vscode-settings-headerBorder: rgba(128, 128, 128, 0.35);
--vscode-settings-sashBorder: rgba(128, 128, 128, 0.35);
--vscode-settings-dropdownBackground: #3c3c3c;
--vscode-settings-dropdownForeground: #f0f0f0;
--vscode-settings-dropdownBorder: #3c3c3c;
--vscode-settings-dropdownListBorder: #454545;
--vscode-settings-checkboxBackground: #3c3c3c;
--vscode-settings-checkboxForeground: #f0f0f0;
--vscode-settings-checkboxBorder: #6b6b6b;
--vscode-settings-textInputBackground: #3c3c3c;
--vscode-settings-textInputForeground: #cccccc;
--vscode-settings-numberInputBackground: #3c3c3c;
--vscode-settings-numberInputForeground: #cccccc;
--vscode-settings-focusedRowBackground: rgba(42, 45, 46, 0.6);
--vscode-settings-rowHoverBackground: rgba(42, 45, 46, 0.3);
--vscode-settings-focusedRowBorder: #007fd4;
--vscode-keybindingTable-headerBackground: rgba(204, 204, 204, 0.04);
--vscode-keybindingTable-rowsBackground: rgba(204, 204, 204, 0.04);
--vscode-debugToolBar-background: #333333;
--vscode-debugIcon-startForeground: #89d185;
--vscode-notebook-cellBorderColor: #37373d;
--vscode-notebook-focusedEditorBorder: #007fd4;
--vscode-notebookStatusSuccessIcon-foreground: #89d185;
--vscode-notebookEditorOverviewRuler-runningCellForeground: #89d185;
--vscode-notebookStatusErrorIcon-foreground: #f48771;
--vscode-notebookStatusRunningIcon-foreground: #cccccc;
--vscode-notebook-cellToolbarSeparator: rgba(128, 128, 128, 0.35);
--vscode-notebook-selectedCellBackground: #37373d;
--vscode-notebook-selectedCellBorder: #37373d;
--vscode-notebook-focusedCellBorder: #007fd4;
--vscode-notebook-inactiveFocusedCellBorder: #37373d;
--vscode-notebook-cellStatusBarItemHoverBackground: rgba(255, 255, 255, 0.15);
--vscode-notebook-cellInsertionIndicator: #007fd4;
--vscode-notebookScrollbarSlider-background: rgba(121, 121, 121, 0.4);
--vscode-notebookScrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
--vscode-notebookScrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4);
--vscode-notebook-symbolHighlightBackground: rgba(255, 255, 255, 0.04);
--vscode-notebook-cellEditorBackground: #252526;
--vscode-notebook-editorBackground: #1e1e1e;
--vscode-debugIcon-breakpointForeground: #e51400;
--vscode-debugIcon-breakpointDisabledForeground: #848484;
--vscode-debugIcon-breakpointUnverifiedForeground: #848484;
--vscode-debugIcon-breakpointCurrentStackframeForeground: #ffcc00;
--vscode-debugIcon-breakpointStackframeForeground: #89d185;
--vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 0, 0.2);
--vscode-editor-focusedStackFrameHighlightBackground: rgba(122, 189, 122, 0.3);
--vscode-multiDiffEditor-headerBackground: #262626;
--vscode-multiDiffEditor-background: #1e1e1e;
--vscode-multiDiffEditor-border: rgba(204, 204, 204, 0.2);
--vscode-interactive-activeCodeBorder: #007acc;
--vscode-interactive-inactiveCodeBorder: #37373d;
--vscode-testing-iconFailed: #f14c4c;
--vscode-testing-iconErrored: #f14c4c;
--vscode-testing-iconPassed: #73c991;
--vscode-testing-runAction: #73c991;
--vscode-testing-iconQueued: #cca700;
--vscode-testing-iconUnset: #848484;
--vscode-testing-iconSkipped: #848484;
--vscode-testing-peekBorder: #f14c4c;
--vscode-testing-messagePeekBorder: #3794ff;
--vscode-testing-peekHeaderBackground: rgba(241, 76, 76, 0.1);
--vscode-testing-messagePeekHeaderBackground: rgba(55, 148, 255, 0.1);
--vscode-testing-coveredBackground: rgba(156, 204, 44, 0.2);
--vscode-testing-coveredBorder: rgba(156, 204, 44, 0.15);
--vscode-testing-coveredGutterBackground: rgba(156, 204, 44, 0.12);
--vscode-testing-uncoveredBranchBackground: #781212;
--vscode-testing-uncoveredBackground: rgba(255, 0, 0, 0.2);
--vscode-testing-uncoveredBorder: rgba(255, 0, 0, 0.15);
--vscode-testing-uncoveredGutterBackground: rgba(255, 0, 0, 0.3);
--vscode-testing-coverCountBadgeBackground: #4d4d4d;
--vscode-testing-coverCountBadgeForeground: #ffffff;
--vscode-testing-message-error-decorationForeground: #f14c4c;
--vscode-testing-message-error-lineBackground: rgba(255, 0, 0, 0.1);
--vscode-testing-message-info-decorationForeground: rgba(212, 212, 212, 0.5);
--vscode-testing-iconErrored-retired: rgba(241, 76, 76, 0.7);
--vscode-testing-iconFailed-retired: rgba(241, 76, 76, 0.7);
--vscode-testing-iconPassed-retired: rgba(115, 201, 145, 0.7);
--vscode-testing-iconQueued-retired: rgba(204, 167, 0, 0.7);
--vscode-testing-iconUnset-retired: rgba(132, 132, 132, 0.7);
--vscode-testing-iconSkipped-retired: rgba(132, 132, 132, 0.7);
--vscode-editorGutter-modifiedBackground: #1b81a8;
--vscode-editorGutter-addedBackground: #487e02;
--vscode-editorGutter-deletedBackground: #f14c4c;
--vscode-minimapGutter-modifiedBackground: #1b81a8;
--vscode-minimapGutter-addedBackground: #487e02;
--vscode-minimapGutter-deletedBackground: #f14c4c;
--vscode-editorOverviewRuler-modifiedForeground: rgba(27, 129, 168, 0.6);
--vscode-editorOverviewRuler-addedForeground: rgba(72, 126, 2, 0.6);
--vscode-editorOverviewRuler-deletedForeground: rgba(241, 76, 76, 0.6);
--vscode-debugExceptionWidget-border: #a31515;
--vscode-debugExceptionWidget-background: #420b0d;
--vscode-editor-inlineValuesForeground: rgba(255, 255, 255, 0.5);
--vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2);
--vscode-statusBar-debuggingBackground: #cc6633;
--vscode-statusBar-debuggingForeground: #ffffff;
--vscode-commandCenter-debuggingBackground: rgba(204, 102, 51, 0.26);
--vscode-debugTokenExpression-name: #c586c0;
--vscode-debugTokenExpression-type: #4a90e2;
--vscode-debugTokenExpression-value: rgba(204, 204, 204, 0.6);
--vscode-debugTokenExpression-string: #ce9178;
--vscode-debugTokenExpression-boolean: #4e94ce;
--vscode-debugTokenExpression-number: #b5cea8;
--vscode-debugTokenExpression-error: #f48771;
--vscode-debugView-exceptionLabelForeground: #cccccc;
--vscode-debugView-exceptionLabelBackground: #6c2022;
--vscode-debugView-stateLabelForeground: #cccccc;
--vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27);
--vscode-debugView-valueChangedHighlight: #569cd6;
--vscode-debugConsole-infoForeground: #3794ff;
--vscode-debugConsole-warningForeground: #cca700;
--vscode-debugConsole-errorForeground: #f48771;
--vscode-debugConsole-sourceForeground: #cccccc;
--vscode-debugConsoleInputIcon-foreground: #cccccc;
--vscode-debugIcon-pauseForeground: #75beff;
--vscode-debugIcon-stopForeground: #f48771;
--vscode-debugIcon-disconnectForeground: #f48771;
--vscode-debugIcon-restartForeground: #89d185;
--vscode-debugIcon-stepOverForeground: #75beff;
--vscode-debugIcon-stepIntoForeground: #75beff;
--vscode-debugIcon-stepOutForeground: #75beff;
--vscode-debugIcon-continueForeground: #75beff;
--vscode-debugIcon-stepBackForeground: #75beff;
--vscode-mergeEditor-change-background: rgba(155, 185, 85, 0.2);
--vscode-mergeEditor-change-word-background: rgba(156, 204, 44, 0.2);
--vscode-mergeEditor-changeBase-background: #4b1818;
--vscode-mergeEditor-changeBase-word-background: #6f1313;
--vscode-mergeEditor-conflict-unhandledUnfocused-border: rgba(255, 166, 0, 0.48);
--vscode-mergeEditor-conflict-unhandledFocused-border: #ffa600;
--vscode-mergeEditor-conflict-handledUnfocused-border: rgba(134, 134, 134, 0.29);
--vscode-mergeEditor-conflict-handledFocused-border: rgba(193, 193, 193, 0.8);
--vscode-mergeEditor-conflict-handled-minimapOverViewRuler: rgba(173, 172, 168, 0.93);
--vscode-mergeEditor-conflict-unhandled-minimapOverViewRuler: #fcba03;
--vscode-mergeEditor-conflictingLines-background: rgba(255, 234, 0, 0.28);
--vscode-mergeEditor-conflict-input1-background: rgba(64, 200, 174, 0.2);
--vscode-mergeEditor-conflict-input2-background: rgba(64, 166, 255, 0.2);
--vscode-extensionIcon-starForeground: #ff8e00;
--vscode-extensionIcon-verifiedForeground: #3794ff;
--vscode-extensionIcon-preReleaseForeground: #1d9271;
--vscode-extensionIcon-sponsorForeground: #d758b3;
--vscode-terminal-ansiBlack: #000000;
--vscode-terminal-ansiRed: #cd3131;
--vscode-terminal-ansiGreen: #0dbc79;
--vscode-terminal-ansiYellow: #e5e510;
--vscode-terminal-ansiBlue: #2472c8;
--vscode-terminal-ansiMagenta: #bc3fbc;
--vscode-terminal-ansiCyan: #11a8cd;
--vscode-terminal-ansiWhite: #e5e5e5;
--vscode-terminal-ansiBrightBlack: #666666;
--vscode-terminal-ansiBrightRed: #f14c4c;
--vscode-terminal-ansiBrightGreen: #23d18b;
--vscode-terminal-ansiBrightYellow: #f5f543;
--vscode-terminal-ansiBrightBlue: #3b8eea;
--vscode-terminal-ansiBrightMagenta: #d670d6;
--vscode-terminal-ansiBrightCyan: #29b8db;
--vscode-terminal-ansiBrightWhite: #e5e5e5;
--vscode-simpleFindWidget-sashBorder: #454545;
--vscode-terminalCommandGuide-foreground: #37373d;
--vscode-welcomePage-tileBackground: #252526;
--vscode-welcomePage-tileHoverBackground: #2c2c2d;
--vscode-welcomePage-tileBorder: rgba(255, 255, 255, 0.1);
--vscode-welcomePage-progress-background: #3c3c3c;
--vscode-welcomePage-progress-foreground: #3794ff;
--vscode-walkthrough-stepTitle-foreground: #ffffff;
--vscode-walkThrough-embeddedEditorBackground: rgba(0, 0, 0, 0.4);
--vscode-profiles-sashBorder: rgba(128, 128, 128, 0.35);
--vscode-gitDecoration-addedResourceForeground: #81b88b;
--vscode-gitDecoration-modifiedResourceForeground: #e2c08d;
--vscode-gitDecoration-deletedResourceForeground: #c74e39;
--vscode-gitDecoration-renamedResourceForeground: #73c991;
--vscode-gitDecoration-untrackedResourceForeground: #73c991;
--vscode-gitDecoration-ignoredResourceForeground: #8c8c8c;
--vscode-gitDecoration-stageModifiedResourceForeground: #e2c08d;
--vscode-gitDecoration-stageDeletedResourceForeground: #c74e39;
--vscode-gitDecoration-conflictingResourceForeground: #e4676b;
--vscode-gitDecoration-submoduleResourceForeground: #8db9e2;
--vscode-gitlens-gutterBackgroundColor: rgba(255, 255, 255, 0.07);
--vscode-gitlens-gutterForegroundColor: #bebebe;
--vscode-gitlens-gutterUncommittedForegroundColor: rgba(0, 188, 242, 0.6);
--vscode-gitlens-trailingLineBackgroundColor: rgba(0, 0, 0, 0);
--vscode-gitlens-trailingLineForegroundColor: rgba(153, 153, 153, 0.35);
--vscode-gitlens-lineHighlightBackgroundColor: rgba(0, 188, 242, 0.2);
--vscode-gitlens-lineHighlightOverviewRulerColor: rgba(0, 188, 242, 0.6);
--vscode-gitlens-openAutolinkedIssueIconColor: #3fb950;
--vscode-gitlens-closedAutolinkedIssueIconColor: #a371f7;
--vscode-gitlens-closedPullRequestIconColor: #f85149;
--vscode-gitlens-openPullRequestIconColor: #3fb950;
--vscode-gitlens-mergedPullRequestIconColor: #a371f7;
--vscode-gitlens-unpublishedChangesIconColor: #35b15e;
--vscode-gitlens-unpublishedCommitIconColor: #35b15e;
--vscode-gitlens-unpulledChangesIconColor: #b15e35;
--vscode-gitlens-decorations-addedForegroundColor: #81b88b;
--vscode-gitlens-decorations-copiedForegroundColor: #73c991;
--vscode-gitlens-decorations-deletedForegroundColor: #c74e39;
--vscode-gitlens-decorations-ignoredForegroundColor: #8c8c8c;
--vscode-gitlens-decorations-modifiedForegroundColor: #e2c08d;
--vscode-gitlens-decorations-untrackedForegroundColor: #73c991;
--vscode-gitlens-decorations-renamedForegroundColor: #73c991;
--vscode-gitlens-decorations-branchAheadForegroundColor: #35b15e;
--vscode-gitlens-decorations-branchBehindForegroundColor: #b15e35;
--vscode-gitlens-decorations-branchDivergedForegroundColor: #d8af1b;
--vscode-gitlens-decorations-branchMissingUpstreamForegroundColor: #c74e39;
--vscode-gitlens-decorations-statusMergingOrRebasingConflictForegroundColor: #c74e39;
--vscode-gitlens-decorations-statusMergingOrRebasingForegroundColor: #d8af1b;
--vscode-gitlens-decorations-workspaceRepoMissingForegroundColor: #909090;
--vscode-gitlens-decorations-workspaceCurrentForegroundColor: #35b15e;
--vscode-gitlens-decorations-workspaceRepoOpenForegroundColor: #35b15e;
--vscode-gitlens-decorations-worktreeHasUncommittedChangesForegroundColor: #e2c08d;
--vscode-gitlens-decorations-worktreeMissingForegroundColor: #c74e39;
--vscode-gitlens-graphLane1Color: #15a0bf;
--vscode-gitlens-graphLane2Color: #0669f7;
--vscode-gitlens-graphLane3Color: #8e00c2;
--vscode-gitlens-graphLane4Color: #c517b6;
--vscode-gitlens-graphLane5Color: #d90171;
--vscode-gitlens-graphLane6Color: #cd0101;
--vscode-gitlens-graphLane7Color: #f25d2e;
--vscode-gitlens-graphLane8Color: #f2ca33;
--vscode-gitlens-graphLane9Color: #7bd938;
--vscode-gitlens-graphLane10Color: #2ece9d;
--vscode-gitlens-graphChangesColumnAddedColor: #347d39;
--vscode-gitlens-graphChangesColumnDeletedColor: #c93c37;
--vscode-gitlens-graphMinimapMarkerHeadColor: #05e617;
--vscode-gitlens-graphScrollMarkerHeadColor: #05e617;
--vscode-gitlens-graphMinimapMarkerUpstreamColor: #09ae17;
--vscode-gitlens-graphScrollMarkerUpstreamColor: #09ae17;
--vscode-gitlens-graphMinimapMarkerHighlightsColor: #fbff0a;
--vscode-gitlens-graphScrollMarkerHighlightsColor: #fbff0a;
--vscode-gitlens-graphMinimapMarkerLocalBranchesColor: #3087cf;
--vscode-gitlens-graphScrollMarkerLocalBranchesColor: #3087cf;
--vscode-gitlens-graphMinimapMarkerPullRequestsColor: #c76801;
--vscode-gitlens-graphScrollMarkerPullRequestsColor: #c76801;
--vscode-gitlens-graphMinimapMarkerRemoteBranchesColor: #2b5e88;
--vscode-gitlens-graphScrollMarkerRemoteBranchesColor: #2b5e88;
--vscode-gitlens-graphMinimapMarkerStashesColor: #b34db3;
--vscode-gitlens-graphScrollMarkerStashesColor: #b34db3;
--vscode-gitlens-graphMinimapMarkerTagsColor: #6b562e;
--vscode-gitlens-graphScrollMarkerTagsColor: #6b562e;
--vscode-gitlens-launchpadIndicatorMergeableColor: #3fb950;
--vscode-gitlens-launchpadIndicatorMergeableHoverColor: #3fb950;
--vscode-gitlens-launchpadIndicatorBlockedColor: #c74e39;
--vscode-gitlens-launchpadIndicatorBlockedHoverColor: #c74e39;
--vscode-gitlens-launchpadIndicatorAttentionColor: #d8af1b;
--vscode-gitlens-launchpadIndicatorAttentionHoverColor: #d8af1b;
--vscode-remoteHub-decorations-addedForegroundColor: #81b88b;
--vscode-remoteHub-decorations-modifiedForegroundColor: #e2c08d;
--vscode-remoteHub-decorations-deletedForegroundColor: #c74e39;
--vscode-remoteHub-decorations-submoduleForegroundColor: #8db9e2;
--vscode-remoteHub-decorations-conflictForegroundColor: #e4676b;
--vscode-remoteHub-decorations-incomingAddedForegroundColor: #81b88b;
--vscode-remoteHub-decorations-incomingModifiedForegroundColor: #e2c08d;
--vscode-remoteHub-decorations-incomingDeletedForegroundColor: #c74e39;
--vscode-remoteHub-decorations-incomingRenamedForegroundColor: #73c991;
--vscode-remoteHub-decorations-possibleConflictForegroundColor: #cca700;
--vscode-remoteHub-decorations-ignoredResourceForeground: #8c8c8c;
--vscode-remoteHub-decorations-workspaceRepositoriesView-hasUncommittedChangesForegroundColor: #e2c08d;
--vscode-rust_analyzer-syntaxTreeBorder: #ffffff;
}

71
news/public/favicon.svg Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="612" height="612" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

115
news/src/App.vue Normal file
View File

@ -0,0 +1,115 @@
<script setup lang="ts">
import OmHeader from './components/Header.vue';
import OmWhatNews from './components/WhatNews.vue';
import OmMoreFeature from './components/MoreFeature.vue';
import OmCoreFeature from './components/CoreFeature.vue';
import OmSponsor from './components/Sponsor.vue';
import OmResource from './components/Resource.vue';
import OmTroubleshoot from './components/Troubleshoot.vue';
import OmContributor from './components/Contributor.vue';
import data from './data.json';``
</script>
<template>
<main class="openmcp-news-root">
<om-header :version="data.version" />
<!-- 1. 📣 What is news in OpenMCP -->
<om-what-news :version="data.version" :changelogs="data.changelogs" />
<!-- 2. 🐳 Learn more features -->
<om-more-feature />
<!-- 3. Core Features -->
<om-core-feature />
<!-- 4. How to sponsor -->
<om-sponsor />
<!-- 5. 📚 Resources -->
<om-resource />
<!-- 6. 🔧 Troubleshooting -->
<om-troubleshoot />
<!-- 7. 👥 Contributors -->
<om-contributor :contributors="data.contributors" />
</main>
</template>
<style>
body {
color: var(--foreground, #222);
background: var(--background, #fff);
font-size: var(--vscode-font-size);
max-width: 900px;
margin: 0 auto;
padding: 2rem;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.6;
}
.openmcp-news-root {
color: var(--foreground, #222);
background: var(--background, #fff);
padding: 32px 0 64px 0;
min-height: 100vh;
box-sizing: border-box;
max-width: 820px;
margin: 0 auto;
}
.release-link {
color: #B988D1;
font-weight: 500;
text-decoration: underline;
margin-bottom: 8px;
display: inline-block;
transition: color 0.2s;
}
.release-link:hover {
color: #8e5bbf;
}
.news-list {
list-style: none;
padding: 0;
margin: 0;
}
.news-badge {
display: inline-block;
background: #B988D1;
color: #fff;
border-radius: 8px;
font-size: 0.85em;
padding: 2px 10px;
margin-right: 10px;
font-weight: 500;
vertical-align: middle;
}
.openmcp-header {
display: flex;
justify-content: center;
align-items: center;
gap: 24px;
margin: 0 0 32px 0;
padding: 0 0 16px 0;
}
@media screen and (max-width: 600px) {
.openmcp-header {
flex-direction: column;
align-items: center;
}
}
.margin-bottom {
margin-bottom: 32px;
}
</style>

View 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>

View File

@ -0,0 +1,92 @@
<template>
<section class="core-section">
<div class="section-title"> Core Features</div>
<ul class="core-list">
<li class="core-card">
<span class="core-dot">🧩</span>
<span>Full support for all MCP protocols, including <b>stdio</b>, <b>SSE</b>, and <b>streamable HTTP</b> connection modes.</span>
<a href="https://kirigaya.cn/openmcp/plugin-tutorial/usage/debug.html" target="_blank">Learn more</a>
</li>
<li class="core-card">
<span class="core-dot">🧩</span>
<span>Connect Multiple MCP Servers and combine more mcp tools in just one instance.</span>
<a href="https://kirigaya.cn/openmcp/plugin-tutorial/usage/multi-server.html" target="_blank">Learn more</a>
</li>
<li class="core-card">
<span class="core-dot">🧩</span>
<span>One-click AI Mock data generation & Automatic mcp tool testing width custom and flexible order.</span>
<a href="https://kirigaya.cn/openmcp/sdk-tutorial/" target="_blank">Learn more</a>
</li>
<li class="core-card">
<span class="core-dot">🧩</span>
<span>Support function calling based on both <strong>XML</strong> and <strong>openai tools protocols.</strong></span>
<a href="https://kirigaya.cn/openmcp/sdk-tutorial/" target="_blank">Learn more</a>
</li>
<li class="core-card">
<span class="core-dot">🧩</span>
<span>Export connection as mcpconfig.json and deploy in openmcp-sdk</span>
<a href="https://kirigaya.cn/openmcp/sdk-tutorial/" target="_blank">Learn more</a>
</li>
<li class="core-card">
<span class="core-dot">🧩</span>
<span>Native VSCode experience, cross-platform support</span>
<a href="https://kirigaya.cn/openmcp/plugin-tutorial/quick-start/acquire-openmcp.html" target="_blank">Learn more</a>
</li>
</ul>
</section>
</template>
<style scoped>
.core-section {
margin-bottom: 20px;
}
.core-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
list-style: none;
padding: 0;
margin: 0;
}
@media (max-width: 950px) {
.core-list {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 630px) {
.core-list {
grid-template-columns: 1fr;
}
}
.core-card {
display: flex;
align-items: flex-start;
flex-direction: column;
gap: 12px;
padding: 1.5rem;
border-radius: 10px;
background-color: var(--vscode-sideBar-background);
transition: transform 0.2s ease, box-shadow 0.2s;
box-shadow: 0 2px 8px var(--vscode-widget-shadow, rgba(0,0,0,0.08));
font-size: 1.05em;
}
.core-card a {
color: #B988D1;
}
.core-card:hover {
transform: translateY(-4px) scale(1.025);
box-shadow: 0 6px 18px var(--vscode-widget-shadow, rgba(0,0,0,0.14));
}
.core-dot {
display: inline-block;
border-radius: 50%;
font-size: 30px;
flex-shrink: 0;
}
</style>

View File

@ -0,0 +1,119 @@
<script setup lang="ts">
const props = defineProps({
version: {
type: String,
default: '0.1.9'
}
});
</script>
<template>
<header class="openmcp-header">
<div class="openmcp-icon openmcp-logo"></div>
<div>
<h1>
OpenMCP Client<sup><small>{{ props.version }}</small></sup>
</h1>
<div class="links">
<a href="https://github.com/LSTM-Kirigaya/openmcp-client" target="_blank" title="GitHub">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
style="vertical-align: middle;">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z">
</path>
</svg>
GitHub
</a>
<a href="https://github.com/LSTM-Kirigaya/openmcp-client/releases" target="_blank" title="Releases">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
style="vertical-align: middle;">
<path
d="M21 10.975V8a2 2 0 00-2-2h-6V4.688c.305-.274.5-.668.5-1.11a1.5 1.5 0 00-3 0c0 .442.195.836.5 1.11V6H5a2 2 0 00-2 2v2.998l-.072.005A.999.999 0 002 12v2a1 1 0 001 1v5a2 2 0 002 2h14a2 2 0 002-2v-5a1 1 0 001-1v-1.975a1 1 0 00-.928-.997L21 10.975zm-5 5.025H8v-3h8v3z">
</path>
</svg>
Releases
</a>
<a href="https://kirigaya.cn/openmcp/" target="_blank" title="Website">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
style="vertical-align: middle;">
<path
d="M12.001 1.993C6.486 1.994 2 6.48 2 11.994c0 5.514 4.486 9.999 10 10 5.515 0 10.001-4.485 10.001-10s-4.486-10-10-10.001zM12 19.994c-4.412 0-8.001-3.589-8.001-8s3.589-8 8-8.001C16.411 3.994 20 7.583 20 11.994c0 4.41-3.589 8-8 8z">
</path>
<path
d="M12.001 8.994l-4.005 4.005 1.414 1.414 2.591-2.591 2.591 2.591 1.414-1.414-4.005-4.005z">
</path>
</svg>
Website
</a>
<a href="https://discord.com/invite/SKTZRf6NzU" target="_blank" title="Discord">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
style="vertical-align: middle;">
<path
d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.09.09 0 00-.07.03c-.18.33-.39.76-.53 1.09a16.09 16.09 0 00-4.8 0c-.14-.34-.35-.76-.54-1.09-.01-.02-.04-.03-.07-.03-1.5.26-2.93.71-4.27 1.33-.01 0-.02.01-.03.02-2.72 4.07-3.47 8.03-3.1 11.95 0 .02.01.04.03.05 1.8 1.32 3.53 2.12 5.24 2.65.03.01.06 0 .07-.02.4-.55.76-1.13 1.07-1.74.02-.04 0-.08-.04-.09-.57-.22-1.11-.48-1.64-.78-.04-.02-.04-.08-.01-.11.11-.08.22-.17.33-.25.02-.02.05-.02.07-.01 3.44 1.57 7.15 1.57 10.55 0 .02-.01.05-.01.07.01.11.09.22.17.33.26.04.03.04.09-.01.11-.52.31-1.07.56-1.64.78-.04.01-.05.06-.04.09.32.61.68 1.19 1.07 1.74.03.01.06.02.09.01 1.72-.53 3.45-1.33 5.25-2.65.02-.01.03-.03.03-.05.44-4.53-.73-8.46-3.1-11.95-.01-.01-.02-.02-.04-.02zM8.52 14.91c-.99 0-1.8-.9-1.8-2s.79-2.01 1.8-2.01c1 0 1.81.9 1.81 2.01-.01 1.1-.8 2-1.81 2zm6.96 0c-.99 0-1.8-.9-1.8-2s.79-2.01 1.8-2.01c1 0 1.81.9 1.81 2.01-.01 1.1-.8 2-1.81 2z">
</path>
</svg>
Discord
</a>
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD"
target="_blank" title="QQ Group">
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor">
<path d="M824.8 613.2c-16-51.4-34.4-94.6-62.7-165.3C766.5 262.2 689.3 112 511.5 112 331.7 112 256.2 265.2 261 447.9c-28.4 70.8-46.7 113.7-62.7 165.3-34 109.5-23 154.8-14.6 155.8 18 2.2 70.1-82.4 70.1-82.4 0 49 25.2 112.9 79.8 159-26.4 8.1-85.7 29.9-71.6 53.8 11.4 19.3 196.2 12.3 249.5 6.3 53.3 6 238.1 13 249.5-6.3 14.1-23.8-45.3-45.7-71.6-53.8 54.6-46.2 79.8-110.1 79.8-159 0 0 52.1 84.6 70.1 82.4 8.5-1.1 19.5-46.4-14.5-155.8z"></path>
</svg>
QQ Group
</a>
</div>
</div>
</header>
<hr>
</template>
<style>
.openmcp-logo {
display: inline-block;
width: 84px;
height: 84px;
border-radius: 16px;
vertical-align: middle;
}
hr {
border: none;
border-top: 1.5px solid #B988D1;
height: 0;
margin: 24px 0;
}
.openmcp-header h1 {
font-size: 2.1rem;
font-weight: bold;
margin: 0 0 20px 0;
display: flex;
justify-content: center;
color: #B988D1;
line-height: 1.2;
}
.openmcp-header .links {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: center;
margin-top: 4px;
}
.openmcp-header .links a {
color: var(--vscode-textLink-foreground);
font-weight: 500;
text-decoration: none;
display: flex;
align-items: center;
gap: 0.5rem;
transition: color 0.18s;
}
.openmcp-header .links a:hover {
color: #8e5bbf;
text-decoration: underline;
}
</style>

View File

@ -0,0 +1,5 @@
<template>
<div>
</div>
</template>

View File

@ -0,0 +1,118 @@
<script setup lang="ts">
import VanillaTilt from 'vanilla-tilt';
import { onMounted, ref } from 'vue';
const container = ref<any>(null);
onMounted(() => {
VanillaTilt.init(container.value, {
max: 12,
speed: 400,
glare: true,
'max-glare': 0.5
});
});
</script>
<template>
<section class="feature-section">
<div class="section-title">🐳 Learn More Features & Usage</div>
<div style="margin-bottom: 1.1rem;">Learn more about how to use openmcp to build your AI Agent & MCP fast</div>
<!-- <a href="https://www.youtube.com/embed/S7igsEhcLiw?si=6sqvbYJxSRoFS26g" target="_blank" class="bilibili-player-container" style="display:flex; width: 100%; justify-content: center;">
<iframe width="100%" height="580" src="https://www.youtube.com/embed/S7igsEhcLiw?si=6sqvbYJxSRoFS26g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</a> -->
<a href="https://www.youtube.com/watch?v=S7igsEhcLiw" target="_blank" class="bilibili-player-container">
<img src="https://pic1.zhimg.com/80/v2-951261f789708621a2c34faa5fa6f330_1440w.png" alt="" ref="container">
</a>
</section>
</template>
<style>
.feature-section {
margin-bottom: 20px;
}
.section-title {
font-size: 1.5rem;
font-weight: bold;
color: #B988D1;
margin-bottom: 12px;
}
.feature-cards {
display: flex;
flex-wrap: wrap;
gap: 18px;
}
.feature-card {
background: none;
border: 1.5px solid #B988D1;
border-radius: 10px;
padding: 18px 22px;
min-width: 180px;
flex: 1 1 180px;
color: var(--foreground, #222);
text-decoration: none;
transition: box-shadow 0.15s, border 0.15s;
box-shadow: 0 2px 8px 0 rgba(185, 136, 209, 0.04);
display: flex;
flex-direction: column;
gap: 6px;
}
.feature-card:hover {
border-color: #8e5bbf;
box-shadow: 0 4px 16px 0 rgba(185, 136, 209, 0.12);
}
.feature-card-title {
font-weight: bold;
color: #B988D1;
font-size: 1.1em;
}
.feature-card-desc {
font-size: 0.98em;
color: var(--foreground, #444);
opacity: 0.85;
}
.bilibili-player-container img {
max-width: 100%;
box-shadow: 0 4px 12px var(--vscode-widget-shadow);
border-radius: .5em;
}
.bilibili-player-container {
position: relative;
width: fit-content;
height: fit-content;
margin: 2rem 0;
border-radius: .5em;
overflow: hidden;
transition: box-shadow 0.3s ease, border-color 0.3s ease;
}
@media (max-width: 2700px) {
.bilibili-player-container {
width: 88%;
}
}
@media (max-width: 1200px) {
.bilibili-player-container {
width: 95%;
}
}
@media screen and (max-width: 741px) {
.bilibili-player-container iframe {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,98 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const svgString = `
<svg width="84" height="84" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg" class="openmcp-logo">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>
`;
const svgContainer = ref<HTMLElement | null>(null);
onMounted(() => {
if (svgContainer.value) {
svgContainer.value.innerHTML = svgString;
}
});
</script>
<template>
<span ref="svgContainer" class="openmcp-logo"></span>
</template>
<style>
.openmcp-logo {
display: inline-block;
width: 84px;
height: 84px;
border-radius: 16px;
vertical-align: middle;
}
</style>

View File

@ -0,0 +1,45 @@
<template>
<section class="resource-section">
<div class="section-title">📚 Resources</div>
<ul class="resource-list">
<li><a data-v-dd258f77="" class="VPNolebaseInlinePreviewLink" relative=""
href="https://www.bilibili.com/video/BV1zYGozgEHc" target="_blank" rel="noreferrer">MCP Series Video
Tutorials (Under Construction)</a></li>
<li><a data-v-dd258f77="" class="VPNolebaseInlinePreviewLink" relative=""
href="https://kirigaya.cn/blog/search?q=mcp" target="_blank" rel="noreferrer">Jin Hui's MCP Series
Blog</a></li>
<li><a data-v-dd258f77="" class="VPNolebaseInlinePreviewLink" relative=""
href="https://kirigaya.cn/openmcp/plugin-tutorial" target="_blank" rel="noreferrer">OpenMCP Official
Documentation</a></li>
<li><a data-v-dd258f77="" class="VPNolebaseInlinePreviewLink" relative=""
href="https://kirigaya.cn/openmcp/sdk-tutorial" target="_blank" rel="noreferrer">openmcp-sdk
Official Documentation</a></li>
</ul>
</section>
</template>
<style>
.resource-section {
margin-bottom: 20px;
padding-bottom: 16px;
}
.resource-list {
padding: 0;
margin: 0;
padding-left: 28px;
}
.resource-list li {
margin-bottom: 0.75rem;
}
.resource-list a {
color: #B988D1;
transition: color 0.2s;
}
.resource-list a:hover {
color: #8e5bbf;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<section class="sponsor-section">
<div class="section-title"> How to Sponsor</div>
<div class="sponsor-content">
<p>If you like openmcp, please support our work!</p>
<a class="sponsor-item" href="https://github.com/LSTM-Kirigaya/openmcp-client" target="_blank">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="vertical-align: middle;">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z">
</path>
</svg>
Github
</a>
<br>
<a class="sponsor-item" href="https://afdian.com/a/kirigaya" target="_blank">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
<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">
</path>
</svg>
爱发电</a>
</div>
</section>
</template>
<style>
.sponsor-section {
margin-bottom: 20px;
padding-bottom: 16px;
}
.sponsor-content {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.sponsor-item {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background-color: #B988D1;
color: var(--vscode-button-foreground);
border-radius: 4px;
text-decoration: none;
transition: transform 0.1s ease;
}
.sponsor-item:hover {
background-color: #8e5bbf;
transition: transform 0.1s ease;
}
.sponsor-item:active {
transform: scale(0.95);
transition: transform 0.1s ease;
}
</style>

View File

@ -0,0 +1,44 @@
<script setup lang="ts">
</script>
<template>
<section class="troubleshoot-section">
<div class="section-title">🔧 Troubleshooting</div>
<ul class="troubleshoot-list">
<li>
If the interface displays abnormally, try restarting VSCode or report an <a href="https://github.com/LSTM-Kirigaya/openmcp-client/issues" target="_blank">Issue</a>.
</li>
<li>
For more questions, refer to the <a href="https://kirigaya.cn/openmcp/" target="_blank">official
documentation</a> or join the community.</li>
<li>Contant Jinhui via <a href="mailto:1193466151@qq.com">1193466151@qq.com</a> to seek technical consultation or business cooperation.</li>
</ul>
</section>
</template>
<style>
.troubleshoot-section {
margin-bottom: 20px;
padding-bottom: 16px;
}
.troubleshoot-list {
list-style: disc inside;
padding-left: 18px;
color: var(--foreground, #444);
}
.troubleshoot-list li {
margin-bottom: 0.75rem;
}
.troubleshoot-list a {
color: #B988D1;
text-decoration: underline;
}
.troubleshoot-list a:hover {
color: #8e5bbf;
}
</style>

View File

@ -0,0 +1,73 @@
<script setup lang="ts">
const props = defineProps({
version: {
type: String,
default: '0.1.9'
},
changelogs: {
type: Array as () => string[],
default: () => [
'Brand new VSCode WebView adaptation, smoother experience',
'Support for AI Mock, toolchain visualization, and automatic topology detection',
'Multi-model concurrency, enhanced plugin capabilities'
]
}
});
</script>
<template>
<section class="news-section">
<div class="news-title">
<span>📣 What's New in <span class="highlight">{{ props.version }}</span></span>
</div>
<div class="news-content">
<ul class="news-list">
<li v-for="(log, index) in props.changelogs" :key="index">
<span class="news-badge">{{ '/' }}</span>
<span>{{ log }}</span>
</li>
</ul>
<br>
<a class="release-link" href="https://kirigaya.cn/openmcp/preview/changelog.html" target="_blank"
rel="noopener">View History Changelog </a>
</div>
</section>
</template>
<style>
.news-section {
margin-bottom: 20px;
}
.news-title {
display: flex;
align-items: center;
font-size: 1.5rem;
font-weight: bold;
color: #B988D1;
margin-bottom: 10px;
}
.news-title .logo {
width: 38px;
height: 38px;
margin-right: 12px;
vertical-align: middle;
}
.news-title .highlight {
color: #B988D1;
}
.news-content {
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
background-color: var(--vscode-sideBar-background);
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
}
.news-content li {
margin-bottom: 0.7rem;
}
</style>

151
news/src/css/vscode.css Normal file
View File

@ -0,0 +1,151 @@
:root {
--font-monospace-family: var(--vscode-editor-font-family);
--font-monospace-weight: var(--vscode-editor-font-weight);
--font-monospace-size: var(--vscode-editor-font-size);
--link-foreground: var(--vscode-textLink-foreground);
--link-active: var(--vscode-textLink-activeForeground);
/* UI & Control */
--input-active-background: var(--vscode-input-background);
--input-active-border: var(--vscode-focusBorder);
--input-active-foreground: var(--vscode-input-foreground);
--input-error-background: var(--vscode-inputValidation-errorBackground);
--input-error-border: var(--vscode-inputValidation-errorBorder);
--input-error-foreground: var(--vscode-inputValidation-errorForeground);
--input-foreground: var(--vscode-input-foreground);
--input-background: var(--vscode-input-background);
--input-border: var(--vscode-input-border);
--input-hover: var(--vscode-input-background);
--input-placeholder: var(--vscode-input-placeholderForeground);
--input-radius: 0px;
--scrollbar-background: var(--vscode-scrollbarSlider-background);
--scrollbar-hover: var(--vscode-scrollbarSlider-hoverBackground);
--scrollbar-active: var(--vscode-scrollbarSlider-activeBackground);
/* Window */
--title-bar: #1f1f1f;
--title-color: #fff;
--foreground: var(--vscode-editor-foreground);
--background: var(--vscode-editor-background);
--label: rgb(189, 189, 189);
--shadow: #000;
--border: var(--vscode-input-border);
--window-button-hover: rgba(255,255,255,0.1);
--window-button-active: rgba(255,255,255,0.2);
--window-blur-background: rgba(0,0,0,0.25);
--window-title-foreground: var(--foreground);
--window-background: var(--sidebar);
--window-border: transparent;
--window-radius: 0px;
/* Sidebar */
--sidebar: var(--vscode-sideBar-background);
--sidebar-border: var(--vscode-sideBar-border);
--sidebar-min-width: 280px;
--sidebar-item-text: var(--vscode-list-inactiveSelectionForeground);
--sidebar-item-border: var(--vscode-input-border);
--sidebar-item-background: var(--sidebar);
--sidebar-item-selected: var(--vscode-list-inactiveSelectionBackground);
--sidebar-item-hover: var(--vscode-list-hoverBackground);
--sidebar-item-max-height: 40px;
--sidebar-item-radix-background: var(--vscode-breadcrumb-background);
--sidebar-group-text: var(--vscode-sideBarSectionHeader-foreground);
--sidebar-group-border: var(--vscode-sideBarSectionHeader-border);
--sidebar-group-background: var(--vscode-sideBarSectionHeader-background);
/* Labels */
--signalSize-background: rgba(0,0,0,0.5);
--signalSize-border: rgba(255,255,255,0.2);
--signalSize-color: var(--foreground);
/* Color Picker */
--picker-swatch-size: 15px;
--picker-swatch-cols: 8;
--picker-background: var(--vscode-breadcrumbPicker-background);
--picker-border: var(--vscode-dropdown-border);
/* Search */
--search-background: var(--vscode-quickInput-background);
--search-border: var(--border);
--search-panel-background: transparent;
--search-panel-border: var(--vscode-pickerGroup-border);
--search-panel-text: var(--vscode-quickInput-foreground);
--search-label: var(--foreground);
--search-selected-background: var(--vscode-list-inactiveSelectionBackground);
/* Properties */
--properties-background: var(--vscode-breadcrumb-background);
--properties-border: var(--border);
/* Navbar */
--navBar-background: var(--sidebar);
--navBar-height: 32px;
--navBar-button: transparent;
--navBar-button-text: var(--foreground);
--navBar-group-background: var(--background);
--navBar-preview-background: var(--vscode-scrollbarSlider-background);
--navBar-slider-border: var(--foreground);
/* Buttons */
--button: var(--vscode-button-background);
--button-text: var(--vscode-button-foreground);
--button-hover: var(--vscode-button-hoverBackground);
--button-active: var(--vscode-button-hoverBackground);
--button-disabled: var(--vscode-activityBar-background);
--button-disabled-text: var(--vscode-activityBar-inactiveForeground);
/* Grid Lines */
--grid-dash: 2;
--grid-space: 4;
--grid-line: var(--vscode-editorIndentGuide-background);
--grid-tick: var(--vscode-editorIndentGuide-activeBackground);
/* Cursor */
--cursor: var(--vscode-editorCursor-foreground);
--cursor-ghost: rgba(255, 255, 255, 0.2);
--cursor-width: 2;
/* X-Axis */
--axis-height: 38px;
--axis-line: var(--border);
--axis-background: var(--vscode-sideBar-background);
--axis-foreground: var(--foreground);
/* Signals */
--signal-highlight: var(--vscode-list-inactiveSelectionBackground);
/* Colors */
--accent: var(--vscode-button-background);
--accent-dim: #234175;
--accent-bright: #24c5f7;
--accent-hover: var(--vscode-button-hoverBackground);
--vscode-font-size: 13px;
--color-red: #ff5252;
--color-pink: #ff4081;
--color-purple: #e040fb;
--color-deepPurple: #7c4dff;
--color-indigo: #536dfe;
--color-blue: #448aff;
--color-lightBlue: #40c4ff;
--color-cyan: #18ffff;
--color-teal: #64ffda;
--color-green: #69f0ae;
--color-lightGreen: #b2ff59;
--color-lime: #eeff41;
--color-yellow: #ffff00;
--color-amber: #ffd740;
--color-orange: #ffab40;
--color-deepOrange: #ff6e40;
/* Settings */
--settings-action-background: var(--background);
}

48
news/src/data.json Normal file
View File

@ -0,0 +1,48 @@
{
"version": "0.1.9",
"changelogs": [
"Add mook functionality: Automatically fill in test tool form data using random seeds or AI generation.",
"Add tool self-check functionality: 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 #36: Ensure successful startup when not opening a folder.",
"Fix issue #45: Array type parameters are not supported.",
"Fix the issue of abnormal dialog styles 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"
}
]
}

5
news/src/main.ts Normal file
View File

@ -0,0 +1,5 @@
import './css/vscode.css';
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app')

12
news/tsconfig.app.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]
}
}
}

11
news/tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

19
news/tsconfig.node.json Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node22/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

20
news/vite.config.ts Normal file
View File

@ -0,0 +1,20 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import { viteSingleFile } from 'vite-plugin-singlefile'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
viteSingleFile(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})

11
package-lock.json generated
View File

@ -52,6 +52,7 @@
"esbuild": "^0.25.5", "esbuild": "^0.25.5",
"fork-ts-checker-webpack-plugin": "^9.1.0", "fork-ts-checker-webpack-plugin": "^9.1.0",
"null-loader": "^4.0.1", "null-loader": "^4.0.1",
"ompipe": "^1.0.2",
"rollup": "^4.43.0", "rollup": "^4.43.0",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"rollup-plugin-visualizer": "^6.0.1", "rollup-plugin-visualizer": "^6.0.1",
@ -10630,6 +10631,16 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/ompipe": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ompipe/-/ompipe-1.0.2.tgz",
"integrity": "sha512-D9SbKT2fqSkVxQtp0AffMdSYNZiScA9YOrS0iymyt6Q4wLWyUzvxhmFcJO8AxlwYLZY/IddwirgM46EfeNdq4A==",
"dev": true,
"license": "ISC",
"dependencies": {
"chalk": "4.1.2"
}
},
"node_modules/on-exit-leak-free": { "node_modules/on-exit-leak-free": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",

View File

@ -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": {
@ -232,6 +238,7 @@
"lint": "eslint src --ext ts", "lint": "eslint src --ext ts",
"test": "node ./dist/test/e2e/runTest.js", "test": "node ./dist/test/e2e/runTest.js",
"prepare:ocr": "rollup -c rollup.tesseract.js --bundleConfigAsCjs", "prepare:ocr": "rollup -c rollup.tesseract.js --bundleConfigAsCjs",
"build:news": "npx tsx scripts/update-news-data.mts",
"build:task-loop": "npx vite build --config renderer/vite.config.task-loop.mjs && node renderer/scripts/task-loop.build.mjs" "build:task-loop": "npx vite build --config renderer/vite.config.task-loop.mjs && node renderer/scripts/task-loop.build.mjs"
}, },
"dependencies": { "dependencies": {
@ -275,6 +282,7 @@
"esbuild": "^0.25.5", "esbuild": "^0.25.5",
"fork-ts-checker-webpack-plugin": "^9.1.0", "fork-ts-checker-webpack-plugin": "^9.1.0",
"null-loader": "^4.0.1", "null-loader": "^4.0.1",
"ompipe": "^1.0.2",
"rollup": "^4.43.0", "rollup": "^4.43.0",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"rollup-plugin-visualizer": "^6.0.1", "rollup-plugin-visualizer": "^6.0.1",

View File

@ -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": "テストニュースレポート"
} }

View File

@ -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"
} }

View File

@ -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": "测试新闻报告"
} }

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4870215 */ font-family: "iconfont"; /* Project id 4870215 */
src: url('iconfont.woff2?t=1750532923458') format('woff2'), src: url('iconfont.woff2?t=1751568095152') format('woff2'),
url('iconfont.woff?t=1750532923458') format('woff'), url('iconfont.woff?t=1751568095152') format('woff'),
url('iconfont.ttf?t=1750532923458') format('truetype'); url('iconfont.ttf?t=1751568095152') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-pin:before {
content: "\e863";
}
.icon-serial:before {
content: "\e78f";
}
.icon-deploy:before { .icon-deploy:before {
content: "\e614"; content: "\e614";
} }

Binary file not shown.

View File

@ -2,19 +2,17 @@
<div class="diagram-item-record" v-if="props.dataView && props.dataView.tool"> <div class="diagram-item-record" v-if="props.dataView && props.dataView.tool">
<div class="item-header"> <div class="item-header">
<span class="item-title">{{ props.dataView.tool.name }}</span> <span class="item-title">{{ props.dataView.tool.name }}</span>
<span class="item-status" :class="props.dataView.status">{{ props.dataView.status }}</span>
</div> </div>
<div class="item-desc">{{ props.dataView.tool.description }}</div> <div class="item-desc">{{ props.dataView.tool.description }}</div>
<div v-if="props.dataView.function !== undefined" class="item-result">
<div class="item-label">Function</div>
<div class="item-json">{{ props.dataView.function.name }}</div>
</div>
<div v-if="props.dataView.function !== undefined" class="item-result"> <div v-if="props.dataView.function !== undefined" class="item-result">
<span class="item-label">Arguments</span> <span class="item-label">Arguments</span>
<div class="code-container">
<json-render :json="props.dataView.function.arguments" /> <json-render :json="props.dataView.function.arguments" />
</div> </div>
</div>
<div v-if="props.dataView.result !== undefined" class="item-result"> <div v-if="props.dataView.result !== undefined" class="item-result">
<span class="item-label">Result</span> <span class="item-label">Result</span>
@ -30,6 +28,49 @@
v-else-if="typeof props.dataView.result === 'string'">{{ props.dataView.result }}</pre> v-else-if="typeof props.dataView.result === 'string'">{{ props.dataView.result }}</pre>
<pre class="item-json" v-else>{{ formatJson(props.dataView.result) }}</pre> <pre class="item-json" v-else>{{ formatJson(props.dataView.result) }}</pre>
</div> </div>
<br>
<div class="item-meta">
<span v-if="props.dataView.createAt" class="item-meta-label">
Created: <b>{{ formatTime(props.dataView.createAt) }}</b>
</span>
<!-- <span v-if="props.dataView.finishAt" class="item-meta-label">
Finished: <b>{{ formatTime(props.dataView.finishAt) }}</b>
</span> -->
<!-- -->
</div>
<div class="item-timecost" v-if="props.dataView.llmTimecost !== undefined || props.dataView.toolcallTimecost !== undefined">
<template v-if="props.dataView.llmTimecost !== undefined && props.dataView.toolcallTimecost !== undefined">
<div class="timecost-bar">
<div
class="timecost-segment llm"
:style="{ width: llmPercent + '%' }"
:title="`LLM: ${props.dataView.llmTimecost}ms`"
></div>
<div
class="timecost-segment toolcall"
:style="{ width: toolcallPercent + '%' }"
:title="`ToolCall: ${props.dataView.toolcallTimecost}ms`"
></div>
</div>
<div class="timecost-labels">
<span class="llm-label">LLM: <b>{{ props.dataView.llmTimecost }}ms</b> ({{ llmPercent }}%)</span>
<span class="toolcall-label">ToolCall: <b>{{ props.dataView.toolcallTimecost }}ms</b> ({{ toolcallPercent }}%)</span>
</div>
</template>
<template v-else-if="props.dataView.llmTimecost !== undefined">
<div class="timecost-labels">
<span class="llm-label">LLM: <b>{{ props.dataView.llmTimecost }}ms</b></span>
</div>
</template>
<template v-else>
<div class="timecost-labels">
<span class="toolcall-label">ToolCall: <b>{{ props.dataView.toolcallTimecost }}ms</b></span>
</div>
</template>
</div>
</div> </div>
<div v-else class="diagram-item-record"> <div v-else class="diagram-item-record">
<div class="item-header"> <div class="item-header">
@ -44,6 +85,7 @@ import type { PropType } from 'vue';
import type { NodeDataView } from './diagram'; import type { NodeDataView } from './diagram';
import JsonRender from '@/components/json-render/index.vue'; import JsonRender from '@/components/json-render/index.vue';
import { computed } from 'vue';
const props = defineProps({ const props = defineProps({
dataView: { dataView: {
@ -59,6 +101,27 @@ function formatJson(obj: any) {
return String(obj) return String(obj)
} }
} }
//
function formatTime(val: string | number | Date) {
if (!val) return '-';
const d = new Date(val);
if (isNaN(d.getTime())) return '-';
return d.toLocaleString();
}
const llmPercent = computed(() => {
const l = props.dataView!.llmTimecost ?? 0;
const t = props.dataView!.toolcallTimecost ?? 0;
const sum = l + t;
return sum > 0 ? Math.round((l / sum) * 100) : 0;
});
const toolcallPercent = computed(() => {
const l = props.dataView!.llmTimecost ?? 0;
const t = props.dataView!.toolcallTimecost ?? 0;
const sum = l + t;
return sum > 0 ? Math.round((t / sum) * 100) : 0;
});
</script> </script>
<style scoped> <style scoped>
@ -85,39 +148,31 @@ function formatJson(obj: any) {
} }
.item-status { .item-status {
font-size: 13px; font-size: 15px;
padding: 2px 10px; padding: 5px 0;
border-radius: 12px; border-radius: 12px;
margin-left: 8px;
text-transform: capitalize; text-transform: capitalize;
} }
.item-status.running {
color: #2196f3;
}
.item-status.success {
color: #43a047;
}
.item-status.error {
color: #e53935;
}
.item-status.waiting {
color: #aaa;
}
.item-status.default {
color: #888;
}
.item-desc { .item-desc {
margin-bottom: 8px; margin-bottom: 15px;
opacity: 0.8; opacity: 0.8;
font-size: 14px; font-size: 14px;
} }
.item-meta {
margin-bottom: 8px;
display: flex;
gap: 12px;
font-size: 13px;
color: #888;
flex-wrap: wrap;
}
.item-meta-label b {
color: var(--main-color, #409EFF);
font-weight: 500;
}
.item-label { .item-label {
font-weight: 500; font-weight: 500;
margin-right: 4px; margin-right: 4px;
@ -127,7 +182,7 @@ function formatJson(obj: any) {
.item-json { .item-json {
border-radius: 4px; border-radius: 4px;
padding: 6px 10px; padding: 6px 10px;
font-size: 13px; font-size: 15px;
font-family: var(--code-font-family, monospace); font-family: var(--code-font-family, monospace);
margin: 2px 0 8px 0; margin: 2px 0 8px 0;
white-space: pre-wrap; white-space: pre-wrap;
@ -137,8 +192,16 @@ function formatJson(obj: any) {
box-sizing: border-box; box-sizing: border-box;
} }
.code-container {
margin-top: 10px;
border-radius: .3em;
padding: 0 10px;
background-color: var(--sidebar);
}
.item-result { .item-result {
margin-top: 6px; margin-top: 6px;
margin-bottom: 15px;
} }
.result-block { .result-block {
@ -149,7 +212,6 @@ function formatJson(obj: any) {
max-width: 100%; max-width: 100%;
} }
.result-block.error { .result-block.error {
background-color: rgba(245, 108, 108, 0.5); background-color: rgba(245, 108, 108, 0.5);
} }
@ -157,4 +219,49 @@ function formatJson(obj: any) {
.result-block.success { .result-block.success {
background-color: rgba(67, 160, 71, 0.5); background-color: rgba(67, 160, 71, 0.5);
} }
.item-timecost {
margin-bottom: 10px;
margin-top: 2px;
font-size: 14px;
color: #333;
}
.timecost-bar {
display: flex;
height: 12px;
border-radius: 6px;
overflow: hidden;
background: #f0eaff;
margin-bottom: 4px;
box-shadow: 0 1px 2px rgba(185,136,209,0.08);
}
.timecost-segment {
height: 100%;
transition: width 0.3s;
}
.llm {
background: #B988D1;
}
.toolcall {
background: #A1A7F6;
}
.timecost-labels {
display: flex;
gap: 18px;
font-size: 12px;
color: #888;
}
.llm-label b {
color: #B988D1;
}
.toolcall-label b {
color: #A1A7F6;
}
</style> </style>

View File

@ -41,11 +41,15 @@ export interface NodeDataView {
tool: ToolItem; tool: ToolItem;
status: 'default' | 'running' | 'waiting' | 'success' | 'error'; status: 'default' | 'running' | 'waiting' | 'success' | 'error';
function?: ChatCompletionChunk.Choice.Delta.ToolCall.Function; function?: ChatCompletionChunk.Choice.Delta.ToolCall.Function;
createAt?: number;
llmTimecost?: number;
toolcallTimecost?: number;
finishAt?: number;
result?: any; result?: any;
} }
export interface DiagramContext { export interface DiagramContext {
reset: () => void, preset: (type: string) => void,
render: () => void, render: () => void,
state?: DiagramState, state?: DiagramState,
setCaption: (value: string) => void setCaption: (value: string) => void
@ -168,6 +172,8 @@ export async function makeNodeTest(
} }
dataView.status = 'running'; dataView.status = 'running';
const createAt = Date.now();
dataView.createAt = createAt;
context.render(); context.render();
try { try {
@ -197,20 +203,19 @@ export async function makeNodeTest(
loop.registerOnToolCall(toolCall => { loop.registerOnToolCall(toolCall => {
dataView.function = toolCall.function; dataView.function = toolCall.function;
dataView.llmTimecost = Date.now() - createAt;
if (toolCall.function?.name === dataView.tool?.name) { if (toolCall.function?.name === dataView.tool?.name) {
try { try {
const toolArgs = JSON.parse(toolCall.function?.arguments || '{}'); const toolArgs = JSON.parse(toolCall.function?.arguments || '{}');
aiMockJson = toolArgs; aiMockJson = toolArgs;
} catch (e) { } catch (e) {
// ElMessage.error('AI 生成的 JSON 解析错误');
dataView.status = 'error'; dataView.status = 'error';
dataView.result = t('ai-gen-error-json'); dataView.result = t('ai-gen-error-json');
context.render(); context.render();
loop.abort(); loop.abort();
} }
} else { } else {
// ElMessage.error('AI 调用了未知的工具');
dataView.status = 'error'; dataView.status = 'error';
dataView.result = t('ai-invoke-unknown-tool') + ' ' + toolCall.function?.name; dataView.result = t('ai-invoke-unknown-tool') + ' ' + toolCall.function?.name;
context.render(); context.render();
@ -220,6 +225,8 @@ export async function makeNodeTest(
}); });
loop.registerOnToolCalled(toolCalled => { loop.registerOnToolCalled(toolCalled => {
dataView.toolcallTimecost = Date.now() - createAt - dataView.llmTimecost!;
if (toolCalled.state === MessageState.Success) { if (toolCalled.state === MessageState.Success) {
dataView.status = 'success'; dataView.status = 'success';
dataView.result = toolCalled.content; dataView.result = toolCalled.content;
@ -240,6 +247,8 @@ export async function makeNodeTest(
await loop.start(chatStorage, usePrompt); await loop.start(chatStorage, usePrompt);
} finally { } finally {
dataView.finishAt = Date.now();
if (dataView.status === 'running') { if (dataView.status === 'running') {
dataView.status = 'success'; dataView.status = 'success';
context.render(); context.render();

View File

@ -1,27 +1,43 @@
<template> <template>
<div style="display: flex; align-items: center; gap: 16px;"> <div style="display: flex; align-items: flex-start; gap: 32px;">
<div ref="svgContainer" class="diagram-container"></div> <div ref="svgContainer" class="diagram-container"></div>
<div class="diagram-info-panel">
<template v-for="(node, index) in state.nodes" :key="node.id + '-popup'"> <div style="display: flex; justify-content: space-between; align-items: center;">
<transition name="collapse-from-top" mode="out-in"> <div v-if="infoNodeId && state.dataView.get(infoNodeId)" class="item-status" :class="state.dataView.get(infoNodeId)?.status || 'waiting'">
<div {{ state.dataView.get(infoNodeId)?.status || 'waiting' }}
v-show="state.hoverNodeId === node.id && state.dataView.get(node.id)?.status !== 'waiting'"
@mouseenter="setHoverItem(node.id)"
@mouseleave="clearHoverItem()"
:style="getNodePopupStyle(node)"
class="node-popup"
>
<el-scrollbar height="100%" width="100%">
<DiagramItemRecord :data-view="state.dataView.get(node.id)"/>
</el-scrollbar>
</div> </div>
</transition> <div v-else>
{{ "Unknown Status" }}
</div>
<el-button
circle
size="small"
:type="state.pinnedNodeId ? 'primary' : 'default'"
@click="togglePin"
style="margin-bottom: 4px;"
:disabled="!infoNodeId"
>
<span class="iconfont icon-pin"></span>
</el-button>
</div>
<template v-if="infoNodeId && state.dataView.get(infoNodeId)">
<el-scrollbar height="500px" width="300px">
<DiagramItemRecord :data-view="state.dataView.get(infoNodeId)" />
</el-scrollbar>
</template> </template>
<template v-else>
<div class="diagram-info-empty">
<div style="color: #bbb; font-size: 15px;">
{{ t('diagram-node-empty') }}
</div>
</div>
</template>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, nextTick, reactive, inject } from 'vue'; import { ref, onMounted, nextTick, reactive, inject, computed } from 'vue';
import * as d3 from 'd3'; import * as d3 from 'd3';
import ELK from 'elkjs/lib/elk.bundled.js'; import ELK from 'elkjs/lib/elk.bundled.js';
import { mcpClientAdapter } from '@/views/connect/core'; import { mcpClientAdapter } from '@/views/connect/core';
@ -53,6 +69,7 @@ const state = reactive({
selectedNodeId: null as string | null, selectedNodeId: null as string | null,
draggingNodeId: null as string | null, draggingNodeId: null as string | null,
hoverNodeId: null as string | null, hoverNodeId: null as string | null,
pinnedNodeId: null as string | null, //
offset: { x: 0, y: 0 }, offset: { x: 0, y: 0 },
dataView: new Map<string, NodeDataView> dataView: new Map<string, NodeDataView>
}); });
@ -66,8 +83,13 @@ if (autoDetectDiagram) {
autoDetectDiagram.views?.forEach(item => { autoDetectDiagram.views?.forEach(item => {
state.dataView.set(item.tool.name, { state.dataView.set(item.tool.name, {
tool: item.tool, tool: item.tool,
function: item.function,
status: item.status || 'waiting', status: item.status || 'waiting',
result: item.result || null result: item.result || null,
createAt: item.createAt,
finishAt: item.finishAt,
llmTimecost: item.llmTimecost,
toolcallTimecost: item.toolcallTimecost
}); });
}); });
} else { } else {
@ -77,20 +99,19 @@ if (autoDetectDiagram) {
}; };
} }
console.log(tabStorage.autoDetectDiagram!.views);
console.log(state.dataView);
let cancelHoverHandler: NodeJS.Timeout | undefined = undefined; let cancelHoverHandler: NodeJS.Timeout | undefined = undefined;
const setHoverItem = (id: string) => { const setHoverItem = (id: string) => {
if (state.pinnedNodeId) return; // pinhover
if (cancelHoverHandler) { if (cancelHoverHandler) {
clearTimeout(cancelHoverHandler); clearTimeout(cancelHoverHandler);
} }
state.hoverNodeId = id; state.hoverNodeId = id;
} };
const clearHoverItem = () => { const clearHoverItem = () => {
if (state.pinnedNodeId) return; // pinhover
cancelHoverHandler = setTimeout(() => { cancelHoverHandler = setTimeout(() => {
if (cancelHoverHandler) { if (cancelHoverHandler) {
clearTimeout(cancelHoverHandler); clearTimeout(cancelHoverHandler);
@ -101,6 +122,19 @@ const clearHoverItem = () => {
}, 300); }, 300);
}; };
// pin
function togglePin() {
if (state.pinnedNodeId) {
state.pinnedNodeId = null;
} else if (state.hoverNodeId) {
state.pinnedNodeId = state.hoverNodeId;
}
}
// pinnedNodeId
const infoNodeId = computed(() => state.pinnedNodeId || state.hoverNodeId);
const getAllTools = async () => { const getAllTools = async () => {
const items = []; const items = [];
for (const client of mcpClientAdapter.clients) { for (const client of mcpClientAdapter.clients) {
@ -154,7 +188,7 @@ const drawDiagram = async () => {
// edges // edges
const reservedEdges = autoDetectDiagram?.edges; const reservedEdges = autoDetectDiagram?.edges;
if (reservedEdges) { if (reservedEdges && reservedEdges.length > 0) {
for (const edge of reservedEdges) { for (const edge of reservedEdges) {
if (edge.sources && edge.targets && edge.sources.length > 0 && edge.targets.length > 0) { if (edge.sources && edge.targets && edge.sources.length > 0 && edge.targets.length > 0) {
edges.push({ edges.push({
@ -188,7 +222,7 @@ const drawDiagram = async () => {
// dataView // dataView
state.dataView.set(tool.name, { state.dataView.set(tool.name, {
tool, tool,
status: 'waiting' status: 'waiting',
}); });
} }
} }
@ -387,7 +421,7 @@ function renderSvg() {
.attr('stroke-width', 2); .attr('stroke-width', 2);
}) })
.on('mouseout', function (event, d) { .on('mouseout', function (event, d) {
clearHoverItem(); // clearHoverItem();
if (state.selectedNodeId === d.id) return; if (state.selectedNodeId === d.id) return;
d3.select(this).select('rect') d3.select(this).select('rect')
.transition() .transition()
@ -557,7 +591,7 @@ function renderSvg() {
} }
// //
function resetConnections() { function serialConnection() {
if (!state.nodes.length) return; if (!state.nodes.length) return;
const edges = []; const edges = [];
for (let i = 0; i < state.nodes.length - 1; ++i) { for (let i = 0; i < state.nodes.length - 1; ++i) {
@ -573,8 +607,21 @@ function resetConnections() {
recomputeLayout().then(renderSvg); recomputeLayout().then(renderSvg);
} }
function parallelConnection() {
if (!state.nodes.length) return;
const edges = [] as Edge[];
state.edges = edges;
recomputeLayout().then(renderSvg);
}
const context = inject('context') as any; const context = inject('context') as any;
context.reset = resetConnections; context.preset = (type: string) => {
if (type === 'serial') {
serialConnection();
} else if (type === 'parallel') {
parallelConnection();
}
};
context.state = state; context.state = state;
context.render = renderSvg; context.render = renderSvg;
@ -619,13 +666,12 @@ function getNodePopupStyle(node: any): any {
<style> <style>
.diagram-container { .diagram-container {
width: 100%; width: 600px;
min-height: 200px; min-height: 200px;
display: flex;
justify-content: center;
align-items: flex-start;
border-radius: 8px; border-radius: 8px;
padding: 24px 0; padding: 24px 0;
display: flex;
justify-content: flex-start;
overflow-x: auto; overflow-x: auto;
} }
@ -651,4 +697,62 @@ function getNodePopupStyle(node: any): any {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.diagram-container {
width: 600px;
min-height: 200px;
display: flex;
align-items: flex-start;
border-radius: 8px;
padding: 24px 0;
overflow-x: auto;
}
.diagram-info-panel {
position: absolute;
right: 30px;
top: 10px;
width: 300px;
min-height: 180px;
border: 1px solid var(--main-color);
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.06);
padding: 10px;
display: flex;
flex-direction: column;
margin-top: 8px;
transition: box-shadow 0.2s;
}
.diagram-info-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
min-height: 120px;
opacity: 0.85;
font-size: 15px;
}
.item-status.running {
color: var(--main-color);
}
.item-status.success {
color: #43a047;
}
.item-status.error {
color: #e53935;
}
.item-status.waiting {
color: #aaa;
}
.item-status.default {
color: #888;
}
</style> </style>

View File

@ -4,15 +4,30 @@
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span>Tool Diagram</span> <span>Tool Diagram</span>
&ensp; &ensp;
<el-button size="small" type="primary" @click="() => context.reset()">{{ t("reset") }}</el-button> <!-- 重置按钮弹出下拉列表 -->
<!-- 自检程序弹出表单 --> <el-popover placement="bottom" width="180" trigger="click" v-model:visible="resetPopoverVisible">
<template #reference>
<el-button size="small" type="primary">
{{ t("preset") }}
</el-button>
</template>
<div style="display: flex; gap: 8px;">
<el-button size="small" @click="tomoPreset('serial')">
<span class="iconfont icon-serial"></span>
</el-button>
<el-button size="small" @click="tomoPreset('parallel')">
<span class="iconfont icon-parallel"></span>
</el-button>
</div>
</el-popover>
<!-- 原有自检程序弹出表单 -->
<el-popover placement="top" width="350" trigger="click" v-model:visible="testFormVisible"> <el-popover placement="top" width="350" trigger="click" v-model:visible="testFormVisible">
<template #reference> <template #reference>
<el-button size="small" type="primary"> <el-button size="small" type="primary">
{{ t('start-auto-detect') }} {{ t('start-auto-detect') }}
</el-button> </el-button>
</template> </template>
<!-- ...原有自检表单内容... -->
<el-input type="textarea" v-model="testPrompt" :rows="2" style="margin-bottom: 8px;" <el-input type="textarea" v-model="testPrompt" :rows="2" style="margin-bottom: 8px;"
placeholder="请输入 prompt" /> placeholder="请输入 prompt" />
<div style="display: flex; align-items: center; margin-bottom: 8px;"> <div style="display: flex; align-items: center; margin-bottom: 8px;">
@ -34,11 +49,21 @@
<el-scrollbar height="80vh"> <el-scrollbar height="80vh">
<Diagram :tab-id="props.tabId" /> <Diagram :tab-id="props.tabId" />
</el-scrollbar> </el-scrollbar>
<transition name="main-fade" mode="out-in">
<div class="caption" v-show="showCaption"> <div class="caption" v-if="showCaption">
{{ caption }} {{ caption }}
</div> </div>
</transition> <div v-else>
<span class="caption">
<el-tooltip
placement="top"
effect="light"
:content="t('self-detect-caption')"
>
<span class="iconfont icon-about"></span>
</el-tooltip>
</span>
</div>
</el-dialog> </el-dialog>
</template> </template>
@ -88,7 +113,7 @@ function setCaption(text: string) {
} }
const context: DiagramContext = { const context: DiagramContext = {
reset: () => { }, preset: () => { },
render: () => { }, render: () => { },
state: undefined, state: undefined,
setCaption setCaption
@ -133,8 +158,14 @@ async function onTestConfirm() {
tool: view.tool, tool: view.tool,
status: view.status, status: view.status,
function: view.function, function: view.function,
result: view.result result: view.result,
createAt: view.createAt,
finishAt: view.finishAt,
llmTimecost: view.llmTimecost,
toolcallTimecost: view.toolcallTimecost,
}); });
context.render();
} }
} }
} }
@ -144,16 +175,24 @@ async function onTestConfirm() {
} }
const resetPopoverVisible = ref(false);
function tomoPreset(type: string) {
resetPopoverVisible.value = false;
context.preset?.(type);
}
</script> </script>
<style> <style>
.no-padding-dialog { .no-padding-dialog {
margin-top: 30px !important; margin-top: 30px !important;
width: 90vw !important;
} }
.no-padding-dialog .caption { .no-padding-dialog .caption {
position: absolute; position: absolute;
left: 20px; right: 30px;
bottom: 10px; bottom: 10px;
margin: 0 auto; margin: 0 auto;
width: fit-content; width: fit-content;

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "استدعت الذكاء الاصطناعي أداة غير معروفة", "ai-invoke-unknown-tool": "استدعت الذكاء الاصطناعي أداة غير معروفة",
"click-edge-to-delete": "انقر على الحافة للحذف", "click-edge-to-delete": "انقر على الحافة للحذف",
"select-node-define-test-tomo": "اختر عقدة أخرى لتحديد طوبولوجيا الاختبار", "select-node-define-test-tomo": "اختر عقدة أخرى لتحديد طوبولوجيا الاختبار",
"tool-self-detect": "الفحص الذاتي للأداة" "tool-self-detect": "الفحص الذاتي للأداة",
"self-detect-caption": "انقر على خط الاتصال لإلغاء التوصيل، انقر على العقدة لإنشاء اتصال",
"diagram-node-empty": "لا توجد معلومات عن العقدة"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "KI hat ein unbekanntes Tool aufgerufen", "ai-invoke-unknown-tool": "KI hat ein unbekanntes Tool aufgerufen",
"click-edge-to-delete": "Klicken Sie auf die Kante, um sie zu löschen", "click-edge-to-delete": "Klicken Sie auf die Kante, um sie zu löschen",
"select-node-define-test-tomo": "Wählen Sie einen anderen Knoten aus, um die Testtopologie zu definieren", "select-node-define-test-tomo": "Wählen Sie einen anderen Knoten aus, um die Testtopologie zu definieren",
"tool-self-detect": "Werkzeug-Selbsttest" "tool-self-detect": "Werkzeug-Selbsttest",
"self-detect-caption": "Klicken Sie auf die Verbindungslinie, um die Verbindung aufzuheben, klicken Sie auf den Knoten, um eine Verbindung herzustellen",
"diagram-node-empty": "Keine Knoteninformationen"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "AI called an unknown tool", "ai-invoke-unknown-tool": "AI called an unknown tool",
"click-edge-to-delete": "Click the edge to delete", "click-edge-to-delete": "Click the edge to delete",
"select-node-define-test-tomo": "Select another node to define the test topology", "select-node-define-test-tomo": "Select another node to define the test topology",
"tool-self-detect": "Tool Self-Check" "tool-self-detect": "Tool Self-Check",
"self-detect-caption": "Click on the connection line to cancel the connection, click on the node to create a connection",
"diagram-node-empty": "No node information"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "L'IA a appelé un outil inconnu", "ai-invoke-unknown-tool": "L'IA a appelé un outil inconnu",
"click-edge-to-delete": "Cliquez sur le bord pour supprimer", "click-edge-to-delete": "Cliquez sur le bord pour supprimer",
"select-node-define-test-tomo": "Sélectionnez un autre nœud pour définir la topologie de test", "select-node-define-test-tomo": "Sélectionnez un autre nœud pour définir la topologie de test",
"tool-self-detect": "Auto-vérification de l'outil" "tool-self-detect": "Auto-vérification de l'outil",
"self-detect-caption": "Cliquez sur la ligne de connexion pour annuler la connexion, cliquez sur le nœud pour créer une connexion",
"diagram-node-empty": "Aucune information sur le nœud"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "AIが未知のツールを呼び出しました", "ai-invoke-unknown-tool": "AIが未知のツールを呼び出しました",
"click-edge-to-delete": "クリックして削除", "click-edge-to-delete": "クリックして削除",
"select-node-define-test-tomo": "テストトポロジを定義するために別のノードを選択してください", "select-node-define-test-tomo": "テストトポロジを定義するために別のノードを選択してください",
"tool-self-detect": "ツール自己診断" "tool-self-detect": "ツール自己診断",
"self-detect-caption": "接続線をクリックして接続を解除し、ノードをクリックして接続を作成します",
"diagram-node-empty": "ノード情報なし"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "AI가 알 수 없는 도구를 호출했습니다", "ai-invoke-unknown-tool": "AI가 알 수 없는 도구를 호출했습니다",
"click-edge-to-delete": "가장자리를 클릭하여 삭제", "click-edge-to-delete": "가장자리를 클릭하여 삭제",
"select-node-define-test-tomo": "테스트 토폴로지를 정의하려면 다른 노드를 선택하세요", "select-node-define-test-tomo": "테스트 토폴로지를 정의하려면 다른 노드를 선택하세요",
"tool-self-detect": "도구 자체 점검" "tool-self-detect": "도구 자체 점검",
"self-detect-caption": "연결선을 클릭하여 연결을 취소하고, 노드를 클릭하여 연결을 생성합니다",
"diagram-node-empty": "노드 정보 없음"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "ИИ вызвал неизвестный инструмент", "ai-invoke-unknown-tool": "ИИ вызвал неизвестный инструмент",
"click-edge-to-delete": "Нажмите на край, чтобы удалить", "click-edge-to-delete": "Нажмите на край, чтобы удалить",
"select-node-define-test-tomo": "Выберите другой узел для определения тестовой топологии", "select-node-define-test-tomo": "Выберите другой узел для определения тестовой топологии",
"tool-self-detect": "Самопроверка инструмента" "tool-self-detect": "Самопроверка инструмента",
"self-detect-caption": "Нажмите на линию соединения, чтобы отменить соединение, нажмите на узел, чтобы создать соединение",
"diagram-node-empty": "Нет информации об узле"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "AI 调用了未知的工具", "ai-invoke-unknown-tool": "AI 调用了未知的工具",
"click-edge-to-delete": "点击边以删除", "click-edge-to-delete": "点击边以删除",
"select-node-define-test-tomo": "选择另一个节点以定义测试拓扑", "select-node-define-test-tomo": "选择另一个节点以定义测试拓扑",
"tool-self-detect": "工具自检" "tool-self-detect": "工具自检",
"self-detect-caption": "点击连接线取消连接,点击节点以创建连接",
"diagram-node-empty": "暂无节点信息"
} }

View File

@ -195,5 +195,7 @@
"ai-invoke-unknown-tool": "AI調用了未知的工具", "ai-invoke-unknown-tool": "AI調用了未知的工具",
"click-edge-to-delete": "點擊邊緣以刪除", "click-edge-to-delete": "點擊邊緣以刪除",
"select-node-define-test-tomo": "選擇另一個節點以定義測試拓撲", "select-node-define-test-tomo": "選擇另一個節點以定義測試拓撲",
"tool-self-detect": "工具自檢" "tool-self-detect": "工具自檢",
"self-detect-caption": "點擊連接線取消連接,點擊節點以創建連接",
"diagram-node-empty": "暫無節點資訊"
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,169 @@
import { readFileSync, writeFileSync } from 'fs';
import fetch from 'node-fetch';
import path from 'path';
import { OpenAI } from 'openai';
import chalk from 'chalk';
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 };
}
console.log(chalk.green('Starting to update contributors...'));
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);

View File

@ -2,6 +2,7 @@ import * as vscode from 'vscode';
import { setRunningCWD, setVscodeWorkspace } from '../openmcp-sdk/service/index.js'; import { setRunningCWD, setVscodeWorkspace } from '../openmcp-sdk/service/index.js';
import { launch } from './common/entry.js'; import { launch } from './common/entry.js';
import { initialiseI18n, getAvailableKeys } from './i18n/index.js'; import { initialiseI18n, getAvailableKeys } from './i18n/index.js';
import { checkNews } from './webview/webview.service.js';
export function activate(context: vscode.ExtensionContext) { export function activate(context: vscode.ExtensionContext) {
console.log('activate openmcp'); console.log('activate openmcp');
@ -19,6 +20,7 @@ export function activate(context: vscode.ExtensionContext) {
console.log('Available i18n keys:', getAvailableKeys().length); console.log('Available i18n keys:', getAvailableKeys().length);
launch(context); launch(context);
checkNews(context);
} }

View File

@ -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,4 +40,8 @@ export class HookController {
} }
} }
@RegisterCommand('openmcp.hook.test-news')
async testNews(context: vscode.ExtensionContext) {
revealOpenMcpNewsWebviewPanel(context);
}
} }

View File

@ -18,9 +18,6 @@ export function getWebviewContent(context: vscode.ExtensionContext, panel: vscod
return replaceHref; return replaceHref;
}); });
console.log(html);
return html; return html;
} }
@ -150,3 +147,53 @@ export function getDefaultLanunchSignature(path: string, cwd: string) {
}; };
} }
} }
export function getNewsWebviewContent(context: vscode.ExtensionContext, panel: vscode.WebviewPanel): string | undefined {
const viewRoot = fspath.join(context.extensionPath, 'resources', 'changelog');
const htmlIndexPath = fspath.join(viewRoot, 'index.html');
const html = fs.readFileSync(htmlIndexPath, { encoding: 'utf-8' });
return html;
}
export function revealOpenMcpNewsWebviewPanel(
context: vscode.ExtensionContext,
) {
const panel = vscode.window.createWebviewPanel(
'What\'s new in OpenMCP',
'What\'s new in OpenMCP',
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
enableFindWidget: true
}
);
// 设置HTML内容
const html = getNewsWebviewContent(context, panel);
panel.webview.html = html || '';
panel.iconPath = vscode.Uri.file(fspath.join(context.extensionPath, 'openmcp-sdk', 'renderer', 'images', 'openmcp.png'));
panel.onDidDispose(async () => {
// 退出
panel.dispose();
});
return panel;
}
export async function checkNews(context: vscode.ExtensionContext) {
const versionKey = 'openmcp-news-version';
const lastVersion = context.globalState.get<string>(versionKey) || '';
const currentVersion = context.extension.packageJSON.version;
if (lastVersion !== currentVersion) {
// 记录新版本
await context.globalState.update(versionKey, currentVersion);
// 展示新闻面板
revealOpenMcpNewsWebviewPanel(context);
}
}

896
yarn.lock

File diff suppressed because it is too large Load Diff