Skip to content

Commit ddb7f35

Browse files
author
ComputelessComputer
committed
fix @ mention edit path missing parent_id support
1 parent b089bfe commit ddb7f35

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

src/llm.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ struct Enriched {
860860
priority: Option<String>,
861861
due_date: Option<String>,
862862
dependencies: Option<Vec<String>>,
863+
parent_id: Option<String>,
863864
subtasks: Option<Vec<SubTaskEnriched>>,
864865
}
865866

@@ -920,7 +921,7 @@ fn edit_task(cfg: &LlmConfig, job: &AiJob, instruction: &str) -> AiResult {
920921
.join("|");
921922

922923
let user = format!(
923-
"Current task:\n{}\n\nInstruction: {}\n\nExisting tasks (id_prefix [bucket] title):\n{}\nReturn JSON with ONLY fields that should change (set unchanged fields to null):\n{{\n \"title\": string | null,\n \"bucket\": {bucket_enum} | null,\n \"description\": string | null,\n \"progress\": \"Backlog\"|\"Todo\"|\"In progress\"|\"Done\" | null,\n \"priority\": \"Low\"|\"Medium\"|\"High\"|\"Critical\" | null,\n \"due_date\": \"YYYY-MM-DD\" | null,\n \"dependencies\": [\"id_prefix\", ...] | null,\n \"subtasks\": [{{\"title\": string, \"description\": string, \"bucket\": {bucket_enum}, \"priority\": \"Low\"|\"Medium\"|\"High\"|\"Critical\", \"progress\": \"Backlog\"|\"Todo\"|\"In progress\"|\"Done\", \"due_date\": \"YYYY-MM-DD\" | null, \"depends_on\": [0-based index, ...]}}] | null\n}}\nRules:\n- If the instruction asks to create sub-issues, sub-tasks, break down, or decompose the task, return them as entries in the \"subtasks\" array. NEVER write sub-task lists, numbered breakdowns, or step-by-step plans into the \"description\" field.\n- depends_on is an array of 0-based indices into the subtasks array representing execution order. Use it to express sequential dependencies between subtasks.\n- Subtasks inherit the parent task's bucket and priority unless the instruction specifies otherwise.\n- Only include fields that should change. Set unchanged fields to null.\n",
924+
"Current task:\n{}\n\nInstruction: {}\n\nExisting tasks (id_prefix [bucket] title):\n{}\nReturn JSON with ONLY fields that should change (set unchanged fields to null):\n{{\n \"title\": string | null,\n \"bucket\": {bucket_enum} | null,\n \"description\": string | null,\n \"progress\": \"Backlog\"|\"Todo\"|\"In progress\"|\"Done\" | null,\n \"priority\": \"Low\"|\"Medium\"|\"High\"|\"Critical\" | null,\n \"due_date\": \"YYYY-MM-DD\" | null,\n \"dependencies\": [\"id_prefix\", ...] | null,\n \"parent_id\": \"id_prefix\" | \"none\" | null,\n \"subtasks\": [{{\"title\": string, \"description\": string, \"bucket\": {bucket_enum}, \"priority\": \"Low\"|\"Medium\"|\"High\"|\"Critical\", \"progress\": \"Backlog\"|\"Todo\"|\"In progress\"|\"Done\", \"due_date\": \"YYYY-MM-DD\" | null, \"depends_on\": [0-based index, ...]}}] | null\n}}\nRules:\n- If the instruction asks to create sub-issues, sub-tasks, break down, or decompose the task, return them as entries in the \"subtasks\" array. NEVER write sub-task lists, numbered breakdowns, or step-by-step plans into the \"description\" field.\n- depends_on is an array of 0-based indices into the subtasks array representing execution order. Use it to express sequential dependencies between subtasks.\n- Subtasks inherit the parent task's bucket and priority unless the instruction specifies otherwise.\n- To move this task under another task as a sub-task, set \"parent_id\" to the target task's id_prefix. To promote to a root task, set \"parent_id\" to \"none\".\n- Only include fields that should change. Set unchanged fields to null.\n",
924925
snapshot,
925926
instruction,
926927
context_lines
@@ -1029,6 +1030,12 @@ fn edit_task(cfg: &LlmConfig, job: &AiJob, instruction: &str) -> AiResult {
10291030
update.dependencies = out;
10301031
}
10311032

1033+
update.parent_id = enriched
1034+
.parent_id
1035+
.as_deref()
1036+
.map(|s| s.trim().to_string())
1037+
.filter(|s| !s.is_empty());
1038+
10321039
let sub_task_specs: Vec<SubTaskSpec> = enriched
10331040
.subtasks
10341041
.unwrap_or_default()

src/main.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ fn spawn_email_poller(
339339
Ok(t) => t,
340340
Err(_) => continue,
341341
};
342-
let emails = match google::get_recent_emails(&token, 10) {
342+
let emails: Vec<google::Email> = match google::get_recent_emails(&token, 10) {
343343
Ok(e) => e,
344344
Err(_) => continue,
345345
};
@@ -3938,6 +3938,45 @@ fn poll_ai(app: &mut App) -> bool {
39383938
changed = true;
39393939
}
39403940
}
3941+
if let Some(ref new_parent_prefix) = result.update.parent_id {
3942+
let task_id = result.task_id;
3943+
let old_parent = app
3944+
.tasks
3945+
.iter()
3946+
.find(|t| t.id == task_id)
3947+
.and_then(|t| t.parent_id);
3948+
if new_parent_prefix.eq_ignore_ascii_case("none") {
3949+
if let Some(task) = app.tasks.iter_mut().find(|t| t.id == task_id) {
3950+
task.parent_id = None;
3951+
changed = true;
3952+
}
3953+
} else {
3954+
let new_parent_id = app.tasks.iter().find_map(|t| {
3955+
let short = t.id.to_string().chars().take(8).collect::<String>();
3956+
if short.eq_ignore_ascii_case(new_parent_prefix) {
3957+
Some(t.id)
3958+
} else {
3959+
None
3960+
}
3961+
});
3962+
if let Some(pid) = new_parent_id {
3963+
if let Some(task) = app.tasks.iter_mut().find(|t| t.id == task_id) {
3964+
task.parent_id = Some(pid);
3965+
changed = true;
3966+
}
3967+
}
3968+
}
3969+
if let Some(old_pid) = old_parent {
3970+
sync_parent_progress(&mut app.tasks, old_pid, Utc::now());
3971+
}
3972+
if !changed {
3973+
app.status = Some((
3974+
format!("AI: parent task {} not found", new_parent_prefix),
3975+
Instant::now(),
3976+
false,
3977+
));
3978+
}
3979+
}
39413980
sync_parent_progress(&mut app.tasks, parent_id, Utc::now());
39423981

39433982
// Create actual sub-task records when the edit response includes subtasks.
@@ -5172,6 +5211,15 @@ fn render_calendar_tab(stdout: &mut Stdout, app: &App, cols: u16, rows: u16) ->
51725211
ResetColor
51735212
)?;
51745213
y_cur += 2;
5214+
} else if !app.google_connected {
5215+
queue!(
5216+
stdout,
5217+
MoveTo(events_x, y_cur),
5218+
SetForegroundColor(Color::DarkGrey),
5219+
Print(clamp_text("Connect Google in Settings (0)", events_width)),
5220+
ResetColor
5221+
)?;
5222+
y_cur += 2;
51755223
}
51765224

51775225
queue!(

0 commit comments

Comments
 (0)