Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

20 changes: 1 addition & 19 deletions crates/db/src/models/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub struct CreateProject {
#[derive(Debug, Deserialize, TS)]
pub struct UpdateProject {
pub name: Option<String>,
pub default_agent_working_dir: Option<String>,
}

#[derive(Debug, Serialize, TS)]
Expand Down Expand Up @@ -196,12 +195,11 @@ impl Project {
.ok_or(sqlx::Error::RowNotFound)?;

let name = payload.name.clone().unwrap_or(existing.name);
let default_agent_working_dir = payload.default_agent_working_dir.clone();

sqlx::query_as!(
Project,
r#"UPDATE projects
SET name = $2, default_agent_working_dir = $3
SET name = $2
WHERE id = $1
RETURNING id as "id!: Uuid",
name,
Expand All @@ -211,27 +209,11 @@ impl Project {
updated_at as "updated_at!: DateTime<Utc>""#,
id,
name,
default_agent_working_dir,
)
.fetch_one(pool)
.await
}

pub async fn clear_default_agent_working_dir(
pool: &SqlitePool,
id: Uuid,
) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"UPDATE projects
SET default_agent_working_dir = ''
WHERE id = $1"#,
id
)
.execute(pool)
.await?;
Ok(())
}

pub async fn set_remote_project_id(
pool: &SqlitePool,
id: Uuid,
Expand Down
21 changes: 11 additions & 10 deletions crates/server/src/routes/task_attempts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,17 @@ pub async fn create_task_attempt(
.await?
.ok_or(SqlxError::RowNotFound)?;

let project = task
.parent_project(pool)
.await?
.ok_or(SqlxError::RowNotFound)?;

let agent_working_dir = project
.default_agent_working_dir
.as_ref()
.filter(|dir| !dir.is_empty())
.cloned();
// Compute agent_working_dir based on repo count:
// - Single repo: use repo name as working dir (agent runs in repo directory)
// - Multiple repos: use None (agent runs in workspace root)
let agent_working_dir = if payload.repos.len() == 1 {
let repo = Repo::find_by_id(pool, payload.repos[0].repo_id)
.await?
.ok_or(RepoError::NotFound)?;
Some(repo.name)
} else {
None
};

let attempt_id = Uuid::new_v4();
let git_branch_name = deployment
Expand Down
23 changes: 12 additions & 11 deletions crates/server/src/routes/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use axum::{
};
use db::models::{
image::TaskImage,
project::{Project, ProjectError},
repo::Repo,
repo::{Repo, RepoError},
task::{CreateTask, Task, TaskWithAttemptStatus, UpdateTask},
workspace::{CreateWorkspace, Workspace},
workspace_repo::{CreateWorkspaceRepo, WorkspaceRepo},
Expand Down Expand Up @@ -178,21 +177,23 @@ pub async fn create_task_and_start(
)
.await;

let project = Project::find_by_id(pool, task.project_id)
.await?
.ok_or(ProjectError::ProjectNotFound)?;

let attempt_id = Uuid::new_v4();
let git_branch_name = deployment
.container()
.git_branch_from_workspace(&attempt_id, &task.title)
.await;

let agent_working_dir = project
.default_agent_working_dir
.as_ref()
.filter(|dir: &&String| !dir.is_empty())
.cloned();
// Compute agent_working_dir based on repo count:
// - Single repo: use repo name as working dir (agent runs in repo directory)
// - Multiple repos: use None (agent runs in workspace root)
let agent_working_dir = if payload.repos.len() == 1 {
let repo = Repo::find_by_id(pool, payload.repos[0].repo_id)
.await?
.ok_or(RepoError::NotFound)?;
Some(repo.name)
} else {
None
};

let workspace = Workspace::create(
pool,
Expand Down
29 changes: 0 additions & 29 deletions crates/services/src/services/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ use db::{
execution_process_repo_state::{
CreateExecutionProcessRepoState, ExecutionProcessRepoState,
},
project::{Project, UpdateProject},
project_repo::ProjectRepo,
repo::Repo,
session::{CreateSession, Session, SessionError},
task::{Task, TaskStatus},
Expand Down Expand Up @@ -371,33 +369,6 @@ pub trait ContainerService {
.to_string();

Repo::update_name(pool, repo.id, &name, &name).await?;

// Update agent_working_dir for single-repo projects
let project_repos = ProjectRepo::find_by_repo_id(pool, repo.id).await?;
for pr in project_repos {
let all_repos = ProjectRepo::find_by_project_id(pool, pr.project_id).await?;
if all_repos.len() == 1
&& let Some(project) = Project::find_by_id(pool, pr.project_id).await?
{
let needs_default_agent_working_dir = project
.default_agent_working_dir
.as_ref()
.map(|s| s.is_empty())
.unwrap_or(true);

if needs_default_agent_working_dir {
Project::update(
pool,
pr.project_id,
&UpdateProject {
name: Some(project.name.clone()),
default_agent_working_dir: Some(name.clone()),
},
)
.await?;
}
}
}
}

Ok(())
Expand Down
28 changes: 0 additions & 28 deletions crates/services/src/services/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,29 +110,11 @@ impl ProjectService {
.await
.map_err(|e| ProjectServiceError::Project(ProjectError::CreateFailed(e.to_string())))?;

let mut created_repo: Option<Repo> = None;
for repo in &normalized_repos {
let repo_entity =
Repo::find_or_create(pool, Path::new(&repo.git_repo_path), &repo.display_name)
.await?;
ProjectRepo::create(pool, project.id, repo_entity.id).await?;
if created_repo.is_none() {
created_repo = Some(repo_entity);
}
}

if normalized_repos.len() == 1
&& let Some(repo) = created_repo
{
Project::update(
pool,
project.id,
&UpdateProject {
name: None,
default_agent_working_dir: Some(repo.name),
},
)
.await?;
}

Ok(project)
Expand Down Expand Up @@ -203,11 +185,6 @@ impl ProjectService {
let path = repo_service.normalize_path(&payload.git_repo_path)?;
repo_service.validate_git_repo_path(&path)?;

// Count repos before adding
let repo_count_before = ProjectRepo::find_by_project_id(pool, project_id)
.await?
.len();

let repository = ProjectRepo::add_repo_to_project(
pool,
project_id,
Expand All @@ -225,11 +202,6 @@ impl ProjectService {
_ => ProjectServiceError::RepositoryNotFound,
})?;

// If project just went from 1 to 2 repos, clear default_agent_working_dir
if repo_count_before == 1 {
Project::clear_default_agent_working_dir(pool, project_id).await?;
}

tracing::info!(
"Added repository {} to project {} (path: {})",
repository.id,
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "The absolute path to your git repository on disk."
}
},
"agentWorkingDir": {
"label": "Agent Working Directory",
"placeholder": "e.g., my-repo",
"helper": "Default directory for new workspaces to run the coding agent from, relative to the workspace root. This value is captured when a workspace is created and won't affect existing workspaces. For single-repo projects, this defaults to the repo name. Leave empty to run from the workspace root."
},
"save": {
"button": "Save Project Settings",
"success": "✓ Project settings saved successfully!",
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/es/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "La ruta absoluta a tu repositorio git en disco."
}
},
"agentWorkingDir": {
"label": "Directorio de Trabajo del Agente",
"placeholder": "ej., mi-repo",
"helper": "Directorio predeterminado para nuevos workspaces donde ejecutar el agente de codificación, relativo a la raíz del workspace. Este valor se captura cuando se crea un workspace y no afectará a los workspaces existentes. Para proyectos de un solo repositorio, esto se establece por defecto al nombre del repositorio. Déjalo vacío para ejecutar desde la raíz del workspace."
},
"save": {
"button": "Guardar Configuración del Proyecto",
"success": "✓ ¡Configuración del proyecto guardada exitosamente!",
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/ja/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "ディスク上のgitリポジトリへの絶対パス。"
}
},
"agentWorkingDir": {
"label": "エージェント作業ディレクトリ",
"placeholder": "例:my-repo",
"helper": "新しいワークスペースでコーディングエージェントを実行するデフォルトディレクトリ。ワークスペースルートからの相対パス。この値はワークスペース作成時に保存され、既存のワークスペースには影響しません。単一リポジトリプロジェクトの場合、リポジトリ名がデフォルトになります。空欄にするとワークスペースルートから実行します。"
},
"save": {
"button": "プロジェクト設定を保存",
"success": "✓ プロジェクト設定が正常に保存されました!",
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/ko/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "디스크에 있는 git 저장소의 절대 경로입니다."
}
},
"agentWorkingDir": {
"label": "에이전트 작업 디렉토리",
"placeholder": "예: my-repo",
"helper": "새 워크스페이스에서 코딩 에이전트를 실행할 기본 디렉토리로, 워크스페이스 루트 기준 상대 경로입니다. 이 값은 워크스페이스 생성 시 저장되며 기존 워크스페이스에는 영향을 주지 않습니다. 단일 저장소 프로젝트의 경우 저장소 이름이 기본값입니다. 비워두면 워크스페이스 루트에서 실행됩니다."
},
"save": {
"button": "프로젝트 설정 저장",
"success": "✓ 프로젝트 설정이 성공적으로 저장되었습니다!",
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/zh-Hans/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "磁盘上 git 仓库的绝对路径。"
}
},
"agentWorkingDir": {
"label": "代理工作目录",
"placeholder": "例如:my-repo",
"helper": "新工作区运行编码代理的默认目录,相对于工作区根目录。此值在创建工作区时保存,不会影响现有工作区。对于单仓库项目,默认为仓库名称。留空则从工作区根目录运行。"
},
"save": {
"button": "保存项目设置",
"success": "✓ 项目设置保存成功!",
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/i18n/locales/zh-Hant/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,6 @@
"helper": "磁碟上的 Git 儲存庫絕對路徑。"
}
},
"agentWorkingDir": {
"label": "代理工作目錄",
"placeholder": "例如:my-repo",
"helper": "新工作區執行編碼代理的預設目錄,相對於工作區根目錄。此值在建立工作區時保存,不會影響現有工作區。單一儲存庫專案預設為儲存庫名稱。留空則從工作區根目錄執行。"
},
"save": {
"button": "儲存專案設定",
"success": "✓ 專案設定儲存成功!",
Expand Down
24 changes: 0 additions & 24 deletions frontend/src/pages/settings/ProjectSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ import type { Project, Repo, UpdateProject } from 'shared/types';

interface ProjectFormState {
name: string;
default_agent_working_dir: string;
}

function projectToFormState(project: Project): ProjectFormState {
return {
name: project.name,
default_agent_working_dir: project.default_agent_working_dir ?? '',
};
}

Expand Down Expand Up @@ -294,8 +292,6 @@ export function ProjectSettings() {
try {
const updateData: UpdateProject = {
name: draft.name.trim(),
default_agent_working_dir:
draft.default_agent_working_dir.trim() || null,
};

updateProject.mutate({
Expand Down Expand Up @@ -429,26 +425,6 @@ export function ProjectSettings() {
</p>
</div>

<div className="space-y-2">
<Label htmlFor="agent-working-dir">
{t('settings.projects.agentWorkingDir.label')}
</Label>
<Input
id="agent-working-dir"
value={draft.default_agent_working_dir}
onChange={(e) =>
updateDraft({ default_agent_working_dir: e.target.value })
}
placeholder={t(
'settings.projects.agentWorkingDir.placeholder'
)}
className="font-mono"
/>
<p className="text-sm text-muted-foreground">
{t('settings.projects.agentWorkingDir.helper')}
</p>
</div>

{/* Save Button */}
<div className="flex items-center justify-between pt-4 border-t">
{hasUnsavedChanges ? (
Expand Down
2 changes: 1 addition & 1 deletion shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type Project = { id: string, name: string, default_agent_working_dir: str

export type CreateProject = { name: string, repositories: Array<CreateProjectRepo>, };

export type UpdateProject = { name: string | null, default_agent_working_dir: string | null, };
export type UpdateProject = { name: string | null, };

export type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType,
/**
Expand Down