harness-tui + engine: jobs pane, subtask drill-in, reminders (M4)
TUI: Ctrl+J (or /jobs) opens a jobs pane listing the current session's board — alias, agent, state, objective, files read — populated on load and kept live via JobUpdated events; Enter drills into a subtask's child session. Snapshot test added. Engine: optional orchestration reminders (off by default) injected as synthetic, non-persisted turn-start blocks and, after a file tool runs, an after-file-tool block on the following turn. Processor reports file-tool usage via StepOutcome. This completes M4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,9 @@ pub struct StepOutcome {
|
||||
/// Dollar cost of this step's usage (0.0 when no pricing is available).
|
||||
pub cost: f64,
|
||||
pub aborted: bool,
|
||||
/// Whether a file-mutating tool (`edit`/`write`) ran this step — drives the optional
|
||||
/// `after_file_tool` reminder injection on the next turn.
|
||||
pub used_file_tool: bool,
|
||||
}
|
||||
|
||||
pub struct StepError {
|
||||
@@ -98,9 +101,13 @@ impl FlushTracker {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tool names that mutate files — after one runs, the optional `after_file_tool` reminder fires.
|
||||
const FILE_TOOLS: &[&str] = &["edit", "write"];
|
||||
|
||||
struct Run<'a> {
|
||||
ctx: &'a StepContext,
|
||||
assistant: Option<Message>,
|
||||
used_file_tool: bool,
|
||||
next_idx: u32,
|
||||
active_text: Option<PartId>,
|
||||
active_reasoning: Option<PartId>,
|
||||
@@ -117,6 +124,7 @@ impl<'a> Run<'a> {
|
||||
Self {
|
||||
ctx,
|
||||
assistant: None,
|
||||
used_file_tool: false,
|
||||
next_idx: 0,
|
||||
active_text: None,
|
||||
active_reasoning: None,
|
||||
@@ -386,6 +394,9 @@ impl<'a> Run<'a> {
|
||||
input: serde_json::Value,
|
||||
doomloop: &mut DoomLoopGuard,
|
||||
) -> Result<(), ProviderError> {
|
||||
if FILE_TOOLS.contains(&name.as_str()) {
|
||||
self.used_file_tool = true;
|
||||
}
|
||||
let part_id = self.pending_tools.remove(&call_id).unwrap_or_default();
|
||||
let running = Part {
|
||||
id: part_id.clone(),
|
||||
@@ -607,6 +618,7 @@ pub async fn process_step(
|
||||
usage,
|
||||
cost: step_cost,
|
||||
aborted: true,
|
||||
used_file_tool: run.used_file_tool,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -679,5 +691,6 @@ pub async fn process_step(
|
||||
usage,
|
||||
cost: step_cost,
|
||||
aborted: false,
|
||||
used_file_tool: run.used_file_tool,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user