first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
+63 -18
View File
@@ -1,27 +1,24 @@
//! Manages how we serialize blocklist AI data for persistence.
#![cfg_attr(not(feature = "local_fs"), allow(dead_code))]
use std::{collections::HashMap, sync::Arc};
use uuid::Uuid;
use std::collections::HashMap;
use std::sync::Arc;
use anyhow::anyhow;
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use crate::{
ai::{
agent::{
conversation::AIConversationId, AIAgentActionType, AIAgentAttachment, AIAgentContext,
AIAgentExchangeId, AIAgentInput, AIAgentPtyWriteMode, AskUserQuestionItem,
FileLocations, PassiveSuggestionResultType, ReadFilesRequest,
RequestComputerUseRequest, SearchCodebaseRequest, UseComputerRequest, UserQueryMode,
},
llms::LLMId,
},
terminal::model::block::{BlockId, SerializedBlock},
};
use serde::{Deserialize, Deserializer, Serialize};
use uuid::Uuid;
use super::AIQueryHistoryOutputStatus;
use crate::ai::agent::conversation::AIConversationId;
use crate::ai::agent::{
AIAgentActionType, AIAgentAttachment, AIAgentContext, AIAgentExchangeId, AIAgentInput,
AIAgentPtyWriteMode, AskUserQuestionItem, FileLocations, PassiveSuggestionResultType,
ReadFilesRequest, RequestComputerUseRequest, SearchCodebaseRequest, UseComputerRequest,
UserQueryMode,
};
use crate::ai::llms::LLMId;
use crate::terminal::model::block::{BlockId, SerializedBlock};
/// Data we persist for each [`AIAgentExchange`] for use in history. Does not contain output data.
#[derive(Debug, Deserialize, Clone)]
pub struct PersistedAIInput {
@@ -93,7 +90,8 @@ impl TryFrom<&AIAgentInput> for PersistedAIInputType {
| AIAgentInput::InvokeSkill { .. }
| AIAgentInput::StartFromAmbientRunPrompt { .. }
| AIAgentInput::MessagesReceivedFromAgents { .. }
| AIAgentInput::EventsFromAgents { .. } => Err(anyhow::anyhow!(
| AIAgentInput::EventsFromAgents { .. }
| AIAgentInput::OrchestrationConfigUpdate { .. } => Err(anyhow::anyhow!(
"This input type is not persisted. Only Query inputs are persisted for up-arrow history."
)),
}
@@ -200,7 +198,8 @@ pub(crate) enum PersistedAIAgentActionType {
InitProject,
UseComputer {
action_summary: String,
actions: Vec<computer_use::Action>,
#[serde(deserialize_with = "deserialize_targeted_actions")]
actions: Vec<computer_use::TargetedAction>,
screenshot_params: Option<computer_use::ScreenshotParams>,
},
RequestComputerUse {
@@ -219,6 +218,45 @@ pub(crate) enum PersistedAIAgentActionType {
NotPersisted,
}
/// Deserializes the persisted `UseComputer` actions, accepting both the current `{ action, target }`
/// shape and the legacy bare-`Action` shape.
///
/// Conversations persisted before `actions` became `Vec<TargetedAction>` stored each element as a
/// bare [`computer_use::Action`]; those decode with the target defaulting to `Target::Screen`. New
/// data round-trips unchanged, and serialization still emits the `{ action, target }` shape via the
/// derived `Serialize` impl.
fn deserialize_targeted_actions<'de, D>(
deserializer: D,
) -> Result<Vec<computer_use::TargetedAction>, D::Error>
where
D: Deserializer<'de>,
{
// Accepts either the new `{ action, target }` wrapper (with `target` optional) or a bare legacy
// `Action` value. `Action`'s variant names never collide with the `action`/`target` keys, so
// the untagged match is unambiguous.
#[derive(Deserialize)]
#[serde(untagged)]
enum TargetedActionCompat {
Targeted {
action: computer_use::Action,
#[serde(default)]
target: computer_use::Target,
},
Bare(computer_use::Action),
}
let actions = Vec::<TargetedActionCompat>::deserialize(deserializer)?;
Ok(actions
.into_iter()
.map(|compat| match compat {
TargetedActionCompat::Targeted { action, target } => {
computer_use::TargetedAction { action, target }
}
TargetedActionCompat::Bare(action) => computer_use::TargetedAction::screen(action),
})
.collect())
}
impl From<&AIAgentActionType> for PersistedAIAgentActionType {
fn from(value: &AIAgentActionType) -> Self {
match value {
@@ -319,6 +357,13 @@ impl From<&AIAgentActionType> for PersistedAIAgentActionType {
},
AIAgentActionType::StartAgent { .. } => Self::NotPersisted,
AIAgentActionType::SendMessageToAgent { .. } => Self::NotPersisted,
// Orchestrate is rendered from the in-history tool call message;
// there is no per-action state we need to persist locally.
AIAgentActionType::RunAgents(_) => Self::NotPersisted,
// The wait is dropped on restart; the unresolved tool call
// stays in the transcript as an orphan until the next
// outbound request triggers the server's supersede.
AIAgentActionType::WaitForEvents { .. } => Self::NotPersisted,
}
}
}