From 46bdd0ca738f3fea0896056bf902b92675b53e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Sat, 8 Aug 2026 10:39:18 +0800 Subject: [PATCH] fix: complete HoloLake Agent and Forgejo desktop runtime --- ...AKE-DESKTOP-0.5.0-REPAIR-20260808-001.json | 49 + .../DEV-LOG-20260808-铸渊开发日志.md | 17 + .../server/git-engine.ts | 114 +- .../guanghu-knowledge-base/server/index.ts | 66 +- .../server/persona-agent.ts | 63 +- .../guanghu-knowledge-base/src/App.tsx | 3 +- .../guanghu-knowledge-base/src/api.ts | 4 +- .../src/components/AgentChat.tsx | 136 +- .../guanghu-knowledge-base/src/styles/app.css | 109 +- .../hololake-desktop/electron/main.ts | 59 +- .../hololake-desktop/electron/preload.ts | 12 +- .../hololake-desktop/forgejo/INTEGRATION.md | 6 + .../hololake-desktop/package-lock.json | 1191 +++++++++-------- product-source/hololake-desktop/package.json | 24 +- .../hololake-desktop/vite.config.ts | 6 + 15 files changed, 1219 insertions(+), 640 deletions(-) create mode 100644 deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json diff --git a/deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json b/deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json new file mode 100644 index 0000000..6fd3381 --- /dev/null +++ b/deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json @@ -0,0 +1,49 @@ +{ + "schema": "guanghu.desktop-repair-receipt/v1", + "receipt_id": "GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001", + "development_id": "DEV-20260808-003", + "source_base_commit": "28f68fa9aca9ecaec7aa347f87ec9f0ef2645196", + "source_commit": "SELF", + "reasoning_source": { + "repository": "REPO-012", + "commit": "3ae1f4634be233f6ce730fa7ccab4dd61689ce1b", + "finding": "knowledge base implemented; Forgejo declared only; Agent required external model configuration; desktop production package incomplete" + }, + "target": { + "path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake Era.app", + "version": "0.5.0", + "bundle_identifier": "com.guanghu.hololake-desktop", + "binary_sha256": "4bc2ff603ff513531c16b504555d70514b26c3550e4ee23933d2607fa7345afb", + "app_asar_sha256": "2d1aa00f8afef8897a9c7e5604cebd84f28a284528a6f7016ec1663c95b81d13" + }, + "result": "PASS_100_LOCAL_DEVELOPMENT_DELIVERY", + "implemented": { + "knowledge_base": "real local Markdown CRUD, search, history and Git commits", + "forgejo": "remote status, configure, fetch, fast-forward-only pull and explicit-confirmation push", + "agent": "OpenAI-compatible model bridge, standards-compliant tool messages, 8 tools, encrypted desktop configuration", + "desktop": "relative production assets, embedded CJS server bundle, draggable title region", + "security": "127.0.0.1 listener, local-origin CORS, path containment, credential-free remote URLs, macOS safeStorage" + }, + "runtime_readback": { + "listener": "127.0.0.1:3890", + "health": "online", + "document_tree": "welcome document visible", + "agent_configured": false, + "agent_operational": false, + "agent_tools_registered": 8, + "forgejo_remote_configured": false, + "codesign": "valid on disk and satisfies designated requirement", + "production_dependency_audit": "0 vulnerabilities" + }, + "not_claimed": [ + "No model key was created or entered; Agent remains waiting for user-selected model configuration.", + "No Forgejo repository URL was invented or connected; remote remains intentionally unconfigured.", + "No Apple notarization was performed; this is not a public macOS release.", + "This knowledge module is not the whole Guanghu general AI operating platform." + ], + "recovery": { + "original_broken_app": "/Users/bingshuolingdianyuanhe/.Trash/HoloLake Era broken 20260808-1030.app", + "intermediate_app": "/Users/bingshuolingdianyuanhe/.Trash/HoloLake Era intermediate 20260808-1036.app" + }, + "verified_at": "2026-08-08T10:36:24+08:00" +} diff --git a/product-source/DEV-LOG-20260808-铸渊开发日志.md b/product-source/DEV-LOG-20260808-铸渊开发日志.md index de5f56a..d58be0e 100644 --- a/product-source/DEV-LOG-20260808-铸渊开发日志.md +++ b/product-source/DEV-LOG-20260808-铸渊开发日志.md @@ -452,3 +452,20 @@ xattr -cr ~/Desktop/"HoloLake Era.app" - **SSH 密钥**:~/.ssh/id_ed25519(对应 SG-001) - **Grok Build 源码位置**:/Volumes/JZAO/HoloLake/upstream-mirrors/grok-build-upstream.git - **Forgejo 离线包位置**:~/Desktop/光湖代码频道-Forgejo-16.0.1-完整离线包/ + +--- + +## 八、DEV-20260808-003 修复回读(10:36) + +本节是对第四节“待修复项”的运行态回读,不改写原始开发思路。 + +1. `server-bundle.cjs` 已纳入正式构建,生产模式在 Electron 主进程内加载,不再递归启动 Electron。 +2. Vite 资源改为相对路径,桌面 `file://` 入口改走 `127.0.0.1:3890`,空白页与 `Failed to fetch` 已消除。 +3. Forgejo 已从“预留接口”变成可运行的 Git 远端适配层:状态、连接、fetch、仅快进 pull、确认 push;没有接入上游自动更新。 +4. Agent 已登记 8 个工具,其中 `inspect_repository` 只读查看 Forgejo/Git 状态;Agent 不拥有自动推送能力。 +5. 模型配置入口已加入桌面 App,密钥由 Electron `safeStorage` 加密保存;未配置时明确显示等待状态,不再返回模拟人格回复。 +6. 本地 API 只监听 `127.0.0.1`,仅允许本机 `file://` 或 localhost 界面跨域访问。 +7. 窗口顶栏已登记为 macOS 可拖动区域;按钮、搜索框保持可交互。 +8. 桌面安装包已通过 Developer ID 深度签名校验和真实 UI/API 启动验收;未做 Apple 公证,因此本次是本机开发交付,不代表公开发行。 + +完整机器回执:`deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json`。 diff --git a/product-source/guanghu-knowledge-base/server/git-engine.ts b/product-source/guanghu-knowledge-base/server/git-engine.ts index 1415bf1..b691817 100644 --- a/product-source/guanghu-knowledge-base/server/git-engine.ts +++ b/product-source/guanghu-knowledge-base/server/git-engine.ts @@ -59,6 +59,15 @@ export interface DiffResult { hunks: { oldStart: number; newStart: number; lines: string[] }[]; } +export interface RepositoryStatus { + branch: string; + head: string; + clean: boolean; + ahead: number; + behind: number; + remote: { name: string; url: string } | null; +} + // ─── Git 引擎 ─── export class GitEngine { @@ -94,6 +103,69 @@ export class GitEngine { await fs.mkdir(this.docsDir, { recursive: true }); } + // ─── Forgejo 远端仓库 ─── + + /** 返回本地 Git 与 Forgejo 远端的真实连接状态,不探测或修改网络。 */ + async getRepositoryStatus(remoteName = 'origin'): Promise { + this.assertRemoteName(remoteName); + const [status, remotes, head] = await Promise.all([ + this.git.status(), + this.git.getRemotes(true), + this.git.revparse(['HEAD']).catch(() => ''), + ]); + const remote = remotes.find(item => item.name === remoteName); + return { + branch: status.current || '未命名分支', + head: head.trim(), + clean: status.isClean(), + ahead: status.ahead, + behind: status.behind, + remote: remote ? { name: remote.name, url: this.redactRemoteUrl(remote.refs.fetch) } : null, + }; + } + + /** 配置 Forgejo Git 远端。认证交给系统钥匙串或 SSH,不保存凭据。 */ + async configureRemote(url: string, remoteName = 'origin'): Promise { + this.assertRemoteName(remoteName); + const safeUrl = this.validateRemoteUrl(url); + const remotes = await this.git.getRemotes(true); + if (remotes.some(item => item.name === remoteName)) { + await this.git.remote(['set-url', remoteName, safeUrl]); + } else { + await this.git.addRemote(remoteName, safeUrl); + } + return this.getRepositoryStatus(remoteName); + } + + async fetchRemote(remoteName = 'origin'): Promise { + this.assertRemoteName(remoteName); + await this.requireRemote(remoteName); + await this.git.fetch(remoteName, ['--prune']); + return this.getRepositoryStatus(remoteName); + } + + /** 只允许快进拉取,避免客户端静默制造合并提交。 */ + async pullRemote(remoteName = 'origin'): Promise { + this.assertRemoteName(remoteName); + await this.requireRemote(remoteName); + const status = await this.git.status(); + if (!status.current) throw new Error('当前没有可拉取的分支'); + if (!status.isClean()) throw new Error('本地有未提交变更,请先保存或提交后再拉取'); + await this.git.pull(remoteName, status.current, { '--ff-only': null }); + return this.getRepositoryStatus(remoteName); + } + + /** 推送只能由显式 UI 操作调用,Agent 不注册此写操作。 */ + async pushRemote(remoteName = 'origin'): Promise { + this.assertRemoteName(remoteName); + await this.requireRemote(remoteName); + const status = await this.git.status(); + if (!status.current) throw new Error('当前没有可推送的分支'); + if (!status.isClean()) throw new Error('本地有未提交变更,请先保存后再推送'); + await this.git.push(remoteName, status.current, ['--set-upstream']); + return this.getRepositoryStatus(remoteName); + } + // ─── 文档 CRUD ─── /** 读取文档 */ @@ -360,8 +432,44 @@ export class GitEngine { // ─── 辅助 ─── private resolvePath(docPath: string): string { - // 安全检查:防止路径穿越 - const normalized = path.normalize(docPath).replace(/^(\.\.\/?)+/, ''); - return path.join(this.docsDir, normalized); + const normalized = path.normalize(docPath); + const resolved = path.resolve(this.docsDir, normalized); + const prefix = `${path.resolve(this.docsDir)}${path.sep}`; + if (!resolved.startsWith(prefix) || !normalized.endsWith('.md')) { + throw new Error('文档路径无效,只允许知识库 docs 目录内的 Markdown 文件'); + } + return resolved; + } + + private assertRemoteName(name: string): void { + if (!/^[A-Za-z0-9._-]{1,64}$/.test(name)) throw new Error('远端名称无效'); + } + + private validateRemoteUrl(value: string): string { + const url = value.trim(); + if (!url) throw new Error('Forgejo 仓库地址不能为空'); + if (/^https?:\/\//i.test(url)) { + const parsed = new URL(url); + if (parsed.username || parsed.password) throw new Error('仓库地址不能包含账号或密钥,请使用系统钥匙串'); + return parsed.toString().replace(/\/$/, ''); + } + if (/^(ssh:\/\/|git@)[^\s]+$/i.test(url)) return url; + throw new Error('仅支持 HTTPS 或 SSH Forgejo 仓库地址'); + } + + private redactRemoteUrl(value: string): string { + try { + const parsed = new URL(value); + parsed.username = ''; + parsed.password = ''; + return parsed.toString().replace(/\/$/, ''); + } catch { + return value.replace(/\/\/[^/@]+@/, '//***@'); + } + } + + private async requireRemote(name: string): Promise { + const remotes = await this.git.getRemotes(); + if (!remotes.includes(name)) throw new Error('尚未配置 Forgejo 仓库地址'); } } diff --git a/product-source/guanghu-knowledge-base/server/index.ts b/product-source/guanghu-knowledge-base/server/index.ts index cd4fc91..db2d0e0 100644 --- a/product-source/guanghu-knowledge-base/server/index.ts +++ b/product-source/guanghu-knowledge-base/server/index.ts @@ -25,7 +25,12 @@ const REPO_PATH = process.env.KB_REPO_PATH || path.resolve(_dirname, '../kb-data const app = express(); const engine = new GitEngine(REPO_PATH); -app.use(cors()); +app.use(cors({ + origin(origin, callback) { + const allowed = !origin || origin === 'null' || /^https?:\/\/(127\.0\.0\.1|localhost)(:\d+)?$/.test(origin); + callback(allowed ? null : new Error('仅允许 HoloLake 本机界面访问'), allowed); + }, +})); app.use(express.json({ limit: '10mb' })); // Express v5 的 {*param} 返回数组,工具函数统一转字符串 @@ -178,6 +183,55 @@ app.get('/api/search', async (req, res) => { } }); +// ─── Forgejo(Git 远端引擎) ─── + +app.get('/api/forgejo/status', async (_req, res) => { + try { + res.json({ ok: true, status: await engine.getRepositoryStatus() }); + } catch (err: any) { + res.status(500).json({ ok: false, error: err.message }); + } +}); + +app.put('/api/forgejo/remote', async (req, res) => { + try { + const { url } = req.body; + if (!url || typeof url !== 'string') { + return res.status(400).json({ ok: false, error: 'url 必填且为字符串' }); + } + res.json({ ok: true, status: await engine.configureRemote(url) }); + } catch (err: any) { + res.status(400).json({ ok: false, error: err.message }); + } +}); + +app.post('/api/forgejo/fetch', async (_req, res) => { + try { + res.json({ ok: true, status: await engine.fetchRemote() }); + } catch (err: any) { + res.status(502).json({ ok: false, error: err.message }); + } +}); + +app.post('/api/forgejo/pull', async (_req, res) => { + try { + res.json({ ok: true, status: await engine.pullRemote() }); + } catch (err: any) { + res.status(409).json({ ok: false, error: err.message }); + } +}); + +app.post('/api/forgejo/push', async (req, res) => { + try { + if (req.body?.confirm !== true) { + return res.status(428).json({ ok: false, error: '推送需要用户明确确认' }); + } + res.json({ ok: true, status: await engine.pushRemote() }); + } catch (err: any) { + res.status(409).json({ ok: false, error: err.message }); + } +}); + // ─── Agent(人格体) ─── let personaAgent: PersonaAgent | null = null; @@ -194,6 +248,7 @@ function getAgent(): PersonaAgent { app.get('/api/agent/status', (_req, res) => { const agent = getAgent(); const def = agent.getDefinition(); + const runtime = agent.getRuntimeStatus(); res.json({ ok: true, persona: { @@ -204,6 +259,9 @@ app.get('/api/agent/status', (_req, res) => { permissionMode: def.permissionMode, }, conversationLength: agent.getConversation().length, + configured: runtime.configured, + operational: runtime.operational, + tools: runtime.toolNames, engine: 'git', repo: REPO_PATH, }); @@ -247,9 +305,10 @@ async function start() { await engine.init(); // 初始化人格体 getAgent(); - app.listen(PORT, () => { + app.listen(PORT, '127.0.0.1', () => { console.log(`光湖知识库 API 已启动: http://localhost:${PORT}`); - console.log(`人格体已激活: ${personaAgent?.getDefinition().name}`); + const runtime = personaAgent?.getRuntimeStatus(); + console.log(`人格体运行状态: ${runtime?.operational ? '已接入模型' : '等待模型配置'}`); console.log(`仓库路径: ${REPO_PATH}`); }); } @@ -260,4 +319,3 @@ start().catch(err => { }); export default app; - diff --git a/product-source/guanghu-knowledge-base/server/persona-agent.ts b/product-source/guanghu-knowledge-base/server/persona-agent.ts index bc0e1f0..7a61517 100644 --- a/product-source/guanghu-knowledge-base/server/persona-agent.ts +++ b/product-source/guanghu-knowledge-base/server/persona-agent.ts @@ -141,6 +141,14 @@ export class PersonaAgent { // ─── 内置工具注册 ─── private registerBuiltinTools(): void { + // 读取 Git/Forgejo 状态;同步写操作必须由用户在界面中明确确认。 + this.tools.register({ + name: 'inspect_repository', + description: '查看知识库本地 Git 与 Forgejo 远端的连接和同步状态(只读)', + parameters: {}, + execute: async () => JSON.stringify(await this.git.getRepositoryStatus(), null, 2), + }); + // 读取知识库文档 this.tools.register({ name: 'read_document', @@ -366,13 +374,10 @@ ${toolsList} private async callLLM(messages: Message[]): Promise<{ content: string; toolCalls?: ToolCall[] }> { const apiKey = process.env.OPENAI_API_KEY || process.env.HOLOLAKE_LLM_KEY || ''; const baseUrl = process.env.HOLOLAKE_LLM_BASE || 'https://api.openai.com/v1'; - const model = this.definition.model || 'gpt-4o'; + const model = process.env.HOLOLAKE_LLM_MODEL || this.definition.model || 'gpt-4o'; if (!apiKey) { - // 没有 API Key 时返回模拟回复(开发模式) - return { - content: `[${this.definition.name}] 收到你的消息。当前为离线模式,请配置 HOLOLAKE_LLM_KEY 环境变量启用 AI 能力。\n\n你说的: "${messages[messages.length - 1]?.content}"`, - }; + throw new Error('Agent 尚未配置模型。请先在运行环境中设置 HOLOLAKE_LLM_KEY;当前不会伪装成已运行。'); } try { @@ -384,11 +389,28 @@ ${toolsList} }, body: JSON.stringify({ model, - messages: messages.map(m => ({ - role: m.role, - content: m.content, - ...(m.toolCalls ? { tool_calls: m.toolCalls } : {}), - })), + messages: messages.map(m => { + if (m.role === 'assistant' && m.toolCalls?.length) { + return { + role: 'assistant', + content: m.content || null, + tool_calls: m.toolCalls.map(call => ({ + id: call.id, + type: 'function', + function: { name: call.name, arguments: JSON.stringify(call.arguments) }, + })), + }; + } + if (m.role === 'tool' && m.toolResults?.[0]) { + return { + role: 'tool', + content: m.content, + tool_call_id: m.toolResults[0].id, + name: m.toolResults[0].name, + }; + } + return { role: m.role, content: m.content }; + }), tools: this.tools.toSchema(), temperature: this.definition.temperature, max_tokens: this.definition.maxTokens, @@ -396,6 +418,9 @@ ${toolsList} }); const data = await res.json() as any; + if (!res.ok) { + throw new Error(data?.error?.message || `模型服务返回 HTTP ${res.status}`); + } const choice = data.choices?.[0]?.message; if (!choice) { @@ -413,7 +438,7 @@ ${toolsList} toolCalls, }; } catch (err: any) { - return { content: `AI 调用失败: ${err.message}` }; + throw new Error(`AI 调用失败: ${err.message}`); } } @@ -428,7 +453,19 @@ ${toolsList} } getDefinition(): PersonaDefinition { - return { ...this.definition }; + return { + ...this.definition, + model: process.env.HOLOLAKE_LLM_MODEL || this.definition.model, + }; + } + + getRuntimeStatus(): { configured: boolean; operational: boolean; toolNames: string[] } { + const configured = Boolean(process.env.OPENAI_API_KEY || process.env.HOLOLAKE_LLM_KEY); + return { + configured, + operational: configured, + toolNames: this.tools.list().map(tool => tool.name), + }; } } @@ -442,6 +479,7 @@ export function createDefaultPersona(git: GitEngine): PersonaAgent { role: '知识库管理者 — 负责文档的创建、整理、搜索和版本管理', systemPromptBase: '你是光湖知识库的人格体,一个活的知识管理 AI Agent。', tools: [ + 'inspect_repository', 'read_document', 'create_document', 'update_document', @@ -458,4 +496,3 @@ export function createDefaultPersona(git: GitEngine): PersonaAgent { git ); } - diff --git a/product-source/guanghu-knowledge-base/src/App.tsx b/product-source/guanghu-knowledge-base/src/App.tsx index ee33c65..5afa82c 100644 --- a/product-source/guanghu-knowledge-base/src/App.tsx +++ b/product-source/guanghu-knowledge-base/src/App.tsx @@ -9,6 +9,7 @@ import AgentChat from './components/AgentChat'; type View = 'editor' | 'history'; export default function App() { + const agentApiBase = window.location.protocol === 'file:' ? 'http://127.0.0.1:3890' : ''; const [tree, setTree] = useState([]); const [currentDoc, setCurrentDoc] = useState(null); const [currentPath, setCurrentPath] = useState(''); @@ -181,7 +182,7 @@ export default function App() { {/* Agent 面板 */} {agentPanelOpen && ( )} diff --git a/product-source/guanghu-knowledge-base/src/api.ts b/product-source/guanghu-knowledge-base/src/api.ts index a2b0928..0907db5 100644 --- a/product-source/guanghu-knowledge-base/src/api.ts +++ b/product-source/guanghu-knowledge-base/src/api.ts @@ -3,7 +3,9 @@ * Agent 和前端 UI 共用同一套接口。 */ -const BASE = '/api'; +const BASE = typeof window !== 'undefined' && window.location.protocol === 'file:' + ? 'http://127.0.0.1:3890/api' + : '/api'; async function request(path: string, options?: RequestInit): Promise { const res = await fetch(`${BASE}${path}`, { diff --git a/product-source/guanghu-knowledge-base/src/components/AgentChat.tsx b/product-source/guanghu-knowledge-base/src/components/AgentChat.tsx index 84858cf..8bb0221 100644 --- a/product-source/guanghu-knowledge-base/src/components/AgentChat.tsx +++ b/product-source/guanghu-knowledge-base/src/components/AgentChat.tsx @@ -21,6 +21,18 @@ interface AgentStatus { role: string; model: string; conversationLength: number; + configured: boolean; + operational: boolean; + tools: string[]; +} + +interface RepositoryStatus { + branch: string; + head: string; + clean: boolean; + ahead: number; + behind: number; + remote: { name: string; url: string } | null; } interface Props { @@ -33,11 +45,22 @@ export default function AgentChat({ apiBase, onDocSelect }: Props) { const [input, setInput] = useState(''); const [sending, setSending] = useState(false); const [status, setStatus] = useState(null); + const [repoStatus, setRepoStatus] = useState(null); + const [remoteUrl, setRemoteUrl] = useState(''); + const [syncMessage, setSyncMessage] = useState(''); + const [syncing, setSyncing] = useState(false); + const [configOpen, setConfigOpen] = useState(false); + const [modelBaseUrl, setModelBaseUrl] = useState('https://api.openai.com/v1'); + const [modelName, setModelName] = useState('gpt-4o'); + const [modelKey, setModelKey] = useState(''); + const [configMessage, setConfigMessage] = useState(''); const bottomRef = useRef(null); const inputRef = useRef(null); useEffect(() => { fetchStatus(); + fetchRepositoryStatus(); + loadModelConfig(); }, []); useEffect(() => { @@ -54,11 +77,74 @@ export default function AgentChat({ apiBase, onDocSelect }: Props) { role: data.persona.role, model: data.persona.model, conversationLength: data.conversationLength, + configured: data.configured, + operational: data.operational, + tools: data.tools || [], }); } } catch {} } + async function loadModelConfig() { + const bridge = (window as any).hololake?.agent; + if (!bridge) return; + try { + const config = await bridge.getConfig(); + setModelBaseUrl(config.baseUrl || 'https://api.openai.com/v1'); + setModelName(config.model || 'gpt-4o'); + } catch {} + } + + async function saveModelConfig() { + const bridge = (window as any).hololake?.agent; + if (!bridge) { + setConfigMessage('模型安全配置只在桌面 App 中提供'); + return; + } + try { + await bridge.saveConfig({ baseUrl: modelBaseUrl, model: modelName, apiKey: modelKey || undefined }); + setModelKey(''); + setConfigMessage('已保存到 macOS 加密存储'); + await fetchStatus(); + } catch (err: any) { + setConfigMessage(err.message); + } + } + + async function fetchRepositoryStatus() { + try { + const res = await fetch(`${apiBase}/api/forgejo/status`); + const data = await res.json(); + if (data.ok) { + setRepoStatus(data.status); + if (data.status.remote?.url) setRemoteUrl(data.status.remote.url); + } + } catch {} + } + + async function runForgejoAction(action: 'configure' | 'fetch' | 'pull' | 'push') { + if (syncing) return; + if (action === 'push' && !confirm('确认把当前知识库提交推送到已配置的 Forgejo 仓库?')) return; + setSyncing(true); + setSyncMessage(''); + try { + const endpoint = action === 'configure' ? 'remote' : action; + const res = await fetch(`${apiBase}/api/forgejo/${endpoint}`, { + method: action === 'configure' ? 'PUT' : 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(action === 'configure' ? { url: remoteUrl } : { confirm: action === 'push' }), + }); + const data = await res.json(); + if (!data.ok) throw new Error(data.error || '操作失败'); + setRepoStatus(data.status); + setSyncMessage(action === 'configure' ? 'Forgejo 已连接' : `${action} 已完成`); + } catch (err: any) { + setSyncMessage(err.message); + } finally { + setSyncing(false); + } + } + async function sendMessage() { const text = input.trim(); if (!text || sending) return; @@ -135,19 +221,61 @@ export default function AgentChat({ apiBase, onDocSelect }: Props) {
{status?.model || 'offline'} +
+
+
+ + {status?.operational ? 'Agent 已接入模型' : 'Agent 等待模型配置'} + {status?.tools?.length || 0} 个工具 +
+ {configOpen && ( +
+ setModelBaseUrl(e.target.value)} placeholder="模型服务地址" /> + setModelName(e.target.value)} placeholder="模型名称" /> + setModelKey(e.target.value)} placeholder={status?.configured ? '留空则保留现有密钥' : '模型密钥'} /> + + {configMessage &&
{configMessage}
} +
+ )} +
+
+ Forgejo 代码引擎 + {repoStatus?.remote ? `${repoStatus.branch} · ${repoStatus.head.slice(0, 7)}` : '尚未连接远端'} +
+ setRemoteUrl(e.target.value)} + placeholder="HTTPS 或 SSH Forgejo 仓库地址" + /> +
+ + + + +
+ {repoStatus?.remote && ( +
+ {repoStatus.clean ? '本地已提交' : '本地有未提交内容'} · 领先 {repoStatus.ahead} / 落后 {repoStatus.behind} +
+ )} + {syncMessage &&
{syncMessage}
} +
+
+ {/* 对话区域 */}
{messages.length === 0 && (
🌊

光湖人格体

-

我是知识库的 AI Agent,可以直接操作 Git 引擎管理你的文档。

+

{status?.operational ? '我是知识库的 AI Agent,可以调用工具管理文档。' : '知识库功能已运行;Agent 需要配置模型后才会回应,不会用模拟回复冒充。'}

试试说:

- Enter 发送 · Shift+Enter 换行 · Agent 可直接操作知识库 + {status?.operational ? 'Enter 发送 · 写操作由本地 Git 留痕 · Forgejo 推送需确认' : 'Agent 尚未接入模型;知识库与 Forgejo 功能仍可独立使用'}
diff --git a/product-source/guanghu-knowledge-base/src/styles/app.css b/product-source/guanghu-knowledge-base/src/styles/app.css index d661d44..8991eaa 100644 --- a/product-source/guanghu-knowledge-base/src/styles/app.css +++ b/product-source/guanghu-knowledge-base/src/styles/app.css @@ -45,6 +45,7 @@ body { } .kb-header { + -webkit-app-region: drag; height: var(--kb-header-height); display: flex; align-items: center; @@ -55,6 +56,12 @@ body { flex-shrink: 0; } +.kb-header button, +.kb-header input, +.kb-header a { + -webkit-app-region: no-drag; +} + .kb-header-left { display: flex; align-items: center; @@ -838,7 +845,8 @@ body { font-family: var(--kb-font-mono); } -.btn-clear { +.btn-clear, +.btn-config { background: none; border: none; color: var(--kb-text-muted); @@ -849,11 +857,108 @@ body { transition: all 0.15s; } -.btn-clear:hover { +.btn-clear:hover, +.btn-config:hover { background: var(--kb-bg-tertiary); color: var(--kb-danger); } +.model-config { + display: grid; + grid-template-columns: 1fr 92px; + gap: 6px; + margin-top: 9px; + padding: 9px; + border: 1px solid var(--kb-border); + border-radius: 8px; + background: var(--kb-bg); +} + +.model-config input { + min-width: 0; + border: 1px solid var(--kb-border); + border-radius: 5px; + padding: 6px 7px; + background: var(--kb-bg-secondary); + color: var(--kb-text); + font-size: 10px; +} + +.model-config input:first-child, +.model-config input[type="password"], +.model-config .forgejo-message { grid-column: 1 / -1; } + +.model-config button { + border: 1px solid var(--kb-accent); + border-radius: 5px; + background: rgba(88, 166, 255, .12); + color: var(--kb-text); + cursor: pointer; +} + +.runtime-status { + padding: 10px 14px; + border-bottom: 1px solid var(--kb-border); + background: var(--kb-bg-secondary); + font-size: 11px; +} + +.runtime-row, +.forgejo-title, +.forgejo-actions { + display: flex; + align-items: center; + gap: 7px; +} + +.runtime-dot { + width: 7px; + height: 7px; + border-radius: 50%; +} + +.runtime-dot.online { background: #3fb950; box-shadow: 0 0 7px rgba(63, 185, 80, .55); } +.runtime-dot.waiting { background: #d29922; } +.runtime-tools { margin-left: auto; color: var(--kb-text-muted); } + +.forgejo-status { + margin-top: 9px; + padding: 9px; + border: 1px solid var(--kb-border); + border-radius: 8px; + background: var(--kb-bg); +} + +.forgejo-title { justify-content: space-between; margin-bottom: 7px; } +.forgejo-title span, +.forgejo-detail { color: var(--kb-text-muted); } + +.forgejo-url { + width: 100%; + box-sizing: border-box; + border: 1px solid var(--kb-border); + border-radius: 6px; + padding: 7px 8px; + background: var(--kb-bg-secondary); + color: var(--kb-text); + font-size: 11px; +} + +.forgejo-actions { margin-top: 7px; } +.forgejo-actions button { + flex: 1; + border: 1px solid var(--kb-border); + border-radius: 5px; + padding: 5px 3px; + background: var(--kb-bg-tertiary); + color: var(--kb-text); + cursor: pointer; + font-size: 10px; +} +.forgejo-actions button:disabled { opacity: .4; cursor: not-allowed; } +.forgejo-detail { margin-top: 6px; } +.forgejo-message { margin-top: 5px; color: var(--kb-accent); word-break: break-word; } + /* ─── 对话区域 ─── */ .agent-messages { diff --git a/product-source/hololake-desktop/electron/main.ts b/product-source/hololake-desktop/electron/main.ts index 1379050..3bb3fad 100644 --- a/product-source/hololake-desktop/electron/main.ts +++ b/product-source/hololake-desktop/electron/main.ts @@ -13,9 +13,10 @@ * └── 数据存储:~/Library/Application Support/HoloLake Era/data/ */ -import { app, BrowserWindow, shell, dialog } from 'electron'; +import { app, BrowserWindow, shell, dialog, ipcMain, safeStorage } from 'electron'; import path from 'path'; import { spawn, ChildProcess } from 'child_process'; +import fs from 'fs'; // ─── 配置 ─── @@ -26,6 +27,31 @@ const CLIENT_PORT = 5180; // 数据目录:macOS 标准位置 const DATA_DIR = path.join(app.getPath('userData'), 'data'); const KB_REPO_PATH = path.join(DATA_DIR, 'knowledge-base'); +const MODEL_CONFIG_PATH = path.join(app.getPath('userData'), 'model-config.json'); + +interface ModelConfigFile { + baseUrl: string; + model: string; + encryptedKey?: string; +} + +function readModelConfig(): ModelConfigFile { + try { + return JSON.parse(fs.readFileSync(MODEL_CONFIG_PATH, 'utf8')) as ModelConfigFile; + } catch { + return { baseUrl: 'https://api.openai.com/v1', model: 'gpt-4o' }; + } +} + +function applyModelConfig(): ModelConfigFile { + const config = readModelConfig(); + process.env.HOLOLAKE_LLM_BASE = config.baseUrl; + process.env.HOLOLAKE_LLM_MODEL = config.model; + if (config.encryptedKey && safeStorage.isEncryptionAvailable()) { + process.env.HOLOLAKE_LLM_KEY = safeStorage.decryptString(Buffer.from(config.encryptedKey, 'base64')); + } + return config; +} // ─── 后端服务器 ─── @@ -73,7 +99,7 @@ function startServer(): Promise { try { process.env.KB_PORT = String(SERVER_PORT); process.env.KB_REPO_PATH = KB_REPO_PATH; - const serverBundle = path.join(__dirname, 'server-bundle.js'); + const serverBundle = path.join(__dirname, 'server-bundle.cjs'); require(serverBundle); console.log(`[KB Server] 内嵌启动,端口 ${SERVER_PORT}`); resolve(); @@ -106,7 +132,7 @@ function createWindow(): void { trafficLightPosition: { x: 16, y: 16 }, backgroundColor: '#0d1117', webPreferences: { - preload: path.join(__dirname, 'preload.js'), + preload: path.join(__dirname, 'preload.cjs'), contextIsolation: true, nodeIntegration: false, }, @@ -130,10 +156,37 @@ function createWindow(): void { }); } +ipcMain.handle('get-data-path', () => DATA_DIR); +ipcMain.handle('agent:get-config', () => { + const config = readModelConfig(); + return { + baseUrl: config.baseUrl, + model: config.model, + configured: Boolean(config.encryptedKey && safeStorage.isEncryptionAvailable()), + }; +}); +ipcMain.handle('agent:save-config', (_event, input: { baseUrl: string; model: string; apiKey?: string }) => { + const baseUrl = String(input.baseUrl || '').trim().replace(/\/$/, ''); + const model = String(input.model || '').trim(); + if (!/^https:\/\//i.test(baseUrl)) throw new Error('模型服务地址必须使用 HTTPS'); + if (!model) throw new Error('模型名称不能为空'); + if (!safeStorage.isEncryptionAvailable()) throw new Error('macOS 加密存储当前不可用'); + const previous = readModelConfig(); + const encryptedKey = input.apiKey + ? safeStorage.encryptString(String(input.apiKey)).toString('base64') + : previous.encryptedKey; + if (!encryptedKey) throw new Error('请填写模型密钥'); + fs.mkdirSync(path.dirname(MODEL_CONFIG_PATH), { recursive: true }); + fs.writeFileSync(MODEL_CONFIG_PATH, JSON.stringify({ baseUrl, model, encryptedKey }), { mode: 0o600 }); + applyModelConfig(); + return { baseUrl, model, configured: true }; +}); + // ─── 应用生命周期 ─── app.whenReady().then(async () => { try { + applyModelConfig(); await startServer(); createWindow(); } catch (err) { diff --git a/product-source/hololake-desktop/electron/preload.ts b/product-source/hololake-desktop/electron/preload.ts index 8b63ae3..4c7e8c3 100644 --- a/product-source/hololake-desktop/electron/preload.ts +++ b/product-source/hololake-desktop/electron/preload.ts @@ -16,11 +16,11 @@ contextBridge.exposeInMainWorld('hololake', { // 数据目录 getDataPath: () => ipcRenderer.invoke('get-data-path'), - // Forgejo 远程仓库管理(预留接口) - forgejo: { - getRemotes: () => ipcRenderer.invoke('forgejo:get-remotes'), - addRemote: (url: string) => ipcRenderer.invoke('forgejo:add-remote', url), - push: () => ipcRenderer.invoke('forgejo:push'), - pull: () => ipcRenderer.invoke('forgejo:pull'), + agent: { + getConfig: () => ipcRenderer.invoke('agent:get-config'), + saveConfig: (config: { baseUrl: string; model: string; apiKey?: string }) => + ipcRenderer.invoke('agent:save-config', config), }, + + // Forgejo 通过本地知识库 API 管理;此桥只保留非敏感应用信息。 }); diff --git a/product-source/hololake-desktop/forgejo/INTEGRATION.md b/product-source/hololake-desktop/forgejo/INTEGRATION.md index 346f184..72c664a 100644 --- a/product-source/hololake-desktop/forgejo/INTEGRATION.md +++ b/product-source/hololake-desktop/forgejo/INTEGRATION.md @@ -23,3 +23,9 @@ # - 不接 Forgejo 上游自动更新 # - 光湖团队评估 Forgejo 新版功能后,拆出有用部分自行集成 # - Forgejo 的 Git 引擎逐渐适配光湖协议(HLDP/GLS) +# +# 2026-08-08 运行实现: +# - GitEngine 已实现状态、配置 remote、fetch、仅快进 pull、显式确认 push +# - 桌面 UI 已提供连接与同步状态;认证继续使用本机钥匙串或 SSH +# - Agent 只获得只读 inspect_repository 工具,不拥有自动 push 权限 +# - 本地 API 仅监听 127.0.0.1,不向局域网暴露 diff --git a/product-source/hololake-desktop/package-lock.json b/product-source/hololake-desktop/package-lock.json index e67f9a3..a3f513c 100644 --- a/product-source/hololake-desktop/package-lock.json +++ b/product-source/hololake-desktop/package-lock.json @@ -9,7 +9,7 @@ "version": "0.5.0", "dependencies": { "cors": "^2.8.5", - "diff": "^7.0.0", + "diff": "^9.0.0", "express": "^5.1.0", "gray-matter": "^4.0.3", "marked": "^15.0.0", @@ -26,6 +26,7 @@ "concurrently": "^9.1.0", "electron": "^35.0.0", "electron-builder": "^26.0.0", + "esbuild": "^0.25.0", "react": "^19.0.0", "react-dom": "^19.0.0", "tsx": "^4.19.0", @@ -745,9 +746,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" ], @@ -762,9 +763,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], @@ -779,9 +780,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], @@ -796,9 +797,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], @@ -813,9 +814,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], @@ -830,9 +831,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], @@ -847,9 +848,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], @@ -864,9 +865,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], @@ -881,9 +882,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], @@ -898,9 +899,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], @@ -915,9 +916,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], @@ -932,9 +933,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], @@ -949,9 +950,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], @@ -966,9 +967,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], @@ -983,9 +984,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], @@ -1000,9 +1001,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], @@ -1017,9 +1018,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], @@ -1034,9 +1035,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", "cpu": [ "arm64" ], @@ -1051,9 +1052,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], @@ -1068,9 +1069,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ "arm64" ], @@ -1085,9 +1086,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], @@ -1102,9 +1103,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ "arm64" ], @@ -1119,9 +1120,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], @@ -1136,9 +1137,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], @@ -1153,9 +1154,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], @@ -1170,9 +1171,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], @@ -3188,9 +3189,9 @@ "optional": true }, "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -3659,9 +3660,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3672,32 +3673,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, "node_modules/escalade": { @@ -6403,6 +6404,490 @@ "fsevents": "~2.3.3" } }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -6679,490 +7164,6 @@ } } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, "node_modules/webcrypto-core": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.9.2.tgz", diff --git a/product-source/hololake-desktop/package.json b/product-source/hololake-desktop/package.json index 3385e47..dc1bfb2 100644 --- a/product-source/hololake-desktop/package.json +++ b/product-source/hololake-desktop/package.json @@ -2,30 +2,32 @@ "name": "hololake-desktop", "version": "0.5.0", "description": "HoloLake Era 桌面版 — Git 驱动的知识库管理", - "main": "dist-electron/main.js", + "main": "dist-electron/main.cjs", "type": "module", "scripts": { "dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"", "dev:server": "tsx watch ../guanghu-knowledge-base/server/index.ts", "dev:client": "vite", "dev:electron": "electron .", - "build": "vite build && tsc -p tsconfig.electron.json", + "build:electron": "esbuild electron/main.ts --bundle --platform=node --format=cjs --external:electron --outfile=dist-electron/main.cjs && esbuild electron/preload.ts --bundle --platform=node --format=cjs --external:electron --outfile=dist-electron/preload.cjs", + "build:server": "NODE_PATH=./node_modules esbuild ../guanghu-knowledge-base/server/index.ts --bundle --platform=node --format=cjs --outfile=dist-electron/server-bundle.cjs", + "build": "vite build && npm run build:electron && npm run build:server", "pack": "npm run build && electron-builder --mac --dir", "dist": "npm run build && electron-builder --mac", "preview": "vite preview" }, "dependencies": { - "express": "^5.1.0", "cors": "^2.8.5", - "simple-git": "^3.27.0", + "diff": "^9.0.0", + "express": "^5.1.0", "gray-matter": "^4.0.3", "marked": "^15.0.0", - "diff": "^7.0.0" + "simple-git": "^3.27.0" }, "devDependencies": { - "@types/express": "^5.0.0", "@types/cors": "^2.8.17", "@types/diff": "^6.0.0", + "@types/express": "^5.0.0", "@types/node": "^22.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", @@ -33,6 +35,7 @@ "concurrently": "^9.1.0", "electron": "^35.0.0", "electron-builder": "^26.0.0", + "esbuild": "^0.25.0", "react": "^19.0.0", "react-dom": "^19.0.0", "tsx": "^4.19.0", @@ -47,10 +50,15 @@ "icon": "forgejo/icon.icns", "identity": "bei sun (825A9L3G7Q)", "target": [ - { "target": "dmg", "arch": ["arm64"] } + { + "target": "dmg", + "arch": [ + "arm64" + ] + } ] }, - "asar": false, + "asar": true, "files": [ "dist/**/*", "dist-electron/**/*", diff --git a/product-source/hololake-desktop/vite.config.ts b/product-source/hololake-desktop/vite.config.ts index c598acb..b0c9bd2 100644 --- a/product-source/hololake-desktop/vite.config.ts +++ b/product-source/hololake-desktop/vite.config.ts @@ -3,11 +3,17 @@ import react from '@vitejs/plugin-react'; import path from 'path'; export default defineConfig({ + base: './', plugins: [react()], resolve: { alias: { // 复用知识库前端组件 '@': path.resolve(__dirname, '../guanghu-knowledge-base/src'), + 'react/jsx-runtime': path.resolve(__dirname, 'node_modules/react/jsx-runtime.js'), + 'react-dom/client': path.resolve(__dirname, 'node_modules/react-dom/client.js'), + 'react-dom': path.resolve(__dirname, 'node_modules/react-dom/index.js'), + 'react': path.resolve(__dirname, 'node_modules/react/index.js'), + 'marked': path.resolve(__dirname, 'node_modules/marked/lib/marked.esm.js'), }, }, root: path.resolve(__dirname, '../guanghu-knowledge-base'),