Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .repository-projection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"projection": "deixic-code",
"projectionSchemaVersion": 1,
"sourceRepository": "dx-corp/mono",
"sourceSha": "ba4af7b8ee1d610e55c13ddc1f7e2f797b77dd87",
"sourceSha": "0dda4b314d332ad6f95f189d10b066d1a080ee34",
"destinationRepository": "dx-corp/code",
"priorProjectedBase": "6d97910afbc6fecb2a1e96c284bb1d2b92a86b9f",
"priorProjectedBase": "8991ebcc446033952c75e0858f46245ab8b0580a",
"definitionDigest": "82936441c776e3e8edb5d215a75007ec9714a233f489d460075d79d5ef5ba32f",
"toolDigest": "c244d99199a7ae3eb8ff644a99462163c23b0bb6a83ef50af01efbdca0b81d04",
"contentDigest": "e2657de302d4b845da675e7d434f3446a33f1c68902dabe7bdc2c9462c9f24ac",
"contentDigest": "93b1fddc5de9161c81eb617fc50c86e6f9bb877a46f1a1206a46d8732b6b39f8",
"publicationEligible": true
}
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/dex-host-rs/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ mod tests {
Event::UserMessage {
turn: TurnId::new("t1"),
message_id: None,
model_binding: None,
principal: PrincipalId::new("alice"),
text: text.into(),
attachments: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions packages/dex-host-rs/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ mod tests {
dex_loop::Event::UserMessage {
turn: dex_loop::TurnId::new("t1"),
message_id: None,
model_binding: None,
principal: PrincipalId::new("alice"),
text: "read a.txt".into(),
attachments: Vec::new(),
Expand Down
2 changes: 2 additions & 0 deletions packages/dex-host-rs/src/turn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub async fn run_local_turn<M: Model>(
log.append(&[Event::UserMessage {
turn: request.turn,
message_id: None,
model_binding: None,
principal: request.principal.clone(),
text: request.text,
attachments: Vec::new(),
Expand Down Expand Up @@ -272,6 +273,7 @@ mod tests {
Event::UserMessage {
turn: TurnId::new("t1"),
message_id: None,
model_binding: None,
principal: principal.clone(),
text: "Work unattended".into(),
attachments: vec![],
Expand Down
1 change: 1 addition & 0 deletions packages/dex-host-rs/tests/turn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ async fn read_then_write_then_done_with_no_approval() {
log.append(&[Event::UserMessage {
turn: TurnId::new("t1"),
message_id: None,
model_binding: None,
principal: alice(),
text: "read notes.txt, then write out.txt".into(),
attachments: Vec::new(),
Expand Down
29 changes: 29 additions & 0 deletions packages/local-host-rs/src/tools/bash/shield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,37 @@ mod tests {
);
}

/// The process environment without the repository, index and config
/// overrides `check` refuses, restored on drop. A CI runner or sandbox may
/// inject `GIT_CONFIG_*` (for example proxy settings); the end-to-end bash
/// test reads the real process environment, so it must not inherit them.
struct AmbientGitOverrides(Vec<(String, std::ffi::OsString)>);

impl AmbientGitOverrides {
fn remove() -> Self {
let removed: Vec<_> = std::env::vars_os()
.filter_map(|(name, value)| Some((name.into_string().ok()?, value)))
.filter(|(name, _)| name.starts_with("GIT_"))
.collect();
for (name, _) in &removed {
std::env::remove_var(name);
}
Self(removed)
}
}

impl Drop for AmbientGitOverrides {
fn drop(&mut self) {
for (name, value) in self.0.drain(..) {
std::env::set_var(name, value);
}
}
}

#[tokio::test]
async fn bash_tool_blocks_before_creating_the_commit() {
let _lock = crate::config::test_process_env_lock_async().await;
let _ambient = AmbientGitOverrides::remove();
let root = repo();
stage(root.path(), &token());
let tool = super::super::BashTool::new(root.path().display().to_string());
Expand Down
73 changes: 72 additions & 1 deletion packages/local-host-rs/src/tools/extract_document/ooxml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ fn local_name(name: &str) -> &str {
name.rsplit(':').next().unwrap_or(name)
}

fn tag_end(src: &str) -> Option<usize> {
let mut quote = None;
for (index, byte) in src.bytes().enumerate() {
match quote {
Some(delimiter) if byte == delimiter => quote = None,
Some(_) => {}
None if matches!(byte, b'\'' | b'"') => quote = Some(byte),
None if byte == b'>' => return Some(index),
None => {}
}
}
None
}

impl<'a> Iterator for XmlEvents<'a> {
type Item = XmlEvent<'a>;

Expand All @@ -91,7 +105,7 @@ impl<'a> Iterator for XmlEvents<'a> {
self.pos += 9 + len + 3.min(body.len() - len);
return Some(XmlEvent::Text(&body[..len]));
}
let Some(close) = rest.find('>') else {
let Some(close) = tag_end(rest) else {
self.pos = self.src.len();
return None;
};
Expand Down Expand Up @@ -1430,6 +1444,63 @@ pub(super) mod tests {
assert_eq!(column_index("12"), None);
}

#[test]
fn xml_tag_end_preserves_quoted_angles_and_following_attributes() {
for xml in [
r#"<sheet name="Q1 > 2026" r:id="rId2"/>"#,
r"<sheet name='Q1 > 2026' r:id='rId2'/>",
r#"<sheet name="Q1 &gt; 2026" r:id="rId2"/>"#,
] {
let mut events = xml_events(xml);
let Some(XmlEvent::Start {
name,
attrs,
self_closing,
}) = events.next()
else {
panic!("sheet start expected: {xml}");
};
assert_eq!(name, "sheet");
assert!(self_closing);
assert_eq!(attr(attrs, "name").as_deref(), Some("Q1 > 2026"));
assert_eq!(attr(attrs, "r:id").as_deref(), Some("rId2"));
assert!(events.next().is_none());
}
assert!(tag_end(r#"<sheet name="unterminated >"#).is_none());
}

#[test]
fn xlsx_preserves_quoted_angles_sheet_binding_order_and_hidden_state() {
let bytes = build_zip(&[
(
"xl/workbook.xml",
r#"<workbook xmlns:r="urn:test"><sheets><sheet name="Q1 > 2026" sheetId="1" state="hidden" r:id="rId2"/><sheet name="Overview" sheetId="2" r:id="rId1"/></sheets></workbook>"#,
),
(
"xl/_rels/workbook.xml.rels",
r#"<Relationships><Relationship Id="rId1" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Target="worksheets/sheet2.xml"/></Relationships>"#,
),
(
"xl/worksheets/sheet1.xml",
r#"<worksheet><sheetData><row><c r="A1"><v>111</v></c></row></sheetData></worksheet>"#,
),
(
"xl/worksheets/sheet2.xml",
r#"<worksheet><sheetData><row><c r="A1"><v>222</v></c></row></sheetData></worksheet>"#,
),
]);
let extracted = xlsx_to_markdown(&bytes).expect("workbook extraction");
let (first, second) = extracted
.text
.split_once("## Sheet: Overview")
.expect("second sheet");
assert!(first.starts_with("## Sheet: Q1 > 2026 (hidden)"));
assert!(first.contains("222"));
assert!(!first.contains("111"));
assert!(second.contains("111"));
assert_eq!(extracted.sections.expect("sheet accounting").count, 2);
}

#[test]
fn decode_entities_handles_numeric_and_double_escaped_references() {
assert_eq!(decode_entities("a &amp;lt; b"), "a &lt; b");
Expand Down
2 changes: 2 additions & 0 deletions packages/local-host-rs/src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub mod orb_delegation;
pub(crate) mod orb_execution;
pub mod process_registry;
pub(crate) mod process_utils;
#[cfg(unix)]
pub use process_utils::{ProcessGroupGuard, set_new_process_group};
mod registry;
mod shell_env;
mod status;
Expand Down
Loading
Loading