mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(desktop): restore packaged terminal hooks
The desktop daemon resolved the CLI through a packaged module entrypoint that is not an executable outside the archive. Publish the existing bundled shim as the daemon's authoritative CLI path so terminal hooks use a callable command.
This commit is contained in:
@@ -107,6 +107,6 @@ Codex also receives the Windows equivalent:
|
||||
if defined PASEO_TERMINAL_ID (if defined PASEO_HOOK_CLI ("%PASEO_HOOK_CLI%" hooks codex <event>) else (paseo hooks codex <event>))
|
||||
```
|
||||
|
||||
Paseo injects `PASEO_HOOK_CLI` so Codex's hook shell cannot pick up a stale global `paseo` before the current one. The command still falls back to bare `paseo` if the env is missing, and it still no-ops outside Paseo terminals because the `PASEO_TERMINAL_ID` gate remains first. Paseo also prepends the CLI binary directory to each terminal `PATH` as a secondary fallback. All other behavior lives in `paseo hooks`: read the env, map the event, POST activity, and no-op/fail-open when anything is missing or unavailable.
|
||||
The daemon resolves the current CLI through `PASEO_CLI` when its launcher supplies one, or through the npm package shim for standalone installs. Terminal setup exposes that resolved executable to hooks as `PASEO_HOOK_CLI`; desktop and other daemon launchers do not know about the hook-specific variable. The generated command falls back to bare `paseo` if the hook env is missing and no-ops outside Paseo terminals because the `PASEO_TERMINAL_ID` gate remains first. Paseo also prepends the resolved CLI directory to each terminal `PATH` as a secondary fallback. All other behavior lives in `paseo hooks`: read the env, map the event, POST activity, and no-op/fail-open when anything is missing or unavailable.
|
||||
|
||||
If config installation fails, daemon startup and terminal spawn continue without terminal activity hooks.
|
||||
|
||||
@@ -46,4 +46,4 @@ CLI_ENTRYPOINT="${RESOURCES_DIR}/app.asar/node_modules/@getpaseo/cli/dist/index.
|
||||
|
||||
# PASEO_DESKTOP_MANAGED marks daemons started through this bundled CLI as
|
||||
# desktop-managed, so the desktop app restarts them when it upgrades.
|
||||
exec env ELECTRON_RUN_AS_NODE=1 PASEO_NODE_ENV=production PASEO_DESKTOP_MANAGED=1 "${APP_EXECUTABLE}" --disable-warning=DEP0040 "${RUNNER_PATH}" node-script "${CLI_ENTRYPOINT}" "$@"
|
||||
exec env ELECTRON_RUN_AS_NODE=1 PASEO_NODE_ENV=production PASEO_DESKTOP_MANAGED=1 PASEO_CLI="${SCRIPT_PATH}" "${APP_EXECUTABLE}" --disable-warning=DEP0040 "${RUNNER_PATH}" node-script "${CLI_ENTRYPOINT}" "$@"
|
||||
|
||||
@@ -14,5 +14,6 @@ set "PASEO_NODE_ENV=production"
|
||||
rem PASEO_DESKTOP_MANAGED marks daemons started through this bundled CLI as
|
||||
rem desktop-managed, so the desktop app restarts them when it upgrades.
|
||||
set "PASEO_DESKTOP_MANAGED=1"
|
||||
set "PASEO_CLI=%~f0"
|
||||
"%APP_EXECUTABLE%" --disable-warning=DEP0040 "%RESOURCES_DIR%\app.asar.unpacked\dist\daemon\node-entrypoint-runner.js" node-script "%RESOURCES_DIR%\app.asar\node_modules\@getpaseo\cli\dist\index.js" %*
|
||||
exit /b %errorlevel%
|
||||
|
||||
@@ -128,6 +128,14 @@ function shellQuoteCliArg(value) {
|
||||
return shellQuote(String(value));
|
||||
}
|
||||
|
||||
function getTerminalHookSmokeCommand(marker) {
|
||||
if (process.platform === "win32") {
|
||||
return `"%PASEO_HOOK_CLI%" hooks codex Stop && echo ${marker}`;
|
||||
}
|
||||
|
||||
return `"$PASEO_HOOK_CLI" hooks codex Stop && echo ${marker}`;
|
||||
}
|
||||
|
||||
function getShellCommand(script) {
|
||||
if (process.platform === "win32") {
|
||||
return {
|
||||
@@ -740,8 +748,8 @@ async function smokeCliTerminal({ appPath, env }) {
|
||||
await runCliShimJsonCommand({
|
||||
appPath,
|
||||
env,
|
||||
args: ["terminal", "send-keys", terminalId, "echo", "Space", marker, "Enter"],
|
||||
label: "Bundled CLI shim terminal send-keys",
|
||||
args: ["terminal", "send-keys", terminalId, getTerminalHookSmokeCommand(marker), "Enter"],
|
||||
label: "Bundled CLI shim terminal hook command",
|
||||
});
|
||||
|
||||
for (let attempt = 1; attempt <= TERMINAL_CAPTURE_ATTEMPTS; attempt += 1) {
|
||||
@@ -753,7 +761,7 @@ async function smokeCliTerminal({ appPath, env }) {
|
||||
});
|
||||
const lines = Array.isArray(capture?.lines) ? capture.lines : [];
|
||||
if (lines.join("\n").includes(marker)) {
|
||||
console.log("Packaged desktop smoke: terminal command output captured");
|
||||
console.log("Packaged desktop smoke: terminal hook command completed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { DEFAULT_DESKTOP_SETTINGS } from "../settings/desktop-settings";
|
||||
import { getBundledCliShimPath } from "../integrations/cli-install";
|
||||
import { createDaemonCommandHandlers } from "./daemon-manager";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
@@ -451,7 +452,10 @@ describe("daemon-manager commands", () => {
|
||||
expect.objectContaining({
|
||||
detached: true,
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
envOverlay: expect.objectContaining({ PASEO_WEB_UI_ENABLED: "false" }),
|
||||
envOverlay: expect.objectContaining({
|
||||
PASEO_CLI: getBundledCliShimPath(),
|
||||
PASEO_WEB_UI_ENABLED: "false",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -18,7 +18,11 @@ import {
|
||||
type AppUpdateCheckIntent,
|
||||
type AppReleaseChannel,
|
||||
} from "../features/auto-updater.js";
|
||||
import { getCliInstallStatus, installCli } from "../integrations/cli-install/index.js";
|
||||
import {
|
||||
getBundledCliShimPath,
|
||||
getCliInstallStatus,
|
||||
installCli,
|
||||
} from "../integrations/cli-install/index.js";
|
||||
import {
|
||||
getSkillsStatus,
|
||||
installSkills,
|
||||
@@ -413,7 +417,11 @@ async function startDaemon(): Promise<DesktopDaemonStatus> {
|
||||
detached: true,
|
||||
envMode: "internal",
|
||||
env: invocation.env,
|
||||
envOverlay: { PASEO_DESKTOP_MANAGED: "1", PASEO_WEB_UI_ENABLED: "false" },
|
||||
envOverlay: {
|
||||
PASEO_DESKTOP_MANAGED: "1",
|
||||
PASEO_CLI: getBundledCliShimPath(),
|
||||
PASEO_WEB_UI_ENABLED: "false",
|
||||
},
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
});
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ function createFakeMacBundle(options: { includeHelper: boolean }): {
|
||||
helperPath,
|
||||
[
|
||||
"#!/bin/sh",
|
||||
'printf "helper env=%s/%s\\n" "$ELECTRON_RUN_AS_NODE" "$PASEO_NODE_ENV"',
|
||||
'printf "helper env=%s/%s cli=%s\\n" "$ELECTRON_RUN_AS_NODE" "$PASEO_NODE_ENV" "$PASEO_CLI"',
|
||||
'printf "args=%s\\n" "$*"',
|
||||
"",
|
||||
].join("\n"),
|
||||
@@ -114,7 +114,7 @@ describe("desktop packaging", () => {
|
||||
const result = spawnSync(bundle.shimPath, ["--version"], { encoding: "utf8" });
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stdout).toContain("helper env=1/production");
|
||||
expect(result.stdout).toContain(`helper env=1/production cli=${bundle.shimPath}`);
|
||||
expect(result.stdout).toContain("node-entrypoint-runner.js");
|
||||
expect(result.stdout).toContain("node-script");
|
||||
expect(result.stdout).toContain("@getpaseo/cli/dist/index.js");
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { getCliInstallStatus, installCli } from "./install.js";
|
||||
export { getBundledCliShimPath } from "./paths.js";
|
||||
|
||||
@@ -308,16 +308,16 @@ function resolveExternalProcessPath(filePath: string): string {
|
||||
}
|
||||
|
||||
export function resolvePaseoCliBinDir(): string | null {
|
||||
const cliEntrypoint = resolvePaseoCliBinEntrypoint();
|
||||
if (!cliEntrypoint) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const externalCliEntrypoint = resolveExternalProcessPath(cliEntrypoint);
|
||||
return findNpmBinDir(dirname(externalCliEntrypoint)) ?? dirname(externalCliEntrypoint);
|
||||
const cliExecutable = resolvePaseoCliExecutablePath();
|
||||
return cliExecutable ? dirname(cliExecutable) : null;
|
||||
}
|
||||
|
||||
export function resolvePaseoCliExecutablePath(): string | null {
|
||||
const configuredCli = process.env.PASEO_CLI?.trim();
|
||||
if (configuredCli) {
|
||||
return resolvePath(configuredCli);
|
||||
}
|
||||
|
||||
const cliEntrypoint = resolvePaseoCliBinEntrypoint();
|
||||
if (!cliEntrypoint) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user