fix: resolve type errors from main merge

- Remove orphaned PID lock code from bootstrap (moved to supervisor)
- Fix worktree archive adapter to look up workspace by directory
- Replace registerWorktreeWorkspaceRecord with inline SQLite implementation
- Remove unused imports (stat, createPersistedWorkspaceRecord, PersistedProjectRecord)
This commit is contained in:
Mohamed Boudra
2026-03-30 17:30:31 +07:00
parent 0d3f59feed
commit 2190910e6f
3 changed files with 105 additions and 87 deletions
-16
View File
@@ -206,19 +206,8 @@ export async function createPaseoDaemon(
const bootstrapStart = performance.now(); const bootstrapStart = performance.now();
const elapsed = () => `${(performance.now() - bootstrapStart).toFixed(0)}ms`; const elapsed = () => `${(performance.now() - bootstrapStart).toFixed(0)}ms`;
const daemonVersion = resolveDaemonVersion(import.meta.url); const daemonVersion = resolveDaemonVersion(import.meta.url);
const pidLockMode = config.pidLock?.mode ?? "self";
const pidLockOwnerPid = config.pidLock?.ownerPid;
const ownsPidLock = pidLockMode === "self";
let database: PaseoDatabaseHandle | null = null; let database: PaseoDatabaseHandle | null = null;
// Acquire PID lock before expensive bootstrap work so duplicate starts fail immediately.
if (ownsPidLock) {
await acquirePidLock(config.paseoHome, config.listen, {
ownerPid: pidLockOwnerPid,
});
logger.info({ elapsed: elapsed() }, "PID lock acquired");
}
try { try {
const serverId = getOrCreateServerId(config.paseoHome, { logger }); const serverId = getOrCreateServerId(config.paseoHome, { logger });
const daemonKeyPair = await loadOrCreateDaemonKeyPair(config.paseoHome, logger); const daemonKeyPair = await loadOrCreateDaemonKeyPair(config.paseoHome, logger);
@@ -796,11 +785,6 @@ export async function createPaseoDaemon(
}; };
} catch (err) { } catch (err) {
await database?.close().catch(() => undefined); await database?.close().catch(() => undefined);
if (ownsPidLock) {
await releasePidLock(config.paseoHome, {
ownerPid: pidLockOwnerPid,
}).catch(() => undefined);
}
throw err; throw err;
} }
} }
+65 -19
View File
@@ -1,6 +1,6 @@
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { watch, type FSWatcher } from "node:fs"; import { watch, type FSWatcher } from "node:fs";
import { readFile, stat } from "fs/promises"; import { readFile } from "fs/promises";
import { exec } from "child_process"; import { exec } from "child_process";
import { promisify } from "util"; import { promisify } from "util";
import { join, resolve, sep } from "path"; import { join, resolve, sep } from "path";
@@ -106,7 +106,6 @@ import type {
ProjectRegistry, ProjectRegistry,
WorkspaceRegistry, WorkspaceRegistry,
} from "./workspace-registry.js"; } from "./workspace-registry.js";
import { createPersistedWorkspaceRecord } from "./workspace-registry.js";
import { AgentLoadingService } from "./agent-loading-service.js"; import { AgentLoadingService } from "./agent-loading-service.js";
import { import {
buildVoiceAgentMcpServerConfig, buildVoiceAgentMcpServerConfig,
@@ -166,7 +165,6 @@ import {
handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest, handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest,
handlePaseoWorktreeListRequest as handleWorktreeListRequest, handlePaseoWorktreeListRequest as handleWorktreeListRequest,
killTerminalsUnderPath as killWorktreeTerminalsUnderPath, killTerminalsUnderPath as killWorktreeTerminalsUnderPath,
registerPendingWorktreeWorkspace as registerPendingWorktreeWorkspaceSession,
} from "./worktree-session.js"; } from "./worktree-session.js";
const execAsync = promisify(exec); const execAsync = promisify(exec);
@@ -4078,7 +4076,12 @@ export class Session {
paseoHome: this.paseoHome, paseoHome: this.paseoHome,
agentManager: this.agentManager, agentManager: this.agentManager,
agentStorage: this.agentStorage, agentStorage: this.agentStorage,
archiveWorkspaceRecord: (workspaceId) => this.archiveWorkspaceRecord(workspaceId), archiveWorkspaceRecord: async (workspaceDirectory) => {
const workspace = await this.findWorkspaceByDirectory(workspaceDirectory);
if (workspace) {
await this.archiveWorkspaceRecord(workspace.id);
}
},
emit: (message) => this.emit(message), emit: (message) => this.emit(message),
emitWorkspaceUpdatesForCwds: (cwds) => this.emitWorkspaceUpdatesForCwds(cwds), emitWorkspaceUpdatesForCwds: (cwds) => this.emitWorkspaceUpdatesForCwds(cwds),
isPathWithinRoot: (rootPath, candidatePath) => isPathWithinRoot: (rootPath, candidatePath) =>
@@ -5113,25 +5116,68 @@ export class Session {
return (await this.workspaceRegistry.get(workspaceId))!; return (await this.workspaceRegistry.get(workspaceId))!;
} }
private async registerWorktreeWorkspaceRecord(options: { private async registerPendingWorktreeWorkspace(options: {
repoRoot: string; repoRoot: string;
worktreePath: string; worktreePath: string;
branchName: string; branchName: string;
}): Promise<PersistedWorkspaceRecord> { }): Promise<PersistedWorkspaceRecord> {
return registerPendingWorktreeWorkspaceSession( await this.findOrCreateWorkspaceForDirectory(options.repoRoot);
{ const workspaceDirectory = normalizePersistedWorkspaceId(options.worktreePath);
buildPersistedProjectRecord: (input) => this.buildPersistedProjectRecord(input), const basePlacement = await this.buildProjectPlacementForCwd(options.repoRoot);
buildPersistedWorkspaceRecord: (input) => this.buildPersistedWorkspaceRecord(input), if (!basePlacement) {
buildProjectPlacement: (cwd) => this.buildProjectPlacement(cwd), throw new Error(`Workspace not found for repo root ${options.repoRoot}`);
projectRegistry: this.projectRegistry, }
syncWorkspaceGitWatchTarget: (cwd, syncOptions) =>
this.syncWorkspaceGitWatchTarget(cwd, syncOptions), const projectId = Number(basePlacement.projectKey);
workspaceRegistry: this.workspaceRegistry, if (!Number.isInteger(projectId)) {
archiveProjectRecordIfEmpty: (projectId, archivedAt) => throw new Error(`Invalid project id for repo root ${options.repoRoot}`);
this.archiveProjectRecordIfEmpty(projectId, archivedAt), }
},
options, const now = new Date().toISOString();
); const existingWorkspace = await this.findWorkspaceByDirectory(workspaceDirectory);
if (!existingWorkspace) {
const workspaceId = await this.workspaceRegistry.insert({
projectId,
directory: workspaceDirectory,
displayName: options.branchName,
kind: "worktree",
createdAt: now,
updatedAt: now,
archivedAt: null,
});
const workspace = await this.workspaceRegistry.get(workspaceId);
if (!workspace) {
throw new Error(`Workspace not found after insert: ${workspaceId}`);
}
await this.syncWorkspaceGitWatchTarget(workspace.directory, { isGit: true });
return workspace;
}
await this.workspaceRegistry.upsert({
id: existingWorkspace.id,
projectId,
directory: workspaceDirectory,
displayName: options.branchName,
kind: "worktree",
createdAt: existingWorkspace.createdAt,
updatedAt: now,
archivedAt: null,
});
await this.syncWorkspaceGitWatchTarget(workspaceDirectory, { isGit: true });
if (!existingWorkspace.archivedAt && existingWorkspace.projectId !== projectId) {
const siblingWorkspaces = (await this.workspaceRegistry.list()).filter(
(workspace) =>
workspace.projectId === existingWorkspace.projectId &&
workspace.id !== existingWorkspace.id &&
!workspace.archivedAt,
);
if (siblingWorkspaces.length === 0) {
await this.projectRegistry.archive(existingWorkspace.projectId, now);
}
}
return (await this.workspaceRegistry.get(existingWorkspace.id))!;
} }
private async archiveWorkspaceRecord(workspaceId: number, archivedAt?: string): Promise<void> { private async archiveWorkspaceRecord(workspaceId: number, archivedAt?: string): Promise<void> {
+40 -52
View File
@@ -14,7 +14,6 @@ import {
type WorkspaceDescriptorPayload, type WorkspaceDescriptorPayload,
} from "./messages.js"; } from "./messages.js";
import type { import type {
PersistedProjectRecord,
PersistedWorkspaceRecord, PersistedWorkspaceRecord,
ProjectRegistry, ProjectRegistry,
WorkspaceRegistry, WorkspaceRegistry,
@@ -77,26 +76,15 @@ type ArchivePaseoWorktreeDependencies = {
}; };
type RegisterPendingWorktreeWorkspaceDependencies = { type RegisterPendingWorktreeWorkspaceDependencies = {
buildPersistedProjectRecord: (input: {
workspaceId: string;
placement: ProjectPlacementPayload;
createdAt: string;
updatedAt: string;
}) => PersistedProjectRecord;
buildPersistedWorkspaceRecord: (input: {
workspaceId: string;
placement: ProjectPlacementPayload;
createdAt: string;
updatedAt: string;
}) => PersistedWorkspaceRecord;
buildProjectPlacement: (cwd: string) => Promise<ProjectPlacementPayload>; buildProjectPlacement: (cwd: string) => Promise<ProjectPlacementPayload>;
projectRegistry: Pick<ProjectRegistry, "get" | "upsert">; findWorkspaceByDirectory: (directory: string) => Promise<PersistedWorkspaceRecord | null>;
projectRegistry: Pick<ProjectRegistry, "get" | "upsert" | "insert" | "archive">;
syncWorkspaceGitWatchTarget: ( syncWorkspaceGitWatchTarget: (
cwd: string, cwd: string,
options: { isGit: boolean }, options: { isGit: boolean },
) => Promise<void>; ) => Promise<void>;
workspaceRegistry: Pick<WorkspaceRegistry, "get" | "upsert">; workspaceRegistry: Pick<WorkspaceRegistry, "get" | "upsert" | "insert" | "list">;
archiveProjectRecordIfEmpty: (projectId: string, archivedAt: string) => Promise<void>; archiveProjectRecordIfEmpty: (projectId: number, archivedAt: string) => Promise<void>;
}; };
type CreatePaseoWorktreeInBackgroundDependencies = { type CreatePaseoWorktreeInBackgroundDependencies = {
@@ -509,50 +497,50 @@ export async function registerPendingWorktreeWorkspace(
branchName: string; branchName: string;
}, },
): Promise<PersistedWorkspaceRecord> { ): Promise<PersistedWorkspaceRecord> {
const workspaceId = normalizePersistedWorkspaceId(options.worktreePath); const workspaceDirectory = normalizePersistedWorkspaceId(options.worktreePath);
const basePlacement = await dependencies.buildProjectPlacement(options.repoRoot); const basePlacement = await dependencies.buildProjectPlacement(options.repoRoot);
const placement: ProjectPlacementPayload = { const projectId = Number(basePlacement.projectKey);
...basePlacement, if (!Number.isInteger(projectId)) {
checkout: { throw new Error(`Invalid project id for repo root ${options.repoRoot}`);
cwd: workspaceId, }
isGit: true,
currentBranch: options.branchName,
remoteUrl: basePlacement.checkout.remoteUrl,
isPaseoOwnedWorktree: true,
mainRepoRoot: options.repoRoot,
},
};
const now = new Date().toISOString(); const now = new Date().toISOString();
const existingWorkspace = await dependencies.workspaceRegistry.get(workspaceId); const existingWorkspace = await dependencies.findWorkspaceByDirectory(workspaceDirectory);
const existingProject = await dependencies.projectRegistry.get(placement.projectKey); if (!existingWorkspace) {
const nextProjectRecord = dependencies.buildPersistedProjectRecord({ const workspaceId = await dependencies.workspaceRegistry.insert({
workspaceId, projectId,
placement, directory: workspaceDirectory,
createdAt: existingProject?.createdAt ?? now, displayName: options.branchName,
updatedAt: now, kind: "worktree",
}); createdAt: now,
const nextWorkspaceRecord = dependencies.buildPersistedWorkspaceRecord({ updatedAt: now,
workspaceId, archivedAt: null,
placement, });
createdAt: existingWorkspace?.createdAt ?? now, const workspace = await dependencies.workspaceRegistry.get(workspaceId);
updatedAt: now, if (!workspace) {
}); throw new Error(`Workspace not found after insert: ${workspaceId}`);
}
await dependencies.syncWorkspaceGitWatchTarget(workspaceDirectory, { isGit: true });
return workspace;
}
await dependencies.projectRegistry.upsert(nextProjectRecord); await dependencies.workspaceRegistry.upsert({
await dependencies.workspaceRegistry.upsert(nextWorkspaceRecord); id: existingWorkspace.id,
await dependencies.syncWorkspaceGitWatchTarget(workspaceId, { projectId,
isGit: placement.checkout.isGit, directory: workspaceDirectory,
displayName: options.branchName,
kind: "worktree",
createdAt: existingWorkspace.createdAt,
updatedAt: now,
archivedAt: null,
}); });
await dependencies.syncWorkspaceGitWatchTarget(workspaceDirectory, { isGit: true });
if ( if (!existingWorkspace.archivedAt && existingWorkspace.projectId !== projectId) {
existingWorkspace &&
!existingWorkspace.archivedAt &&
existingWorkspace.projectId !== nextWorkspaceRecord.projectId
) {
await dependencies.archiveProjectRecordIfEmpty(existingWorkspace.projectId, now); await dependencies.archiveProjectRecordIfEmpty(existingWorkspace.projectId, now);
} }
return nextWorkspaceRecord; return (await dependencies.workspaceRegistry.get(existingWorkspace.id))!;
} }
export async function handleCreatePaseoWorktreeRequest( export async function handleCreatePaseoWorktreeRequest(