From 0edd7c0b475d828dad16a7353a8ffce0273d7f2e Mon Sep 17 00:00:00 2001 From: JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:46:16 +0800 Subject: [PATCH] feat: Windows NSIS installer, embedded icons, GUI auto-launch backend - Add package/installer.nsi (Full/Server/Client) and toolchain.nsi - Embed icon.ico (rounded corners) into homed.exe/waiter.exe via .syso - GUI auto-launches homed.exe from parent dir (Windows only) - GUI fallback connections.json from app resource dir - Add initconfig command for config.db seeding - Replace waiter rawmode* with raw_{unix,windows,other}.go - Fix .gitignore: /homed instead of homed, add login.json - Update icon.svg with rounded rect, new mascot.svg --- .gitignore | 4 +- cmd/gui/icon.ico | Bin 0 -> 302430 bytes cmd/gui/icon.svg | 2 +- cmd/gui/main.js | 101 ++++- cmd/gui/package-lock.json | 824 +++++++++++++++++++++++++++++++++++- cmd/gui/package.json | 4 +- cmd/gui/renderer/app.js | 60 ++- cmd/gui/renderer/index.html | 2 +- cmd/gui/renderer/mascot.svg | 9 + cmd/homed/homed.rc | 1 + cmd/homed/homed.syso | Bin 0 -> 302918 bytes cmd/initconfig/main.go | 67 +++ cmd/waiter/raw_other.go | 11 + cmd/waiter/raw_unix.go | 43 ++ cmd/waiter/raw_windows.go | 52 +++ cmd/waiter/waiter.rc | 1 + cmd/waiter/waiter.syso | Bin 0 -> 302918 bytes go.mod | 2 +- package/installer.nsi | 326 ++++++++++++++ package/toolchain.nsi | 137 ++++++ 20 files changed, 1631 insertions(+), 15 deletions(-) create mode 100644 cmd/gui/icon.ico create mode 100644 cmd/gui/renderer/mascot.svg create mode 100644 cmd/homed/homed.rc create mode 100644 cmd/homed/homed.syso create mode 100644 cmd/initconfig/main.go create mode 100644 cmd/waiter/raw_other.go create mode 100644 cmd/waiter/raw_unix.go create mode 100644 cmd/waiter/raw_windows.go create mode 100644 cmd/waiter/waiter.rc create mode 100644 cmd/waiter/waiter.syso create mode 100644 package/installer.nsi create mode 100644 package/toolchain.nsi diff --git a/.gitignore b/.gitignore index 06c7b2a..423fffa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -homed +/homed /waiter *.exe *.log @@ -15,6 +15,8 @@ internal/meta/ *.hmap dev/ +login.json + # GUI cmd/gui/node_modules/ cmd/gui/dist/ diff --git a/cmd/gui/icon.ico b/cmd/gui/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e121e63b68931c993b84cc2646a68589c53d0e68 GIT binary patch literal 302430 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 literal 0 HcmV?d00001 diff --git a/cmd/gui/icon.svg b/cmd/gui/icon.svg index e8214ec..66dfe03 100644 --- a/cmd/gui/icon.svg +++ b/cmd/gui/icon.svg @@ -1,5 +1,5 @@ - + diff --git a/cmd/gui/main.js b/cmd/gui/main.js index a47f36c..4270e12 100644 --- a/cmd/gui/main.js +++ b/cmd/gui/main.js @@ -1,9 +1,14 @@ -const { app, BrowserWindow, ipcMain, dialog } = require('electron'); +const { app, BrowserWindow, ipcMain, dialog, Menu } = require('electron'); const path = require('path'); const fs = require('fs'); +const { spawn } = require('child_process'); +const http = require('http'); const CONNECTIONS_FILE = path.join(app.getPath('userData'), 'connections.json'); +let homedProcess = null; +let mainWindow; + function loadConnections() { try { if (fs.existsSync(CONNECTIONS_FILE)) { @@ -12,6 +17,18 @@ function loadConnections() { } catch (e) { console.error('Failed to load connections:', e); } + // Fallback: check app resource dir (installer writes fallback copy there) + try { + const fallback = path.join(__dirname, 'connections.json'); + if (fs.existsSync(fallback)) { + const data = JSON.parse(fs.readFileSync(fallback, 'utf-8')); + saveConnections(data); + console.log('Imported connections from app resource dir'); + return data; + } + } catch (e) { + console.error('Fallback connections load failed:', e); + } return { connections: [], currentId: null }; } @@ -23,9 +40,69 @@ function saveConnections(data) { } } -let mainWindow; +function findHomed() { + if (process.platform !== 'win32') return null; + const exeDir = path.dirname(app.getPath('exe')); + const p = path.resolve(exeDir, '..', 'homed.exe'); + return fs.existsSync(p) ? p : null; +} + +function isServerRunning() { + return new Promise((resolve) => { + const req = http.get('http://localhost:8080/', () => resolve(true)); + req.on('error', () => resolve(false)); + req.setTimeout(2000, () => { req.destroy(); resolve(false); }); + }); +} + +function waitForServer(maxWait = 8000) { + return new Promise((resolve) => { + const start = Date.now(); + const check = () => { + isServerRunning().then((running) => { + if (running) return resolve(true); + if (Date.now() - start > maxWait) return resolve(false); + setTimeout(check, 300); + }); + }; + check(); + }); +} + +function startHomed() { + const homedBin = findHomed(); + if (!homedBin) { + console.log('homed.exe not found near GUI, skipping auto-launch'); + return; + } + const dataDir = path.resolve(path.dirname(homedBin), 'data'); + console.log('Starting homed:', homedBin, '-data', dataDir); + homedProcess = spawn(homedBin, ['-data', dataDir], { + stdio: 'ignore', + detached: false, + windowsHide: true, + }); + homedProcess.on('error', (err) => { + console.error('homed start failed:', err.message); + homedProcess = null; + }); + homedProcess.on('exit', (code) => { + console.log('homed exited with code', code); + homedProcess = null; + }); +} + +function stopHomed() { + if (homedProcess) { + homedProcess.kill(); + homedProcess = null; + } +} function createWindow() { + const menu = Menu.buildFromTemplate([]); + Menu.setApplicationMenu(menu); + mainWindow = new BrowserWindow({ width: 1280, height: 860, @@ -93,12 +170,28 @@ ipcMain.handle('connections:setCurrent', (_, id) => { return data; }); -app.whenReady().then(createWindow); +app.whenReady().then(async () => { + const running = await isServerRunning(); + if (!running) { + startHomed(); + const started = await waitForServer(); + if (started) { + console.log('homed started successfully'); + } else { + console.error('homed failed to start within timeout'); + } + } + createWindow(); +}); + +app.on('before-quit', stopHomed); app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); }); app.on('activate', () => { - if (mainWindow === null) createWindow(); + if (mainWindow === null) { + createWindow(); + } }); diff --git a/cmd/gui/package-lock.json b/cmd/gui/package-lock.json index 0f06951..4e10aae 100644 --- a/cmd/gui/package-lock.json +++ b/cmd/gui/package-lock.json @@ -13,9 +13,29 @@ "devDependencies": { "asar": "^3.2.0", "electron-builder": "^26.15.3", - "electron-packager": "^17.1.2" + "electron-packager": "^17.1.2", + "icojs": "^0.23.0", + "sharp": "^0.35.3" } }, + "node_modules/@borewit/text-codec": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/@borewit/text-codec/-/text-codec-0.2.2.tgz", + "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@canvas/image-data": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@canvas/image-data/-/image-data-1.1.0.tgz", + "integrity": "sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==", + "dev": true, + "license": "MIT" + }, "node_modules/@electron/asar": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", @@ -367,6 +387,544 @@ "node": ">= 10.0.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.11.2", + "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -536,6 +1094,31 @@ "node": ">=10" } }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -1278,6 +1861,13 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", + "dev": true, + "license": "MIT" + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -1640,6 +2230,35 @@ } } }, + "node_modules/decode-bmp": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/decode-bmp/-/decode-bmp-0.2.1.tgz", + "integrity": "sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/decode-ico": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/decode-ico/-/decode-ico-0.4.1.tgz", + "integrity": "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "decode-bmp": "^0.2.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1721,6 +2340,16 @@ "node": ">=0.4.0" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -2301,6 +2930,25 @@ } } }, + "node_modules/file-type": { + "version": "21.3.4", + "resolved": "https://registry.npmmirror.com/file-type/-/file-type-21.3.4.tgz", + "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/filelist": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", @@ -2827,6 +3475,44 @@ "node": ">= 14" } }, + "node_modules/icojs": { + "version": "0.23.0", + "resolved": "https://registry.npmmirror.com/icojs/-/icojs-0.23.0.tgz", + "integrity": "sha512-l2r+WSRnwF7OAUcyVBh8N5y8j0usPYs9QQPskO1fXygxpLV+l+SeqLtklxUz1WVF3Ao+gGzoY7sh9jZRy04WmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bmp-ts": "^1.0.9", + "decode-ico": "^0.4.1", + "file-type": "^21.3.4", + "jpeg-js": "^0.4.4", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2951,6 +3637,13 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmmirror.com/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/js-yaml": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", @@ -3609,6 +4302,16 @@ "node": ">=10.4.0" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/postject": { "version": "1.0.0-alpha.6", "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", @@ -3963,6 +4666,69 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4146,6 +4912,23 @@ "node": ">=0.8.0" } }, + "node_modules/strtok3": { + "version": "10.3.5", + "resolved": "https://registry.npmmirror.com/strtok3/-/strtok3-10.3.5.tgz", + "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -4309,6 +5092,32 @@ "tmp": "^0.2.0" } }, + "node_modules/to-data-view": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/to-data-view/-/to-data-view-1.1.0.tgz", + "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -4358,6 +5167,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/undici": { "version": "6.27.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", diff --git a/cmd/gui/package.json b/cmd/gui/package.json index df6fae0..dedb7d7 100644 --- a/cmd/gui/package.json +++ b/cmd/gui/package.json @@ -13,7 +13,9 @@ "devDependencies": { "asar": "^3.2.0", "electron-builder": "^26.15.3", - "electron-packager": "^17.1.2" + "electron-packager": "^17.1.2", + "icojs": "^0.23.0", + "sharp": "^0.35.3" }, "build": { "appId": "com.homeagent.gui", diff --git a/cmd/gui/renderer/app.js b/cmd/gui/renderer/app.js index 1736c58..4e6a2ac 100644 --- a/cmd/gui/renderer/app.js +++ b/cmd/gui/renderer/app.js @@ -32,7 +32,57 @@ window._i18n = { navAdapters: ['适配器','Adapters'], navKernel: ['内核','Kernel'], navLogout: ['退出登录','Logout'], - themeToggle: ['切换亮色/暗色模式','Toggle theme'] + themeToggle: ['切换亮色/暗色模式','Toggle theme'], + clickManage: ['点击管理连接','Click to manage connections'], + secondsAgo: ['秒前','s ago'], + minutesAgo: ['分钟前','min ago'], + hoursAgo: ['小时前','h ago'], + noConnection: ['未连接','Not connected'], + agentAvatar: ['小宅','Agent'], + waitingAI: ['等待AI回复...','Waiting for AI...'], + noResponse: ['(无响应)','(no response)'], + error: ['错误: ','Error: '], + requestFailed: ['请求失败: ','Request failed: '], + send: ['发送','Send'], + queryFailed: ['查询失败: ','Query failed: '], + searchFailed: ['搜索失败: ','Search failed: '], + getFailed: ['获取失败: ','Get failed: '], + createFailed: ['创建失败','Create failed'], + createFailedWith: ['创建失败: ','Create failed: '], + nameContentEmpty: ['名称和内容不能为空','Name and content cannot be empty'], + knowledgeCreated: ['知识「','Knowledge "'], + knowledgeCreatedEnd: ['」已创建','" created'], + noContext: ['无上下文','No context'], + noSessions: ['暂无终端会话','No terminal sessions'], + noHistory: ['暂无命令记录','No command history'], + running: ['运行中','Running'], + closed: ['已关闭','Closed'], + command: ['命令','Command'], + status: ['状态','Status'], + created: ['创建时间','Created'], + uptime: ['运行时长','Uptime'], + output: ['输出预览','Output'], + time: ['时间','Time'], + actions: ['操作','Actions'], + name: ['名称','Name'], + description: ['描述','Description'], + version: ['版本','Version'], + details: ['详情','Details'], + close: ['关闭','Close'], + install: ['安装','Install'], + installPlugin: ['安装插件','Install Plugin'], + packageUrl: ['.hmap 包下载 URL','Package URL'], + uploadHmap: ['选择 .hmap 文件上传','Upload .hmap file'], + loadedPlugins: ['已加载插件','Loaded Plugins'], + noLoadedPlugins: ['暂无已加载插件','No loaded plugins'], + loaded: ['已加载','Loaded'], + builtin: ['内置','Built-in'], + unload: ['卸载','Unload'], + installedExternal: ['已安装外部插件','Installed Plugins'], + pluginDetails: ['插件详情','Plugin Details'], + registeredTools: ['已注册工具','Registered Tools'], + systemOps: ['系统操作','System Operations'], + reloadPlugins: ['重载插件','Reload Plugins'], }; function __(zh, en) { return state.lang === 'en' ? en : zh } @@ -84,10 +134,10 @@ function escHtml(s) { function timeAgo(t) { var s = Math.floor((Date.now() - new Date(t).getTime()) / 1000); - if (s < 60) return s + '秒前'; + if (s < 60) return s + __('秒前','s ago'); var m = Math.floor(s / 60); - if (m < 60) return m + '分钟前'; - return Math.floor(m / 60) + '小时前'; + if (m < 60) return m + __('分钟前','min ago'); + return Math.floor(m / 60) + __('小时前','h ago'); } function toast(m, isError) { @@ -325,7 +375,7 @@ function renderChat() { html += '
' + body + '
'; } else { var userAvatar = ''; - var aiAvatar = '小宅'; + var aiAvatar = '' + __('小宅','Agent') + ''; html += '
' + '
' + (role === 'user' ? userAvatar : aiAvatar) + '
' + '
' + body + '
' diff --git a/cmd/gui/renderer/index.html b/cmd/gui/renderer/index.html index 15ce857..d08778d 100644 --- a/cmd/gui/renderer/index.html +++ b/cmd/gui/renderer/index.html @@ -45,7 +45,7 @@ 适配器 内核
- + 未连接 diff --git a/cmd/gui/renderer/mascot.svg b/cmd/gui/renderer/mascot.svg new file mode 100644 index 0000000..838dd1b --- /dev/null +++ b/cmd/gui/renderer/mascot.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/cmd/homed/homed.rc b/cmd/homed/homed.rc new file mode 100644 index 0000000..af6a395 --- /dev/null +++ b/cmd/homed/homed.rc @@ -0,0 +1 @@ +1 ICON "E:/program/homeagent/homeagent/build/icon.ico" diff --git a/cmd/homed/homed.syso b/cmd/homed/homed.syso new file mode 100644 index 0000000000000000000000000000000000000000..0a1e60ea3760a0ea62659307d9b500a7eaf6b17c GIT binary patch literal 302918 zcmeHw2b?5VdFNsa8~c11V~mZBK?s96pU=nHBuN;A5a1));D`?pT7iN|A_xNpga9Rk z0!TtyX|uGetkveMU2V>3HqOq@%udcTJ>6B+T|M*N|NpA1r>3Vvb*`Fu^ZUK2>Pjzt z|1Z7oy?6C3FPX)^x6Z#{mUDK&tiSsDH@-ewU3LDgop-^kcjGjQBmaH_>9SdGy^QA* zf4?^C*YV@RS+j0>IgW>M#KH6TQuY0R#r0pq)vw{m=WoN2UtNIXOL1I_BMzRwm(2Pt zKHwB?%Jo;|xPD=d>u=3*{jx0Ad8s=`dHx7yd4owG9o-H~;e0)sC$C5IZw2=}rW+x_JPK|rs1qKtnGo~?160U6=*)-==oaSYy4~cSD6OD z2b7OMf?*fXcd2~$*?5+|RzBa?ZK&HY3k?u+YTTfT{<}h-CLc;B^q8HNc~zEqS?FK4 zIosUT1qvax!uMVOp6(Ydn=}p7od)P1tXcek!am0HbieC1&@>Pj8er@|wRwQ@?=wzM z_q%QbO#^|W0mmm$9lxN)zP52S-w!?wRD}mn=ht#SaQt55G5C0_M;{TZ6|)7jy{~bv zb^XxMK&AWvDvnq8f9U$Z9&$(L87zH7jSG}9^yiH42dhq+#&myZ8t_j8POM<@On|XP zI=07uJ8PQMZ52!!K#Wk)^NF>;FPMF)F{b;acp6atz#`@gghTJ=8X}BEFeMo`Bx%Kp zPkfKQ4a}*~bX7cEO`A50lZJ{+q`MIL#r)a<9On-{9)MSKRP3g`5?^z-Sc|_Z=Dcf) zOY^T4>+x?(eEXwf_cWm|H4g|AJ(pWnD>fp-z3tM|dRn^9ohUkWH=mS&&Sr^?42VtM z5p-U_d4s@qp}$c0`+@!VwuNH;{G($0=n^q*dRJ-bM;D9n<9Cbs@N7w(-J^Lx&}q0r z|MFAY$%7IZ=nlOO5O~>7JAJ52tc724!pV+4#pisL7=Dx;%c>1ag zoK}n8H2yR3p9t5wz8e1;|7GwMjsFb%bNvkX0jkAsEB;-L|M2ux891#t-K5H*@jn^= zp~61|7LKG*oy_;+ccgrk=KA?E`c{~G@#;9krBkmKI%bB%wEf0q_YIBNMHaz3E( zukl|3?zQ|6Iquy)*Z40F|8Z07xS^7Z3HRt+HzkQ@+-uYAsO5ji`GCfMUToTyAqgvn zXC^Sr-_fC786D`B(f&?}^mXFAOZcpd?}QnZhq&-s3Z)_)c`N zdlJ^;#;C(P`tc3$6XqE=BI$hG{DOSc_}BOkGyW;FNy9G2sIwERBRy@vW``rUfo(?z znCNTuUg}--zULe6x2X5?o=WQ33H^Z2kf)GGi~|46YowoDL z)~&0lL0TL3O6&1`l}#u1i!m|~uKo1t+#f~L#|+f}Nwbu_q%C6IijJi5Pt5W+bpWNC z<9E?*S|kmyJj{!EGI{eeM~74ySyq;r&wB6I`&{FHLMGI^FG|XPhT)&sro5$mSMoL! z|3zZAq&6=i4{LN-;h$w?nQ3=q@`!4eA>a2k{x$xCt^ZG!mnQH;znqe%khMY9tzF!) zjKsV#(mz#SAup+;PN4Cx@gGF|lP<03uo%MwlQ7QfwDDbRh3&}ld-1OPjKlq^uIgS9 zxv0Jel*92*C`2O!gpT@nh(-9+%W{!m33y_Ysud<{zHs? z%8KcPf5;*OvQXLfy&Xzl_Kw>H3AdFj3+qVRU<7q$-IdS0MtXq8zs7&1^#3u?tV(w3 zSON{xUqfZqt5c5c!z;5@wg>} zF-uy8EIHb1O5=bfeWR8bmL=ol2S}OiNZO-ctd{z2W*LJ1o4!LUMw?)=AJi!~@NOs2 z{2X`e5_9CF#0C$F6={Oa)Qfiz_h{QGzA&}@`3;T#?ClbCx=5F=j`%08W2Pl9w3+hV z-G;npxgl?QJSG<|iOCz6#^i6FG345%e3wgi! z)Qvdap?m{~L!6`&0r&A(rwp|%mA1pP<;>QxoE#{V>+p*rE8*r$yD%63EE0KEUvqlR3v!jwo={kO;^qjg@I*)x?&h2`aoZRp#@PyY&`_b!RQ=QDp1GM~~+}@$1 zzdGQb*gw#1$p=;%@&}6z`G?JMd89chn+C^a+sL@=jEu{6q%Fha@uIds}!pNB<+`58zmV_Wy;RUTUcSgK(6ukM=%we#(76*mrpWpQXO=2a95I*Wqmb z?2z-~5@dQY^w-;X2Qd75!190PkolR|cYhyNdO-W3e^CAa`UIVE0geA++CPxb))4<3 z|4u#sH@tqR8sVS1Kgajq^StBdr?1Zs z<};t64sg|uxV-MMnC$K}RqTL249r~JV9ZX+Xx}zq_chXe;_4!0zsm!l1HdQ9aRH7E zGCqLuLbU(8&z-=$|H{w*KY#LoS`#H{JGO@I=PJ-}4e{RsoBhu)zRxi}`uQ`l?dLaj zfFC#5^2&uVS$gEhR)wwyzEc;201R!fw4ix2QWs+i5Ik_zrCrl z>wcux5$S9^hB2PW>mm55uYRToK2a`TZWAtrDu;)W$z<@PDJeFN}5^?%0uoml_-(s$;D zlI1^Rgcv8-h*)9H7jWf2F{)w;v91bz0ZJFZ+I_7>Ch`yJ{FM7aTH|P1^Pn2xpKZvo z|7#G>e<5P|oJ%*23)hy7#URaFgX{~cf$I|%HGd9SII{`1Hfyu zwMn3_)e!&0>Qm6!8P9*+ZYTC9AKo+X?M>PK96$WlPOOQA@x(y4ZII{@bNMf=MQ`sJYaQ756IyURPn)wCDykX^9BBwnlnT{LSEUQmG|hr zD!#93)MhotzuOK^oZ(!an7kQt`o4#l-qncfbNK*y0TX3D?R}2-QSQ@j_~Bm6T{Rp& z!k8lWd-_!ank@Er$BTjIWiu*sa<&D7p zMKaj-7`~z7uBR2P)d~LzV0TT6Depx*;Hxo~_qOLvnY}YEKRIs8y^XdSFkUFc6mTw)7^6Vg*PdG0DXcS7vR`nr1O5n z2;HXQ1Q{#LIX`DHXK18rrN;hrls7fTzgnXXK4GreLF}GKOd#j-d=P5^Fs7GreT?n- zeH=N)_b&MPzX4z0eykTjouBptv47WLL+%4V;2Z$W1M=|zU_XjE|Iqt;8*fwd0Gzda z4CN2#Z1|cQ7vR_+;{%9y9vLgl`2sy>ZWS|fR`C$_T@353B(M+Bw330-5!Zg}R73nT zPK5hmsx`Y(G~{BJINpVL{^y%aS%|nkjuX&N(1bBQ`uW{)K0ePlg8Ppd^5ty~59rW5 zAO{{X=NB@c*l#~_tvXKj-NA>CaRH7E(ypgpf1qWqiWTO30Y_hO^atXdWAf}f_96RH z^MHJOHzfCJh<}a?tM#cNLo)41;+wI2OzCsP_PDtB(i+DR$S>}PAMl&d4fb}KS_jC= z@8c5f--Vd{uR7R=9+1^5qDXt53{qdW5f!Yxi<~9^!P!1FUFkcI;=;LxJC1 zPmt?~Mf$L>3i@zlCmhdZ81=>e6&eY(HUmyQmneE{h;2`ewC75=N(KEygP&+&l&fKPDF zam+`j92z&qTl>e@BazFI6UPT%VZQE2G|DQ*EN%hBzsPmHt zJbc`cl~@;q`v$qTL1_ENH@!Ogy&WHw;m+r!|J?m4?B|Km_xdH^rwvi z{a0oD#~%Ew7(+c((fc#|j(Dfscd_4#J%jp@rnepdxo`BOWAf?mOBj6>wf8gI+5OEi zK#m7QhqzamwgudF3DvRM`2W>s#K3rQt=hzu`HT%@i~z?7Rg4hygG!e{<%RF2$18Ep z@k?*wy=;3IR;Da&Y|p*W_wP#cfJ*xM3YAmsErjvFO8RvR<*Dyikd~{Af8(Jm5l22; zaqQ)z0pfB1a{mEujL=Bs^Z*y{^gB|&XvUtUC;CmbzS)6p6MGvu=e)*ye1^}GFYw)b zW%qxNu|2J7Tt6M#V|3%&wYB%vxGwe`j}GXVApd<=DH^E2cdCqkbIw&YvHvsMo;<*b z5i;b49foZ0C_P4q-y(LI$1v=ReO>f3nCiR#wBC?Qm&N4IF+bt;h+pPh1}2`r1=o0w z&)l%XRJzDEl!Ls9-{LpvyG7{%^};^enezeEevEn_ z<`Q|i#=k2|Dt#n|-9&w0RkJCaFHlGi=lxN{6|Tb^#j9R0)Vig=JufCN1+IS!_Td*5o?-pUh>ZlIWnF;2cGj9@9`Nv%Xj#$`wi}KJ{#X=9;2x_&H3w}itT}q z--*q4{QmXCzEfVt1L!e;{C!tPjOUYg(^&p{`-5_y*#9#29%P(At{5TmiUe$R&PBR% zGxjKj9{;kGOy|C1?}hB<9!88eYQ)^6KIrn~6MTpI2G=8H;yJJJ9-rab$Ba+pyH`Mm z;M_*)3H0rN z|5kkaD&)bunCI^zZ{4ITyOB^ea^h0dSKt}Bj#;l?$WOgwaA|?>Qy{|dH~B>3thx5N2$knY(&KZ z>GgqXFF#7^vl)ngV(b8XeeZycO+A}(pV+595Cn{|3}&oP9t01d9>6lvH?a?8t|xEu zLtoqn&_cX-CDwTIlb?R3Og=Ni@K3#;V|@R#!SVG`_rC-BwmWAqDD9B*^|{Jz?%4n7^0nPp^IX$Sld#3k)SY+~T;0E`9b zF@O;8pc#UH>eHNS^I62%(%<(Q#M>|iDCjsMUt$>cEfu@JZsH z^MPZ-T!$nC7?{artSSC6cFldGZ5xT}&DSoCqn>M9EcnwLTl(s)2^leyGM4m~!A9(U zA|1o;#`4$xIJu2j#$lB8s;zP52Vfo6wSq68PPJ@9Coks7*u&g$2wV$jw7**=tpfy{ z|J4ltpqCipLORz;qUjMyoVl-N$wpqor{~I5YnmWGO}TJUw`|?LK$49UW#BVIc;?w7 zN95+cQOw$AU<-=1g4AI|TSWh=fe_9m9aDMK7I-MaoG^47&C6}J8xeC_p2 zzbW6-^U;TNxXyJJ!Gyn7H zdBD_EyhJx%DmOg!Xx*{z>K!*c{isAYT{;EZEc>^go(~>j$Qx0oovX3FYMt6v_34gJ zial~RGgYw+UuLCbr zbrD`Wxc1Y~yHCLesGkl%+5f*G`wy)7ci1S|%K1)tX2myEU0A0Fm;H2-EmNy@P3N=a zGO-7b0{<8n(D(~q8&n0(d?Em!Rt5x2)WWQTR*5Uil%u#jv^F`<680whKSKvNh z)ng9)Q|5DDz(`+*o(G`uUl;q7zCZf({&Yc?!pa@6?fv-5sW)t1^+kEZ!nT^|0F?dA zYtyQ0e93Xv;db~4$kSf8uoHFsw?N`QHq@8Ge=NB6Z;-KBi?U5?`Tus=yXG_U2lEHy zHxX0w%VoDqa`QyoPcFGg`8&Gt-E!m83o!3CTJo2IxS^_c0QG+6!MvEK zAB=_q|Jb99YXLfIfol8*mj6w2{2yFXy#DWEkmHB?W&EFB|0AG&KbMb8Yy30*_fo|FF7Xxrn+)kVu~+6gND7cmWtY5p2wn}Znt%XPpR|HpMe0&Dxa z7?{b&s^dRc^M5$^->;wD;$@*CfK<`MNxe%sB*&yo0lX2mxq z=Knlj=lMS`WS{>-xzE@i@&Jwh0P6r%#eWdy|GoqBf3L#)UniF5J5SGryiQqt1AGK~0h?F{Ow0cnD*tbKmzZ4tt7kXXiu&ieuK#t5yZ#sE z*eqLlLrHVyiNE#@e~&a&lS5q`sOe%|L;=Gjj;>wjLP*8luWo!9@|o)g>7 z`d?8!_isk)|B(MF{3{s|<@(=irC#fQf8MkH_ltYxPg?)m@0!_MZ##1O5xI7KbJ6(c zJ0p0vlr_7#{`VHo`roVz*EBEXTYl@B^*Ocv_u7K%e`}c^V43gbNmaG~z4&K)Ku-+F z{vTg>G28wh-n~F_pO0fdj=f!${3Z6{;=Y`P)(GG;fB95Q_TU}9TkM`4?*1RMJ^O#G z4ex)X=4AcryEP(|I0?(-Mkm#43uFJZ|8?w7Y5iRajg?F{B;QiLKg|0zM~6z{ceN^~&S&Px zf48qQ_y4{g`+pC`EExly-DmtBsZ-29VagvYioq8!RS)1b-kXPK_^jXWy3Y~g+?)J5 zl+oS)n|qhD4(>BSJaWvBV}IlWK`fsxlZSq0ko;%A6X#tKOa5`ap=|e8E{w^~51C?G z#q$7SdLTOStxP+Bvj0=ahtCv?e?HGL-HEcXjQkeM%(9olt7=B`YTZx0?pMv)y9Bv1 zscbV0|ExRZ>OT15-uA44z5ZfqPvAK_2gDkQ6pbx@Yi)}uuX}8=4nW!er?|#@#p>$B zz6IU+k$s&gTU3?t?Iw+l;^TeJ`Qg5wD()A&pw{{8{5-PVM}N%}|6e9u z5M#^Fneykbr(Xuy`nq|;LLNYwTMWkdov3NaSGF6<1|aU4D6hYaYrMy2GV{;%n|ZSg zbM|)1>lO^4Y=*q~@t7)WG2hAc{c2yg5%(J%=y7a+;=h=LHG`^MKK=a+TAYFMpEN)n zIx#dNi=R6q7d^GO-#Y?j!_ zfQ}m~LS~dj12Yl-z-y9Ng1&EUJg9g8{pz#@ejm0reS&9F;{twVE}uI!V9Bo3vg>ru}uy5^sR+6IwPMHJB1BltKrUq#}zRyVwd!@CMg!kJ{9ReR| z(>$OSJYc5bpV$ZPlhJ6J2T%{7EkJ(&^>+H&IX3td;sZtu|1z991vbM~$*+%&xQ`%@ zXU>``Pv*@suq-SS<-Wo`W2X$n(vuHliMKCH29!x>jPaj@eU}H6acnzzP$C1}+8!vg zZwk`IOu|29XaAri*6owTj)n;y01Q%A@9Vadzy9UW-#OO)M~h=}^%g_6wL3OG0$Pf) z3v#tRG0$(&H}GP+DPP=bDBFX1GH?3%8DGdUDV?9?HX@QZx=s?ipAdTpdujzp4;X^1 zPRso=FhA)V&>d(GIO~UI*sRsY#7z4BOu|30zj}|vA6_kqwR;^s0627UN?dY$jbrS8 zf!JQ!-;~7{E{Vw(zy~Og+eRE*@>wQ@(LD6x-uFJ=jXYL0o9dgd$G4dW^P&yHyjcc5 z@0Lqp9dbXh`$>r}zeN%|mw*R!PTbFvfBGBMdItWzo|aRU$A8KWP%%US;&oMT&uaBk zuJ6ti{3B*2vHz6BA6cV#fDK-d^kOX4KFTkMXLoj*@>#?R(0&(%1J{#Pl*Yk+D75 zZ3pN8!(9sd@fEj9;^dY^miPUtyXeercDl!T9~>UohmNr5M)(R$mGoo$~rs@X=9T|KHVyTm$|6rhSI| z41W9jk2#6wyvBQf2fTBf@l}iy^n8Qgyb9lDi~#eRB=fV;HE{sl-zN5H1E^<+jr!q( z`0u3OkG{SN@;^{dsG}J`NsGVtW#s^w;tI zVT{i+4sXtJQ@*ytP`np!PuBP^f^Sdizks|~ZTvs%tp8Ig_DXt>SREdb#2R4VwfCv> zSE&7|6A-(!)rsZiAxn<;nR2Aplmp#P;`s?&<2^pZXZcP+9p85uq1(U*nAo*c=nshF znB-Vtjcoyq|A64wH{E2Ex61f89{e2Q>N#eek#Dtr6Z_PK2ca87_A}A$uZC=-?53~I zzl+hbtAS)LDJU0Ub?+5G%9<42Y3t8CvQ-bW$#iG9j`6LC#Z>N?fu0bJvo z{`tE;sLluK2Xhk1MzLv6A9S2 zPi~dOo~LROBNW5_-oxGJrTz5b%KQE~mZ1Ir)u-Jm;5!iS68}JXgpV<2pVuXHL^%x3Z^Hi;WEsNC_gmKQRU7}Q^}nqs{Bg8RD@=>7esA~mD<0s)^#KQ!&L=G2qa8pV z0PNfS=Tq&#_NZK&updVt`(wj>n4^a^iFEu=c)*=leZ^M*{ot)pzEP5#pW%J#O zi2eXKM!>ZN*rw3m?LM@7(_UwO@qy#y-2P+Vv5>CAph z|E@LuVLNhP$VfkIRO*kg+vCf3ih1)AF|NB$jH~VzWA;7H@eB8g`P~H)U$jB&rgmq( z8)=cg{^zkKRuyA=((U879fSHD+slm+dT{}K1DH3gaBqs;-XQTccZ>PZ=ft@E17h5A zxfr*;AIJBJap#A{oPV9fw=WWVpdEdMwG0PS>-u@>s`0P!Z`^#TWKG=vH@*MgL_3+I z!!pv{Cb6A|#r(k{g?H%Bv>yD7;s@pIqPUoS6zHnHqA3iF^)%QyL3Cw+Ud4PuwL(|@MD>HZi`2g1F zjBk8EjN7gd>yg=#-1n4>cN~-PzO$24?^zjZ!Q8?Z9s-~E2Z`PF2{HC9Q~rK$TWkDl z{AZQ@)Csc5f6$2EFn4F{^m&Q@{27M_U|x?q2i8lA z`n&)w(r*vBZ`}3)i9dFOj5Y0&@%|?8TVTJpacUw@z`f+LHDW#RX{9gN@Dr##TvL2Z z^VxnwFBm)33O!)4vIUesfZq#x z`v#?a`@~sL=peHk zwZuQh^b$LcDH)zvv{A;pv&j2w*mtjS4lis0`UB__RO14f_0hkx^F;XX;%n|w_I`5T z(-~HWlMiN+SfOZ4dA$4^Cjem`Q-}*o1aAmaoy=JU4!#`ihKXFm8@{IJ-yL z{q*xIUtcD^{rv7c4!!G3V!{`YjKBs!9D&Ba#=k%OgI0if^FQua^K{0$`b);Yz5alT z4@m698va`T=f^&IBVsD4vvYi(V|*p!zx%YrpTAkmyFMm%FV<6|PeI537Hp$nKIYaS%Cp7j;pe16J z^Y~(SeO#>j|4qg8j`yC)?GGgOA@}Vq55wp0%m=o6&P{52jem{*qU68J0~#TVZhlPZ z0kj2_KY%_#jtg*XknsWF6O0pNtT5*bm|uHPtgTp=!d=^{1PtWlgEQb;T(5t$uTzY@ z&nX>%JF}`v5`N!ewqrD%0;@i#~VE7K~wquj9ul4_sW1lo% zYx(cuETsp~7N9?XG5s7D;MgGJ1GsNj{I(|)?ztX_b;pxx-eBguKdwc|bwp+|u8XO= zvt}RG{6RdR_1M={Od$C{eDRkN+w)@;;01x0^J@g5xaRH1CDmjlBA@e^V?-47^`2q>d6HE?F-NVa<4|;T{>#R{7e|~YM69diuWe}qa81#Xo_2{1Vx6lQtOpp8LA5Uj_vT=m_}_EE zZF85`=El62muUR^qfu|01?s$>`o9`9eDxvzxlSkBBHweB zx~K84@n2E-UqO6uoPb#1K9vdR#H7_q(S5zY!@7{yaV=FZkK^@P){}YZ{eMEt1E!Ju z&%`9{-YDz=`Ua>E^PE1hFxv<8d9n_wUZ@lI;flll$*g;=erx=P82gm9(-{B60O^yu zaBK+v0bqstKv?n5x~P3O6+grNd#IDr^Krdac+bp7<6q-HsQP~sqVd8vh#qVZnbUCP=%)KF1AcBSa7z$MFO5 ziOgqf@td(Z#5Q$%?vcbYQQp@g?^5&7_}BOkEB;CIO3u=c78z2u0eOJZsZ)MP`qt=E zCoXAsQy$wKPtVl3`CDD1F775TZ8$QWJ_&w<-%`E^^{n$8f0GwQl%3M8^30U~rQ)<& z?`iyd`#6N>)7<_qitd45@&nSe`yR&-7(+u@%y=4CPw?vBe201jQGa2~J>+W~> zyz?DL*WkCvYrN0!JWzH>iU+!N$ad8D4L`S-;EB_`)=QB{A>KXv{1rP>;EC=0~-Gt|0UpF z%m0w$-tBXZe~o{a7D_m3`5$sVpz*KqUjpv6{0}+q-9Fd&*Z6m7p@gHB{~_lC8vh#q zCE#Am|B&O}?Q@NPjenOGN;qoyA96mR@vre;0`9f^4>|7LKG*oy_;+ccgrk=KA?E`c z{~G@#;9krBkmKI%bB%wEf0q_YIBNMHaz3E(ukl|3?zQ|6Iquy)*Z9}?cWI%7qn7_! z_<$V`4^3(Oho`Sfz^5yxt98`)&%i&hKV~PwLsJ_6;pr=l|G@VZu|Jm7_*ZKJ-t;ap z=UgR8b2RY%RxSBB-M_2l|77`3?2kdFhNj=O{0~oGY55=cz9RO=$C80BXPQ50{D-Hn zH2wqMSH%AK_?RTa;sez94?In!d9}uWu=@&_C-(6VKERNS0ciXOo2CMYc`rZG_Wy+a zPs|hh{0of_K;vKIzYHFu@$bPue1Gm=XnX(~{~G@q{}rJDVm|#xA3!1mHh{)|Mf%>W z6VIe`E&o&UU+Mm^{XKu7hy$uR{y(qB|I3iCLFXmJe`iyJv^MOO*5mssn@;Q(V`Lx{ zzI2ZJXa0r421w)oy^?bu&zmnT?H=QQ9-gi7Kh5#qRVDnNSNI$bNIq=f&=B1pf}ve28g|RTs0BJX+Ba={yS` zKn3mpwvz`XGSD4-*^x)~yF4NAIsj=Nb95-H%{xEh@Br!pr6l0qxcS|%`>&Ej<8Jg{ z2*yA(=F7%eY^2}A1KkBV+tYely3U;_I#J&r=xA0x z|1e;mzCB{w&tE9U0w}AMt`5Fy8A!3>QylM6o@$+cX7fMF?qX9S`10P%-?RDrbMpeu z3D9=1xBc|_MC_<;i*U6Cv5a8<+;GowN6ib=_VCP>i`v&P4f;Pd&o2wc3tb9_9S|;F ztYxR}uUgVTaeDt$ju49R04=Acft=EOq0)T8kH3E^;xn#reSk2n5vX~A<^`Gt6lUG| z{TYZZ`X|Q?v_DYGr%KBw{k`hYl=Aoa9P9JT3^Wg@PG4yZ=yt6n4G{Z&$NBwY-+fN= z08Oivq*eW`%FYWmy=<`cdqh=2=|#RgM5IxiW)D}wt<$pxoBKp&!7#+ zddBepJ7JLbnYhpT8-7BE7ucv9*Y4210xcu8o}_4iGMC@s26zo0b&=_ z7=q>r8FE15W7_dZg>}$7X+DK_cOTw*Kz^3~(=DJ|K(~Ny0o?++1#}DO7SJuATR^vf zZUNl_x&?F#=oZi|pj$wBF1q9oxqIy~zh&RU3Hr4N^2;@IB-++AntV0kuCT_vo~n_K7{z zh1jUM8+#-6ww{smC-x&9NT-3$W?%JZon1cfr@fNKh?w)QbM|At`BLn!jKuxbfALRZ z4|e!#Lm&O(t1S3V+=xoYnIqWm8+-h^dwyfD-)`*rX}kMB7RZlu?_0*P{tK?3TK`}E zbDitIuk`vC!@H(o{r%FKdQR7W+R?x6|03ehHT`S)ub}*+jOPB@PD<_9TtHrX@j4;@ zOP7D%?-e{Rll~KCOz9=@SVU~-sBvRdc#S$N&($^FL%Z;Lq4ET+{?wyT36;j&enkJW ze$-V}9o@Z{-TRrx6g@cYfp&n7r}l4F&(Y4IZH@$cBS`g6LjR3gaoOK($@UIQx+C1X z9Q}>N`WNcUT=(6!OR)W-?K0Z8MWO?{@!esGFXX5fulPwEclXA~- zOV0L1WUL~4X~$9L<1)~4x5WA%lhN+EGSoIttY{zVe{@3kr43M|{-3MevtG}E|HOU& zEc?!O$V2DGWN&m__QuBLx$ZGpdKNZjCViLmJ1)cRk4ZeT8rV99bX2uLq<6b?HXfH2 z)S2~W;(2%TNySsM)}f^QQ#wMP`foekAq&o<{;2yNw87f`FIJ#J%j$q?n&!}^c_j%51yyuiHfx7pIF?>R`K{o#)bqb{);JuRSQ|x;=>aXZO zhyRQH&bpr+bdGG3eO;#9e$bTf?J?xX`wjUC(syxw8?Nyl>&m*DBd63cTisb-;=UZ+ zqUbg&q5jN+{mwQxjedTp!IU5DHDqUpDZ{vyARQy|oY%g;*Oa-(BN7=tld8K*^V$1Y z>CZm>y+zkIlRom+zZ3M&veFMeHL>4WclL4A1f3@*aL;>eBVOaZyABPb4MwwmXY#i} z1H^z2TcPZ_vn}$~f1pj0;L}N?e@YrR`(4@xpbWu3KNK@%AZlezyvJw0k7xJc z9lo3Go9bHJv5{(qfvokvM9h2tUg8IDlK7s_B7J5`vT*&@)lbT<%{R(ZFFYa_FEjEc zKC=_g@*TdL?VG%oIP*)8OhnmL6E;$IoK&y>F$VCnzZGlE#bRxGyI33FF)772zFj)k zUm@Rl`Vkr0@E+N)@{96^^Lyks=Nj^|xv@!!*LZKk%4^iKe24Gy8=2p=Hoi@)Z66go z((LHEv@0|5TIt_e`ychc;}X>WU8w)ml-TqRIkE0ja`Uqfh`H%viEX+>zWmfudD%Qu z{@c9Rq{M5y$7lE~-{HIb#?)`W6ZQXyBuAPg9&>yLL9f4oI@zep(Y5~~f3c`Ze#_Ga zJm<9|xW{Mste^VZs6TZf%EG$UzX1Jrr0BnY!)1z=6QJEYp8dJ}&b-ld|NqXssJg~` zq<22+m;U1h{Yv$!zkmL>ebawRa?ig@V$c7R_MKmm_dakIL^Yh^fSLUgJGJ!)GZo{mDPbL7Tp@ zRH`)JbHA6B|E20bm|y>4+2$UL$=&;-GHSw4n2h6S$>%m3@>wLFJJ;fJ_koDaZGg{= z^~s`3OH(NL3Wv5_V~ZsuYQlE)Sq=984*n2>d`_IUD|B#IL z4yraF9r&u>r2d|aarb@pJL^8)cNTe^lVrnsu^M+v$JvIu<6qVP&|yjLJdX0A{%8Zz z0kKdX?N9I$(meZ}byxL2yh5zzgQ)+p`q!WOALMmn>rqLv&imlETfblI&R*rybo;RM zBm9Aog`|1*dlGfG4=%@e&_FQgpYM(p8kC-(IGG5Cbw_XyDVXFC27dTo-4vMYsa*1>591NA8|u8(%&^XYmsj?ry9 zepAU<%GqFzf2Zr8hnLYtb;tFc7zigOK>2Xdm%PW=U0-nm$Y(z@xI) z-M;2AmAuasIuCRG3)RifeO>?H#D5e^|9<+n&@;OKb^iw?{wd7#Khx(w_?!C#TZI0f zX*mC-sQFK8vdw?`PN?TUaSoV28i4*i4d=hH{+tu)Z|)~;km)!7(P;v|ZIInZQ%GM4 z%Khx~UsVe@bin@g*snn;ciH7YorrVNdZ9meUZii?n8)rdyWC}dn{{BlS*L7&?m7Va zI5S&->qNX2=}M&ZIuU|8y^oJ^Uwg>0GI3Sy_gO}k)%(Za*~S7@ zSy(6biJQ{nWmS?_%+F0Z+tO19(hQ%^_AIX3eJzsM_pBs#KZ)^_r{O<8T{StxvD1;h zPNWWXq(3rixlmS?nd?R5)e+Iw@%6uS=7#_15*!hq_3TX(zT0edF5_C?`9^2nM{3T? zU}sCt^0QtAv5GocD{gbj&w2efA(n0Fx6~Y_T9IX8&%iTk4ltfk^FQ&MGT&yrd#X-T`Df+n zKmPcQ(lH#9XIkR&cynADdQoOoZvU~SYFrEb6dODwk?zNlo)&AgRjpg2<}CW<|K9e= zcAkZQ8cS}JXU-Y2rhi;s7#^2JO>t)~R<`$ZUUTMPMY^nzM{$^YHF>iu&TTlb#&UB zx;s*ehn3ad-m>#NOZly(Q}s92gLP;bwxj`NeGqf19y^V)pLY_^dF?djp2s6+JY}EU zevW+b&&LYZHCOq`yWKSlQpa(`a5VJA<<7$nJ)x7}fKDZxlg55=WJFH)M`c{u*!0JF z6XM}ij7Wi4lFT;F_d8qpmwW^3S{+Ah`@u;m)^|i6+J8>=H8*0uqM_oJ8N2KzUfYj* zd?wb9SV-^t{a8D0_!MXeGO&{K)-uZv8_b;Z5wTuG+JZIOQYo?JGC8{8bFyUR4`kii zZ_4Wy56i0;VcyZ=m`Xh7HQwVh$M7uQao< zY9s8(O%ut+9IFkhu9c0eu8~2^5&78C7ciH~lHbN$A|{@HY{?dNkI!txvwX+<4Quly zh^gI(_6Kc}KE35A^}NXPvktQPuVwAZ>*X~IdQf&lrPnOzRo8gWsb}u;+wmN}gi`7- zrTqEnXVHouDY}Slxk9dgW|^AL#ra#;KfO$NjWok&^3hL4=dWj$pZ0qm{64t9SDXwIm?fE)SQ37xhJETCz&d{w>|Rd zZ!A04wovPPMlcr{b1`VUagCM9_DkjUe+%|k;@o+$cOA!^xD#R@YE*S7E~Xmzr3HzMi-$=)DxbXzJ=qVH5wfv1T5v!zk?;pa0^j{rYfN@$EB3*`* zj?;QY?l`USv1Da@Glggm^uoNne^Yop>D-$NeY1r7ie^y=Rd4V6@Cn)N$0fe%PKmF) z19Qm_qAZw0>3zoMImgL3ZpQIG`j9fek+sc%rNo{m#rWYn#rVP7CB9{@6Qkub&vYJW zzoG8)YTS`yj*MNJ;(KEoXMWesU&SR|Tz3BMej8cy&&->@b^cEOd)lA0>Rl7m9Vd6j zb)5OXlg9|blR>lW|4OufPt2AMtUbeZrPE_!unW?(gY$_p#jw^g=C>Q2W#?~VznIQ- zb7gtgxGd|m;j4wuHXF^Puf;KbdRok(l}M{)pq=ZT>{oOC8NWA${?qSy#%4V9$NbN) zoh#3Gk0T}JB-UP`|1Vwd%=gje=17BBBdd}BDvUih0(V_X_u@R|obP$RcN2WjOh!ZM-12!F%z-^ z@g)bbb~?w}nGSZFvY}-dWq=>VrW|v|KTBHc&6__kXs!M)NwhAJMDrp^HZPQ;$5+a8 z`?t!kj*iN`M@*G?&TB`HuTszO*+lbVtaAWAninV8>YI6OQvMj%Tlj8gJPvCm#*sFz z`l9S#^J)2;#mD3~=9((;oY#1d&p7KJzD*L14=so|fTrPs@i_^sB^kUgJIX(M0>7EU*5ge-HhUu1wI| z#VUNH=Y|6(}0gLO@B!-B17qznQZbuD?jkIKl8`>p2;!NGh{W_u*O;$ zX3S8SbH`DLKa+bOV9kr98iV1Q4+$CUYRxbI3-&+8l)-;&_~Y%i9*k`u?kBa5_Ei1@ z+Ckpj-_7nhi)UM95POTcdu^2@|G|Ib%du|h39J)zvPG34FAqnZnK##d89TdE2AjCw zm&^aN=s!N{A76Q&%0GD=Ylm_?D4WjYeh2r|7*^vBmH$xl#CkI&)nD;n=zqf)N9e=2 zfKU0GV7a_}PRX3g=^tv2g4@P^k0?W>^q*;+eL!C7rVzqDS=bLem8<^I7vP}e{DDd3h+zKXP;;)1Duit+K( zJS_4V#yNQTO_utrcxhZ$^P=2$DIc&l9>>aUt_y|VQ)Mu0h|wX8S;CHpIyQTH9ul#E zb<~X85VLdYMWriEc^~Z?9qNLhd*N8U`TpQrqZlUpT$_H7w5RBUBKpDCTgLl`$@-*Buoi{6R%xeu&y zJJ#u5f3+BgzbP;7_=Q}vp-m;88wYPd8$G1PVyAo~vD)BtV_ZuHX zEJ_x8E2I2uyWW9_?COZA)H{T==q#+KinY=>W;#V@^S-}pjU+n}<6)uA(RNI#-q1gy ztqleHKe1=6Bzv88&)j+{8H)IkXxquW{ZINylNv<3)5$BO`lzsKKuLh*&Ri&tp5*>XWVE2 literal 0 HcmV?d00001 diff --git a/cmd/initconfig/main.go b/cmd/initconfig/main.go new file mode 100644 index 0000000..4000048 --- /dev/null +++ b/cmd/initconfig/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "crypto/rand" + "database/sql" + "encoding/hex" + "flag" + "fmt" + "os" + + _ "github.com/mattn/go-sqlite3" +) + +func randomSecret(n int) string { + b := make([]byte, n) + rand.Read(b) + return hex.EncodeToString(b) +} + +func main() { + dataDir := flag.String("data", "", "data directory") + webuiUsername := flag.String("username", "admin", "webui username") + webuiPassword := flag.String("password", "", "webui password (auto-generated if empty)") + webuiApiKey := flag.String("apikey", "", "api key (auto-generated if empty)") + flag.Parse() + + if *dataDir == "" { + fmt.Fprintln(os.Stderr, "-data is required") + os.Exit(1) + } + + os.MkdirAll(*dataDir, 0755) + + dbPath := *dataDir + "/config.db" + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + fmt.Fprintf(os.Stderr, "open db: %v\n", err) + os.Exit(1) + } + defer db.Close() + + db.Exec("PRAGMA journal_mode=WAL") + + db.Exec(`CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, value TEXT NOT NULL)`) + db.Exec(`INSERT OR IGNORE INTO config (key, value) VALUES (?, ?)`, "webui.listen_addr", ":8080") + + pw := *webuiPassword + if pw == "" { + pw = randomSecret(12) + } + apiKey := *webuiApiKey + if apiKey == "" { + apiKey = randomSecret(16) + } + + pt := "config_webui" + db.Exec(fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s (key TEXT PRIMARY KEY, value TEXT NOT NULL)`, pt)) + ws := fmt.Sprintf(`INSERT OR REPLACE INTO %s (key, value) VALUES (?, ?)`, pt) + db.Exec(ws, "api_key", apiKey) + db.Exec(ws, "username", *webuiUsername) + db.Exec(ws, "password", pw) + db.Exec(ws, "session_ttl_hours", "24") + + fmt.Printf("API_KEY=%s\n", apiKey) + fmt.Printf("WEBUI_USERNAME=%s\n", *webuiUsername) + fmt.Printf("WEBUI_PASSWORD=%s\n", pw) +} diff --git a/cmd/waiter/raw_other.go b/cmd/waiter/raw_other.go new file mode 100644 index 0000000..89d0063 --- /dev/null +++ b/cmd/waiter/raw_other.go @@ -0,0 +1,11 @@ +//go:build !linux && !windows + +package main + +func setRawMode(fd int) (func(), error) { + return func() {}, nil +} + +func isTerminal(fd int) bool { + return false +} diff --git a/cmd/waiter/raw_unix.go b/cmd/waiter/raw_unix.go new file mode 100644 index 0000000..debf14d --- /dev/null +++ b/cmd/waiter/raw_unix.go @@ -0,0 +1,43 @@ +//go:build linux + +package main + +import ( + "fmt" + "os" + "syscall" + "unsafe" +) + +func setRawMode(fd int) (func(), error) { + if fd == 0 { + fd = int(os.Stdin.Fd()) + } + if !isTerminal(fd) { + return func() {}, nil + } + var oldState syscall.Termios + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { + return func() {}, fmt.Errorf("tcgets: %v", err) + } + newState := oldState + newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON + newState.Oflag &^= syscall.OPOST + newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN + newState.Cflag &^= syscall.CSIZE | syscall.PARENB + newState.Cflag |= syscall.CS8 + newState.Cc[syscall.VMIN] = 1 + newState.Cc[syscall.VTIME] = 0 + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCSETS, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + return func() {}, fmt.Errorf("tcset: %v", err) + } + return func() { + syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCSETS, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) + }, nil +} + +func isTerminal(fd int) bool { + var t syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&t)), 0, 0, 0) + return err == 0 +} diff --git a/cmd/waiter/raw_windows.go b/cmd/waiter/raw_windows.go new file mode 100644 index 0000000..8d2f769 --- /dev/null +++ b/cmd/waiter/raw_windows.go @@ -0,0 +1,52 @@ +//go:build windows + +package main + +import ( + "os" + "syscall" + "unsafe" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") + procGetStdHandle = kernel32.NewProc("GetStdHandle") +) + +const ( + stdInputHandle = ^uint32(9) + 1 // -10 + enableVirtualTerminalProcessing = 0x0004 + enableProcessedOutput = 0x0001 + enableWrapAtEOLOutput = 0x0002 + disableNewlineAutoReturn = 0x0008 +) + +func setRawMode(fd int) (func(), error) { + if fd == 0 { + fd = int(os.Stdin.Fd()) + } + if !isTerminal(fd) { + return func() {}, nil + } + // Enable virtual terminal processing for ANSI escape sequences on Windows + h, _, _ := procGetStdHandle.Call(uintptr(^uint32(10) + 1)) // STD_OUTPUT_HANDLE = -11 + if h != 0 && h != ^uintptr(0) { + var mode uint32 + procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))) + newMode := mode | enableVirtualTerminalProcessing | enableProcessedOutput | enableWrapAtEOLOutput + procSetConsoleMode.Call(h, uintptr(newMode)) + } + return func() {}, nil +} + +func isTerminal(fd int) bool { + var mode uint32 + h, _, _ := procGetStdHandle.Call(uintptr(^uint32(10) + 1)) // STD_OUTPUT_HANDLE = -11 + if h == 0 || h == ^uintptr(0) { + return false + } + ret, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))) + return ret != 0 +} diff --git a/cmd/waiter/waiter.rc b/cmd/waiter/waiter.rc new file mode 100644 index 0000000..af6a395 --- /dev/null +++ b/cmd/waiter/waiter.rc @@ -0,0 +1 @@ +1 ICON "E:/program/homeagent/homeagent/build/icon.ico" diff --git a/cmd/waiter/waiter.syso b/cmd/waiter/waiter.syso new file mode 100644 index 0000000000000000000000000000000000000000..0a1e60ea3760a0ea62659307d9b500a7eaf6b17c GIT binary patch literal 302918 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 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index d4662da..a824350 100644 --- a/go.mod +++ b/go.mod @@ -12,4 +12,4 @@ require github.com/yanyiwu/gojieba v1.4.7 require gitcode.com/JianFeeeee/homeagent-sdk v0.0.0-20260708004841-e9bdcf9304b0 // direct -replace gitcode.com/JianFeeeee/homeagent-sdk => /tmp/opencode/homeagent-sdk-repo +replace gitcode.com/JianFeeeee/homeagent-sdk => E:\program\homeagent\homeagentsdk diff --git a/package/installer.nsi b/package/installer.nsi new file mode 100644 index 0000000..3e41704 --- /dev/null +++ b/package/installer.nsi @@ -0,0 +1,326 @@ +!include "MUI2.nsh" +!include "nsDialogs.nsh" +!include "LogicLib.nsh" +!include "WinVer.nsh" +!include "x64.nsh" + +!ifndef VARIANT + !define VARIANT "full" +!endif + +!define PRODUCT_NAME "HomeAgent" +!define PRODUCT_PUBLISHER "HomeAgent Team" +!define PRODUCT_VERSION "0.7.1" + +!if "${VARIANT}" == "full" + !define PRODUCT_DISPLAY_NAME "HomeAgent 完整版" + !define OUTPUT_FILE "HomeAgent_v${PRODUCT_VERSION}_Full_win64.exe" + !define HAS_CORE 1 + !define HAS_WAITER 1 + !define HAS_GUI 1 + !define HAS_CREDENTIALS 1 +!else if "${VARIANT}" == "server" + !define PRODUCT_DISPLAY_NAME "HomeAgent 服务端" + !define OUTPUT_FILE "HomeAgent_v${PRODUCT_VERSION}_Server_win64.exe" + !define HAS_CORE 1 + !define HAS_WAITER 0 + !define HAS_GUI 0 + !define HAS_CREDENTIALS 1 +!else if "${VARIANT}" == "client" + !define PRODUCT_DISPLAY_NAME "HomeAgent 客户端" + !define OUTPUT_FILE "HomeAgent_v${PRODUCT_VERSION}_Client_win64.exe" + !define HAS_CORE 0 + !define HAS_WAITER 1 + !define HAS_GUI 1 + !define HAS_CREDENTIALS 0 +!else + !error "Unknown variant: ${VARIANT}" +!endif + +Name "${PRODUCT_DISPLAY_NAME}" +OutFile "${OUTPUT_FILE}" +InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}" +InstallDirRegKey HKLM "Software\${PRODUCT_NAME}" "" +RequestExecutionLevel admin +BrandingText "HomeAgent Installer" +SetCompressor /SOLID lzma +ShowInstDetails show +ShowUninstDetails show + +Var apiKey +Var webuiUsername +Var webuiPassword +Var hwndApiKey +Var hwndUsername +Var hwndPassword +Var autoStart +Var startNow +Var hwndAutoStart +Var hwndStartNow + +Function GenKey + nsExec::ExecToStack 'powershell -NoProfile -C "[System.Guid]::NewGuid().ToString($\'N$\')"' + Pop $0 + Pop $1 + ${If} $1 == "" + StrCpy $1 "homeagent" + ${Else} + StrCpy $1 $1 32 + ${EndIf} + Push $1 +FunctionEnd + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY + +!if "${HAS_CREDENTIALS}" == "1" +Page custom pageApiKeys pageApiKeysLeave +Page custom pageCredentials pageCredentialsLeave +!endif + +!if "${HAS_CORE}" == "1" +Page custom pageStartupOptions pageStartupOptionsLeave +!endif + +!insertmacro MUI_PAGE_INSTFILES + +Page custom pageFinishSummary + +!insertmacro MUI_LANGUAGE "SimpChinese" +!insertmacro MUI_LANGUAGE "English" + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY + StrCpy $autoStart "1" + StrCpy $startNow "1" +!if "${HAS_CREDENTIALS}" == "0" + Call GenKey + Pop $apiKey +!endif +FunctionEnd + +!if "${HAS_CORE}" == "1" + +Function pageStartupOptions + !insertmacro MUI_HEADER_TEXT "启动选项" "设置 HomeAgent 后端的启动方式" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + ${NSD_CreateLabel} 0 5u 100% 20u "HomeAgent 后端 (homed) 是持续运行的服务进程。$\r$\n请选择启动方式:" + Pop $0 + ${NSD_CreateCheckBox} 10u 35u 100% 12u "开机自动启动后端 (添加到注册表启动项)" + Pop $hwndAutoStart + ${If} $autoStart == "1" + ${NSD_Check} $hwndAutoStart + ${EndIf} + ${NSD_CreateCheckBox} 10u 55u 100% 12u "安装完成后立即启动后端" + Pop $hwndStartNow + ${If} $startNow == "1" + ${NSD_Check} $hwndStartNow + ${EndIf} + ${NSD_CreateLabel} 10u 80u 100% 20u "如果选择开机自启动,homed 将在每次登录 Windows 时自动运行。$\r$\n你也可以稍后从开始菜单手动启动。" + Pop $0 + nsDialogs::Show +FunctionEnd + +Function pageStartupOptionsLeave + ${NSD_GetState} $hwndAutoStart $autoStart + ${NSD_GetState} $hwndStartNow $startNow +FunctionEnd + +!endif + +!if "${HAS_CREDENTIALS}" == "1" + +Function pageApiKeys + !insertmacro MUI_HEADER_TEXT "生成 API 密钥" "请复制此密钥,安装完成后将无法再次查看" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + Call GenKey + Pop $apiKey + ${NSD_CreateLabel} 0 5u 100% 12u "API Key (用于 WebUI 和 GUI 认证):" + Pop $0 + ${NSD_CreateText} 0 20u 300u 12u $apiKey + Pop $hwndApiKey + ${NSD_CreateLabel} 0 45u 100% 30u "请用鼠标选中文本框中的密钥并复制 (Ctrl+C)。$\r$\n此密钥同时用于:$\r$\n • Web 管理界面 (http://localhost:8080) 的 API 认证$\r$\n • 桌面 GUI 应用的自动连接配置" + Pop $0 + nsDialogs::Show +FunctionEnd + +Function pageApiKeysLeave + ${NSD_GetText} $hwndApiKey $apiKey +FunctionEnd + +Function pageCredentials + !insertmacro MUI_HEADER_TEXT "WebUI 登录设置" "设置 Web 管理界面的登录账号和密码" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + StrCpy $webuiUsername "admin" + ${NSD_CreateLabel} 0 5u 70u 12u "用户名:" + Pop $0 + ${NSD_CreateText} 85u 5u 180u 12u $webuiUsername + Pop $hwndUsername + ${NSD_CreateLabel} 0 25u 70u 12u "密码:" + Pop $0 + ${NSD_CreatePassword} 85u 25u 180u 12u "" + Pop $hwndPassword + ${NSD_CreateLabel} 0 50u 100% 20u "这些凭证用于登录 Web 管理界面 http://localhost:8080" + Pop $0 + nsDialogs::Show +FunctionEnd + +Function pageCredentialsLeave + ${NSD_GetText} $hwndUsername $webuiUsername + ${NSD_GetText} $hwndPassword $webuiPassword + ${If} $webuiPassword == "" + StrCpy $webuiPassword "homeagent" + ${EndIf} +FunctionEnd + +!endif + +Function pageFinishSummary + !insertmacro MUI_HEADER_TEXT "安装完成" "以下为安装的关键信息,请截图或记录" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + ${NSD_CreateLabel} 0 5u 100% 12u "API Key: $apiKey" + Pop $0 + ${NSD_CreateLabel} 0 20u 100% 12u "GUI 预配置: 已自动写入连接配置" + Pop $0 + ${NSD_CreateLabel} 0 35u 100% 12u "WebUI 地址: http://localhost:8080" + Pop $0 +!if "${HAS_CREDENTIALS}" == "1" + ${NSD_CreateLabel} 0 50u 100% 12u "WebUI 用户名: $webuiUsername" + Pop $0 + ${NSD_CreateLabel} 0 65u 100% 12u "WebUI 密码: $webuiPassword" + Pop $0 +!endif + nsDialogs::Show +FunctionEnd + +Section "Install" SEC_INSTALL + SetOutPath "$INSTDIR" + CreateDirectory "$INSTDIR\data" + CreateDirectory "$INSTDIR\data\log" + CreateDirectory "$INSTDIR\data\plugins" + CreateDirectory "$INSTDIR\data\adapters" + +!if "${HAS_CORE}" == "1" + File "initconfig.exe" + File "homed.exe" +!endif + +!if "${HAS_WAITER}" == "1" + File "waiter.exe" +!endif + +!if "${HAS_GUI}" == "1" + SetOutPath "$INSTDIR\homeagent-gui-win32-x64" + File /r "homeagent-gui-win32-x64\*.*" + SetOutPath "$INSTDIR" +!endif + +!if "${HAS_CORE}" == "1" + DetailPrint "初始化配置数据库..." + nsExec::Exec '"$INSTDIR\initconfig.exe" -data "$INSTDIR\data" -username "$webuiUsername" -password "$webuiPassword" -apikey "$apiKey"' + Pop $0 + ${If} $0 != 0 + DetailPrint "警告: 数据库初始化可能未成功完成" + ${EndIf} +!endif + +!if "${HAS_GUI}" == "1" + DetailPrint "配置 GUI 连接..." + CreateDirectory "$APPDATA\homeagent-gui" + FileOpen $0 "$APPDATA\homeagent-gui\connections.json" w + FileWrite $0 '{$\r$\n "connections": [$\r$\n {$\r$\n "id": "local",$\r$\n "name": "本地",$\r$\n "url": "http://localhost:8080",$\r$\n "apiKey": "$apiKey"$\r$\n }$\r$\n ],$\r$\n "currentId": "local"$\r$\n}' + FileClose $0 + ; 同时写入 GUI 包目录作为备用(适配 UAC 提升后 $APPDATA 异常的情况) + CreateDirectory "$INSTDIR\homeagent-gui-win32-x64\resources\app" + FileOpen $0 "$INSTDIR\homeagent-gui-win32-x64\resources\app\connections.json" w + FileWrite $0 '{$\r$\n "connections": [$\r$\n {$\r$\n "id": "local",$\r$\n "name": "本地",$\r$\n "url": "http://localhost:8080",$\r$\n "apiKey": "$apiKey"$\r$\n }$\r$\n ],$\r$\n "currentId": "local"$\r$\n}' + FileClose $0 +!endif + +!if "${HAS_WAITER}" == "1" + DetailPrint "配置 CLI 连接..." + FileOpen $0 "$INSTDIR\waiter.yaml" w + FileWrite $0 "socket: $\"$INSTDIR\data\cli.sock$\"$\r$\napi_key: $apiKey$\r$\ndefault: local$\r$\nconnections:$\r$\n - name: local$\r$\n socket: $\"$INSTDIR\data\cli.sock$\"$\r$\n api_key: $apiKey$\r$\n" + FileClose $0 +!endif + + DetailPrint "创建快捷方式..." + CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" +!if "${HAS_CORE}" == "1" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent Server.lnk" "$INSTDIR\homed.exe" '-data "$INSTDIR\data"' "$INSTDIR\homed.exe" 0 +!endif +!if "${HAS_WAITER}" == "1" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent CLI.lnk" "$INSTDIR\waiter.exe" "" "$INSTDIR\waiter.exe" 0 +!endif +!if "${HAS_GUI}" == "1" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent GUI.lnk" "$INSTDIR\homeagent-gui-win32-x64\homeagent-gui.exe" "" "$INSTDIR\homeagent-gui-win32-x64\homeagent-gui.exe" 0 +!endif + + DetailPrint "设置环境变量..." + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_DATA" "$INSTDIR\data" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SOCKET" "$INSTDIR\data\cli.sock" + +!if "${HAS_CORE}" == "1" + ${If} $autoStart == "1" + DetailPrint "设置开机自启动..." + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "HomeAgent" '"$INSTDIR\homed.exe" -data "$INSTDIR\data"' + ${EndIf} +!endif + + DetailPrint "写入注册表..." + WriteRegStr HKLM "Software\${PRODUCT_NAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_DISPLAY_NAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${PRODUCT_PUBLISHER}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1 + + WriteUninstaller "$INSTDIR\Uninstall.exe" + +!if "${HAS_CORE}" == "1" + ${If} $startNow == "1" + DetailPrint "启动 HomeAgent 后端..." + Exec '"$INSTDIR\homed.exe" -data "$INSTDIR\data"' + ${EndIf} +!endif +SectionEnd + +Section "Uninstall" +!if "${HAS_CORE}" == "1" + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "HomeAgent" +!endif + Delete "$INSTDIR\Uninstall.exe" + Delete "$INSTDIR\initconfig.exe" + Delete "$INSTDIR\homed.exe" + Delete "$INSTDIR\waiter.exe" + Delete "$INSTDIR\waiter.yaml" + RMDir /r "$INSTDIR\data" + RMDir /r "$INSTDIR\homeagent-gui-win32-x64" + RMDir "$INSTDIR" + Delete "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent Server.lnk" + Delete "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent CLI.lnk" + Delete "$SMPROGRAMS\${PRODUCT_NAME}\HomeAgent GUI.lnk" + RMDir "$SMPROGRAMS\${PRODUCT_NAME}" + DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_DATA" + DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SOCKET" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" + DeleteRegKey HKLM "Software\${PRODUCT_NAME}" +SectionEnd diff --git a/package/toolchain.nsi b/package/toolchain.nsi new file mode 100644 index 0000000..5e3685d --- /dev/null +++ b/package/toolchain.nsi @@ -0,0 +1,137 @@ +!include "MUI2.nsh" +!include "nsDialogs.nsh" +!include "LogicLib.nsh" +!include "x64.nsh" +!include "WinVer.nsh" + +!define PRODUCT_NAME "HomeAgent Toolchain" +!define PRODUCT_PUBLISHER "HomeAgent Team" +!define PRODUCT_VERSION "0.7.1" +!define PRODUCT_DISPLAY_NAME "HomeAgent 工具链" +!define OUTPUT_FILE "HomeAgent_v${PRODUCT_VERSION}_Toolchain_win64.exe" +!define SDK_VERSION "v0.7.1" + +Name "${PRODUCT_DISPLAY_NAME} v${PRODUCT_VERSION}" +OutFile "${OUTPUT_FILE}" +InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}" +InstallDirRegKey HKLM "Software\${PRODUCT_NAME}" "" +RequestExecutionLevel admin +BrandingText "HomeAgent Toolchain Installer" +SetCompressor /SOLID lzma +ShowInstDetails show +ShowUninstDetails show + +Var hasGit +Var sdkInstallOk + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +Page custom pageConfirm pageConfirmLeave +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_LANGUAGE "SimpChinese" +!insertmacro MUI_LANGUAGE "English" + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY + StrCpy $hasGit "0" + StrCpy $sdkInstallOk "0" +FunctionEnd + +Function pageConfirm + !insertmacro MUI_HEADER_TEXT "确认安装" "将安装 HomeAgent 工具链并自动下载 SDK ${SDK_VERSION}" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + ${NSD_CreateLabel} 0 5u 100% 12u "将安装以下组件:" + Pop $0 + ${NSD_CreateLabel} 15u 20u 100% 12u "• plugindev.exe — 插件开发工具" + Pop $0 + ${NSD_CreateLabel} 15u 35u 100% 12u "• SDK ${SDK_VERSION} — 将从远程仓库自动下载" + Pop $0 + ${NSD_CreateLabel} 0 60u 100% 20u "SDK 需要 Git 客户端。如果未安装 Git,请先安装:$\r$\nhttps://git-scm.com/downloads" + Pop $0 + nsDialogs::Show +FunctionEnd + +Function pageConfirmLeave +FunctionEnd + +Section "Install" SEC_INSTALL + SetOutPath "$INSTDIR" + + DetailPrint "复制工具链文件..." + File "plugindev.exe" + + DetailPrint "创建快捷方式..." + CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\plugindev.lnk" "$INSTDIR\plugindev.exe" "" "$INSTDIR\plugindev.exe" 0 + + DetailPrint "配置环境变量..." + ; Add to system PATH + ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" + ${If} $0 != "" + ${If} $0 != "*$INSTDIR*" + StrCpy $0 "$0;$INSTDIR" + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0 + ${EndIf} + ${Else} + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" "$INSTDIR" + ${EndIf} + WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SDK_DIR" "$INSTDIR\sdk" + WriteRegStr HKLM "Software\${PRODUCT_NAME}" "" "$INSTDIR" + + DetailPrint "检测 Git 客户端..." + nsExec::ExecToStack '"git" --version' + Pop $0 + Pop $1 + ${If} $0 == 0 + StrCpy $hasGit "1" + DetailPrint "Git 已安装: $1" + ${Else} + DetailPrint "未检测到 Git,将跳过 SDK 自动下载" + DetailPrint "安装完成后请手动运行: plugindev sdk install ${SDK_VERSION}" + ${EndIf} + + ${If} $hasGit == "1" + DetailPrint "正在下载 SDK ${SDK_VERSION}..." + nsExec::ExecToStack '"$INSTDIR\plugindev.exe" sdk install ${SDK_VERSION}' + Pop $0 + Pop $1 + ${If} $0 == 0 + StrCpy $sdkInstallOk "1" + DetailPrint "SDK ${SDK_VERSION} 下载完成" + DetailPrint "正在激活 SDK ${SDK_VERSION}..." + nsExec::Exec '"$INSTDIR\plugindev.exe" sdk use ${SDK_VERSION}' + Pop $0 + ${Else} + DetailPrint "SDK 下载失败 (错误码: $0)" + DetailPrint "请手动运行: plugindev sdk install ${SDK_VERSION}" + ${EndIf} + ${EndIf} + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_DISPLAY_NAME} v${PRODUCT_VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${PRODUCT_PUBLISHER}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1 + + WriteUninstaller "$INSTDIR\Uninstall.exe" +SectionEnd + +Section "Uninstall" + Delete "$INSTDIR\Uninstall.exe" + Delete "$INSTDIR\plugindev.exe" + RMDir /r "$INSTDIR\sdk" + RMDir "$INSTDIR" + Delete "$SMPROGRAMS\${PRODUCT_NAME}\plugindev.lnk" + RMDir "$SMPROGRAMS\${PRODUCT_NAME}" + DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SDK_DIR" + DeleteRegKey HKLM "Software\Microsoft\CurrentVersion\Uninstall\${PRODUCT_NAME}" + DeleteRegKey HKLM "Software\${PRODUCT_NAME}" +SectionEnd