From c85ae5f0dec45f47520b4d2a00cfdced5569eb70 Mon Sep 17 00:00:00 2001
From: Gabriel Gordon-Hall
Date: Wed, 7 Jan 2026 18:52:33 +0000
Subject: [PATCH 1/3] remove configurable agent_working_dir
(cherry picked from commit 285b3e04abceeb8e4a4ee1be16e3de97a8f32299)
---
...7d2217281d0082965cca6b15a9f3e9be1c3b.json} | 6 ++--
...aef5e16eb58d847540b1d998a741996967643.json | 12 --------
crates/db/src/models/project.rs | 20 +------------
crates/server/src/routes/task_attempts.rs | 21 +++++++-------
crates/services/src/services/container.rs | 29 -------------------
crates/services/src/services/project.rs | 28 ------------------
frontend/src/i18n/locales/en/settings.json | 5 ----
frontend/src/i18n/locales/es/settings.json | 5 ----
frontend/src/i18n/locales/ja/settings.json | 5 ----
frontend/src/i18n/locales/ko/settings.json | 5 ----
.../src/i18n/locales/zh-Hans/settings.json | 5 ----
.../src/pages/settings/ProjectSettings.tsx | 24 ---------------
shared/types.ts | 2 +-
13 files changed, 16 insertions(+), 151 deletions(-)
rename crates/db/.sqlx/{query-e3f01fc53c00ee217b823ca588dc9a5320c9ba6ddf2bd718c817dfbf5fefd21c.json => query-38d1abbfb839e62833308d65b9417d2217281d0082965cca6b15a9f3e9be1c3b.json} (59%)
delete mode 100644 crates/db/.sqlx/query-43c10bbafd851c362132fd0657eaef5e16eb58d847540b1d998a741996967643.json
diff --git a/crates/db/.sqlx/query-e3f01fc53c00ee217b823ca588dc9a5320c9ba6ddf2bd718c817dfbf5fefd21c.json b/crates/db/.sqlx/query-38d1abbfb839e62833308d65b9417d2217281d0082965cca6b15a9f3e9be1c3b.json
similarity index 59%
rename from crates/db/.sqlx/query-e3f01fc53c00ee217b823ca588dc9a5320c9ba6ddf2bd718c817dfbf5fefd21c.json
rename to crates/db/.sqlx/query-38d1abbfb839e62833308d65b9417d2217281d0082965cca6b15a9f3e9be1c3b.json
index 5dfa4f8648..c046a0f2a6 100644
--- a/crates/db/.sqlx/query-e3f01fc53c00ee217b823ca588dc9a5320c9ba6ddf2bd718c817dfbf5fefd21c.json
+++ b/crates/db/.sqlx/query-38d1abbfb839e62833308d65b9417d2217281d0082965cca6b15a9f3e9be1c3b.json
@@ -1,6 +1,6 @@
{
"db_name": "SQLite",
- "query": "UPDATE projects\n SET name = $2, default_agent_working_dir = $3\n WHERE id = $1\n RETURNING id as \"id!: Uuid\",\n name,\n default_agent_working_dir,\n remote_project_id as \"remote_project_id: Uuid\",\n created_at as \"created_at!: DateTime\",\n updated_at as \"updated_at!: DateTime\"",
+ "query": "UPDATE projects\n SET name = $2\n WHERE id = $1\n RETURNING id as \"id!: Uuid\",\n name,\n default_agent_working_dir,\n remote_project_id as \"remote_project_id: Uuid\",\n created_at as \"created_at!: DateTime\",\n updated_at as \"updated_at!: DateTime\"",
"describe": {
"columns": [
{
@@ -35,7 +35,7 @@
}
],
"parameters": {
- "Right": 3
+ "Right": 2
},
"nullable": [
true,
@@ -46,5 +46,5 @@
false
]
},
- "hash": "e3f01fc53c00ee217b823ca588dc9a5320c9ba6ddf2bd718c817dfbf5fefd21c"
+ "hash": "38d1abbfb839e62833308d65b9417d2217281d0082965cca6b15a9f3e9be1c3b"
}
diff --git a/crates/db/.sqlx/query-43c10bbafd851c362132fd0657eaef5e16eb58d847540b1d998a741996967643.json b/crates/db/.sqlx/query-43c10bbafd851c362132fd0657eaef5e16eb58d847540b1d998a741996967643.json
deleted file mode 100644
index 1e5b0e98c2..0000000000
--- a/crates/db/.sqlx/query-43c10bbafd851c362132fd0657eaef5e16eb58d847540b1d998a741996967643.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "db_name": "SQLite",
- "query": "UPDATE projects\n SET default_agent_working_dir = ''\n WHERE id = $1",
- "describe": {
- "columns": [],
- "parameters": {
- "Right": 1
- },
- "nullable": []
- },
- "hash": "43c10bbafd851c362132fd0657eaef5e16eb58d847540b1d998a741996967643"
-}
diff --git a/crates/db/src/models/project.rs b/crates/db/src/models/project.rs
index e22086f881..c4c2ca0117 100644
--- a/crates/db/src/models/project.rs
+++ b/crates/db/src/models/project.rs
@@ -38,7 +38,6 @@ pub struct CreateProject {
#[derive(Debug, Deserialize, TS)]
pub struct UpdateProject {
pub name: Option,
- pub default_agent_working_dir: Option,
}
#[derive(Debug, Serialize, TS)]
@@ -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,
@@ -211,27 +209,11 @@ impl Project {
updated_at as "updated_at!: DateTime""#,
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,
diff --git a/crates/server/src/routes/task_attempts.rs b/crates/server/src/routes/task_attempts.rs
index 9a2811dbd5..2c953bcd4f 100644
--- a/crates/server/src/routes/task_attempts.rs
+++ b/crates/server/src/routes/task_attempts.rs
@@ -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
diff --git a/crates/services/src/services/container.rs b/crates/services/src/services/container.rs
index ae46a06cdc..b49c722a62 100644
--- a/crates/services/src/services/container.rs
+++ b/crates/services/src/services/container.rs
@@ -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},
@@ -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(())
diff --git a/crates/services/src/services/project.rs b/crates/services/src/services/project.rs
index b56c8a02d1..a11acfa990 100644
--- a/crates/services/src/services/project.rs
+++ b/crates/services/src/services/project.rs
@@ -110,29 +110,11 @@ impl ProjectService {
.await
.map_err(|e| ProjectServiceError::Project(ProjectError::CreateFailed(e.to_string())))?;
- let mut created_repo: Option = 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)
@@ -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,
@@ -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,
diff --git a/frontend/src/i18n/locales/en/settings.json b/frontend/src/i18n/locales/en/settings.json
index 8b109cfd01..e417be7d26 100644
--- a/frontend/src/i18n/locales/en/settings.json
+++ b/frontend/src/i18n/locales/en/settings.json
@@ -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!",
diff --git a/frontend/src/i18n/locales/es/settings.json b/frontend/src/i18n/locales/es/settings.json
index 33295a501b..81ada94032 100644
--- a/frontend/src/i18n/locales/es/settings.json
+++ b/frontend/src/i18n/locales/es/settings.json
@@ -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!",
diff --git a/frontend/src/i18n/locales/ja/settings.json b/frontend/src/i18n/locales/ja/settings.json
index 4ee1b39971..8c52b7e24e 100644
--- a/frontend/src/i18n/locales/ja/settings.json
+++ b/frontend/src/i18n/locales/ja/settings.json
@@ -333,11 +333,6 @@
"helper": "ディスク上のgitリポジトリへの絶対パス。"
}
},
- "agentWorkingDir": {
- "label": "エージェント作業ディレクトリ",
- "placeholder": "例:my-repo",
- "helper": "新しいワークスペースでコーディングエージェントを実行するデフォルトディレクトリ。ワークスペースルートからの相対パス。この値はワークスペース作成時に保存され、既存のワークスペースには影響しません。単一リポジトリプロジェクトの場合、リポジトリ名がデフォルトになります。空欄にするとワークスペースルートから実行します。"
- },
"save": {
"button": "プロジェクト設定を保存",
"success": "✓ プロジェクト設定が正常に保存されました!",
diff --git a/frontend/src/i18n/locales/ko/settings.json b/frontend/src/i18n/locales/ko/settings.json
index 3e9ce49d70..b639f54c03 100644
--- a/frontend/src/i18n/locales/ko/settings.json
+++ b/frontend/src/i18n/locales/ko/settings.json
@@ -333,11 +333,6 @@
"helper": "디스크에 있는 git 저장소의 절대 경로입니다."
}
},
- "agentWorkingDir": {
- "label": "에이전트 작업 디렉토리",
- "placeholder": "예: my-repo",
- "helper": "새 워크스페이스에서 코딩 에이전트를 실행할 기본 디렉토리로, 워크스페이스 루트 기준 상대 경로입니다. 이 값은 워크스페이스 생성 시 저장되며 기존 워크스페이스에는 영향을 주지 않습니다. 단일 저장소 프로젝트의 경우 저장소 이름이 기본값입니다. 비워두면 워크스페이스 루트에서 실행됩니다."
- },
"save": {
"button": "프로젝트 설정 저장",
"success": "✓ 프로젝트 설정이 성공적으로 저장되었습니다!",
diff --git a/frontend/src/i18n/locales/zh-Hans/settings.json b/frontend/src/i18n/locales/zh-Hans/settings.json
index 92cb7122be..809c0c8a3d 100644
--- a/frontend/src/i18n/locales/zh-Hans/settings.json
+++ b/frontend/src/i18n/locales/zh-Hans/settings.json
@@ -333,11 +333,6 @@
"helper": "磁盘上 git 仓库的绝对路径。"
}
},
- "agentWorkingDir": {
- "label": "代理工作目录",
- "placeholder": "例如:my-repo",
- "helper": "新工作区运行编码代理的默认目录,相对于工作区根目录。此值在创建工作区时保存,不会影响现有工作区。对于单仓库项目,默认为仓库名称。留空则从工作区根目录运行。"
- },
"save": {
"button": "保存项目设置",
"success": "✓ 项目设置保存成功!",
diff --git a/frontend/src/pages/settings/ProjectSettings.tsx b/frontend/src/pages/settings/ProjectSettings.tsx
index a116930d8a..d1ec5f7b1d 100644
--- a/frontend/src/pages/settings/ProjectSettings.tsx
+++ b/frontend/src/pages/settings/ProjectSettings.tsx
@@ -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 ?? '',
};
}
@@ -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({
@@ -429,26 +425,6 @@ export function ProjectSettings() {
-
-
-
- updateDraft({ default_agent_working_dir: e.target.value })
- }
- placeholder={t(
- 'settings.projects.agentWorkingDir.placeholder'
- )}
- className="font-mono"
- />
-
- {t('settings.projects.agentWorkingDir.helper')}
-
-
-
{/* Save Button */}
{hasUnsavedChanges ? (
diff --git a/shared/types.ts b/shared/types.ts
index 4c4db60df6..c04c9abaf4 100644
--- a/shared/types.ts
+++ b/shared/types.ts
@@ -16,7 +16,7 @@ export type Project = { id: string, name: string, default_agent_working_dir: str
export type CreateProject = { name: string, repositories: Array, };
-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,
/**
From fb6101586b4066471abd7b3929f81ac2b192eb62 Mon Sep 17 00:00:00 2001
From: Gabriel Gordon-Hall
Date: Fri, 9 Jan 2026 16:06:51 +0000
Subject: [PATCH 2/3] calculate agent_working_dir on create and start task
---
crates/server/src/routes/tasks.rs | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/crates/server/src/routes/tasks.rs b/crates/server/src/routes/tasks.rs
index c194033c56..c37d186d4b 100644
--- a/crates/server/src/routes/tasks.rs
+++ b/crates/server/src/routes/tasks.rs
@@ -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},
@@ -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,
From 14be50322133728270749da5782914fa25a60a76 Mon Sep 17 00:00:00 2001
From: Gabriel Gordon-Hall
Date: Fri, 9 Jan 2026 16:08:56 +0000
Subject: [PATCH 3/3] i18n
---
frontend/src/i18n/locales/zh-Hant/settings.json | 5 -----
1 file changed, 5 deletions(-)
diff --git a/frontend/src/i18n/locales/zh-Hant/settings.json b/frontend/src/i18n/locales/zh-Hant/settings.json
index 0b48784126..0c2e67d530 100644
--- a/frontend/src/i18n/locales/zh-Hant/settings.json
+++ b/frontend/src/i18n/locales/zh-Hant/settings.json
@@ -333,11 +333,6 @@
"helper": "磁碟上的 Git 儲存庫絕對路徑。"
}
},
- "agentWorkingDir": {
- "label": "代理工作目錄",
- "placeholder": "例如:my-repo",
- "helper": "新工作區執行編碼代理的預設目錄,相對於工作區根目錄。此值在建立工作區時保存,不會影響現有工作區。單一儲存庫專案預設為儲存庫名稱。留空則從工作區根目錄執行。"
- },
"save": {
"button": "儲存專案設定",
"success": "✓ 專案設定儲存成功!",