解决无法重新连接的问题 | 优化调试器布局
This commit is contained in:
parent
69b907901f
commit
471ad41c8e
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-scrollbar height="100%">
|
||||||
<div class="prompt-module">
|
<div class="prompt-module">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<h2>
|
<h2>
|
||||||
@ -7,21 +8,16 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<h3><code>prompts/list</code></h3>
|
<h3><code>prompts/list</code></h3>
|
||||||
|
|
||||||
<PromptTemplates
|
<PromptTemplates :tab-id="props.tabId"></PromptTemplates>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></PromptTemplates>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<PromptReader
|
<PromptReader :tab-id="props.tabId"></PromptReader>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></PromptReader>
|
|
||||||
|
|
||||||
<PromptLogger
|
<PromptLogger :tab-id="props.tabId"></PromptLogger>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></PromptLogger>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-scrollbar height="100%">
|
||||||
<div class="resource-module">
|
<div class="resource-module">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<h2>
|
<h2>
|
||||||
@ -21,7 +22,8 @@
|
|||||||
:tab-id="props.tabId"
|
:tab-id="props.tabId"
|
||||||
></ResourceLogger>
|
></ResourceLogger>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-scrollbar height="100%">
|
||||||
<div class="tool-module">
|
<div class="tool-module">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<h2>
|
<h2>
|
||||||
@ -7,21 +8,17 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<h3><code>tools/list</code></h3>
|
<h3><code>tools/list</code></h3>
|
||||||
|
|
||||||
<ToolList
|
<ToolList :tab-id="props.tabId"></ToolList>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></ToolList>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<ToolExecutor
|
<ToolExecutor :tab-id="props.tabId"></ToolExecutor>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></ToolExecutor>
|
|
||||||
|
|
||||||
<ToolLogger
|
<ToolLogger :tab-id="props.tabId"></ToolLogger>
|
||||||
:tab-id="props.tabId"
|
|
||||||
></ToolLogger>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
<div class="tool-executor-container">
|
<div class="tool-executor-container">
|
||||||
<el-form :model="formData" :rules="formRules" ref="formRef" label-position="top">
|
<el-form :model="formData" :rules="formRules" ref="formRef" label-position="top">
|
||||||
<template v-if="currentTool?.inputSchema?.properties">
|
<template v-if="currentTool?.inputSchema?.properties">
|
||||||
<el-scrollbar height="150px">
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-for="[name, property] in Object.entries(currentTool.inputSchema.properties)"
|
v-for="[name, property] in Object.entries(currentTool.inputSchema.properties)"
|
||||||
:key="name"
|
:key="name"
|
||||||
@ -34,7 +33,6 @@
|
|||||||
v-model="formData[name]"
|
v-model="formData[name]"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-scrollbar>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<el-scrollbar height="300px">
|
<el-scrollbar height="500px">
|
||||||
<div
|
<div
|
||||||
class="output-content"
|
class="output-content"
|
||||||
contenteditable="false"
|
contenteditable="false"
|
||||||
@ -95,7 +95,7 @@ const formattedJson = computed(() => {
|
|||||||
.tool-logger .output-content {
|
.tool-logger .output-content {
|
||||||
border-radius: .5em;
|
border-radius: .5em;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
min-height: 300px;
|
min-height: 450px;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
font-family: var(--code-font-family);
|
font-family: var(--code-font-family);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
@ -81,6 +81,7 @@ export function doConnect() {
|
|||||||
resolve(void 0);
|
resolve(void 0);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
|
|
||||||
|
// TODO: 增加判断,获取 cwd
|
||||||
if (connectionMethods.current === 'STDIO') {
|
if (connectionMethods.current === 'STDIO') {
|
||||||
|
|
||||||
if (connectionArgs.commandString.length === 0) {
|
if (connectionArgs.commandString.length === 0) {
|
||||||
@ -124,20 +125,26 @@ export function doConnect() {
|
|||||||
/**
|
/**
|
||||||
* @description vscode 中初始化启动
|
* @description vscode 中初始化启动
|
||||||
*/
|
*/
|
||||||
export async function launchConnect() {
|
export async function launchConnect(option: { updateCommandString?: boolean } = {}) {
|
||||||
// 本地开发只用 IPC 进行启动
|
// 本地开发只用 IPC 进行启动
|
||||||
// 后续需要考虑到不同的连接方式
|
// 后续需要考虑到不同的连接方式
|
||||||
|
|
||||||
|
const {
|
||||||
|
updateCommandString = true
|
||||||
|
} = option;
|
||||||
|
|
||||||
connectionMethods.current = 'STDIO';
|
connectionMethods.current = 'STDIO';
|
||||||
const bridge = useMessageBridge();
|
const bridge = useMessageBridge();
|
||||||
|
|
||||||
pinkLog('请求启动参数');
|
pinkLog('请求启动参数');
|
||||||
const { commandString, cwd } = await getLaunchCommand();
|
const { commandString, cwd } = await getLaunchCommand();
|
||||||
connectionArgs.commandString = commandString;
|
|
||||||
|
|
||||||
|
if (updateCommandString) {
|
||||||
|
connectionArgs.commandString = commandString;
|
||||||
if (connectionArgs.commandString.length === 0) {
|
if (connectionArgs.commandString.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
// 监听 connect
|
// 监听 connect
|
||||||
@ -146,9 +153,17 @@ export async function launchConnect() {
|
|||||||
connectionResult.success = (code === 200);
|
connectionResult.success = (code === 200);
|
||||||
connectionResult.logString = msg;
|
connectionResult.logString = msg;
|
||||||
|
|
||||||
|
if (code === 200) {
|
||||||
const res = await getServerVersion() as { name: string, version: string };
|
const res = await getServerVersion() as { name: string, version: string };
|
||||||
connectionResult.serverInfo.name = res.name || '';
|
connectionResult.serverInfo.name = res.name || '';
|
||||||
connectionResult.serverInfo.version = res.version || '';
|
connectionResult.serverInfo.version = res.version || '';
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'error',
|
||||||
|
message: msg
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
resolve(void 0);
|
resolve(void 0);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="large"
|
size="large"
|
||||||
:disabled="!connectionResult"
|
:disabled="!connectionResult"
|
||||||
@click="doConnect()"
|
@click="suitableConnect()"
|
||||||
>
|
>
|
||||||
{{ t('connect.appearance.connect') }}
|
{{ t('connect.appearance.connect') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -38,7 +38,7 @@ import { useI18n } from 'vue-i18n';
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
import { connectionResult, doConnect, doReconnect } from './connection';
|
import { connectionResult, doConnect, doReconnect, launchConnect } from './connection';
|
||||||
|
|
||||||
import ConnectionMethod from './connection-method.vue';
|
import ConnectionMethod from './connection-method.vue';
|
||||||
import ConnectionArgs from './connection-args.vue';
|
import ConnectionArgs from './connection-args.vue';
|
||||||
@ -46,7 +46,7 @@ import EnvVar from './env-var.vue';
|
|||||||
|
|
||||||
import ConnectionLog from './connection-log.vue';
|
import ConnectionLog from './connection-log.vue';
|
||||||
|
|
||||||
import { useMessageBridge } from '@/api/message-bridge';
|
import { acquireVsCodeApi, useMessageBridge } from '@/api/message-bridge';
|
||||||
|
|
||||||
defineComponent({ name: 'connect' });
|
defineComponent({ name: 'connect' });
|
||||||
|
|
||||||
@ -58,6 +58,13 @@ bridge.addCommandListener('connect', data => {
|
|||||||
connectionResult.logString = msg;
|
connectionResult.logString = msg;
|
||||||
}, { once: false });
|
}, { once: false });
|
||||||
|
|
||||||
|
function suitableConnect() {
|
||||||
|
if (acquireVsCodeApi === undefined) {
|
||||||
|
doConnect();
|
||||||
|
} else {
|
||||||
|
launchConnect({ updateCommandString: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
74
servers/bing-picture.py
Normal file
74
servers/bing-picture.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import requests
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Optional, List
|
||||||
|
from mcp.server.fastmcp import FastMCP
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
from urllib import parse
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import uuid
|
||||||
|
import time
|
||||||
|
from threading import Thread
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class ImageResult(BaseModel):
|
||||||
|
url: str
|
||||||
|
title: str
|
||||||
|
source: str
|
||||||
|
|
||||||
|
class BingImage:
|
||||||
|
path = 'https://cn.bing.com/images/search'
|
||||||
|
block_num = 35
|
||||||
|
headers = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
|
||||||
|
}
|
||||||
|
|
||||||
|
def bing_crawler(key_word: str, image_num: int) -> Optional[List[ImageResult]]:
|
||||||
|
query = {
|
||||||
|
'q': key_word,
|
||||||
|
'count': image_num
|
||||||
|
}
|
||||||
|
|
||||||
|
url = BingImage.path + '?' + parse.urlencode(query)
|
||||||
|
res = requests.get(url, headers=BingImage.headers)
|
||||||
|
|
||||||
|
soup = BeautifulSoup(res.content, "html.parser")
|
||||||
|
results = []
|
||||||
|
for a in soup.select('.iusc'):
|
||||||
|
href = a.attrs['href']
|
||||||
|
decode_href = parse.unquote(href)
|
||||||
|
media_url = decode_href.split('&')[4][9:]
|
||||||
|
title = a.get('alt', '')
|
||||||
|
|
||||||
|
results.append(ImageResult(
|
||||||
|
url=media_url,
|
||||||
|
title=title,
|
||||||
|
source="bing"
|
||||||
|
))
|
||||||
|
if len(results) >= image_num:
|
||||||
|
break
|
||||||
|
|
||||||
|
return results if results else None
|
||||||
|
|
||||||
|
mcp = FastMCP('image_crawler', version="0.0.1")
|
||||||
|
|
||||||
|
@mcp.tool(
|
||||||
|
name='image_crawler',
|
||||||
|
description='根据关键词从指定搜索引擎爬取图片'
|
||||||
|
)
|
||||||
|
def image_crawler_tool(key_word: str, image_num: int) -> str:
|
||||||
|
"""图片爬取工具,返回格式化字符串"""
|
||||||
|
images = bing_crawler(key_word, image_num)
|
||||||
|
return str(images)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
images = bing_crawler("明日方舟 m3", 5)
|
||||||
|
print(images)
|
@ -5,6 +5,7 @@ description = "Add your description here"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bs4>=0.0.2",
|
||||||
"mcp[cli]>=1.5.0",
|
"mcp[cli]>=1.5.0",
|
||||||
"requests>=2.32.3",
|
"requests>=2.32.3",
|
||||||
]
|
]
|
||||||
|
36
servers/uv.lock
generated
36
servers/uv.lock
generated
@ -25,6 +25,31 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
|
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "beautifulsoup4"
|
||||||
|
version = "4.13.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "soupsieve" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bs4"
|
||||||
|
version = "0.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "beautifulsoup4" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/aa/4acaf814ff901145da37332e05bb510452ebed97bc9602695059dd46ef39/bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925", size = 698 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/51/bb/bf7aab772a159614954d84aa832c129624ba6c32faa559dfb200a534e50b/bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc", size = 1189 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2025.1.31"
|
version = "2025.1.31"
|
||||||
@ -335,12 +360,14 @@ name = "servers"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
{ name = "bs4" },
|
||||||
{ name = "mcp", extra = ["cli"] },
|
{ name = "mcp", extra = ["cli"] },
|
||||||
{ name = "requests" },
|
{ name = "requests" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
|
{ name = "bs4", specifier = ">=0.0.2" },
|
||||||
{ name = "mcp", extras = ["cli"], specifier = ">=1.5.0" },
|
{ name = "mcp", extras = ["cli"], specifier = ">=1.5.0" },
|
||||||
{ name = "requests", specifier = ">=2.32.3" },
|
{ name = "requests", specifier = ">=2.32.3" },
|
||||||
]
|
]
|
||||||
@ -363,6 +390,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "soupsieve"
|
||||||
|
version = "2.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sse-starlette"
|
name = "sse-starlette"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
|
@ -63,21 +63,9 @@ export class MCPClient {
|
|||||||
this.transport = new StdioClientTransport({
|
this.transport = new StdioClientTransport({
|
||||||
command: this.options.command || '',
|
command: this.options.command || '',
|
||||||
args: this.options.args || [],
|
args: this.options.args || [],
|
||||||
cwd: this.options.cwd || process.cwd(),
|
cwd: this.options.cwd || process.cwd()
|
||||||
// TODO
|
|
||||||
stderr: 'pipe'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.transport.onmessage = (message) => {
|
|
||||||
console.log('Received message from server:', message);
|
|
||||||
this.transportStdErr += message;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.transport.onerror = (error) => {
|
|
||||||
console.log('Error from server:', error);
|
|
||||||
this.transportStdErr += error;
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'SSE':
|
case 'SSE':
|
||||||
if (!this.options.url) {
|
if (!this.options.url) {
|
||||||
|
@ -15,6 +15,9 @@ let client: MCPClient | undefined = undefined;
|
|||||||
|
|
||||||
function tryGetRunCommandError(command: string, args: string[] = [], cwd?: string): string | null {
|
function tryGetRunCommandError(command: string, args: string[] = [], cwd?: string): string | null {
|
||||||
try {
|
try {
|
||||||
|
console.log('current command', command);
|
||||||
|
console.log('current args', args);
|
||||||
|
|
||||||
const result = spawnSync(command, args, {
|
const result = spawnSync(command, args, {
|
||||||
cwd: cwd || process.cwd(),
|
cwd: cwd || process.cwd(),
|
||||||
stdio: 'pipe',
|
stdio: 'pipe',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"currentIndex": 0,
|
"currentIndex": 2,
|
||||||
"tabs": [
|
"tabs": [
|
||||||
{
|
{
|
||||||
"name": "交互测试",
|
"name": "交互测试",
|
||||||
@ -43,6 +43,24 @@
|
|||||||
"systemPrompt": ""
|
"systemPrompt": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "工具",
|
||||||
|
"icon": "icon-tool",
|
||||||
|
"type": "blank",
|
||||||
|
"componentIndex": 2,
|
||||||
|
"storage": {
|
||||||
|
"currentToolName": "add"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "资源",
|
||||||
|
"icon": "icon-file",
|
||||||
|
"type": "blank",
|
||||||
|
"componentIndex": 0,
|
||||||
|
"storage": {
|
||||||
|
"currentResourceName": "greeting"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user