Synced from monorepo
Synced from monorepo Changes: - Shell: accept target response id on rewind execute - Shell: stamp response id on chat user message chunks - Worktree: optional rebuild and stale git registration cleanup in auto-GC - Worktree: kind-aware auto-GC TTLs and config knobs - Worktree: macOS process CWD scan and Unix PID liveness for GC guards - Worktree: automatic throttled GC on startup (Linux age-based; non-Linux dead-only) - Pager: add `[ui].combine_queued_prompts` to batch queued follow-ups - Shell: stop overwriting user skills - Tools: read markdown in `skills/` directories untruncated - `/usage` shows per-session token and dollar usage in the TUI - Security: prompt on environment-dumping `ps` variants - Security: always-safe `kubectl` no longer runs arbitrary kubeconfig credential plugins without permission - Tools: make scheduler deletion durable - Shell: add relocation storage primitives - Shell: give side model calls their own conversation ids - Fix five workflow-runtime bugs (budget, pause, cancel, reconnect) - Security: peel `env -S` / `--split-string` operands in the Bash permission gate (managed deny/ask) - Pager: expose doctor in the TUI - Security: block unauthorized RCE via abused safe commands - Pager idle watcher cue: "1 subagent still running" instead of "watching · 1 subagent" - Security: block `rg --pre` arbitrary code execution in auto-mode - Voice: diagnose silent-mic failures (macOS permission) and add doctor/terminal-setup Voice section - App builder deployer: `allow_forking` and `show_built_with_grok` - Pager: stop stacking duplicate "Worked for" markers on parked turns - Shell: support `max` as a distinct reasoning effort tier - Tools: serialize background `/loop` fires on the whole work unit - Shell: add working-directory relocation state primitives - Proto: `ClientToolResult` and `ChatConfig` client-side tools - Shell: model providers - Chat: select App Builder product on the Build path - Shell: attach author identity to feedback when the deployment opts in - Doctor: fix for SSH wrap setup - Workflow authoring skills: create-workflow and import-claude-workflow docs - Add read-only grok doctor - Sandbox: apply Landlock without a controlling TTY - Pager: recover image paste over grok wrap on headless remotes - Pager: make actions screen-mode aware - Shell: resume sessions when the working directory moves - Pager: centralize terminal diagnostics - Workspace: gate inline shell file access - Pager: centralize terminal probes - Pager: edit minimal prompts in an external editor - Pager: standardize backgrounding on Ctrl+B - Shell: recap rides the parent turn's prompt cache - Tools: add scheduler lifecycle version clock Source-Revision: 0f4d7c91b8b2b408333f6de1e8a76cb8eaa71899
This commit is contained in:
parent
a881e6703f
commit
3af4d5d398
556 changed files with 56609 additions and 21892 deletions
|
|
@ -532,6 +532,10 @@ pub struct TodoSummary {
|
|||
/// handled by the consumer (e.g. `xai-grok-shell`), which has access to
|
||||
/// memory backends and other shell-specific dependencies.
|
||||
pub struct CompactionStateContext {
|
||||
/// Monotonic cwd generation; zero preserves the legacy compaction shape.
|
||||
pub cwd_generation: u64,
|
||||
/// Project instructions resolved for the latest destination cwd.
|
||||
pub destination_project_instructions: Option<String>,
|
||||
/// Messages since the last **real** user turn (assistant + omitted tool
|
||||
/// results). Synthetic user injections (system reminders) do not reset
|
||||
/// the boundary, preventing orphaned ToolResults in the compacted output.
|
||||
|
|
@ -555,6 +559,8 @@ pub struct CompactionStateContext {
|
|||
/// [`CompactionStateContext::build`].
|
||||
#[derive(Default)]
|
||||
pub struct CompactionInputs {
|
||||
pub cwd_generation: u64,
|
||||
pub destination_project_instructions: Option<String>,
|
||||
pub running_tasks: Vec<BackgroundTaskSummary>,
|
||||
pub running_subagents: Vec<RunningSubagentSummary>,
|
||||
pub agent_edited_paths: BTreeSet<String>,
|
||||
|
|
@ -569,6 +575,8 @@ impl CompactionStateContext {
|
|||
/// compaction boundary.
|
||||
pub async fn build(conversation: &[ConversationItem], inputs: CompactionInputs) -> Self {
|
||||
Self {
|
||||
cwd_generation: inputs.cwd_generation,
|
||||
destination_project_instructions: inputs.destination_project_instructions,
|
||||
recent_messages: extract_messages_since_last_real_user(conversation),
|
||||
last_user_query: extract_last_real_user_query(conversation),
|
||||
agent_edited_paths: inputs.agent_edited_paths.into_iter().collect(),
|
||||
|
|
@ -602,6 +610,8 @@ impl CompactionStateContext {
|
|||
/// `recent_messages` so the model keeps verbatim tool context.
|
||||
pub fn for_compaction(&self) -> Self {
|
||||
Self {
|
||||
cwd_generation: self.cwd_generation,
|
||||
destination_project_instructions: self.destination_project_instructions.clone(),
|
||||
recent_messages: Vec::new(),
|
||||
last_user_query: self.last_user_query.clone(),
|
||||
agent_edited_paths: self.agent_edited_paths.clone(),
|
||||
|
|
@ -839,7 +849,15 @@ pub fn build_compacted_history(input: CompactedHistoryInput<'_>) -> Vec<Conversa
|
|||
input.system_message,
|
||||
ConversationItem::user_meta(input.user_message_prefix),
|
||||
];
|
||||
if let Some(ref reminder) = input.agents_md_reminder {
|
||||
let project_instructions = if input.state_context.cwd_generation == 0 {
|
||||
input.agents_md_reminder.as_ref()
|
||||
} else {
|
||||
input
|
||||
.state_context
|
||||
.destination_project_instructions
|
||||
.as_ref()
|
||||
};
|
||||
if let Some(reminder) = project_instructions {
|
||||
compacted.push(ConversationItem::project_instructions(reminder.clone()));
|
||||
}
|
||||
if let Some(ref last_query) = input.state_context.last_user_query {
|
||||
|
|
@ -2852,21 +2870,94 @@ The user asked to read main.rs and lib.rs. main.rs prints hello world, lib.rs ha
|
|||
"system-reminder should list edited files"
|
||||
);
|
||||
}
|
||||
/// End-to-end test: build a compacted history with realistic file re-reads
|
||||
/// (line-numbered content matching extract_file_content_lines output),
|
||||
/// a truncated file, and a too-large file reference.
|
||||
///
|
||||
/// Verifies the exact string content of every message in the compacted
|
||||
/// history, including the plain-text "Called the read_file tool..." /
|
||||
/// AGENTS.md slot in the post-compaction conversation must be tagged
|
||||
/// `SyntheticReason::ProjectInstructions`, NOT `CompactionMeta`. This is
|
||||
/// the contract `spawn_session_actor`'s idempotence guard relies on when
|
||||
/// a session is resumed from a post-compaction `chat_history.jsonl`: it
|
||||
/// skips re-inserting AGENTS.md when it sees a tagged `User` item,
|
||||
/// preserving the KV-cache invariant.
|
||||
/// Generation zero ignores relocation-only fields and preserves legacy output.
|
||||
#[test]
|
||||
fn generation_zero_compaction_keeps_legacy_project_instructions() {
|
||||
let state_context = CompactionStateContext {
|
||||
cwd_generation: 0,
|
||||
destination_project_instructions: Some("destination rules".into()),
|
||||
recent_messages: vec![],
|
||||
last_user_query: None,
|
||||
agent_edited_paths: vec![],
|
||||
running_tasks: vec![],
|
||||
running_subagents: vec![],
|
||||
connected_mcp_servers: vec![],
|
||||
todos: vec![],
|
||||
};
|
||||
let compacted = build_compacted_history(CompactedHistoryInput {
|
||||
system_message: ConversationItem::system("sys"),
|
||||
user_message_prefix: "prefix".into(),
|
||||
agents_md_reminder: Some("startup rules".into()),
|
||||
state_context: &state_context,
|
||||
compaction_summary: "summary".into(),
|
||||
system_reminder: None,
|
||||
summary_before_recent: false,
|
||||
transcript_hint: None,
|
||||
summary_count: 1,
|
||||
});
|
||||
assert_eq!(compacted[2].text_content(), "startup rules");
|
||||
}
|
||||
#[test]
|
||||
fn relocated_compaction_uses_destination_project_instructions() {
|
||||
let state_context = CompactionStateContext {
|
||||
cwd_generation: 1,
|
||||
destination_project_instructions: Some("destination rules".into()),
|
||||
recent_messages: vec![],
|
||||
last_user_query: None,
|
||||
agent_edited_paths: vec![],
|
||||
running_tasks: vec![],
|
||||
running_subagents: vec![],
|
||||
connected_mcp_servers: vec![],
|
||||
todos: vec![],
|
||||
};
|
||||
let compacted = build_compacted_history(CompactedHistoryInput {
|
||||
system_message: ConversationItem::system("sys"),
|
||||
user_message_prefix: "prefix".into(),
|
||||
agents_md_reminder: Some("startup rules".into()),
|
||||
state_context: &state_context,
|
||||
compaction_summary: "summary".into(),
|
||||
system_reminder: None,
|
||||
summary_before_recent: false,
|
||||
transcript_hint: None,
|
||||
summary_count: 1,
|
||||
});
|
||||
assert_eq!(compacted[2].text_content(), "destination rules");
|
||||
}
|
||||
#[test]
|
||||
fn relocated_compaction_does_not_restore_source_instructions_when_destination_has_none() {
|
||||
let state_context = CompactionStateContext {
|
||||
cwd_generation: 1,
|
||||
destination_project_instructions: None,
|
||||
recent_messages: vec![],
|
||||
last_user_query: None,
|
||||
agent_edited_paths: vec![],
|
||||
running_tasks: vec![],
|
||||
running_subagents: vec![],
|
||||
connected_mcp_servers: vec![],
|
||||
todos: vec![],
|
||||
};
|
||||
let compacted = build_compacted_history(CompactedHistoryInput {
|
||||
system_message: ConversationItem::system("sys"),
|
||||
user_message_prefix: "prefix".into(),
|
||||
agents_md_reminder: Some("source rules".into()),
|
||||
state_context: &state_context,
|
||||
compaction_summary: "summary".into(),
|
||||
system_reminder: None,
|
||||
summary_before_recent: false,
|
||||
transcript_hint: None,
|
||||
summary_count: 1,
|
||||
});
|
||||
assert!(!compacted.iter().any(|item| {
|
||||
matches!(item, ConversationItem::User(user)
|
||||
if user.synthetic_reason == Some(SyntheticReason::ProjectInstructions))
|
||||
}));
|
||||
}
|
||||
/// The AGENTS.md slot must use the structural project-instructions tag.
|
||||
#[test]
|
||||
fn build_compacted_history_tags_agents_md_with_project_instructions() {
|
||||
let state_context = CompactionStateContext {
|
||||
cwd_generation: 0,
|
||||
destination_project_instructions: None,
|
||||
recent_messages: vec![],
|
||||
last_user_query: None,
|
||||
agent_edited_paths: vec![],
|
||||
|
|
@ -2908,6 +2999,8 @@ The user asked to read main.rs and lib.rs. main.rs prints hello world, lib.rs ha
|
|||
#[test]
|
||||
fn build_compacted_history_omits_agents_md_when_none() {
|
||||
let state_context = CompactionStateContext {
|
||||
cwd_generation: 0,
|
||||
destination_project_instructions: None,
|
||||
recent_messages: vec![],
|
||||
last_user_query: None,
|
||||
agent_edited_paths: vec![],
|
||||
|
|
|
|||
Loading…
Reference in a new issue