Compare commits
17 Commits
fix/move-n
...
feat/mcp-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cd7f91fff | ||
|
|
ad7a043fb3 | ||
|
|
7db628702d | ||
|
|
866e8e8734 | ||
|
|
80e1784777 | ||
|
|
0d760ffa2e | ||
|
|
88f7e6a854 | ||
|
|
44d2cb345f | ||
|
|
49eec68434 | ||
|
|
d5ae3e6edc | ||
|
|
6eedcc29ba | ||
|
|
71d35eddf7 | ||
|
|
9f1c8f2c17 | ||
|
|
651e9a529e | ||
|
|
f68f6e9896 | ||
|
|
2dcc68da87 | ||
|
|
1db259cd3e |
4
.github/workflows/claude-translator.yml
vendored
4
.github/workflows/claude-translator.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
# See: https://github.com/anthropics/claude-code-action/blob/main/docs/security.md
|
||||
github_token: ${{ secrets.TOKEN_GITHUB_WRITE }}
|
||||
allowed_non_write_users: "*"
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
anthropic_api_key: ${{ secrets.CLAUDE_TRANSLATOR_APIKEY }}
|
||||
claude_args: "--allowed-tools Bash(gh issue:*),Bash(gh api:repos/*/issues:*),Bash(gh api:repos/*/pulls/*/reviews/*),Bash(gh api:repos/*/pulls/comments/*)"
|
||||
prompt: |
|
||||
你是一个多语言翻译助手。你需要响应 GitHub Webhooks 中的以下四种事件:
|
||||
@@ -108,3 +108,5 @@ jobs:
|
||||
|
||||
使用以下命令获取完整信息:
|
||||
gh issue view ${{ github.event.issue.number }} --json title,body,comments
|
||||
env:
|
||||
ANTHROPIC_BASE_URL: ${{ secrets.CLAUDE_TRANSLATOR_BASEURL }}
|
||||
|
||||
@@ -372,6 +372,7 @@
|
||||
"app-builder-lib@npm:26.0.13": "patch:app-builder-lib@npm%3A26.0.13#~/.yarn/patches/app-builder-lib-npm-26.0.13-a064c9e1d0.patch",
|
||||
"app-builder-lib@npm:26.0.15": "patch:app-builder-lib@npm%3A26.0.15#~/.yarn/patches/app-builder-lib-npm-26.0.15-360e5b0476.patch",
|
||||
"atomically@npm:^1.7.0": "patch:atomically@npm%3A1.7.0#~/.yarn/patches/atomically-npm-1.7.0-e742e5293b.patch",
|
||||
"esbuild": "^0.25.0",
|
||||
"file-stream-rotator@npm:^0.6.1": "patch:file-stream-rotator@npm%3A0.6.1#~/.yarn/patches/file-stream-rotator-npm-0.6.1-eab45fb13d.patch",
|
||||
"libsql@npm:^0.4.4": "patch:libsql@npm%3A0.4.7#~/.yarn/patches/libsql-npm-0.4.7-444e260fb1.patch",
|
||||
"node-abi": "4.12.0",
|
||||
@@ -379,6 +380,7 @@
|
||||
"openai@npm:^4.87.3": "patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch",
|
||||
"pdf-parse@npm:1.1.1": "patch:pdf-parse@npm%3A1.1.1#~/.yarn/patches/pdf-parse-npm-1.1.1-04a6109b2a.patch",
|
||||
"pkce-challenge@npm:^4.1.0": "patch:pkce-challenge@npm%3A4.1.0#~/.yarn/patches/pkce-challenge-npm-4.1.0-fbc51695a3.patch",
|
||||
"tar-fs": "^2.1.4",
|
||||
"undici": "6.21.2",
|
||||
"vite": "npm:rolldown-vite@latest",
|
||||
"tesseract.js@npm:*": "patch:tesseract.js@npm%3A6.0.1#~/.yarn/patches/tesseract.js-npm-6.0.1-2562a7e46d.patch",
|
||||
|
||||
@@ -96,6 +96,9 @@ export enum IpcChannel {
|
||||
AgentMessage_PersistExchange = 'agent-message:persist-exchange',
|
||||
AgentMessage_GetHistory = 'agent-message:get-history',
|
||||
|
||||
// JavaScript
|
||||
Js_Execute = 'js:execute',
|
||||
|
||||
//copilot
|
||||
Copilot_GetAuthMessage = 'copilot:get-auth-message',
|
||||
Copilot_GetCopilotToken = 'copilot:get-copilot-token',
|
||||
|
||||
BIN
resources/wasm/qjs-wasi.wasm
Normal file
BIN
resources/wasm/qjs-wasi.wasm
Normal file
Binary file not shown.
@@ -37,6 +37,7 @@ import DxtService from './services/DxtService'
|
||||
import { ExportService } from './services/ExportService'
|
||||
import { fileStorage as fileManager } from './services/FileStorage'
|
||||
import FileService from './services/FileSystemService'
|
||||
import { jsService } from './services/JsService'
|
||||
import KnowledgeService from './services/KnowledgeService'
|
||||
import mcpService from './services/MCPService'
|
||||
import MemoryService from './services/memory/MemoryService'
|
||||
@@ -741,6 +742,11 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
}
|
||||
)
|
||||
|
||||
// Register JavaScript execution handler
|
||||
ipcMain.handle(IpcChannel.Js_Execute, async (_, code: string, timeout?: number) => {
|
||||
return await jsService.executeScript(code, { timeout })
|
||||
})
|
||||
|
||||
ipcMain.handle(IpcChannel.App_IsBinaryExist, (_, name: string) => isBinaryExists(name))
|
||||
ipcMain.handle(IpcChannel.App_GetBinaryPath, (_, name: string) => getBinaryPath(name))
|
||||
ipcMain.handle(IpcChannel.App_InstallUvBinary, () => runInstallScript('install-uv.js'))
|
||||
|
||||
@@ -6,6 +6,7 @@ import BraveSearchServer from './brave-search'
|
||||
import DifyKnowledgeServer from './dify-knowledge'
|
||||
import FetchServer from './fetch'
|
||||
import FileSystemServer from './filesystem'
|
||||
import JsServer from './js'
|
||||
import MemoryServer from './memory'
|
||||
import PythonServer from './python'
|
||||
import ThinkingServer from './sequentialthinking'
|
||||
@@ -42,6 +43,9 @@ export function createInMemoryMCPServer(
|
||||
case BuiltinMCPServerNames.python: {
|
||||
return new PythonServer().server
|
||||
}
|
||||
case BuiltinMCPServerNames.js: {
|
||||
return new JsServer().server
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unknown in-memory MCP server: ${name}`)
|
||||
}
|
||||
|
||||
139
src/main/mcpServers/js.ts
Normal file
139
src/main/mcpServers/js.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
// port from https://github.com/jlucaso1/mcp-javascript-sandbox
|
||||
import { loggerService } from '@logger'
|
||||
import { jsService } from '@main/services/JsService'
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
||||
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types'
|
||||
import * as z from 'zod'
|
||||
|
||||
const TOOL_NAME = 'run_javascript_code'
|
||||
const DEFAULT_TIMEOUT = 60_000
|
||||
|
||||
export const RequestPayloadSchema = z.object({
|
||||
javascript_code: z.string().min(1).describe('The JavaScript code to execute in the sandbox.'),
|
||||
timeout: z
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.max(5 * 60_000)
|
||||
.optional()
|
||||
.describe('Execution timeout in milliseconds (default 60000, max 300000).')
|
||||
})
|
||||
|
||||
const logger = loggerService.withContext('MCPServer:JavaScript')
|
||||
|
||||
function formatExecutionResult(result: {
|
||||
stdout: string
|
||||
stderr: string
|
||||
error?: string | undefined
|
||||
exitCode: number
|
||||
}) {
|
||||
let combinedOutput = ''
|
||||
if (result.stdout) {
|
||||
combinedOutput += result.stdout
|
||||
}
|
||||
if (result.stderr) {
|
||||
combinedOutput += `--- stderr ---\n${result.stderr}\n--- stderr ---\n`
|
||||
}
|
||||
if (result.error) {
|
||||
combinedOutput += `--- Execution Error ---\n${result.error}\n--- Execution Error ---\n`
|
||||
}
|
||||
|
||||
const isError = Boolean(result.error) || Boolean(result.stderr?.trim()) || result.exitCode !== 0
|
||||
|
||||
return {
|
||||
combinedOutput: combinedOutput.trim(),
|
||||
isError
|
||||
}
|
||||
}
|
||||
|
||||
class JsServer {
|
||||
public server: Server
|
||||
|
||||
constructor() {
|
||||
this.server = new Server(
|
||||
{
|
||||
name: 'MCP QuickJS Runner',
|
||||
version: '1.0.0',
|
||||
description: 'An MCP server that provides a tool to execute JavaScript code in a QuickJS WASM sandbox.'
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
tools: {}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
this.setupHandlers()
|
||||
}
|
||||
|
||||
private setupHandlers() {
|
||||
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: [
|
||||
{
|
||||
name: TOOL_NAME,
|
||||
description:
|
||||
'Executes the provided JavaScript code in a secure WASM sandbox (QuickJS). Returns stdout and stderr. Non-zero exit code indicates an error.',
|
||||
inputSchema: z.toJSONSchema(RequestPayloadSchema)
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params
|
||||
|
||||
if (name !== TOOL_NAME) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Tool not found: ${name}` }],
|
||||
isError: true
|
||||
}
|
||||
}
|
||||
|
||||
const parseResult = RequestPayloadSchema.safeParse(args)
|
||||
if (!parseResult.success) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Invalid arguments: ${parseResult.error.message}` }],
|
||||
isError: true
|
||||
}
|
||||
}
|
||||
|
||||
const { javascript_code, timeout } = parseResult.data
|
||||
|
||||
try {
|
||||
logger.debug('Executing JavaScript code via JsService')
|
||||
const result = await jsService.executeScript(javascript_code, {
|
||||
timeout: timeout ?? DEFAULT_TIMEOUT
|
||||
})
|
||||
|
||||
const { combinedOutput, isError } = formatExecutionResult(result)
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: combinedOutput
|
||||
}
|
||||
],
|
||||
isError
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
logger.error(`JavaScript execution failed: ${message}`)
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Server error during tool execution: ${message}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default JsServer
|
||||
115
src/main/services/JsService.ts
Normal file
115
src/main/services/JsService.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { loggerService } from '@logger'
|
||||
|
||||
import type { JsExecutionResult } from './workers/JsWorker'
|
||||
// oxlint-disable-next-line default
|
||||
import createJsWorker from './workers/JsWorker?nodeWorker'
|
||||
|
||||
interface ExecuteScriptOptions {
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
type WorkerResponse =
|
||||
| {
|
||||
success: true
|
||||
result: JsExecutionResult
|
||||
}
|
||||
| {
|
||||
success: false
|
||||
error: string
|
||||
}
|
||||
|
||||
const DEFAULT_TIMEOUT = 60_000
|
||||
|
||||
const logger = loggerService.withContext('JsService')
|
||||
|
||||
export class JsService {
|
||||
private static instance: JsService | null = null
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): JsService {
|
||||
if (!JsService.instance) {
|
||||
JsService.instance = new JsService()
|
||||
}
|
||||
return JsService.instance
|
||||
}
|
||||
|
||||
public async executeScript(code: string, options: ExecuteScriptOptions = {}): Promise<JsExecutionResult> {
|
||||
const { timeout = DEFAULT_TIMEOUT } = options
|
||||
|
||||
if (!code || typeof code !== 'string') {
|
||||
throw new Error('JavaScript code must be a non-empty string')
|
||||
}
|
||||
|
||||
// Limit code size to 1MB to prevent memory issues
|
||||
const MAX_CODE_SIZE = 1_000_000
|
||||
if (code.length > MAX_CODE_SIZE) {
|
||||
throw new Error(`JavaScript code exceeds maximum size of ${MAX_CODE_SIZE / 1_000_000}MB`)
|
||||
}
|
||||
|
||||
return new Promise<JsExecutionResult>((resolve, reject) => {
|
||||
const worker = createJsWorker({
|
||||
workerData: { code },
|
||||
argv: [],
|
||||
trackUnmanagedFds: false
|
||||
})
|
||||
|
||||
let settled = false
|
||||
let timeoutId: NodeJS.Timeout | null = null
|
||||
|
||||
const cleanup = async () => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = null
|
||||
}
|
||||
try {
|
||||
await worker.terminate()
|
||||
} catch {
|
||||
// ignore termination errors
|
||||
}
|
||||
}
|
||||
|
||||
const settleSuccess = async (result: JsExecutionResult) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
await cleanup()
|
||||
resolve(result)
|
||||
}
|
||||
|
||||
const settleError = async (error: Error) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
await cleanup()
|
||||
reject(error)
|
||||
}
|
||||
|
||||
worker.once('message', async (message: WorkerResponse) => {
|
||||
if (message.success) {
|
||||
await settleSuccess(message.result)
|
||||
} else {
|
||||
await settleError(new Error(message.error))
|
||||
}
|
||||
})
|
||||
|
||||
worker.once('error', async (error) => {
|
||||
logger.error(`JsWorker error: ${error instanceof Error ? error.message : String(error)}`)
|
||||
await settleError(error instanceof Error ? error : new Error(String(error)))
|
||||
})
|
||||
|
||||
worker.once('exit', async (exitCode) => {
|
||||
if (!settled && exitCode !== 0) {
|
||||
await settleError(new Error(`JsWorker exited with code ${exitCode}`))
|
||||
}
|
||||
})
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
logger.warn(`JavaScript execution timed out after ${timeout}ms`)
|
||||
settleError(new Error('JavaScript execution timed out')).catch((err) => {
|
||||
logger.error('Error during timeout cleanup:', err instanceof Error ? err : new Error(String(err)))
|
||||
})
|
||||
}, timeout)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const jsService = JsService.getInstance()
|
||||
118
src/main/services/workers/JsWorker.ts
Normal file
118
src/main/services/workers/JsWorker.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { mkdtemp, open, readFile, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { WASI } from 'node:wasi'
|
||||
import { parentPort, workerData } from 'node:worker_threads'
|
||||
|
||||
import loadWasm from '../../../../resources/wasm/qjs-wasi.wasm?loader'
|
||||
|
||||
interface WorkerPayload {
|
||||
code: string
|
||||
}
|
||||
|
||||
export interface JsExecutionResult {
|
||||
stdout: string
|
||||
stderr: string
|
||||
error?: string
|
||||
exitCode: number
|
||||
}
|
||||
|
||||
if (!parentPort) {
|
||||
throw new Error('JsWorker requires a parent port')
|
||||
}
|
||||
|
||||
async function runQuickJsInSandbox(jsCode: string): Promise<JsExecutionResult> {
|
||||
let tempDir: string | undefined
|
||||
let stdoutHandle: Awaited<ReturnType<typeof open>> | undefined
|
||||
let stderrHandle: Awaited<ReturnType<typeof open>> | undefined
|
||||
let stdoutPath: string | undefined
|
||||
let stderrPath: string | undefined
|
||||
|
||||
try {
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'quickjs-wasi-'))
|
||||
stdoutPath = join(tempDir, 'stdout.log')
|
||||
stderrPath = join(tempDir, 'stderr.log')
|
||||
|
||||
stdoutHandle = await open(stdoutPath, 'w')
|
||||
stderrHandle = await open(stderrPath, 'w')
|
||||
|
||||
const wasi = new WASI({
|
||||
version: 'preview1',
|
||||
args: ['qjs', '-e', jsCode],
|
||||
env: {}, // Empty environment for security - don't expose host env vars
|
||||
stdin: 0,
|
||||
stdout: stdoutHandle.fd,
|
||||
stderr: stderrHandle.fd,
|
||||
returnOnExit: true
|
||||
})
|
||||
const instance = await loadWasm(wasi.getImportObject() as WebAssembly.Imports)
|
||||
|
||||
let exitCode = 0
|
||||
try {
|
||||
exitCode = wasi.start(instance)
|
||||
} catch (wasiError: any) {
|
||||
return {
|
||||
stdout: '',
|
||||
stderr: `WASI start error: ${wasiError?.message ?? String(wasiError)}`,
|
||||
error: `Sandbox execution failed during start: ${wasiError?.message ?? String(wasiError)}`,
|
||||
exitCode: -1
|
||||
}
|
||||
}
|
||||
|
||||
// Close handles before reading files to prevent descriptor leak
|
||||
const _stdoutHandle = stdoutHandle
|
||||
stdoutHandle = undefined
|
||||
await _stdoutHandle.close()
|
||||
|
||||
const _stderrHandle = stderrHandle
|
||||
stderrHandle = undefined
|
||||
await _stderrHandle.close()
|
||||
|
||||
const capturedStdout = await readFile(stdoutPath, 'utf8')
|
||||
const capturedStderr = await readFile(stderrPath, 'utf8')
|
||||
|
||||
let executionError: string | undefined
|
||||
if (exitCode !== 0) {
|
||||
executionError = `QuickJS process exited with code ${exitCode}. Check stderr for details.`
|
||||
}
|
||||
|
||||
return {
|
||||
stdout: capturedStdout,
|
||||
stderr: capturedStderr,
|
||||
error: executionError,
|
||||
exitCode
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
stdout: '',
|
||||
stderr: '',
|
||||
error: `Sandbox setup or execution failed: ${error?.message ?? String(error)}`,
|
||||
exitCode: -1
|
||||
}
|
||||
} finally {
|
||||
if (stdoutHandle) await stdoutHandle.close()
|
||||
if (stderrHandle) await stderrHandle.close()
|
||||
if (tempDir) {
|
||||
await rm(tempDir, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function execute(code: string) {
|
||||
return runQuickJsInSandbox(code)
|
||||
}
|
||||
|
||||
const payload = workerData as WorkerPayload | undefined
|
||||
|
||||
if (!payload?.code || typeof payload.code !== 'string') {
|
||||
parentPort.postMessage({ success: false, error: 'JavaScript code must be provided to the worker' })
|
||||
} else {
|
||||
execute(payload.code)
|
||||
.then((result) => {
|
||||
parentPort?.postMessage({ success: true, result })
|
||||
})
|
||||
.catch((error: any) => {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
parentPort?.postMessage({ success: false, error: errorMessage })
|
||||
})
|
||||
}
|
||||
@@ -345,6 +345,9 @@ const api = {
|
||||
execute: (script: string, context?: Record<string, any>, timeout?: number) =>
|
||||
ipcRenderer.invoke(IpcChannel.Python_Execute, script, context, timeout)
|
||||
},
|
||||
js: {
|
||||
execute: (code: string, timeout?: number) => ipcRenderer.invoke(IpcChannel.Js_Execute, code, timeout)
|
||||
},
|
||||
shell: {
|
||||
openExternal: (url: string, options?: Electron.OpenExternalOptions) => shell.openExternal(url, options)
|
||||
},
|
||||
|
||||
@@ -87,7 +87,8 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
||||
const [tools, setTools] = useState<ActionTool[]>([])
|
||||
|
||||
const isExecutable = useMemo(() => {
|
||||
return codeExecution.enabled && language === 'python'
|
||||
const executableLanguages = ['python', 'py', 'javascript', 'js']
|
||||
return codeExecution.enabled && executableLanguages.includes(language.toLowerCase())
|
||||
}, [codeExecution.enabled, language])
|
||||
|
||||
const sourceViewRef = useRef<CodeEditorHandles>(null)
|
||||
@@ -152,21 +153,49 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
||||
setIsRunning(true)
|
||||
setExecutionResult(null)
|
||||
|
||||
pyodideService
|
||||
.runScript(children, {}, codeExecution.timeoutMinutes * 60000)
|
||||
.then((result) => {
|
||||
setExecutionResult(result)
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Unexpected error:', error)
|
||||
setExecutionResult({
|
||||
text: `Unexpected error: ${error.message || 'Unknown error'}`
|
||||
const isPython = ['python', 'py'].includes(language.toLowerCase())
|
||||
const isJavaScript = ['javascript', 'js'].includes(language.toLowerCase())
|
||||
|
||||
if (isPython) {
|
||||
pyodideService
|
||||
.runScript(children, {}, codeExecution.timeoutMinutes * 60000)
|
||||
.then((result) => {
|
||||
setExecutionResult(result)
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
setIsRunning(false)
|
||||
})
|
||||
}, [children, codeExecution.timeoutMinutes])
|
||||
.catch((error) => {
|
||||
logger.error('Unexpected error:', error)
|
||||
setExecutionResult({
|
||||
text: `Unexpected error: ${error.message || 'Unknown error'}`
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
setIsRunning(false)
|
||||
})
|
||||
} else if (isJavaScript) {
|
||||
window.api.js
|
||||
.execute(children, codeExecution.timeoutMinutes * 60000)
|
||||
.then((result) => {
|
||||
if (result.error) {
|
||||
setExecutionResult({
|
||||
text: `Error: ${result.error}\n${result.stderr || ''}`
|
||||
})
|
||||
} else {
|
||||
setExecutionResult({
|
||||
text: result.stdout || (result.stderr ? `stderr: ${result.stderr}` : 'Execution completed')
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Unexpected error:', error)
|
||||
setExecutionResult({
|
||||
text: `Unexpected error: ${error.message || 'Unknown error'}`
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
setIsRunning(false)
|
||||
})
|
||||
}
|
||||
}, [children, codeExecution.timeoutMinutes, language])
|
||||
|
||||
const showPreviewTools = useMemo(() => {
|
||||
return viewMode !== 'source' && hasSpecialView
|
||||
|
||||
@@ -329,7 +329,8 @@ const builtInMcpDescriptionKeyMap: Record<BuiltinMCPServerName, string> = {
|
||||
[BuiltinMCPServerNames.fetch]: 'settings.mcp.builtinServersDescriptions.fetch',
|
||||
[BuiltinMCPServerNames.filesystem]: 'settings.mcp.builtinServersDescriptions.filesystem',
|
||||
[BuiltinMCPServerNames.difyKnowledge]: 'settings.mcp.builtinServersDescriptions.dify_knowledge',
|
||||
[BuiltinMCPServerNames.python]: 'settings.mcp.builtinServersDescriptions.python'
|
||||
[BuiltinMCPServerNames.python]: 'settings.mcp.builtinServersDescriptions.python',
|
||||
[BuiltinMCPServerNames.js]: 'settings.mcp.builtinServersDescriptions.js'
|
||||
} as const
|
||||
|
||||
export const getBuiltInMcpServerDescriptionLabel = (key: string): string => {
|
||||
|
||||
@@ -3571,6 +3571,7 @@
|
||||
"dify_knowledge": "Dify's MCP server implementation provides a simple API to interact with Dify. Requires configuring the Dify Key",
|
||||
"fetch": "MCP server for retrieving URL web content",
|
||||
"filesystem": "A Node.js server implementing the Model Context Protocol (MCP) for file system operations. Requires configuration of directories allowed for access.",
|
||||
"js": "Execute JavaScript code in a secure sandbox environment. Run JavaScript using QuickJS, supporting most standard libraries and popular third-party libraries.",
|
||||
"mcp_auto_install": "Automatically install MCP service (beta)",
|
||||
"memory": "Persistent memory implementation based on a local knowledge graph. This enables the model to remember user-related information across different conversations. Requires configuring the MEMORY_FILE_PATH environment variable.",
|
||||
"no": "No description",
|
||||
|
||||
@@ -3571,6 +3571,7 @@
|
||||
"dify_knowledge": "Dify 的 MCP 服务器实现,提供了一个简单的 API 来与 Dify 进行交互。需要配置 Dify Key",
|
||||
"fetch": "用于获取 URL 网页内容的 MCP 服务器",
|
||||
"filesystem": "实现文件系统操作的模型上下文协议(MCP)的 Node.js 服务器。需要配置允许访问的目录",
|
||||
"js": "在安全的沙盒环境中执行 JavaScript 代码。使用 quickJs 运行 JavaScript,支持大多数标准库和流行的第三方库",
|
||||
"mcp_auto_install": "自动安装 MCP 服务(测试版)",
|
||||
"memory": "基于本地知识图谱的持久性记忆基础实现。这使得模型能够在不同对话间记住用户的相关信息。需要配置 MEMORY_FILE_PATH 环境变量。",
|
||||
"no": "无描述",
|
||||
|
||||
@@ -3571,6 +3571,7 @@
|
||||
"dify_knowledge": "Dify 的 MCP 伺服器實現,提供了一個簡單的 API 來與 Dify 進行互動。需要配置 Dify Key",
|
||||
"fetch": "用於獲取 URL 網頁內容的 MCP 伺服器",
|
||||
"filesystem": "實現文件系統操作的模型上下文協議(MCP)的 Node.js 伺服器。需要配置允許訪問的目錄",
|
||||
"js": "在安全的沙盒環境中執行 JavaScript 程式碼。使用 quickJs 執行 JavaScript,支援大多數標準函式庫和流行的第三方函式庫",
|
||||
"mcp_auto_install": "自動安裝 MCP 服務(測試版)",
|
||||
"memory": "基於本地知識圖譜的持久性記憶基礎實現。這使得模型能夠在不同對話間記住使用者的相關資訊。需要配置 MEMORY_FILE_PATH 環境變數。",
|
||||
"no": "無描述",
|
||||
|
||||
@@ -535,7 +535,30 @@ const CollapsedContent: FC<{ isExpanded: boolean; resultString: string }> = ({ i
|
||||
}
|
||||
|
||||
const highlight = async () => {
|
||||
const result = await highlightCode(resultString, 'json')
|
||||
// 处理转义字符
|
||||
let processedString = resultString
|
||||
try {
|
||||
// 尝试解析字符串以处理可能的转义
|
||||
const parsed = JSON.parse(resultString)
|
||||
if (typeof parsed === 'string') {
|
||||
// 如果解析后是字符串,再次尝试解析(处理双重转义)
|
||||
try {
|
||||
const doubleParsed = JSON.parse(parsed)
|
||||
processedString = JSON.stringify(doubleParsed, null, 2)
|
||||
} catch {
|
||||
// 不是有效的 JSON,使用解析后的字符串
|
||||
processedString = parsed
|
||||
}
|
||||
} else {
|
||||
// 重新格式化 JSON
|
||||
processedString = JSON.stringify(parsed, null, 2)
|
||||
}
|
||||
} catch {
|
||||
// 解析失败,使用原始字符串
|
||||
processedString = resultString
|
||||
}
|
||||
|
||||
const result = await highlightCode(processedString, 'json')
|
||||
setStyledResult(result)
|
||||
}
|
||||
|
||||
|
||||
40
src/renderer/src/pages/home/Tabs/AgentSettingsTab.tsx
Normal file
40
src/renderer/src/pages/home/Tabs/AgentSettingsTab.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Button, Divider } from '@heroui/react'
|
||||
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||
import { AgentSettingsPopup } from '@renderer/pages/settings/AgentSettings'
|
||||
import AdvancedSettings from '@renderer/pages/settings/AgentSettings/AdvancedSettings'
|
||||
import AgentEssentialSettings from '@renderer/pages/settings/AgentSettings/AgentEssentialSettings'
|
||||
import { GetAgentResponse } from '@renderer/types/agent'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
interface Props {
|
||||
agent: GetAgentResponse | undefined | null
|
||||
update: ReturnType<typeof useUpdateAgent>['updateAgent']
|
||||
}
|
||||
|
||||
const AgentSettingsTab: FC<Props> = ({ agent, update }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const onMoreSetting = () => {
|
||||
if (agent?.id) {
|
||||
AgentSettingsPopup.show({ agentId: agent.id! })
|
||||
}
|
||||
}
|
||||
|
||||
if (!agent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-[var(--assistants-width)] p-2 px-3 pt-4">
|
||||
<AgentEssentialSettings agent={agent} update={update} showModelSetting={false} />
|
||||
<AdvancedSettings agentBase={agent} update={update} />
|
||||
<Divider className="my-2" />
|
||||
<Button size="sm" fullWidth onPress={onMoreSetting}>
|
||||
{t('settings.moresetting.label')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentSettingsTab
|
||||
@@ -116,8 +116,6 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<UnifiedAddButton onCreateAssistant={onCreateAssistant} />
|
||||
|
||||
{agentsLoading && <Spinner />}
|
||||
{apiServer.enabled && agentsError && <Alert color="danger" title={t('agent.list.error.failed')} />}
|
||||
|
||||
@@ -165,6 +163,8 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<UnifiedAddButton onCreateAssistant={onCreateAssistant} />
|
||||
|
||||
{!dragging && <div style={{ minHeight: 10 }}></div>}
|
||||
</Container>
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ const AddButton: FC<Props> = ({ children, className, ...props }) => {
|
||||
{...props}
|
||||
onPress={props.onPress}
|
||||
className={cn(
|
||||
'h-9 w-[calc(var(--assistants-width)-20px)] justify-start rounded-full bg-transparent px-3 text-[13px] text-[var(--color-text-2)] hover:bg-[var(--color-list-item)]',
|
||||
'h-9 w-[calc(var(--assistants-width)-20px)] justify-start rounded-lg bg-transparent px-3 text-[13px] text-[var(--color-text-2)] hover:bg-[var(--color-list-item)]',
|
||||
className
|
||||
)}
|
||||
startContent={<PlusIcon size={16} className="shrink-0" />}>
|
||||
|
||||
@@ -45,19 +45,12 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
||||
</AgentNameWrapper>
|
||||
</AssistantNameRow>
|
||||
<MenuButton>
|
||||
{isActive ? <SessionCount>{sessions.length}</SessionCount> : <Bot size={12} className="text-primary" />}
|
||||
{isActive ? <SessionCount>{sessions.length}</SessionCount> : <Bot size={14} className="text-primary" />}
|
||||
</MenuButton>
|
||||
</Container>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuItem
|
||||
key="edit"
|
||||
onClick={async () => {
|
||||
// onOpen()
|
||||
await AgentSettingsPopup.show({
|
||||
agentId: agent.id
|
||||
})
|
||||
}}>
|
||||
<ContextMenuItem key="edit" onClick={() => AgentSettingsPopup.show({ agentId: agent.id })}>
|
||||
<EditIcon size={14} />
|
||||
{t('common.edit')}
|
||||
</ContextMenuItem>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
||||
import { useAgent } from '@renderer/hooks/agents/useAgent'
|
||||
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
@@ -11,6 +13,7 @@ import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import AgentSettingsTab from './AgentSettingsTab'
|
||||
import Assistants from './AssistantsTab'
|
||||
import Settings from './SettingsTab'
|
||||
import Topics from './TopicsTab'
|
||||
@@ -41,11 +44,12 @@ const HomeTabs: FC<Props> = ({
|
||||
const { defaultAssistant } = useDefaultAssistant()
|
||||
const { toggleShowTopics } = useShowTopics()
|
||||
const { isLeftNavbar } = useNavbarPosition()
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { chat } = useRuntime()
|
||||
const { activeTopicOrSession } = chat
|
||||
const { activeTopicOrSession, activeAgentId } = chat
|
||||
const { agent } = useAgent(activeAgentId)
|
||||
const { updateAgent } = useUpdateAgent()
|
||||
|
||||
const isSessionView = activeTopicOrSession === 'session'
|
||||
const isTopicView = activeTopicOrSession === 'topic'
|
||||
|
||||
@@ -61,7 +65,6 @@ const HomeTabs: FC<Props> = ({
|
||||
}
|
||||
|
||||
const showTab = position === 'left' && topicPosition === 'left'
|
||||
const shouldShowSettingsTab = !isSessionView
|
||||
|
||||
const onCreateAssistant = async () => {
|
||||
const assistant = await AddAssistantPopup.show()
|
||||
@@ -104,12 +107,6 @@ const HomeTabs: FC<Props> = ({
|
||||
}
|
||||
}, [position, tab, topicPosition, forceToSeeAllTab])
|
||||
|
||||
useEffect(() => {
|
||||
if (activeTopicOrSession === 'session' && tab === 'settings') {
|
||||
setTab('topic')
|
||||
}
|
||||
}, [activeTopicOrSession, tab])
|
||||
|
||||
return (
|
||||
<Container
|
||||
style={{ ...border, ...style }}
|
||||
@@ -120,13 +117,11 @@ const HomeTabs: FC<Props> = ({
|
||||
{t('assistants.abbr')}
|
||||
</TabItem>
|
||||
<TabItem active={tab === 'topic'} onClick={() => setTab('topic')}>
|
||||
{isTopicView ? t('common.topics') : t('agent.session.label_other')}
|
||||
{t('common.topics')}
|
||||
</TabItem>
|
||||
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
||||
{t('settings.title')}
|
||||
</TabItem>
|
||||
{shouldShowSettingsTab && (
|
||||
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
||||
{t('settings.title')}
|
||||
</TabItem>
|
||||
)}
|
||||
</CustomTabs>
|
||||
)}
|
||||
|
||||
@@ -158,7 +153,8 @@ const HomeTabs: FC<Props> = ({
|
||||
position={position}
|
||||
/>
|
||||
)}
|
||||
{tab === 'settings' && shouldShowSettingsTab && <Settings assistant={activeAssistant} />}
|
||||
{tab === 'settings' && isTopicView && <Settings assistant={activeAssistant} />}
|
||||
{tab === 'settings' && isSessionView && <AgentSettingsTab agent={agent} update={updateAgent} />}
|
||||
</TabContent>
|
||||
</Container>
|
||||
)
|
||||
@@ -214,7 +210,7 @@ const CustomTabs = styled.div`
|
||||
|
||||
const TabItem = styled.button<{ active: boolean }>`
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
height: 30px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: ${(props) => (props.active ? 'var(--color-text)' : 'var(--color-text-secondary)')};
|
||||
@@ -239,7 +235,7 @@ const TabItem = styled.button<{ active: boolean }>`
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -9px;
|
||||
bottom: -8px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: ${(props) => (props.active ? '30px' : '0')};
|
||||
|
||||
@@ -46,15 +46,58 @@ const WebviewSearch: FC<WebviewSearchProps> = ({ webviewRef, isWebviewReady, app
|
||||
setActiveIndex(0)
|
||||
}, [])
|
||||
|
||||
const stopSearch = useCallback(() => {
|
||||
const target = webviewRef.current ?? attachedWebviewRef.current
|
||||
if (!target) return
|
||||
try {
|
||||
target.stopFindInPage('clearSelection')
|
||||
} catch (error) {
|
||||
logger.error('stopFindInPage failed', { error })
|
||||
const ensureWebviewReady = useCallback(
|
||||
(candidate: WebviewTag | null) => {
|
||||
if (!candidate) return null
|
||||
try {
|
||||
const webContentsId = candidate.getWebContentsId?.()
|
||||
if (!webContentsId) {
|
||||
logger.debug('WebviewSearch: missing webContentsId before action', { appId })
|
||||
return null
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug('WebviewSearch: getWebContentsId failed before action', { appId, error })
|
||||
return null
|
||||
}
|
||||
|
||||
return candidate
|
||||
},
|
||||
[appId]
|
||||
)
|
||||
|
||||
const stopFindOnWebview = useCallback(
|
||||
(webview: WebviewTag | null) => {
|
||||
const usable = ensureWebviewReady(webview)
|
||||
if (!usable) return false
|
||||
try {
|
||||
usable.stopFindInPage('clearSelection')
|
||||
return true
|
||||
} catch (error) {
|
||||
logger.debug('stopFindInPage failed', { appId, error })
|
||||
return false
|
||||
}
|
||||
},
|
||||
[appId, ensureWebviewReady]
|
||||
)
|
||||
|
||||
const getUsableWebview = useCallback(() => {
|
||||
const candidates = [webviewRef.current, attachedWebviewRef.current]
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const usable = ensureWebviewReady(candidate)
|
||||
if (usable) {
|
||||
return usable
|
||||
}
|
||||
}
|
||||
}, [webviewRef])
|
||||
|
||||
return null
|
||||
}, [ensureWebviewReady, webviewRef])
|
||||
|
||||
const stopSearch = useCallback(() => {
|
||||
const target = getUsableWebview()
|
||||
if (!target) return
|
||||
stopFindOnWebview(target)
|
||||
}, [getUsableWebview, stopFindOnWebview])
|
||||
|
||||
const closeSearch = useCallback(() => {
|
||||
setIsVisible(false)
|
||||
@@ -64,7 +107,7 @@ const WebviewSearch: FC<WebviewSearchProps> = ({ webviewRef, isWebviewReady, app
|
||||
|
||||
const performSearch = useCallback(
|
||||
(text: string, options?: Electron.FindInPageOptions) => {
|
||||
const target = webviewRef.current ?? attachedWebviewRef.current
|
||||
const target = getUsableWebview()
|
||||
if (!target) {
|
||||
logger.debug('Skip performSearch: webview not attached')
|
||||
return
|
||||
@@ -81,7 +124,7 @@ const WebviewSearch: FC<WebviewSearchProps> = ({ webviewRef, isWebviewReady, app
|
||||
window.toast?.error(t('common.error'))
|
||||
}
|
||||
},
|
||||
[resetSearchState, stopSearch, t, webviewRef]
|
||||
[getUsableWebview, resetSearchState, stopSearch, t]
|
||||
)
|
||||
|
||||
const handleFoundInPage = useCallback((event: Event & { result?: FoundInPageResult }) => {
|
||||
@@ -129,22 +172,26 @@ const WebviewSearch: FC<WebviewSearchProps> = ({ webviewRef, isWebviewReady, app
|
||||
return () => {
|
||||
activeWebview.removeEventListener('found-in-page', handle)
|
||||
if (attachedWebviewRef.current === activeWebview) {
|
||||
try {
|
||||
activeWebview.stopFindInPage('clearSelection')
|
||||
} catch (error) {
|
||||
logger.error('stopFindInPage failed', { error })
|
||||
}
|
||||
stopFindOnWebview(activeWebview)
|
||||
attachedWebviewRef.current = null
|
||||
}
|
||||
}
|
||||
}, [activeWebview, handleFoundInPage])
|
||||
}, [activeWebview, handleFoundInPage, stopFindOnWebview])
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeWebview) return
|
||||
if (!isWebviewReady) return
|
||||
const onFindShortcut = window.api?.webview?.onFindShortcut
|
||||
if (!onFindShortcut) return
|
||||
|
||||
const webContentsId = activeWebview.getWebContentsId?.()
|
||||
let webContentsId: number | undefined
|
||||
try {
|
||||
webContentsId = activeWebview.getWebContentsId?.()
|
||||
} catch (error) {
|
||||
logger.debug('WebviewSearch: getWebContentsId failed', { appId, error })
|
||||
return
|
||||
}
|
||||
|
||||
if (!webContentsId) {
|
||||
logger.warn('WebviewSearch: missing webContentsId', { appId })
|
||||
return
|
||||
@@ -177,7 +224,7 @@ const WebviewSearch: FC<WebviewSearchProps> = ({ webviewRef, isWebviewReady, app
|
||||
return () => {
|
||||
unsubscribe?.()
|
||||
}
|
||||
}, [appId, activeWebview, closeSearch, goToNext, goToPrevious, isVisible, openSearch])
|
||||
}, [appId, activeWebview, closeSearch, goToNext, goToPrevious, isVisible, isWebviewReady, openSearch])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isVisible) return
|
||||
|
||||
@@ -164,6 +164,61 @@ describe('WebviewSearch', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('skips shortcut wiring when getWebContentsId throws', async () => {
|
||||
const { webview } = createWebviewMock()
|
||||
const error = new Error('not ready')
|
||||
;(webview as any).getWebContentsId = vi.fn(() => {
|
||||
throw error
|
||||
})
|
||||
const webviewRef = { current: webview } as React.RefObject<WebviewTag | null>
|
||||
|
||||
const getWebContentsIdMock = vi.fn(() => {
|
||||
throw error
|
||||
})
|
||||
;(webview as any).getWebContentsId = getWebContentsIdMock
|
||||
const { rerender } = render(<WebviewSearch webviewRef={webviewRef} isWebviewReady appId="app-1" />)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getWebContentsIdMock).toHaveBeenCalled()
|
||||
})
|
||||
expect(onFindShortcutMock).not.toHaveBeenCalled()
|
||||
|
||||
;(webview as any).getWebContentsId = vi.fn(() => 1)
|
||||
|
||||
rerender(<WebviewSearch webviewRef={webviewRef} isWebviewReady={false} appId="app-1" />)
|
||||
rerender(<WebviewSearch webviewRef={webviewRef} isWebviewReady appId="app-1" />)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onFindShortcutMock).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
it('does not call stopFindInPage when webview is not ready', async () => {
|
||||
const { stopFindInPageMock, webview } = createWebviewMock()
|
||||
const error = new Error('loading')
|
||||
const getWebContentsIdMock = vi.fn(() => {
|
||||
throw error
|
||||
})
|
||||
;(webview as any).getWebContentsId = getWebContentsIdMock
|
||||
const webviewRef = { current: webview } as React.RefObject<WebviewTag | null>
|
||||
|
||||
const { rerender, unmount } = render(<WebviewSearch webviewRef={webviewRef} isWebviewReady appId="app-1" />)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getWebContentsIdMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
stopFindInPageMock.mockImplementation(() => {
|
||||
throw new Error('should not be called')
|
||||
})
|
||||
|
||||
rerender(<WebviewSearch webviewRef={webviewRef} isWebviewReady={false} appId="app-1" />)
|
||||
expect(stopFindInPageMock).not.toHaveBeenCalled()
|
||||
|
||||
unmount()
|
||||
expect(stopFindInPageMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('closes the search overlay when escape is forwarded from the webview', async () => {
|
||||
const { webview } = createWebviewMock()
|
||||
const webviewRef = { current: webview } as React.RefObject<WebviewTag | null>
|
||||
|
||||
@@ -71,11 +71,11 @@ export const AccessibleDirsSetting: React.FC<AccessibleDirsSettingProps> = ({ ba
|
||||
}>
|
||||
{t('agent.session.accessible_paths.label')}
|
||||
</SettingsTitle>
|
||||
<ul className="mt-2 flex flex-col gap-2 rounded-xl border p-2">
|
||||
<ul className="flex flex-col gap-2">
|
||||
{base.accessible_paths.map((path) => (
|
||||
<li
|
||||
key={path}
|
||||
className="flex items-center justify-between gap-2 rounded-medium border border-default-200 px-3 py-2">
|
||||
className="flex items-center justify-between gap-2 rounded-medium border border-default-200 px-2 py-1">
|
||||
<span className="w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-sm" title={path}>
|
||||
{path}
|
||||
</span>
|
||||
|
||||
@@ -18,9 +18,10 @@ import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||
interface AgentEssentialSettingsProps {
|
||||
agent: GetAgentResponse | undefined | null
|
||||
update: ReturnType<typeof useUpdateAgent>['updateAgent']
|
||||
showModelSetting?: boolean
|
||||
}
|
||||
|
||||
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update }) => {
|
||||
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update, showModelSetting = true }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (!agent) return null
|
||||
@@ -36,7 +37,7 @@ const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update
|
||||
</SettingsItem>
|
||||
<AvatarSetting agent={agent} update={update} />
|
||||
<NameSetting base={agent} update={update} />
|
||||
<ModelSetting base={agent} update={update} />
|
||||
{showModelSetting && <ModelSetting base={agent} update={update} />}
|
||||
<AccessibleDirsSetting base={agent} update={update} />
|
||||
<DescriptionSetting base={agent} update={update} />
|
||||
</SettingsContainer>
|
||||
|
||||
@@ -25,6 +25,7 @@ export const NameSetting: React.FC<NameSettingsProps> = ({ base, update }) => {
|
||||
<Input
|
||||
placeholder={t('common.agent_one') + t('common.name')}
|
||||
value={name}
|
||||
size="sm"
|
||||
onValueChange={(value) => setName(value)}
|
||||
onBlur={() => {
|
||||
if (name !== base.name) {
|
||||
|
||||
@@ -144,6 +144,13 @@ export const builtinMCPServers: BuiltinMCPServer[] = [
|
||||
type: 'inMemory',
|
||||
isActive: false,
|
||||
provider: 'CherryAI'
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
name: BuiltinMCPServerNames.js,
|
||||
type: 'inMemory',
|
||||
isActive: false,
|
||||
provider: 'CherryAI'
|
||||
}
|
||||
] as const
|
||||
|
||||
|
||||
@@ -688,7 +688,8 @@ export const BuiltinMCPServerNames = {
|
||||
fetch: '@cherry/fetch',
|
||||
filesystem: '@cherry/filesystem',
|
||||
difyKnowledge: '@cherry/dify-knowledge',
|
||||
python: '@cherry/python'
|
||||
python: '@cherry/python',
|
||||
js: '@cherry/js'
|
||||
} as const
|
||||
|
||||
export type BuiltinMCPServerName = (typeof BuiltinMCPServerNames)[keyof typeof BuiltinMCPServerNames]
|
||||
|
||||
512
yarn.lock
512
yarn.lock
@@ -3552,20 +3552,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/aix-ppc64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/aix-ppc64@npm:0.25.8"
|
||||
conditions: os=aix & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/android-arm64@npm:0.18.20"
|
||||
conditions: os=android & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/android-arm64@npm:0.25.10"
|
||||
@@ -3573,20 +3559,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/android-arm64@npm:0.25.8"
|
||||
conditions: os=android & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/android-arm@npm:0.18.20"
|
||||
conditions: os=android & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/android-arm@npm:0.25.10"
|
||||
@@ -3594,20 +3566,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/android-arm@npm:0.25.8"
|
||||
conditions: os=android & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/android-x64@npm:0.18.20"
|
||||
conditions: os=android & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/android-x64@npm:0.25.10"
|
||||
@@ -3615,20 +3573,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/android-x64@npm:0.25.8"
|
||||
conditions: os=android & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-arm64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/darwin-arm64@npm:0.18.20"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/darwin-arm64@npm:0.25.10"
|
||||
@@ -3636,20 +3580,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/darwin-arm64@npm:0.25.8"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/darwin-x64@npm:0.18.20"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/darwin-x64@npm:0.25.10"
|
||||
@@ -3657,20 +3587,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/darwin-x64@npm:0.25.8"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-arm64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/freebsd-arm64@npm:0.18.20"
|
||||
conditions: os=freebsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/freebsd-arm64@npm:0.25.10"
|
||||
@@ -3678,20 +3594,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/freebsd-arm64@npm:0.25.8"
|
||||
conditions: os=freebsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/freebsd-x64@npm:0.18.20"
|
||||
conditions: os=freebsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/freebsd-x64@npm:0.25.10"
|
||||
@@ -3699,20 +3601,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/freebsd-x64@npm:0.25.8"
|
||||
conditions: os=freebsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-arm64@npm:0.18.20"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-arm64@npm:0.25.10"
|
||||
@@ -3720,20 +3608,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-arm64@npm:0.25.8"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-arm@npm:0.18.20"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-arm@npm:0.25.10"
|
||||
@@ -3741,20 +3615,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-arm@npm:0.25.8"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ia32@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-ia32@npm:0.18.20"
|
||||
conditions: os=linux & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ia32@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-ia32@npm:0.25.10"
|
||||
@@ -3762,20 +3622,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ia32@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-ia32@npm:0.25.8"
|
||||
conditions: os=linux & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-loong64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-loong64@npm:0.18.20"
|
||||
conditions: os=linux & cpu=loong64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-loong64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-loong64@npm:0.25.10"
|
||||
@@ -3783,20 +3629,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-loong64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-loong64@npm:0.25.8"
|
||||
conditions: os=linux & cpu=loong64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-mips64el@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-mips64el@npm:0.18.20"
|
||||
conditions: os=linux & cpu=mips64el
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-mips64el@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-mips64el@npm:0.25.10"
|
||||
@@ -3804,20 +3636,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-mips64el@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-mips64el@npm:0.25.8"
|
||||
conditions: os=linux & cpu=mips64el
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ppc64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-ppc64@npm:0.18.20"
|
||||
conditions: os=linux & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ppc64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-ppc64@npm:0.25.10"
|
||||
@@ -3825,20 +3643,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ppc64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-ppc64@npm:0.25.8"
|
||||
conditions: os=linux & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-riscv64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-riscv64@npm:0.18.20"
|
||||
conditions: os=linux & cpu=riscv64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-riscv64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-riscv64@npm:0.25.10"
|
||||
@@ -3846,20 +3650,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-riscv64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-riscv64@npm:0.25.8"
|
||||
conditions: os=linux & cpu=riscv64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-s390x@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-s390x@npm:0.18.20"
|
||||
conditions: os=linux & cpu=s390x
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-s390x@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-s390x@npm:0.25.10"
|
||||
@@ -3867,20 +3657,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-s390x@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-s390x@npm:0.25.8"
|
||||
conditions: os=linux & cpu=s390x
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/linux-x64@npm:0.18.20"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/linux-x64@npm:0.25.10"
|
||||
@@ -3888,13 +3664,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/linux-x64@npm:0.25.8"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/netbsd-arm64@npm:0.25.10"
|
||||
@@ -3902,20 +3671,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/netbsd-arm64@npm:0.25.8"
|
||||
conditions: os=netbsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/netbsd-x64@npm:0.18.20"
|
||||
conditions: os=netbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/netbsd-x64@npm:0.25.10"
|
||||
@@ -3923,13 +3678,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/netbsd-x64@npm:0.25.8"
|
||||
conditions: os=netbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/openbsd-arm64@npm:0.25.10"
|
||||
@@ -3937,20 +3685,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/openbsd-arm64@npm:0.25.8"
|
||||
conditions: os=openbsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/openbsd-x64@npm:0.18.20"
|
||||
conditions: os=openbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/openbsd-x64@npm:0.25.10"
|
||||
@@ -3958,13 +3692,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/openbsd-x64@npm:0.25.8"
|
||||
conditions: os=openbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openharmony-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/openharmony-arm64@npm:0.25.10"
|
||||
@@ -3972,20 +3699,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openharmony-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/openharmony-arm64@npm:0.25.8"
|
||||
conditions: os=openharmony & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/sunos-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/sunos-x64@npm:0.18.20"
|
||||
conditions: os=sunos & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/sunos-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/sunos-x64@npm:0.25.10"
|
||||
@@ -3993,20 +3706,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/sunos-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/sunos-x64@npm:0.25.8"
|
||||
conditions: os=sunos & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-arm64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/win32-arm64@npm:0.18.20"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-arm64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/win32-arm64@npm:0.25.10"
|
||||
@@ -4014,20 +3713,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-arm64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/win32-arm64@npm:0.25.8"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-ia32@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/win32-ia32@npm:0.18.20"
|
||||
conditions: os=win32 & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-ia32@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/win32-ia32@npm:0.25.10"
|
||||
@@ -4035,20 +3720,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-ia32@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/win32-ia32@npm:0.25.8"
|
||||
conditions: os=win32 & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-x64@npm:0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "@esbuild/win32-x64@npm:0.18.20"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-x64@npm:0.25.10":
|
||||
version: 0.25.10
|
||||
resolution: "@esbuild/win32-x64@npm:0.25.10"
|
||||
@@ -4056,13 +3727,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-x64@npm:0.25.8":
|
||||
version: 0.25.8
|
||||
resolution: "@esbuild/win32-x64@npm:0.25.8"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0":
|
||||
version: 4.6.0
|
||||
resolution: "@eslint-community/eslint-utils@npm:4.6.0"
|
||||
@@ -18302,7 +17966,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"esbuild@npm:^0.25.4":
|
||||
"esbuild@npm:^0.25.0":
|
||||
version: 0.25.10
|
||||
resolution: "esbuild@npm:0.25.10"
|
||||
dependencies:
|
||||
@@ -18391,172 +18055,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"esbuild@npm:^0.25.5, esbuild@npm:~0.25.0":
|
||||
version: 0.25.8
|
||||
resolution: "esbuild@npm:0.25.8"
|
||||
dependencies:
|
||||
"@esbuild/aix-ppc64": "npm:0.25.8"
|
||||
"@esbuild/android-arm": "npm:0.25.8"
|
||||
"@esbuild/android-arm64": "npm:0.25.8"
|
||||
"@esbuild/android-x64": "npm:0.25.8"
|
||||
"@esbuild/darwin-arm64": "npm:0.25.8"
|
||||
"@esbuild/darwin-x64": "npm:0.25.8"
|
||||
"@esbuild/freebsd-arm64": "npm:0.25.8"
|
||||
"@esbuild/freebsd-x64": "npm:0.25.8"
|
||||
"@esbuild/linux-arm": "npm:0.25.8"
|
||||
"@esbuild/linux-arm64": "npm:0.25.8"
|
||||
"@esbuild/linux-ia32": "npm:0.25.8"
|
||||
"@esbuild/linux-loong64": "npm:0.25.8"
|
||||
"@esbuild/linux-mips64el": "npm:0.25.8"
|
||||
"@esbuild/linux-ppc64": "npm:0.25.8"
|
||||
"@esbuild/linux-riscv64": "npm:0.25.8"
|
||||
"@esbuild/linux-s390x": "npm:0.25.8"
|
||||
"@esbuild/linux-x64": "npm:0.25.8"
|
||||
"@esbuild/netbsd-arm64": "npm:0.25.8"
|
||||
"@esbuild/netbsd-x64": "npm:0.25.8"
|
||||
"@esbuild/openbsd-arm64": "npm:0.25.8"
|
||||
"@esbuild/openbsd-x64": "npm:0.25.8"
|
||||
"@esbuild/openharmony-arm64": "npm:0.25.8"
|
||||
"@esbuild/sunos-x64": "npm:0.25.8"
|
||||
"@esbuild/win32-arm64": "npm:0.25.8"
|
||||
"@esbuild/win32-ia32": "npm:0.25.8"
|
||||
"@esbuild/win32-x64": "npm:0.25.8"
|
||||
dependenciesMeta:
|
||||
"@esbuild/aix-ppc64":
|
||||
optional: true
|
||||
"@esbuild/android-arm":
|
||||
optional: true
|
||||
"@esbuild/android-arm64":
|
||||
optional: true
|
||||
"@esbuild/android-x64":
|
||||
optional: true
|
||||
"@esbuild/darwin-arm64":
|
||||
optional: true
|
||||
"@esbuild/darwin-x64":
|
||||
optional: true
|
||||
"@esbuild/freebsd-arm64":
|
||||
optional: true
|
||||
"@esbuild/freebsd-x64":
|
||||
optional: true
|
||||
"@esbuild/linux-arm":
|
||||
optional: true
|
||||
"@esbuild/linux-arm64":
|
||||
optional: true
|
||||
"@esbuild/linux-ia32":
|
||||
optional: true
|
||||
"@esbuild/linux-loong64":
|
||||
optional: true
|
||||
"@esbuild/linux-mips64el":
|
||||
optional: true
|
||||
"@esbuild/linux-ppc64":
|
||||
optional: true
|
||||
"@esbuild/linux-riscv64":
|
||||
optional: true
|
||||
"@esbuild/linux-s390x":
|
||||
optional: true
|
||||
"@esbuild/linux-x64":
|
||||
optional: true
|
||||
"@esbuild/netbsd-arm64":
|
||||
optional: true
|
||||
"@esbuild/netbsd-x64":
|
||||
optional: true
|
||||
"@esbuild/openbsd-arm64":
|
||||
optional: true
|
||||
"@esbuild/openbsd-x64":
|
||||
optional: true
|
||||
"@esbuild/openharmony-arm64":
|
||||
optional: true
|
||||
"@esbuild/sunos-x64":
|
||||
optional: true
|
||||
"@esbuild/win32-arm64":
|
||||
optional: true
|
||||
"@esbuild/win32-ia32":
|
||||
optional: true
|
||||
"@esbuild/win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
esbuild: bin/esbuild
|
||||
checksum: 10c0/43747a25e120d5dd9ce75c82f57306580d715647c8db4f4a0a84e73b04cf16c27572d3937d3cfb95d5ac3266a4d1bbd3913e3d76ae719693516289fc86f8a5fd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"esbuild@npm:~0.18.20":
|
||||
version: 0.18.20
|
||||
resolution: "esbuild@npm:0.18.20"
|
||||
dependencies:
|
||||
"@esbuild/android-arm": "npm:0.18.20"
|
||||
"@esbuild/android-arm64": "npm:0.18.20"
|
||||
"@esbuild/android-x64": "npm:0.18.20"
|
||||
"@esbuild/darwin-arm64": "npm:0.18.20"
|
||||
"@esbuild/darwin-x64": "npm:0.18.20"
|
||||
"@esbuild/freebsd-arm64": "npm:0.18.20"
|
||||
"@esbuild/freebsd-x64": "npm:0.18.20"
|
||||
"@esbuild/linux-arm": "npm:0.18.20"
|
||||
"@esbuild/linux-arm64": "npm:0.18.20"
|
||||
"@esbuild/linux-ia32": "npm:0.18.20"
|
||||
"@esbuild/linux-loong64": "npm:0.18.20"
|
||||
"@esbuild/linux-mips64el": "npm:0.18.20"
|
||||
"@esbuild/linux-ppc64": "npm:0.18.20"
|
||||
"@esbuild/linux-riscv64": "npm:0.18.20"
|
||||
"@esbuild/linux-s390x": "npm:0.18.20"
|
||||
"@esbuild/linux-x64": "npm:0.18.20"
|
||||
"@esbuild/netbsd-x64": "npm:0.18.20"
|
||||
"@esbuild/openbsd-x64": "npm:0.18.20"
|
||||
"@esbuild/sunos-x64": "npm:0.18.20"
|
||||
"@esbuild/win32-arm64": "npm:0.18.20"
|
||||
"@esbuild/win32-ia32": "npm:0.18.20"
|
||||
"@esbuild/win32-x64": "npm:0.18.20"
|
||||
dependenciesMeta:
|
||||
"@esbuild/android-arm":
|
||||
optional: true
|
||||
"@esbuild/android-arm64":
|
||||
optional: true
|
||||
"@esbuild/android-x64":
|
||||
optional: true
|
||||
"@esbuild/darwin-arm64":
|
||||
optional: true
|
||||
"@esbuild/darwin-x64":
|
||||
optional: true
|
||||
"@esbuild/freebsd-arm64":
|
||||
optional: true
|
||||
"@esbuild/freebsd-x64":
|
||||
optional: true
|
||||
"@esbuild/linux-arm":
|
||||
optional: true
|
||||
"@esbuild/linux-arm64":
|
||||
optional: true
|
||||
"@esbuild/linux-ia32":
|
||||
optional: true
|
||||
"@esbuild/linux-loong64":
|
||||
optional: true
|
||||
"@esbuild/linux-mips64el":
|
||||
optional: true
|
||||
"@esbuild/linux-ppc64":
|
||||
optional: true
|
||||
"@esbuild/linux-riscv64":
|
||||
optional: true
|
||||
"@esbuild/linux-s390x":
|
||||
optional: true
|
||||
"@esbuild/linux-x64":
|
||||
optional: true
|
||||
"@esbuild/netbsd-x64":
|
||||
optional: true
|
||||
"@esbuild/openbsd-x64":
|
||||
optional: true
|
||||
"@esbuild/sunos-x64":
|
||||
optional: true
|
||||
"@esbuild/win32-arm64":
|
||||
optional: true
|
||||
"@esbuild/win32-ia32":
|
||||
optional: true
|
||||
"@esbuild/win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
esbuild: bin/esbuild
|
||||
checksum: 10c0/473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"escalade@npm:^3.1.1, escalade@npm:^3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "escalade@npm:3.2.0"
|
||||
@@ -28588,15 +28086,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tar-fs@npm:^2.0.0":
|
||||
version: 2.1.3
|
||||
resolution: "tar-fs@npm:2.1.3"
|
||||
"tar-fs@npm:^2.1.4":
|
||||
version: 2.1.4
|
||||
resolution: "tar-fs@npm:2.1.4"
|
||||
dependencies:
|
||||
chownr: "npm:^1.1.1"
|
||||
mkdirp-classic: "npm:^0.5.2"
|
||||
pump: "npm:^3.0.0"
|
||||
tar-stream: "npm:^2.1.4"
|
||||
checksum: 10c0/472ee0c3c862605165163113ab6924f411c07506a1fb24c51a1a80085f0d4d381d86d2fd6b189236c8d932d1cd97b69cce35016767ceb658a35f7584fe77f305
|
||||
checksum: 10c0/decb25acdc6839182c06ec83cba6136205bda1db984e120c8ffd0d80182bc5baa1d916f9b6c5c663ea3f9975b4dd49e3c6bb7b1707cbcdaba4e76042f43ec84c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user