Merge branch 'main' into dev

Resolve 38 conflicts preserving both sides' work:
- Server: DB-based registries (dev) + WorkspaceGitService/DaemonConfigStore (main)
- App: script proxy/voice MCP (dev) + pin/hide tabs/bootstrap boundary (main)
- Shared: WorkspaceScriptPayload (dev) + git/GitHub runtime schemas (main)
- Deleted workspace-registry-bootstrap.ts (dev's DB approach supersedes)
This commit is contained in:
Mohamed Boudra
2026-04-14 03:05:45 +07:00
333 changed files with 13490 additions and 6317 deletions
@@ -149,7 +149,6 @@ function logDesktopDaemonLifecycle(message: string, details?: Record<string, unk
});
}
function toTrimmedString(value: unknown): string | null {
if (typeof value !== "string") {
return null;
@@ -244,12 +243,7 @@ async function startDaemon(): Promise<DesktopDaemonStatus> {
if (current.status === "running") {
const appVersion = normalizeVersion(resolveDesktopAppVersion());
const daemonVersion = normalizeVersion(current.version);
if (
current.desktopManaged &&
appVersion &&
daemonVersion &&
appVersion !== daemonVersion
) {
if (current.desktopManaged && appVersion && daemonVersion && appVersion !== daemonVersion) {
logDesktopDaemonLifecycle("daemon version mismatch, restarting", {
appVersion,
daemonVersion,
@@ -65,11 +65,7 @@ describe("node-entrypoint-launcher", () => {
it("passes --open-project through as a normal CLI arg", () => {
expect(
parseCliPassthroughArgsFromArgv({
argv: [
"/Applications/Paseo.app/Contents/MacOS/Paseo",
"--open-project",
"/tmp/project",
],
argv: ["/Applications/Paseo.app/Contents/MacOS/Paseo", "--open-project", "/tmp/project"],
isDefaultApp: false,
forceCli: false,
}),
@@ -93,7 +89,8 @@ describe("node-entrypoint-launcher", () => {
createNodeEntrypointInvocation({
execPath: "/Applications/Paseo.app/Contents/MacOS/Paseo",
isPackaged: true,
packagedRunnerPath: "/Applications/Paseo.app/Contents/Resources/app.asar/dist/daemon/node-entrypoint-runner.js",
packagedRunnerPath:
"/Applications/Paseo.app/Contents/Resources/app.asar/dist/daemon/node-entrypoint-runner.js",
entrypoint: CLI_ENTRYPOINT,
argvMode: "node-script",
args: ["ls", "--json"],
@@ -142,7 +139,8 @@ describe("node-entrypoint-launcher", () => {
createNodeEntrypointInvocation({
execPath: "/Applications/Paseo.app/Contents/MacOS/Paseo",
isPackaged: true,
packagedRunnerPath: "/Applications/Paseo.app/Contents/Resources/app.asar/dist/daemon/node-entrypoint-runner.js",
packagedRunnerPath:
"/Applications/Paseo.app/Contents/Resources/app.asar/dist/daemon/node-entrypoint-runner.js",
entrypoint: CLI_ENTRYPOINT,
argvMode: "node-script",
args: ["--dev"],
@@ -70,7 +70,13 @@ export function createNodeEntrypointInvocation(
return {
command: input.execPath,
args: ["--disable-warning=DEP0040", input.packagedRunnerPath, input.argvMode, input.entrypoint.entryPath, ...input.args],
args: [
"--disable-warning=DEP0040",
input.packagedRunnerPath,
input.argvMode,
input.entrypoint.entryPath,
...input.args,
],
env,
};
}
@@ -10,7 +10,9 @@ async function main(): Promise<void> {
}
process.argv =
argvMode === "bare" ? [process.argv[0] ?? "node", ...args] : [process.argv[0] ?? "node", entryPath, ...args];
argvMode === "bare"
? [process.argv[0] ?? "node", ...args]
: [process.argv[0] ?? "node", entryPath, ...args];
await import(pathToFileURL(entryPath).href);
}
+8 -7
View File
@@ -78,7 +78,13 @@ function resolvePackagedAsarPath(): string {
}
function resolvePackagedNodeEntrypointRunnerPath(): string {
return path.join(process.resourcesPath, "app.asar.unpacked", "dist", "daemon", "node-entrypoint-runner.js");
return path.join(
process.resourcesPath,
"app.asar.unpacked",
"dist",
"daemon",
"node-entrypoint-runner.js",
);
}
function assertPathExists(input: { label: string; filePath: string }): string {
@@ -117,12 +123,7 @@ export function resolveDaemonRunnerEntrypoint(): NodeEntrypointSpec {
}
const serverPackage = resolveServerPackageInfo();
const distRunner = path.join(
serverPackage.root,
"dist",
"scripts",
"supervisor-entrypoint.js",
);
const distRunner = path.join(serverPackage.root, "dist", "scripts", "supervisor-entrypoint.js");
if (existsSync(distRunner)) {
return {
entryPath: distRunner,
@@ -238,13 +238,21 @@ export async function getCliInstallStatus(): Promise<InstallStatus> {
// Skills Installation
// ---------------------------------------------------------------------------
async function copySkillFile(sourceFile: string, destDir: string, skillName: string): Promise<void> {
async function copySkillFile(
sourceFile: string,
destDir: string,
skillName: string,
): Promise<void> {
const destSkillDir = path.join(destDir, skillName);
await fs.mkdir(destSkillDir, { recursive: true });
await fs.copyFile(sourceFile, path.join(destSkillDir, "SKILL.md"));
}
async function symlinkSkillDir(skillName: string, targetDir: string, linkParentDir: string): Promise<void> {
async function symlinkSkillDir(
skillName: string,
targetDir: string,
linkParentDir: string,
): Promise<void> {
await fs.mkdir(linkParentDir, { recursive: true });
const target = path.join(targetDir, skillName);
const linkPath = path.join(linkParentDir, skillName);
@@ -57,11 +57,7 @@ describe("open-project-routing", () => {
expect(
parseOpenProjectPathFromArgv({
argv: [
"/Applications/Paseo.app/Contents/MacOS/Paseo",
"--open-project",
projectPath,
],
argv: ["/Applications/Paseo.app/Contents/MacOS/Paseo", "--open-project", projectPath],
isDefaultApp: false,
}),
).toBe(projectPath);
+1 -3
View File
@@ -22,9 +22,7 @@ export function parseOpenProjectPathFromArgv(input: {
}): string | null {
const effectiveArgs = input.argv
.slice(input.isDefaultApp ? 2 : 1)
.filter(
(arg) => !OPEN_PROJECT_IGNORED_ARG_PREFIXES.some((prefix) => arg.startsWith(prefix)),
);
.filter((arg) => !OPEN_PROJECT_IGNORED_ARG_PREFIXES.some((prefix) => arg.startsWith(prefix)));
const positionalProjectPath = effectiveArgs.find(
(arg) => !arg.startsWith("-") && isExistingDirectoryAbsolutePath(arg),
@@ -94,7 +94,9 @@ function readOverlayColor(input: unknown): string | null {
return input;
}
export function readWindowControlsOverlayUpdate(input: unknown): WindowControlsOverlayUpdate | null {
export function readWindowControlsOverlayUpdate(
input: unknown,
): WindowControlsOverlayUpdate | null {
if (!input || typeof input !== "object") {
return null;
}