Further WIP
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "INSERT INTO task_attempts (id, task_id, worktree_path, merge_commit, executor, stdout, stderr) \n VALUES ($1, $2, $3, $4, $5, $6, $7) \n RETURNING id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, stdout, stderr, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"",
|
||||
"query": "INSERT INTO task_attempts (id, task_id, worktree_path, merge_commit, executor) \n VALUES ($1, $2, $3, $4, $5) \n RETURNING id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -29,28 +29,18 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "updated_at!: DateTime<Utc>",
|
||||
"ordinal": 8,
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 7
|
||||
"Right": 5
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
@@ -58,11 +48,9 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "32932b7fbc42de6c671d44d5e9a4ec7f73aadf48a482d4a8a9102cb503a9ffb9"
|
||||
"hash": "0fc0dec5876cbe904d288a8e3bef15e0b7f75eb8e3c0fc1aeccd533ae73aab05"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "UPDATE task_attempts SET stdout = COALESCE(stdout, '') || $1, updated_at = datetime('now') WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3380f443d21ac408f96b014830322bd3411296b9ee8d29fe5f18974221bb0035"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, stdout, stderr, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts \n WHERE id = $1",
|
||||
"query": "SELECT id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts \n WHERE task_id = $1 \n ORDER BY created_at DESC",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -29,23 +29,13 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "updated_at!: DateTime<Utc>",
|
||||
"ordinal": 8,
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -58,11 +48,9 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ab93108e1b1a983b7d7fe2bce4e37ea6cbd1bf7aa7b802d92e7bc33dab90b933"
|
||||
"hash": "58bd05ee7354bb2aa7abffa7fa962f7143e071b9a1d39bca44e2e94512931209"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "UPDATE task_attempts SET stderr = COALESCE(stderr, '') || $1, updated_at = datetime('now') WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "96957aa26773ee77bba123ebe27c675aa7698c235029ba09f2d503fea746baf6"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, stdout, stderr, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts \n WHERE task_id = $1 \n ORDER BY created_at DESC",
|
||||
"query": "SELECT id as \"id!: Uuid\", task_id as \"task_id!: Uuid\", worktree_path, merge_commit, executor, created_at as \"created_at!: DateTime<Utc>\", updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts \n WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -29,23 +29,13 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "updated_at!: DateTime<Utc>",
|
||||
"ordinal": 8,
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -58,11 +48,9 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3c109510d6e312b21f74508040a14c4f3c264cc8e53d864473b35e54662e99d5"
|
||||
"hash": "a6058c6a30c6e3011e02b0ad81b2a98c5eca3bd88dec9632284ef7489f784fcd"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT ta.id as \"id!: Uuid\", ta.task_id as \"task_id!: Uuid\", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as \"created_at!: DateTime<Utc>\", ta.updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts ta \n JOIN tasks t ON ta.task_id = t.id \n WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3",
|
||||
"query": "SELECT ta.id as \"id!: Uuid\", ta.task_id as \"task_id!: Uuid\", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as \"created_at!: DateTime<Utc>\", ta.updated_at as \"updated_at!: DateTime<Utc>\"\n FROM task_attempts ta \n JOIN tasks t ON ta.task_id = t.id \n WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -29,23 +29,13 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at!: DateTime<Utc>",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "updated_at!: DateTime<Utc>",
|
||||
"ordinal": 8,
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -58,11 +48,9 @@
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "6c31a378ab5073e71dea882d4bdbe27c4091b5995f9c214f4e1b1043f6bcfeae"
|
||||
"hash": "acb63e12f7fa91c1f1cd5513b6dae0d8bff94f8b675c0c5b81f429e44158d8a8"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
-- Remove stdout and stderr columns from task_attempts table
|
||||
-- These are now tracked in the execution_processes table for better granularity
|
||||
|
||||
-- SQLite doesn't support DROP COLUMN directly, so we need to recreate the table
|
||||
-- First, create a new table without stdout and stderr
|
||||
CREATE TABLE task_attempts_new (
|
||||
id BLOB PRIMARY KEY,
|
||||
task_id BLOB NOT NULL,
|
||||
worktree_path TEXT NOT NULL,
|
||||
merge_commit TEXT,
|
||||
executor TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now', 'subsec')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now', 'subsec')),
|
||||
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Copy data from old table to new table (excluding stdout and stderr)
|
||||
INSERT INTO task_attempts_new (id, task_id, worktree_path, merge_commit, executor, created_at, updated_at)
|
||||
SELECT id, task_id, worktree_path, merge_commit, executor, created_at, updated_at
|
||||
FROM task_attempts;
|
||||
|
||||
-- Drop the old table
|
||||
DROP TABLE task_attempts;
|
||||
|
||||
-- Rename the new table to the original name
|
||||
ALTER TABLE task_attempts_new RENAME TO task_attempts;
|
||||
@@ -49,6 +49,7 @@ pub trait Executor: Send + Sync {
|
||||
pool: &sqlx::SqlitePool,
|
||||
task_id: Uuid,
|
||||
attempt_id: Uuid,
|
||||
execution_process_id: Uuid,
|
||||
worktree_path: &str,
|
||||
) -> Result<Child, ExecutorError> {
|
||||
let mut child = self.spawn(pool, task_id, worktree_path).await?;
|
||||
@@ -67,8 +68,20 @@ pub trait Executor: Send + Sync {
|
||||
let pool_clone1 = pool.clone();
|
||||
let pool_clone2 = pool.clone();
|
||||
|
||||
tokio::spawn(stream_output_to_db(stdout, pool_clone1, attempt_id, true));
|
||||
tokio::spawn(stream_output_to_db(stderr, pool_clone2, attempt_id, false));
|
||||
tokio::spawn(stream_output_to_db(
|
||||
stdout,
|
||||
pool_clone1,
|
||||
attempt_id,
|
||||
execution_process_id,
|
||||
true,
|
||||
));
|
||||
tokio::spawn(stream_output_to_db(
|
||||
stderr,
|
||||
pool_clone2,
|
||||
attempt_id,
|
||||
execution_process_id,
|
||||
false,
|
||||
));
|
||||
|
||||
Ok(child)
|
||||
}
|
||||
@@ -102,9 +115,10 @@ async fn stream_output_to_db(
|
||||
output: impl tokio::io::AsyncRead + Unpin,
|
||||
pool: sqlx::SqlitePool,
|
||||
attempt_id: Uuid,
|
||||
execution_process_id: Uuid,
|
||||
is_stdout: bool,
|
||||
) {
|
||||
use crate::models::task_attempt::TaskAttempt;
|
||||
use crate::models::execution_process::ExecutionProcess;
|
||||
|
||||
let mut reader = BufReader::new(output);
|
||||
let mut line = String::new();
|
||||
@@ -121,9 +135,9 @@ async fn stream_output_to_db(
|
||||
|
||||
// Update database every 1 lines or when we have a significant amount of data
|
||||
if update_counter >= 1 || accumulated_output.len() > 1024 {
|
||||
if let Err(e) = TaskAttempt::append_output(
|
||||
if let Err(e) = ExecutionProcess::append_output(
|
||||
&pool,
|
||||
attempt_id,
|
||||
execution_process_id,
|
||||
if is_stdout {
|
||||
Some(&accumulated_output)
|
||||
} else {
|
||||
@@ -162,9 +176,9 @@ async fn stream_output_to_db(
|
||||
|
||||
// Flush any remaining output
|
||||
if !accumulated_output.is_empty() {
|
||||
if let Err(e) = TaskAttempt::append_output(
|
||||
if let Err(e) = ExecutionProcess::append_output(
|
||||
&pool,
|
||||
attempt_id,
|
||||
execution_process_id,
|
||||
if is_stdout {
|
||||
Some(&accumulated_output)
|
||||
} else {
|
||||
|
||||
@@ -69,8 +69,6 @@ pub struct TaskAttempt {
|
||||
pub worktree_path: String,
|
||||
pub merge_commit: Option<String>,
|
||||
pub executor: Option<String>, // Name of the executor to use
|
||||
pub stdout: Option<String>,
|
||||
pub stderr: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -132,7 +130,7 @@ impl TaskAttempt {
|
||||
pub async fn find_by_id(pool: &SqlitePool, id: Uuid) -> Result<Option<Self>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, stdout, stderr, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts
|
||||
WHERE id = $1"#,
|
||||
id
|
||||
@@ -147,7 +145,7 @@ impl TaskAttempt {
|
||||
) -> Result<Vec<Self>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, stdout, stderr, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts
|
||||
WHERE task_id = $1
|
||||
ORDER BY created_at DESC"#,
|
||||
@@ -191,16 +189,14 @@ impl TaskAttempt {
|
||||
// Insert the record into the database
|
||||
Ok(sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"INSERT INTO task_attempts (id, task_id, worktree_path, merge_commit, executor, stdout, stderr)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, stdout, stderr, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>""#,
|
||||
r#"INSERT INTO task_attempts (id, task_id, worktree_path, merge_commit, executor)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id as "id!: Uuid", task_id as "task_id!: Uuid", worktree_path, merge_commit, executor, created_at as "created_at!: DateTime<Utc>", updated_at as "updated_at!: DateTime<Utc>""#,
|
||||
attempt_id,
|
||||
data.task_id,
|
||||
data.worktree_path,
|
||||
data.merge_commit,
|
||||
data.executor,
|
||||
None::<String>, // stdout
|
||||
None::<String> // stderr
|
||||
data.executor
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?)
|
||||
@@ -240,36 +236,6 @@ impl TaskAttempt {
|
||||
}
|
||||
}
|
||||
|
||||
/// Append to stdout and stderr for this task attempt (for streaming updates)
|
||||
pub async fn append_output(
|
||||
pool: &SqlitePool,
|
||||
id: Uuid,
|
||||
stdout_append: Option<&str>,
|
||||
stderr_append: Option<&str>,
|
||||
) -> Result<(), sqlx::Error> {
|
||||
if let Some(stdout_data) = stdout_append {
|
||||
sqlx::query!(
|
||||
"UPDATE task_attempts SET stdout = COALESCE(stdout, '') || $1, updated_at = datetime('now') WHERE id = $2",
|
||||
stdout_data,
|
||||
id
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if let Some(stderr_data) = stderr_append {
|
||||
sqlx::query!(
|
||||
"UPDATE task_attempts SET stderr = COALESCE(stderr, '') || $1, updated_at = datetime('now') WHERE id = $2",
|
||||
stderr_data,
|
||||
id
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform the actual git merge operations (synchronous)
|
||||
fn perform_merge_operation(
|
||||
worktree_path: &str,
|
||||
@@ -381,7 +347,7 @@ impl TaskAttempt {
|
||||
// Get the task attempt with validation
|
||||
let attempt = sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts ta
|
||||
JOIN tasks t ON ta.task_id = t.id
|
||||
WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3"#,
|
||||
@@ -585,7 +551,13 @@ impl TaskAttempt {
|
||||
ExecutionProcess::create(pool, &create_agent_process, agent_process_id).await?;
|
||||
|
||||
let child = executor
|
||||
.execute_streaming(pool, task_id, attempt_id, &task_attempt.worktree_path)
|
||||
.execute_streaming(
|
||||
pool,
|
||||
task_id,
|
||||
attempt_id,
|
||||
agent_process_id,
|
||||
&task_attempt.worktree_path,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| TaskAttemptError::Git(git2::Error::from_str(&e.to_string())))?;
|
||||
|
||||
@@ -620,7 +592,7 @@ impl TaskAttempt {
|
||||
// Get the task attempt with validation
|
||||
let attempt = sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts ta
|
||||
JOIN tasks t ON ta.task_id = t.id
|
||||
WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3"#,
|
||||
@@ -881,7 +853,7 @@ impl TaskAttempt {
|
||||
// Get the task attempt with validation
|
||||
let attempt = sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts ta
|
||||
JOIN tasks t ON ta.task_id = t.id
|
||||
WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3"#,
|
||||
@@ -1020,7 +992,7 @@ impl TaskAttempt {
|
||||
// Get the task attempt with validation
|
||||
let attempt = sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts ta
|
||||
JOIN tasks t ON ta.task_id = t.id
|
||||
WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3"#,
|
||||
@@ -1056,7 +1028,7 @@ impl TaskAttempt {
|
||||
// Get the task attempt with validation
|
||||
let attempt = sqlx::query_as!(
|
||||
TaskAttempt,
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.stdout, ta.stderr, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
r#"SELECT ta.id as "id!: Uuid", ta.task_id as "task_id!: Uuid", ta.worktree_path, ta.merge_commit, ta.executor, ta.created_at as "created_at!: DateTime<Utc>", ta.updated_at as "updated_at!: DateTime<Utc>"
|
||||
FROM task_attempts ta
|
||||
JOIN tasks t ON ta.task_id = t.id
|
||||
WHERE ta.id = $1 AND t.id = $2 AND t.project_id = $3"#,
|
||||
|
||||
@@ -388,51 +388,8 @@ export function TaskDetailsDialog({
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Task Attempt Output */}
|
||||
{selectedAttempt &&
|
||||
(selectedAttempt.stdout || selectedAttempt.stderr) && (
|
||||
<Card className="bg-black">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="text-lg font-semibold mb-4 text-green-400">
|
||||
Execution Output
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
{selectedAttempt.stdout && (
|
||||
<div>
|
||||
<Label className="text-sm font-medium mb-2 block text-console-success">
|
||||
STDOUT
|
||||
</Label>
|
||||
<div
|
||||
className="bg-console text-console-success border border-console-success rounded-md p-4 font-mono text-sm max-h-96 overflow-y-auto whitespace-pre-wrap shadow-inner"
|
||||
style={{
|
||||
fontFamily:
|
||||
'ui-monospace, SFMono-Regular, "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
}}
|
||||
>
|
||||
{selectedAttempt.stdout}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selectedAttempt.stderr && (
|
||||
<div>
|
||||
<Label className="text-sm font-medium mb-2 block text-console-error">
|
||||
STDERR
|
||||
</Label>
|
||||
<div
|
||||
className="bg-console text-console-error border border-console-error rounded-md p-4 font-mono text-sm max-h-96 overflow-y-auto whitespace-pre-wrap shadow-inner"
|
||||
style={{
|
||||
fontFamily:
|
||||
'ui-monospace, SFMono-Regular, "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
}}
|
||||
>
|
||||
{selectedAttempt.stderr}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{/* TODO: Task Attempt Output - migrate to use ExecutionProcess data */}
|
||||
{/* ExecutionProcess stdout/stderr display will be implemented when execution processes are exposed via API */}
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ArrowLeft, FileText, Code, Monitor, Braces } from "lucide-react";
|
||||
import { ArrowLeft, FileText, Code /* , Monitor, Braces */ } from "lucide-react";
|
||||
import { makeRequest } from "@/lib/api";
|
||||
import { TaskFormDialog } from "@/components/tasks/TaskFormDialog";
|
||||
import { useKeyboardShortcuts } from "@/lib/keyboard-shortcuts";
|
||||
@@ -91,7 +91,7 @@ export function TaskDetailsPage() {
|
||||
const [stoppingAttempt, setStoppingAttempt] = useState(false);
|
||||
const [openingEditor, setOpeningEditor] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [outputViewMode, setOutputViewMode] = useState<'console' | 'json'>('console');
|
||||
// const [outputViewMode, setOutputViewMode] = useState<'console' | 'json'>('console');
|
||||
|
||||
const [isTaskDialogOpen, setIsTaskDialogOpen] = useState(false);
|
||||
|
||||
@@ -416,7 +416,7 @@ export function TaskDetailsPage() {
|
||||
navigate(`/projects/${projectId}/tasks`);
|
||||
};
|
||||
|
||||
const parseJsonLines = (jsonlText: string) => {
|
||||
/* const parseJsonLines = (jsonlText: string) => {
|
||||
const lines = jsonlText.split('\n').filter(line => line.trim());
|
||||
const parsedLines: { json: any; error?: string; raw: string }[] = [];
|
||||
|
||||
@@ -434,7 +434,7 @@ export function TaskDetailsPage() {
|
||||
});
|
||||
|
||||
return parsedLines;
|
||||
};
|
||||
}; */
|
||||
|
||||
if (taskLoading) {
|
||||
return (
|
||||
@@ -526,9 +526,10 @@ export function TaskDetailsPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Task Attempt Output */}
|
||||
{selectedAttempt &&
|
||||
(selectedAttempt.stdout || selectedAttempt.stderr) && (
|
||||
{/* TODO: Task Attempt Output - migrate to use ExecutionProcess data */}
|
||||
{/* ExecutionProcess stdout/stderr display will be implemented when execution processes are exposed via API */}
|
||||
{/*
|
||||
{selectedAttempt && (
|
||||
<Card className="bg-black">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
@@ -675,7 +676,8 @@ export function TaskDetailsPage() {
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
)
|
||||
*/}
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
|
||||
@@ -36,7 +36,7 @@ export type UpdateTask = { title: string | null, description: string | null, sta
|
||||
|
||||
export type TaskAttemptStatus = "init" | "setuprunning" | "setupcomplete" | "setupfailed" | "executorrunning" | "executorcomplete" | "executorfailed" | "paused";
|
||||
|
||||
export type TaskAttempt = { id: string, task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, stdout: string | null, stderr: string | null, created_at: string, updated_at: string, };
|
||||
export type TaskAttempt = { id: string, task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, created_at: string, updated_at: string, };
|
||||
|
||||
export type CreateTaskAttempt = { task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user