use saya_agent::ToolError;
use super::workspace_edit::WORKSPACE_EDIT_MAX_FILE_BYTES;
use super::workspace_edit_anchor::hex_digest;
pub(super) fn splice_text(current: &str, range: std::ops::Range<usize>, new_text: &str) -> String {
let mut resulting =
String::with_capacity(current.len() - (range.end - range.start) + new_text.len());
resulting.push_str(¤t[..range.start]);
resulting.push_str(new_text);
resulting.push_str(¤t[range.end..]);
resulting
}
pub(super) fn commit_splice(
workspace: &saya_harness::workspace::Workspace,
rel: &str,
range: std::ops::Range<u64>,
expected_len: u64,
bytes: &[u8],
) -> Result<(), ToolError> {
workspace
.patch_range(rel, range, expected_len, bytes)
.map_err(|error| {
match error {
saya_harness::HarnessError::LengthMismatch { current, .. } => {
let (size, digest) = match workspace.read(rel, WORKSPACE_EDIT_MAX_FILE_BYTES) {
Ok(file) => (file.size, hex_digest(&file.bytes)),
Err(_) => (current, hex_digest(&[])),
};
ToolError::WorkspaceAppendOffset {
path: rel.to_string(),
expected_offset: expected_len,
current_size: size,
current_digest: digest,
}
}
other => ToolError::WorkspaceEdit(other.to_string()),
}
})
}
pub(super) fn workspace_size(
workspace: &saya_harness::workspace::Workspace,
rel: &str,
) -> Result<u64, ToolError> {
let probe = workspace
.read(rel, 0)
.map_err(|error| ToolError::WorkspaceEdit(error.to_string()))?;
Ok(probe.size)
}
pub(super) fn workspace_probe(
workspace: &saya_harness::workspace::Workspace,
rel: &str,
) -> Result<Option<u64>, ToolError> {
match workspace.read(rel, 0) {
Ok(probe) => Ok(Some(probe.size)),
Err(error) => {
if error.is_not_found() {
Ok(None)
} else {
Err(ToolError::WorkspaceEdit(error.to_string()))
}
}
}
}
pub(super) fn write_new(
workspace: &saya_harness::workspace::Workspace,
rel: &str,
bytes: &[u8],
) -> Result<(), ToolError> {
workspace
.write(rel, bytes)
.map_err(|error| ToolError::WorkspaceEdit(error.to_string()))
}