chore(product): fix link in app (#22)
This commit is contained in:
@@ -62,9 +62,12 @@ mac:
|
|||||||
NSCameraUsageDescription: ClawX requires camera access for video features
|
NSCameraUsageDescription: ClawX requires camera access for video features
|
||||||
|
|
||||||
dmg:
|
dmg:
|
||||||
# background: resources/dmg-background.png
|
background: resources/dmg-background.png
|
||||||
icon: resources/icons/icon.icns
|
icon: resources/icons/icon.icns
|
||||||
iconSize: 100
|
iconSize: 100
|
||||||
|
window:
|
||||||
|
width: 540
|
||||||
|
height: 380
|
||||||
contents:
|
contents:
|
||||||
- type: file
|
- type: file
|
||||||
x: 130
|
x: 130
|
||||||
|
|||||||
@@ -63,6 +63,39 @@ const DEFAULT_RECONNECT_CONFIG: ReconnectConfig = {
|
|||||||
maxDelay: 30000,
|
maxDelay: 30000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Node.js-compatible executable path for spawning child processes.
|
||||||
|
*
|
||||||
|
* On macOS in packaged mode, using `process.execPath` directly causes the
|
||||||
|
* child process to appear as a separate dock icon (named "exec") because the
|
||||||
|
* binary lives inside a `.app` bundle that macOS treats as a GUI application.
|
||||||
|
*
|
||||||
|
* To avoid this, we resolve the Electron Helper binary which has
|
||||||
|
* `LSUIElement` set in its Info.plist, preventing dock icon creation.
|
||||||
|
* Falls back to `process.execPath` if the Helper binary is not found.
|
||||||
|
*/
|
||||||
|
function getNodeExecutablePath(): string {
|
||||||
|
if (process.platform === 'darwin' && app.isPackaged) {
|
||||||
|
// Electron Helper binary lives at:
|
||||||
|
// <App>.app/Contents/Frameworks/<ProductName> Helper.app/Contents/MacOS/<ProductName> Helper
|
||||||
|
const appName = app.getName();
|
||||||
|
const helperName = `${appName} Helper`;
|
||||||
|
const helperPath = path.join(
|
||||||
|
path.dirname(process.execPath), // .../Contents/MacOS
|
||||||
|
'../Frameworks',
|
||||||
|
`${helperName}.app`,
|
||||||
|
'Contents/MacOS',
|
||||||
|
helperName,
|
||||||
|
);
|
||||||
|
if (existsSync(helperPath)) {
|
||||||
|
logger.info(`Using Electron Helper binary to avoid dock icon: ${helperPath}`);
|
||||||
|
return helperPath;
|
||||||
|
}
|
||||||
|
logger.warn(`Electron Helper binary not found at ${helperPath}, falling back to process.execPath`);
|
||||||
|
}
|
||||||
|
return process.execPath;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gateway Manager
|
* Gateway Manager
|
||||||
* Handles starting, stopping, and communicating with the OpenClaw Gateway
|
* Handles starting, stopping, and communicating with the OpenClaw Gateway
|
||||||
@@ -377,11 +410,13 @@ export class GatewayManager extends EventEmitter {
|
|||||||
const gatewayArgs = ['gateway', '--port', String(this.status.port), '--token', gatewayToken, '--dev', '--allow-unconfigured'];
|
const gatewayArgs = ['gateway', '--port', String(this.status.port), '--token', gatewayToken, '--dev', '--allow-unconfigured'];
|
||||||
|
|
||||||
if (app.isPackaged) {
|
if (app.isPackaged) {
|
||||||
// Production: always use Electron binary as Node.js via ELECTRON_RUN_AS_NODE
|
// Production: use Electron binary as Node.js via ELECTRON_RUN_AS_NODE
|
||||||
|
// On macOS, use the Electron Helper binary to avoid extra dock icons
|
||||||
if (existsSync(entryScript)) {
|
if (existsSync(entryScript)) {
|
||||||
command = process.execPath;
|
command = getNodeExecutablePath();
|
||||||
args = [entryScript, ...gatewayArgs];
|
args = [entryScript, ...gatewayArgs];
|
||||||
logger.info('Starting Gateway in PACKAGED mode (ELECTRON_RUN_AS_NODE)');
|
logger.info('Starting Gateway in PACKAGED mode (ELECTRON_RUN_AS_NODE)');
|
||||||
|
logger.info(`Using executable: ${command}`);
|
||||||
} else {
|
} else {
|
||||||
const errMsg = `OpenClaw entry script not found at: ${entryScript}`;
|
const errMsg = `OpenClaw entry script not found at: ${entryScript}`;
|
||||||
logger.error(errMsg);
|
logger.error(errMsg);
|
||||||
@@ -449,6 +484,15 @@ export class GatewayManager extends EventEmitter {
|
|||||||
// Critical: In packaged mode, make Electron binary act as Node.js
|
// Critical: In packaged mode, make Electron binary act as Node.js
|
||||||
if (app.isPackaged) {
|
if (app.isPackaged) {
|
||||||
spawnEnv['ELECTRON_RUN_AS_NODE'] = '1';
|
spawnEnv['ELECTRON_RUN_AS_NODE'] = '1';
|
||||||
|
// Prevent OpenClaw entry.ts from respawning itself (which would create
|
||||||
|
// another child process and a second "exec" dock icon on macOS)
|
||||||
|
spawnEnv['OPENCLAW_NO_RESPAWN'] = '1';
|
||||||
|
// Pre-set the NODE_OPTIONS that entry.ts would have added via respawn
|
||||||
|
const existingNodeOpts = spawnEnv['NODE_OPTIONS'] ?? '';
|
||||||
|
if (!existingNodeOpts.includes('--disable-warning=ExperimentalWarning') &&
|
||||||
|
!existingNodeOpts.includes('--no-warnings')) {
|
||||||
|
spawnEnv['NODE_OPTIONS'] = `${existingNodeOpts} --disable-warning=ExperimentalWarning`.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.process = spawn(command, args, {
|
this.process = spawn(command, args, {
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ export function createMenu(): void {
|
|||||||
{
|
{
|
||||||
label: 'Documentation',
|
label: 'Documentation',
|
||||||
click: async () => {
|
click: async () => {
|
||||||
await shell.openExternal('https://docs.clawx.app');
|
await shell.openExternal('https://clawx.dev');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
resources/dmg-background.png
Normal file
BIN
resources/dmg-background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
@@ -347,7 +347,7 @@ export function Settings() {
|
|||||||
<Button
|
<Button
|
||||||
variant="link"
|
variant="link"
|
||||||
className="h-auto p-0"
|
className="h-auto p-0"
|
||||||
onClick={() => window.electron.openExternal('https://docs.clawx.app')}
|
onClick={() => window.electron.openExternal('https://clawx.dev')}
|
||||||
>
|
>
|
||||||
Documentation
|
Documentation
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user