diff --git a/packages/server/src/server/session/project-config/import/sources/conductor/importer.test.ts b/packages/server/src/server/session/project-config/import/sources/conductor/importer.test.ts index 402198cfc..dee519394 100644 --- a/packages/server/src/server/session/project-config/import/sources/conductor/importer.test.ts +++ b/packages/server/src/server/session/project-config/import/sources/conductor/importer.test.ts @@ -114,11 +114,11 @@ enabled = true scripts: { dev: { type: "service", - port: "$PASEO_PORT", command: "cd -- 'apps/web' && npm run dev -- --port $PASEO_PORT '--host' '0.0.0.0'", }, }, }); + expect(preview.preview?.scripts?.dev).not.toHaveProperty("port"); expect(preview.items).toEqual( expect.arrayContaining([ expect.objectContaining({ key: "worktree.setup", outcome: "import" }), @@ -316,7 +316,6 @@ args = ["--port", "$CONDUCTOR_PORT", "--label=$WORKSPACE_NAME"] scripts: { dev: { type: "service", - port: "$PASEO_PORT", command: `npm run dev '--port' "$PASEO_PORT" '--label='"$WORKSPACE_NAME"`, }, }, @@ -338,7 +337,6 @@ args = ["--port=\${CONDUCTOR_PORT:-3000}"] scripts: { dev: { type: "service", - port: "$PASEO_PORT", command: `npm run dev '--port='"\${PASEO_PORT:-3000}"`, }, }, @@ -416,7 +414,6 @@ command = "npm run dev -- --port \${CONDUCTOR_PORT:-3000}" scripts: { dev: { type: "service", - port: "$PASEO_PORT", command: "npm run dev -- --port ${PASEO_PORT:-3000}", }, }, @@ -550,6 +547,7 @@ CLOUD_TOKEN = "cloud-secret" claude_code_executable_path: "/opt/claude", codex_executable_path: "/opt/codex", claude_provider: "bedrock", + codex_provider: "custom", bedrock_region: "eu-west-1", vertex_project_id: "project", ssh_key_path: "~/.ssh/id_ed25519", @@ -563,6 +561,7 @@ CLOUD_TOKEN = "cloud-secret" expect.objectContaining({ key: "claude_code_executable_path", outcome: "unsupported" }), expect.objectContaining({ key: "codex_executable_path", outcome: "unsupported" }), expect.objectContaining({ key: "claude_provider", outcome: "unsupported" }), + expect.objectContaining({ key: "codex_provider", outcome: "unsupported" }), expect.objectContaining({ key: "bedrock_region", outcome: "unsupported" }), expect.objectContaining({ key: "vertex_project_id", outcome: "unsupported" }), expect.objectContaining({ key: "ssh_key_path", outcome: "unsupported" }), @@ -620,7 +619,7 @@ command = "npm run other -- --port $CONDUCTOR_PORT" const preview = inspect(repo); expect(preview.preview?.scripts).toMatchObject({ - "app-server": { type: "service", port: "$PASEO_PORT" }, + "app-server": { type: "service" }, }); expect(preview.preview?.scripts).not.toHaveProperty("app.server"); expect(preview.items).toEqual( @@ -656,6 +655,16 @@ command = "npm run other -- --port $CONDUCTOR_PORT" }); }); + test("unreadable source paths identify the invalid relative file", () => { + const repo = makeRepo(); + mkdirSync(join(repo, ".conductor", "settings.toml"), { recursive: true }); + + expect(captureInvalidSourceError(repo)).toMatchObject({ + source: CONDUCTOR_SOURCE, + relativePath: ".conductor/settings.toml", + }); + }); + test(".worktreeinclude is reported and not converted to shell commands", () => { const repo = makeRepo(); writeSharedToml(repo, '[scripts]\nsetup = "npm ci"\n'); diff --git a/packages/server/src/server/session/project-config/import/sources/conductor/importer.ts b/packages/server/src/server/session/project-config/import/sources/conductor/importer.ts index 3fd68b555..635dee100 100644 --- a/packages/server/src/server/session/project-config/import/sources/conductor/importer.ts +++ b/packages/server/src/server/session/project-config/import/sources/conductor/importer.ts @@ -63,7 +63,7 @@ function inspectConductorImport(input: { repoRoot: string; source: ProjectConfigImportSource; }): ProjectConfigImportCandidate | null { - const sourceFiles = discoverConductorSources(input.repoRoot); + const sourceFiles = discoverConductorSources(input.repoRoot, input.source); if (sourceFiles.length === 0) { return null; } @@ -101,7 +101,10 @@ function inspectConductorImport(input: { }; } -function discoverConductorSources(repoRoot: string): SourceFile[] { +function discoverConductorSources( + repoRoot: string, + source: ProjectConfigImportSource, +): SourceFile[] { const localTomlPath = join(repoRoot, ".conductor", "settings.local.toml"); const localJsonPath = join(repoRoot, ".conductor", "settings.local.json"); const sharedTomlPath = join(repoRoot, ".conductor", "settings.toml"); @@ -111,22 +114,22 @@ function discoverConductorSources(repoRoot: string): SourceFile[] { const files: SourceFile[] = []; if (existsSync(sharedJsonPath)) { - files.push(readSourceFile(repoRoot, sharedJsonPath, "shared", true)); + files.push(readSourceFile(repoRoot, sharedJsonPath, "shared", true, source)); } if (existsSync(sharedTomlPath)) { - files.push(readSourceFile(repoRoot, sharedTomlPath, "shared", true)); + files.push(readSourceFile(repoRoot, sharedTomlPath, "shared", true, source)); } if (!existsSync(sharedJsonPath) && !existsSync(sharedTomlPath) && existsSync(rootLegacyPath)) { - files.push(readSourceFile(repoRoot, rootLegacyPath, "legacy", true)); + files.push(readSourceFile(repoRoot, rootLegacyPath, "legacy", true, source)); } if (existsSync(localJsonPath)) { - files.push(readSourceFile(repoRoot, localJsonPath, "local", true)); + files.push(readSourceFile(repoRoot, localJsonPath, "local", true, source)); } if (existsSync(localTomlPath)) { - files.push(readSourceFile(repoRoot, localTomlPath, "local", true)); + files.push(readSourceFile(repoRoot, localTomlPath, "local", true, source)); } if (existsSync(worktreeIncludePath)) { - files.push(readSourceFile(repoRoot, worktreeIncludePath, "include", false)); + files.push(readSourceFile(repoRoot, worktreeIncludePath, "include", false, source)); } return files; } @@ -136,12 +139,20 @@ function readSourceFile( path: string, role: string, containsSettings: boolean, + source: ProjectConfigImportSource, ): SourceFile { + const relativePath = relative(repoRoot, path).replaceAll("\\", "/"); + let bytes: string; + try { + bytes = readFileSync(path, "utf8"); + } catch { + throw new InvalidProjectConfigImportSourceError(source, relativePath); + } return { role, - relativePath: relative(repoRoot, path).replaceAll("\\", "/"), + relativePath, path, - bytes: readFileSync(path, "utf8"), + bytes, containsSettings, }; } @@ -344,7 +355,6 @@ function mapRunScript( const entry: PaseoScriptEntryRaw = { command: rewritten.command }; if (isService) { entry.type = "service"; - entry.port = "$PASEO_PORT"; } patch.scripts = { ...patch.scripts, [scriptId]: entry }; @@ -419,6 +429,7 @@ function reportUnsupported( "claude_code_executable_path", "codex_executable_path", "claude_provider", + "codex_provider", "bedrock_region", "vertex_project_id", "ssh_key_path",