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:
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user