Merge branch 'session-todo-tools' into develop
# Conflicts: # tickets/session-todo.md
This commit is contained in:
@@ -133,6 +133,7 @@ impl PodController {
|
||||
// Stashed during tool registration below so we can attach a
|
||||
// `PodFsView` to the shared state once the latter exists.
|
||||
let fs_for_view: tools::ScopedFs;
|
||||
let task_store = pod.task_store();
|
||||
|
||||
let scope_change_sink = pod.scope_change_sink();
|
||||
|
||||
@@ -266,7 +267,12 @@ impl PodController {
|
||||
// query — keep a clone for the FS view we attach below,
|
||||
// since the tools consume `fs` itself.
|
||||
fs_for_view = fs.clone();
|
||||
worker.register_tools(tools::builtin_tools(fs, tracker.clone(), bash_output_dir));
|
||||
worker.register_tools(tools::builtin_tools(
|
||||
fs,
|
||||
tracker.clone(),
|
||||
task_store.clone(),
|
||||
bash_output_dir,
|
||||
));
|
||||
|
||||
// Memory subsystem opt-in. When `[memory]` is present in
|
||||
// the manifest, register the memory-specific Read/Write/Edit
|
||||
|
||||
@@ -150,7 +150,7 @@ impl Interceptor for PodInterceptor {
|
||||
|
||||
// Internal mechanism: between-requests compaction trigger (safety net).
|
||||
if let Some(state) = self.compact_state.as_ref() {
|
||||
if !state.is_disabled() {
|
||||
if !state.is_disabled() && !state.just_compacted() {
|
||||
let current = current_tokens.unwrap_or(0);
|
||||
if state.exceeds_request(current) {
|
||||
info!(
|
||||
|
||||
+63
-4
@@ -95,6 +95,11 @@ pub struct Pod<C: LlmClient, St: Store> {
|
||||
/// tools so that Pod-owned operations (e.g. compaction) can consult
|
||||
/// the recency of touched files.
|
||||
tracker: Option<tools::Tracker>,
|
||||
/// Session-lifetime task store from the builtin `tools` crate. Shared by
|
||||
/// TaskCreate / TaskUpdate / TaskList / TaskGet and preserved across
|
||||
/// compaction by keeping the same handle while the Worker history is
|
||||
/// replaced. Restored Pods reconstruct it by replaying Task* tool calls.
|
||||
task_store: tools::TaskStore,
|
||||
/// Parsed system-prompt template awaiting first-turn materialisation.
|
||||
/// `Some` until `ensure_system_prompt_materialized` renders it once,
|
||||
/// then `None` forever — including after compaction.
|
||||
@@ -215,6 +220,7 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||
metrics_tracker: Arc::new(crate::compact::metrics_tracker::MetricsTracker::new()),
|
||||
usage_history: Arc::new(Mutex::new(Vec::<UsageRecord>::new())),
|
||||
tracker: None,
|
||||
task_store: tools::TaskStore::new(),
|
||||
system_prompt_template: None,
|
||||
alerter: None,
|
||||
event_tx: None,
|
||||
@@ -479,6 +485,18 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||
self.tracker = Some(tracker);
|
||||
}
|
||||
|
||||
/// Attach the session-scoped TaskStore from the builtin `tools` crate.
|
||||
/// Called by the Controller before registering builtin tools so the Pod
|
||||
/// and Worker share one store.
|
||||
pub fn attach_task_store(&mut self, task_store: tools::TaskStore) {
|
||||
self.task_store = task_store;
|
||||
}
|
||||
|
||||
/// Shared TaskStore handle.
|
||||
pub fn task_store(&self) -> tools::TaskStore {
|
||||
self.task_store.clone()
|
||||
}
|
||||
|
||||
/// The attached session-scoped file-operation tracker, if any.
|
||||
pub fn tracker(&self) -> Option<&tools::Tracker> {
|
||||
self.tracker.as_ref()
|
||||
@@ -1314,8 +1332,14 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||
.unwrap_or_default();
|
||||
|
||||
// Input text fed to the compact worker. Includes the default
|
||||
// references and the (pruned) conversation text.
|
||||
let summary_input = build_summary_input(&items_to_summarise, &default_refs);
|
||||
// references, current TaskStore snapshot, and the (pruned)
|
||||
// conversation text.
|
||||
let task_snapshot_text = self.task_store.snapshot_text();
|
||||
let summary_input = build_summary_input(
|
||||
&items_to_summarise,
|
||||
&default_refs,
|
||||
Some(task_snapshot_text.as_str()),
|
||||
);
|
||||
|
||||
// Worker-side state collected by the compact worker's tool calls.
|
||||
let ctx = Arc::new(std::sync::Mutex::new(CompactWorkerContext::with_budget(
|
||||
@@ -1430,9 +1454,15 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||
.filter(|i| i.is_user_message())
|
||||
.count();
|
||||
|
||||
// Build new history: [summary, ...auto-read, references, ...retained].
|
||||
// Build new history: [summary, ...auto-read, references, ...retained, task snapshot, TaskList synthetic call/result].
|
||||
// The TaskStore snapshot trails the retained items so that, on resume,
|
||||
// `replay_history` walks any pre-compact Task* calls preserved verbatim
|
||||
// in retained_items first and the trailing snapshot's `replace_with`
|
||||
// is the final word — pre-compact `TaskCreate` calls cannot leak as
|
||||
// duplicate entries.
|
||||
let mut new_history = Vec::with_capacity(
|
||||
1 + auto_read_messages.len()
|
||||
+ 3
|
||||
+ reference_message.is_some() as usize
|
||||
+ retained_items.len(),
|
||||
);
|
||||
@@ -1444,6 +1474,17 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||
new_history.push(msg);
|
||||
}
|
||||
new_history.extend(retained_items);
|
||||
new_history.push(Item::system_message(format!(
|
||||
"[Session TaskStore snapshot]\n\n{task_snapshot_text}\n\n\
|
||||
This is the complete session task list preserved across compaction. \
|
||||
The following TaskList tool result presents the same state through the tool lane."
|
||||
)));
|
||||
new_history.push(Item::tool_call("compact-tasklist", "TaskList", "{}"));
|
||||
new_history.push(Item::tool_result_with_content(
|
||||
"compact-tasklist",
|
||||
tools::task::snapshot_overview(&self.task_store.list()),
|
||||
task_snapshot_text.clone(),
|
||||
));
|
||||
|
||||
// Persist as a new compacted session.
|
||||
let old_session_id = self.session_id;
|
||||
@@ -2038,6 +2079,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
|
||||
metrics_tracker: Arc::new(crate::compact::metrics_tracker::MetricsTracker::new()),
|
||||
usage_history: Arc::new(Mutex::new(Vec::new())),
|
||||
tracker: None,
|
||||
task_store: tools::TaskStore::new(),
|
||||
system_prompt_template: common.system_prompt_template,
|
||||
alerter: None,
|
||||
event_tx: None,
|
||||
@@ -2101,6 +2143,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
|
||||
metrics_tracker: Arc::new(crate::compact::metrics_tracker::MetricsTracker::new()),
|
||||
usage_history: Arc::new(Mutex::new(Vec::new())),
|
||||
tracker: None,
|
||||
task_store: tools::TaskStore::new(),
|
||||
system_prompt_template: common.system_prompt_template,
|
||||
alerter: None,
|
||||
event_tx: None,
|
||||
@@ -2211,6 +2254,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
|
||||
}
|
||||
|
||||
let extract_pointer = memory::extract::fold_pointer(&state.extensions);
|
||||
let task_store = tools::TaskStore::from_history(&state.history);
|
||||
|
||||
let mut pod = Self {
|
||||
manifest,
|
||||
@@ -2227,6 +2271,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
|
||||
metrics_tracker: Arc::new(crate::compact::metrics_tracker::MetricsTracker::new()),
|
||||
usage_history: Arc::new(Mutex::new(state.usage_history)),
|
||||
tracker: None,
|
||||
task_store,
|
||||
// Restore replays the saved system_prompt verbatim — no
|
||||
// template re-render on resume.
|
||||
system_prompt_template: None,
|
||||
@@ -2323,7 +2368,11 @@ impl From<WorkerResult> for PodRunResult {
|
||||
/// Build the compact worker's input: default-reference instructions,
|
||||
/// the list of recently-touched files, and the pruned conversation
|
||||
/// produced by [`build_summary_prompt`].
|
||||
fn build_summary_input(items: &[Item], default_refs: &[PathBuf]) -> String {
|
||||
fn build_summary_input(
|
||||
items: &[Item],
|
||||
default_refs: &[PathBuf],
|
||||
task_snapshot: Option<&str>,
|
||||
) -> String {
|
||||
let mut out = String::new();
|
||||
out.push_str(
|
||||
"Summarise the conversation below into a structured summary and nominate \
|
||||
@@ -2343,6 +2392,16 @@ fn build_summary_input(items: &[Item], default_refs: &[PathBuf]) -> String {
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
if let Some(task_snapshot) = task_snapshot {
|
||||
out.push_str(
|
||||
"## Current Session TaskStore\n\
|
||||
This is the full current task list. Use it as source material for the \
|
||||
summary, especially active (pending/inprogress) tasks, but do not edit tasks \
|
||||
from the compact worker.\n",
|
||||
);
|
||||
out.push_str(task_snapshot);
|
||||
out.push_str("\n\n");
|
||||
}
|
||||
out.push_str("## Conversation\n");
|
||||
out.push_str(&build_summary_prompt(items));
|
||||
out.push_str("\n\nWhen you are done, call `write_summary` with the final 5-section text.");
|
||||
|
||||
Reference in New Issue
Block a user