proto becomes bxcore, the one shared crate (M5b task 00)
Done the way the owner asked and the spike mapped: the crate and the manifests renamed, then what the build reported fixed. Layers: 138 "proto unresolved" errors across 169 files; cargo fmt reordering imports; six fixture paths built as strings in brokerd's and bxctl's tests, which the compiler cannot see, and comments naming crates/proto/; the crate-dependency check and its self-test. One more the spike did not reach: a `\nproto =` key inside a printf format in the self-test, which a word-boundary replacement skips because `n` and `p` are both word characters. make gate: gate: ok, 944 tests; no new entry in /tmp. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ publish.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
proto.workspace = true
|
||||
bxcore.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
toml.workspace = true
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
||||
use crate::config::Config;
|
||||
use crate::llama::{ChatMessage, ToolSchema};
|
||||
use crate::tools::Registry;
|
||||
use proto::{Hash32, LogRecord, sha256};
|
||||
use bxcore::{Hash32, LogRecord, sha256};
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::path::PathBuf;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::tools::{Pending, ToolPort};
|
||||
use proto::{
|
||||
use bxcore::{
|
||||
Envelope, FrameError, Message, PROTOCOL_VERSION, Timestamp, ToolRequest, ToolResponse,
|
||||
read_frame, write_frame,
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::memory::MemorySource;
|
||||
use crate::session::{Session, SessionError};
|
||||
use crate::tools::{Registry, ToolPort};
|
||||
use crate::turn::{Runtime, TurnError, run_turn};
|
||||
use proto::{
|
||||
use bxcore::{
|
||||
Envelope, ErrorCode, FrameError, Message, PROTOCOL_VERSION, SessionId, TurnDone, WireError,
|
||||
read_frame, write_frame,
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ pub struct Slots {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Expect {
|
||||
pub template_sha256: proto::Hash32,
|
||||
pub template_sha256: bxcore::Hash32,
|
||||
pub n_ctx: u64,
|
||||
pub slots: u32,
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ impl Assembler {
|
||||
));
|
||||
}
|
||||
};
|
||||
tool_calls.push(proto::ToolCall {
|
||||
tool_calls.push(bxcore::ToolCall {
|
||||
id,
|
||||
name,
|
||||
arguments: call.arguments,
|
||||
|
||||
@@ -18,7 +18,7 @@ pub enum ChatMessage {
|
||||
Assistant {
|
||||
content: Option<String>,
|
||||
reasoning_content: Option<String>,
|
||||
tool_calls: Vec<proto::ToolCall>,
|
||||
tool_calls: Vec<bxcore::ToolCall>,
|
||||
},
|
||||
Tool {
|
||||
tool_call_id: String,
|
||||
@@ -93,7 +93,7 @@ pub struct Completion {
|
||||
pub id: String,
|
||||
pub content: Option<String>,
|
||||
pub reasoning_content: Option<String>,
|
||||
pub tool_calls: Vec<proto::ToolCall>,
|
||||
pub tool_calls: Vec<bxcore::ToolCall>,
|
||||
pub finish_reason: FinishReason,
|
||||
pub timings: Timings,
|
||||
pub reasoning_tokens: u64,
|
||||
|
||||
@@ -73,7 +73,7 @@ fn serialize_message(message: &ChatMessage) -> Result<serde_json::Value, serde_j
|
||||
}
|
||||
}
|
||||
|
||||
fn serialized_call(call: &proto::ToolCall) -> SerializedToolCall {
|
||||
fn serialized_call(call: &bxcore::ToolCall) -> SerializedToolCall {
|
||||
SerializedToolCall {
|
||||
id: call.id.clone(),
|
||||
kind: "function",
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use proto::{
|
||||
use bxcore::{
|
||||
Empty, Envelope, Message, PROTOCOL_VERSION, SessionId, SessionUpdated, read_frame, write_frame,
|
||||
};
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ fn server_matches(client: &Client) -> Result<(), SelfTestError> {
|
||||
let expect = &client.config().expect;
|
||||
|
||||
let expected = expect.template_sha256;
|
||||
let got = proto::sha256(props.chat_template.as_bytes()).map_err(|_| SelfTestError::Hash)?;
|
||||
let got = bxcore::sha256(props.chat_template.as_bytes()).map_err(|_| SelfTestError::Hash)?;
|
||||
if expected != got {
|
||||
return Err(SelfTestError::Mismatch {
|
||||
what: "chat template sha256",
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::baseline::{Baseline, BaselineError};
|
||||
use proto::{CallId, Epoch, LogRecord, SessionId, Timestamp};
|
||||
use bxcore::{CallId, Epoch, LogRecord, SessionId, Timestamp};
|
||||
|
||||
/// Creating, opening, appending and resuming a session, and the errors each can raise.
|
||||
#[derive(Debug)]
|
||||
@@ -193,7 +193,7 @@ impl Session {
|
||||
id
|
||||
}
|
||||
|
||||
pub fn last_usage(&self) -> Option<proto::Usage> {
|
||||
pub fn last_usage(&self) -> Option<bxcore::Usage> {
|
||||
for record in self.records.iter().rev() {
|
||||
if let LogRecord::Usage {
|
||||
cache_n,
|
||||
@@ -204,7 +204,7 @@ impl Session {
|
||||
..
|
||||
} = record
|
||||
{
|
||||
return Some(proto::Usage {
|
||||
return Some(bxcore::Usage {
|
||||
cache_n: *cache_n,
|
||||
prompt_n: *prompt_n,
|
||||
predicted_n: *predicted_n,
|
||||
|
||||
+27
-25
@@ -11,16 +11,16 @@ pub trait ToolPort: Send + Sync {
|
||||
/// for the owner, the port calls `on_pending` once and goes on waiting.
|
||||
fn call(
|
||||
&self,
|
||||
request: &proto::ToolRequest,
|
||||
request: &bxcore::ToolRequest,
|
||||
on_pending: &mut dyn FnMut(&Pending),
|
||||
) -> proto::ToolResponse;
|
||||
) -> bxcore::ToolResponse;
|
||||
}
|
||||
|
||||
/// One waiting call, as the broker reports it.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Pending {
|
||||
pub approval: u64,
|
||||
pub expires: proto::Timestamp,
|
||||
pub expires: bxcore::Timestamp,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -281,7 +281,7 @@ pub fn dispatch(registry: &Registry, name: &str, arguments: &str) -> Dispatch {
|
||||
return dispatch_call_tool(registry, arguments);
|
||||
}
|
||||
if name == CLOCK {
|
||||
return Dispatch::Local(proto::Timestamp::now().to_rfc3339());
|
||||
return Dispatch::Local(bxcore::Timestamp::now().to_rfc3339());
|
||||
}
|
||||
Dispatch::Port {
|
||||
tool: name.to_string(),
|
||||
@@ -351,33 +351,35 @@ pub fn cap_result(text: &str, cap: usize) -> (String, bool) {
|
||||
}
|
||||
|
||||
/// The one fixed sentence a denial reaches the model as, named by its reason.
|
||||
pub fn denial_text(reason: proto::DenyReason) -> &'static str {
|
||||
pub fn denial_text(reason: bxcore::DenyReason) -> &'static str {
|
||||
match reason {
|
||||
proto::DenyReason::NoGrant => "Denied: no grant allows this call.",
|
||||
proto::DenyReason::GrantExpired => "Denied: the grant for this call has expired.",
|
||||
proto::DenyReason::TaintTooHigh => {
|
||||
bxcore::DenyReason::NoGrant => "Denied: no grant allows this call.",
|
||||
bxcore::DenyReason::GrantExpired => "Denied: the grant for this call has expired.",
|
||||
bxcore::DenyReason::TaintTooHigh => {
|
||||
"Denied: this session has seen data too sensitive for this call."
|
||||
}
|
||||
proto::DenyReason::DeniedByGrant => "Denied: a grant forbids this call.",
|
||||
proto::DenyReason::ApprovalRefused => "Denied: the owner refused this call.",
|
||||
proto::DenyReason::ApprovalExpired => {
|
||||
bxcore::DenyReason::DeniedByGrant => "Denied: a grant forbids this call.",
|
||||
bxcore::DenyReason::ApprovalRefused => "Denied: the owner refused this call.",
|
||||
bxcore::DenyReason::ApprovalExpired => {
|
||||
"Denied: the approval request expired without an answer."
|
||||
}
|
||||
proto::DenyReason::InvalidArguments => "Denied: the arguments are not valid for this tool.",
|
||||
proto::DenyReason::GrantsInvalid => {
|
||||
bxcore::DenyReason::InvalidArguments => {
|
||||
"Denied: the arguments are not valid for this tool."
|
||||
}
|
||||
bxcore::DenyReason::GrantsInvalid => {
|
||||
"Denied: the grant files have an error; the owner has been told."
|
||||
}
|
||||
proto::DenyReason::AuditUnavailable => {
|
||||
bxcore::DenyReason::AuditUnavailable => {
|
||||
"Denied: the audit log cannot be written; the owner has been told."
|
||||
}
|
||||
proto::DenyReason::StateUnreadable => {
|
||||
bxcore::DenyReason::StateUnreadable => {
|
||||
"Denied: this session's broker state is damaged; the owner has been told."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FakeTools {
|
||||
calls: Mutex<Vec<proto::ToolRequest>>,
|
||||
calls: Mutex<Vec<bxcore::ToolRequest>>,
|
||||
}
|
||||
|
||||
impl Default for FakeTools {
|
||||
@@ -393,7 +395,7 @@ impl FakeTools {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calls(&self) -> Vec<proto::ToolRequest> {
|
||||
pub fn calls(&self) -> Vec<bxcore::ToolRequest> {
|
||||
self.calls.lock().unwrap_or_else(|p| p.into_inner()).clone()
|
||||
}
|
||||
}
|
||||
@@ -401,9 +403,9 @@ impl FakeTools {
|
||||
impl ToolPort for FakeTools {
|
||||
fn call(
|
||||
&self,
|
||||
request: &proto::ToolRequest,
|
||||
request: &bxcore::ToolRequest,
|
||||
_on_pending: &mut dyn FnMut(&Pending),
|
||||
) -> proto::ToolResponse {
|
||||
) -> bxcore::ToolResponse {
|
||||
self.calls
|
||||
.lock()
|
||||
.unwrap_or_else(|p| p.into_inner())
|
||||
@@ -413,23 +415,23 @@ impl ToolPort for FakeTools {
|
||||
"echo" => match serde_json::from_str::<serde_json::Value>(&request.arguments) {
|
||||
Ok(serde_json::Value::Object(obj)) => {
|
||||
match obj.get("text").and_then(|v| v.as_str()) {
|
||||
Some(text) => proto::ToolResponse::Result {
|
||||
Some(text) => bxcore::ToolResponse::Result {
|
||||
content: text.to_string(),
|
||||
class: proto::DataClass::Public,
|
||||
class: bxcore::DataClass::Public,
|
||||
untrusted: false,
|
||||
truncated: false,
|
||||
},
|
||||
None => proto::ToolResponse::Failed {
|
||||
None => bxcore::ToolResponse::Failed {
|
||||
message: "missing text argument".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => proto::ToolResponse::Failed {
|
||||
_ => bxcore::ToolResponse::Failed {
|
||||
message: "arguments must be a JSON object".to_string(),
|
||||
},
|
||||
},
|
||||
_ => proto::ToolResponse::Denied {
|
||||
reason: proto::DenyReason::NoGrant,
|
||||
_ => bxcore::ToolResponse::Denied {
|
||||
reason: bxcore::DenyReason::NoGrant,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ use crate::llama::info::{CacheOutcome, cache_outcome};
|
||||
use crate::llama::{ChatEvent, ChatRequest, Client, InferError};
|
||||
use crate::session::{Session, SessionError};
|
||||
use crate::tools::{Registry, ToolPort, cap_result, denial_text, dispatch};
|
||||
use proto::{CallId, DataClass, LogRecord, Timestamp, ToolRequest, ToolResponse, TurnEvent, Usage};
|
||||
use bxcore::{
|
||||
CallId, DataClass, LogRecord, Timestamp, ToolRequest, ToolResponse, TurnEvent, Usage,
|
||||
};
|
||||
|
||||
/// What one turn can fail with, beyond the inference server.
|
||||
#[derive(Debug)]
|
||||
@@ -258,7 +260,7 @@ pub fn run_turn(
|
||||
fn run_call(
|
||||
rt: &Runtime<'_>,
|
||||
session: &Session,
|
||||
call: &proto::ToolCall,
|
||||
call: &bxcore::ToolCall,
|
||||
call_id: CallId,
|
||||
on_event: &mut dyn FnMut(&TurnEvent),
|
||||
) -> (String, DataClass, bool) {
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
mod support;
|
||||
|
||||
use bxcore::{CallId, DataClass, Epoch, Hash32, LogRecord, SessionId, Timestamp, ToolCall};
|
||||
use loopd::baseline::{Baseline, messages};
|
||||
use loopd::llama::ChatMessage;
|
||||
use loopd::tools::Registry;
|
||||
use proto::{CallId, DataClass, Epoch, Hash32, LogRecord, SessionId, Timestamp, ToolCall};
|
||||
use std::path::Path;
|
||||
use support::Home;
|
||||
|
||||
@@ -67,7 +67,7 @@ fn json_round_trip_and_hash() {
|
||||
assert_eq!(Baseline::from_json(&text).unwrap(), b);
|
||||
assert_eq!(
|
||||
b.hash().unwrap(),
|
||||
proto::sha256(text.as_bytes()).unwrap(),
|
||||
bxcore::sha256(text.as_bytes()).unwrap(),
|
||||
"the hash is of the JSON as written"
|
||||
);
|
||||
assert_ne!(b.hash().unwrap(), Hash32::ZERO);
|
||||
|
||||
@@ -9,12 +9,12 @@ use std::os::unix::net::UnixListener;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::{
|
||||
DenyReason, Message, PROTOCOL_VERSION, Timestamp, ToolResponse, read_frame, write_frame,
|
||||
};
|
||||
use fake::{assert_unavailable, broker, call, frame, in_ms, request, result, send, socket_path};
|
||||
use loopd::broker_port::{BrokerPort, NoBroker, POINTER, TOO_LARGE};
|
||||
use loopd::tools::{Pending, ToolPort};
|
||||
use proto::{
|
||||
DenyReason, Message, PROTOCOL_VERSION, Timestamp, ToolResponse, read_frame, write_frame,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn a_result_comes_back_as_it_was_sent() {
|
||||
@@ -259,7 +259,7 @@ fn a_request_too_large_for_a_frame_is_its_own_failure() {
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let _listener = UnixListener::bind(&path).unwrap();
|
||||
let mut big = request();
|
||||
big.arguments = format!(r#"{{"path":"/{}"}}"#, "a".repeat(proto::MAX_FRAME));
|
||||
big.arguments = format!(r#"{{"path":"/{}"}}"#, "a".repeat(bxcore::MAX_FRAME));
|
||||
let got = call(path.to_path_buf(), 1_000, &big);
|
||||
assert_eq!(
|
||||
got.response,
|
||||
|
||||
@@ -9,8 +9,10 @@ use std::os::unix::net::UnixStream;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::{
|
||||
Envelope, ErrorCode, Message, PROTOCOL_VERSION, ToolResponse, WireError, write_frame,
|
||||
};
|
||||
use fake::{assert_unavailable, broker, call, frame, in_ms, request, result, send};
|
||||
use proto::{Envelope, ErrorCode, Message, PROTOCOL_VERSION, ToolResponse, WireError, write_frame};
|
||||
|
||||
#[test]
|
||||
fn frames_that_break_the_protocol_are_unavailable() {
|
||||
|
||||
@@ -9,10 +9,10 @@ use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use bxcore::{Timestamp, ToolResponse};
|
||||
use fake::{broker, request, send};
|
||||
use loopd::broker_port::{BrokerPort, MAX_PENDING_WAIT, UNAVAILABLE};
|
||||
use loopd::tools::ToolPort;
|
||||
use proto::{Timestamp, ToolResponse};
|
||||
|
||||
#[test]
|
||||
fn the_default_cap_is_a_day() {
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
mod support;
|
||||
|
||||
use bxcore::{
|
||||
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, TurnEvent, read_frame,
|
||||
write_frame,
|
||||
};
|
||||
use loopd::channel::{Context, serve};
|
||||
use loopd::llama::Client;
|
||||
use loopd::memory::NoMemory;
|
||||
use loopd::tools::Registry;
|
||||
use proto::{
|
||||
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, TurnEvent, read_frame,
|
||||
write_frame,
|
||||
};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
@@ -30,7 +30,7 @@ struct Loopd {
|
||||
home: Home,
|
||||
}
|
||||
|
||||
fn start(replies: Vec<proto::ToolResponse>) -> Loopd {
|
||||
fn start(replies: Vec<bxcore::ToolResponse>) -> Loopd {
|
||||
let home = Home::new();
|
||||
let server = FakeServer::start();
|
||||
let cfg = home.config(&server.socket);
|
||||
@@ -177,7 +177,7 @@ fn tool_calls_are_reported_by_name_only() {
|
||||
tool_events[1],
|
||||
&TurnEvent::ToolResult {
|
||||
name: "read_file".to_string(),
|
||||
class: proto::DataClass::Private,
|
||||
class: bxcore::DataClass::Private,
|
||||
truncated: false
|
||||
}
|
||||
);
|
||||
@@ -292,7 +292,7 @@ fn bad_frames_get_an_error_and_a_close() {
|
||||
stream
|
||||
.set_read_timeout(Some(Duration::from_secs(5)))
|
||||
.unwrap();
|
||||
let msg = Message::Error(proto::WireError {
|
||||
let msg = Message::Error(bxcore::WireError {
|
||||
code: ErrorCode::Internal,
|
||||
detail: String::new(),
|
||||
});
|
||||
@@ -311,7 +311,7 @@ fn bad_frames_get_an_error_and_a_close() {
|
||||
assert!(
|
||||
matches!(
|
||||
reply.msg,
|
||||
Message::Error(proto::WireError {
|
||||
Message::Error(bxcore::WireError {
|
||||
code: ErrorCode::BadMessage,
|
||||
..
|
||||
})
|
||||
@@ -319,7 +319,7 @@ fn bad_frames_get_an_error_and_a_close() {
|
||||
"{reply:?}"
|
||||
);
|
||||
assert!(
|
||||
matches!(read_frame(&mut stream), Err(proto::FrameError::Closed)),
|
||||
matches!(read_frame(&mut stream), Err(bxcore::FrameError::Closed)),
|
||||
"then the connection is closed"
|
||||
);
|
||||
|
||||
@@ -333,7 +333,7 @@ fn bad_frames_get_an_error_and_a_close() {
|
||||
assert!(
|
||||
matches!(
|
||||
reply.msg,
|
||||
Message::Error(proto::WireError {
|
||||
Message::Error(bxcore::WireError {
|
||||
code: ErrorCode::BadMessage,
|
||||
..
|
||||
})
|
||||
@@ -365,7 +365,7 @@ fn bad_frames_get_an_error_and_a_close() {
|
||||
assert!(
|
||||
matches!(
|
||||
reply.msg,
|
||||
Message::Error(proto::WireError {
|
||||
Message::Error(bxcore::WireError {
|
||||
code: ErrorCode::BadVersion,
|
||||
..
|
||||
})
|
||||
|
||||
@@ -339,7 +339,7 @@ impl Served {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn records(&self, session: &str) -> Vec<proto::LogRecord> {
|
||||
fn records(&self, session: &str) -> Vec<bxcore::LogRecord> {
|
||||
let text =
|
||||
std::fs::read_to_string(self.home.join("sessions").join(session).join("0.jsonl"))
|
||||
.unwrap();
|
||||
@@ -441,7 +441,7 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
|
||||
let tool_names: Vec<String> = records
|
||||
.iter()
|
||||
.filter_map(|r| match r {
|
||||
proto::LogRecord::Assistant { tool_calls, .. } => Some(
|
||||
bxcore::LogRecord::Assistant { tool_calls, .. } => Some(
|
||||
tool_calls
|
||||
.iter()
|
||||
.map(|c| c.name.clone())
|
||||
@@ -459,16 +459,16 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
|
||||
);
|
||||
let usages = records
|
||||
.iter()
|
||||
.filter(|r| matches!(r, proto::LogRecord::Usage { .. }))
|
||||
.filter(|r| matches!(r, bxcore::LogRecord::Usage { .. }))
|
||||
.count();
|
||||
let assistants = records
|
||||
.iter()
|
||||
.filter(|r| matches!(r, proto::LogRecord::Assistant { .. }))
|
||||
.filter(|r| matches!(r, bxcore::LogRecord::Assistant { .. }))
|
||||
.count();
|
||||
assert_eq!(usages, assistants, "one usage record per completion");
|
||||
let losses: Vec<&proto::LogRecord> = records
|
||||
let losses: Vec<&bxcore::LogRecord> = records
|
||||
.iter()
|
||||
.filter(|r| matches!(r, proto::LogRecord::CacheLoss { .. }))
|
||||
.filter(|r| matches!(r, bxcore::LogRecord::CacheLoss { .. }))
|
||||
.collect();
|
||||
assert!(
|
||||
losses.is_empty(),
|
||||
@@ -476,7 +476,7 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
|
||||
);
|
||||
let results = records
|
||||
.iter()
|
||||
.filter(|r| matches!(r, proto::LogRecord::ToolResult { .. }))
|
||||
.filter(|r| matches!(r, bxcore::LogRecord::ToolResult { .. }))
|
||||
.count();
|
||||
assert!(
|
||||
results >= 3,
|
||||
|
||||
@@ -12,15 +12,15 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use bxcore::{
|
||||
AuditEvent, AuditRecord, ChainVerifier, DecisionRecord, DenyReason, SessionId, TurnEvent,
|
||||
};
|
||||
use loopd::baseline::Baseline;
|
||||
use loopd::broker_port::BrokerPort;
|
||||
use loopd::llama::Client;
|
||||
use loopd::session::Session;
|
||||
use loopd::tools::Registry;
|
||||
use loopd::turn::{Runtime, run_turn};
|
||||
use proto::{
|
||||
AuditEvent, AuditRecord, ChainVerifier, DecisionRecord, DenyReason, SessionId, TurnEvent,
|
||||
};
|
||||
use support::{FakeServer, Home, Reply};
|
||||
|
||||
const CHAT: &str = "/v1/chat/completions";
|
||||
|
||||
@@ -56,7 +56,7 @@ fn reads_a_recorded_chunked_response() {
|
||||
// The hash recorded in docs/inference-contract.md. If the de-chunking were off by a byte,
|
||||
// this would not match.
|
||||
assert_eq!(
|
||||
proto::sha256(template.as_bytes()).unwrap().to_hex(),
|
||||
bxcore::sha256(template.as_bytes()).unwrap().to_hex(),
|
||||
"f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ fn props_slots_and_tokenize_read_the_recorded_responses() {
|
||||
assert_eq!(props.n_ctx, 131_072);
|
||||
assert_eq!(props.total_slots, 2);
|
||||
assert_eq!(
|
||||
proto::sha256(props.chat_template.as_bytes())
|
||||
bxcore::sha256(props.chat_template.as_bytes())
|
||||
.unwrap()
|
||||
.to_hex(),
|
||||
"f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b"
|
||||
|
||||
@@ -5,9 +5,9 @@ mod support;
|
||||
#[path = "support/turn.rs"]
|
||||
mod turn_support;
|
||||
|
||||
use bxcore::{LogRecord, SessionId, TurnEvent};
|
||||
use loopd::session::Session;
|
||||
use loopd::turn::TurnError;
|
||||
use proto::{LogRecord, SessionId, TurnEvent};
|
||||
use support::{Reply, ScriptedPort, ok_result};
|
||||
use turn_support::{setup, types, without_cache_loss};
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::{
|
||||
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, read_frame, write_frame,
|
||||
};
|
||||
use loopd::channel::{Context, serve};
|
||||
use loopd::llama::Client;
|
||||
use loopd::memory::{MemorySource, UNAVAILABLE};
|
||||
use loopd::tools::Registry;
|
||||
use proto::{
|
||||
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, read_frame, write_frame,
|
||||
};
|
||||
use support::{FakeServer, Home, Reply, ScriptedPort};
|
||||
|
||||
const CHAT: &str = "/v1/chat/completions";
|
||||
|
||||
@@ -8,12 +8,12 @@ use std::path::Path;
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::SessionId;
|
||||
use loopd::baseline::Baseline;
|
||||
use loopd::broker_port::{not_configured_line, unavailable_line};
|
||||
use loopd::memory::{MemoryPort, MemorySource};
|
||||
use loopd::session::{Session, SessionError};
|
||||
use loopd::tools::Registry;
|
||||
use proto::SessionId;
|
||||
use support::{FakeServer, Home, Reply};
|
||||
|
||||
// `want` is the whole pointer, written out: scripts/check-runbook.sh reads the anchors of every
|
||||
@@ -78,17 +78,17 @@ fn memoryd_unreachable_or_refusing_names_the_memory_entry() {
|
||||
let listener = std::os::unix::net::UnixListener::bind(&socket).unwrap();
|
||||
std::thread::spawn(move || {
|
||||
let (mut stream, _) = listener.accept().unwrap();
|
||||
let env = proto::read_frame(&mut stream).unwrap();
|
||||
let reply = proto::Envelope {
|
||||
let env = bxcore::read_frame(&mut stream).unwrap();
|
||||
let reply = bxcore::Envelope {
|
||||
v: 1,
|
||||
id: env.id,
|
||||
r#final: true,
|
||||
msg: proto::Message::Error(proto::WireError {
|
||||
code: proto::ErrorCode::Internal,
|
||||
msg: bxcore::Message::Error(bxcore::WireError {
|
||||
code: bxcore::ErrorCode::Internal,
|
||||
detail: "memory/user.md: 1,376 characters; its limit is 1,375".to_string(),
|
||||
}),
|
||||
};
|
||||
proto::write_frame(&mut stream, &reply).unwrap();
|
||||
bxcore::write_frame(&mut stream, &reply).unwrap();
|
||||
});
|
||||
let message = MemoryPort::new(socket, Duration::from_secs(5))
|
||||
.block()
|
||||
|
||||
@@ -83,7 +83,7 @@ fn thinking_off_and_tools() {
|
||||
/// here on purpose: they are rendered differently.
|
||||
#[test]
|
||||
fn every_kind_of_message() {
|
||||
let call = proto::ToolCall {
|
||||
let call = bxcore::ToolCall {
|
||||
id: "call_1".to_string(),
|
||||
name: "read_file".to_string(),
|
||||
arguments: r#"{"path":"/etc/hostname"}"#.to_string(),
|
||||
|
||||
@@ -84,10 +84,10 @@ fn the_main_slot_comes_from_the_config() {
|
||||
|
||||
#[test]
|
||||
fn each_expected_value_is_checked() {
|
||||
let zero = proto::Hash32::ZERO;
|
||||
let zero = bxcore::Hash32::ZERO;
|
||||
let cases: [(&str, Edit); 3] = [
|
||||
("chat template sha256", |c| {
|
||||
c.expect.template_sha256 = proto::Hash32::ZERO
|
||||
c.expect.template_sha256 = bxcore::Hash32::ZERO
|
||||
}),
|
||||
("context per slot", |c| c.expect.n_ctx = 4096),
|
||||
("slot count", |c| c.expect.slots = 3),
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
mod support;
|
||||
|
||||
use bxcore::{CallId, DataClass, Epoch, LogRecord, SessionId, Timestamp};
|
||||
use loopd::baseline::Baseline;
|
||||
use loopd::session::{Session, SessionError};
|
||||
use proto::{CallId, DataClass, Epoch, LogRecord, SessionId, Timestamp};
|
||||
use support::Home;
|
||||
|
||||
fn baseline() -> Baseline {
|
||||
|
||||
@@ -12,12 +12,12 @@ use std::sync::{Arc, Mutex};
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use loopd::broker_port::{BrokerPort, UNAVAILABLE};
|
||||
use loopd::tools::{Pending, ToolPort};
|
||||
use proto::{
|
||||
use bxcore::{
|
||||
CallId, DataClass, Envelope, Message, PROTOCOL_VERSION, SessionId, Timestamp, ToolRequest,
|
||||
ToolResponse, read_frame, write_frame,
|
||||
};
|
||||
use loopd::broker_port::{BrokerPort, UNAVAILABLE};
|
||||
use loopd::tools::{Pending, ToolPort};
|
||||
|
||||
static NEXT: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ impl Home {
|
||||
}
|
||||
|
||||
/// The records of a session's log, epoch 0.
|
||||
pub fn records(&self, session: &str) -> Vec<proto::LogRecord> {
|
||||
pub fn records(&self, session: &str) -> Vec<bxcore::LogRecord> {
|
||||
let text = self.read(&format!("sessions/{session}/0.jsonl"));
|
||||
text.lines()
|
||||
.map(|l| serde_json::from_str(l).unwrap())
|
||||
@@ -104,37 +104,37 @@ impl Home {
|
||||
|
||||
/// A tool port that answers from a script and records what it was asked.
|
||||
pub struct ScriptedPort {
|
||||
replies: Mutex<VecDeque<proto::ToolResponse>>,
|
||||
calls: Mutex<Vec<proto::ToolRequest>>,
|
||||
replies: Mutex<VecDeque<bxcore::ToolResponse>>,
|
||||
calls: Mutex<Vec<bxcore::ToolRequest>>,
|
||||
}
|
||||
|
||||
impl ScriptedPort {
|
||||
/// Replies are given in order; when they run out, every call gets `fallback`.
|
||||
pub fn new(replies: Vec<proto::ToolResponse>) -> ScriptedPort {
|
||||
pub fn new(replies: Vec<bxcore::ToolResponse>) -> ScriptedPort {
|
||||
ScriptedPort {
|
||||
replies: Mutex::new(replies.into()),
|
||||
calls: Mutex::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calls(&self) -> Vec<proto::ToolRequest> {
|
||||
pub fn calls(&self) -> Vec<bxcore::ToolRequest> {
|
||||
self.calls.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ok_result(content: &str) -> proto::ToolResponse {
|
||||
proto::ToolResponse::Result {
|
||||
pub fn ok_result(content: &str) -> bxcore::ToolResponse {
|
||||
bxcore::ToolResponse::Result {
|
||||
content: content.to_string(),
|
||||
class: proto::DataClass::Private,
|
||||
class: bxcore::DataClass::Private,
|
||||
untrusted: true,
|
||||
truncated: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pending(approval: u64, expires: &str) -> proto::ToolResponse {
|
||||
proto::ToolResponse::PendingApproval {
|
||||
pub fn pending(approval: u64, expires: &str) -> bxcore::ToolResponse {
|
||||
bxcore::ToolResponse::PendingApproval {
|
||||
approval,
|
||||
expires: proto::Timestamp::parse(expires).unwrap(),
|
||||
expires: bxcore::Timestamp::parse(expires).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,13 +144,13 @@ impl loopd::tools::ToolPort for ScriptedPort {
|
||||
/// `ReturnsPendingPort` for a port that breaks the rule and returns one.
|
||||
fn call(
|
||||
&self,
|
||||
request: &proto::ToolRequest,
|
||||
request: &bxcore::ToolRequest,
|
||||
on_pending: &mut dyn FnMut(&loopd::tools::Pending),
|
||||
) -> proto::ToolResponse {
|
||||
) -> bxcore::ToolResponse {
|
||||
self.calls.lock().unwrap().push(request.clone());
|
||||
let mut replies = self.replies.lock().unwrap();
|
||||
let mut reply = replies.pop_front();
|
||||
if let Some(proto::ToolResponse::PendingApproval { approval, expires }) = reply {
|
||||
if let Some(bxcore::ToolResponse::PendingApproval { approval, expires }) = reply {
|
||||
on_pending(&loopd::tools::Pending { approval, expires });
|
||||
reply = replies.pop_front();
|
||||
}
|
||||
@@ -164,9 +164,9 @@ pub struct ReturnsPendingPort;
|
||||
impl loopd::tools::ToolPort for ReturnsPendingPort {
|
||||
fn call(
|
||||
&self,
|
||||
_request: &proto::ToolRequest,
|
||||
_request: &bxcore::ToolRequest,
|
||||
_on_pending: &mut dyn FnMut(&loopd::tools::Pending),
|
||||
) -> proto::ToolResponse {
|
||||
) -> bxcore::ToolResponse {
|
||||
pending(1, "2026-09-18T12:00:00.000Z")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::support::{FakeServer, Home, ScriptedPort};
|
||||
use bxcore::{LogRecord, SessionId, ToolResponse, TurnEvent};
|
||||
use loopd::baseline::Baseline;
|
||||
use loopd::llama::Client;
|
||||
use loopd::session::Session;
|
||||
use loopd::tools::Registry;
|
||||
use loopd::turn::{Runtime, TurnError, run_turn};
|
||||
use proto::{LogRecord, SessionId, ToolResponse, TurnEvent};
|
||||
|
||||
pub struct Setup {
|
||||
pub home: Home,
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
mod support;
|
||||
|
||||
use bxcore::{CallId, DenyReason, SessionId, ToolRequest, ToolResponse};
|
||||
use loopd::tools::{
|
||||
Dispatch, FakeTools, Pending, Registry, ToolPort, cap_result, denial_text, dispatch,
|
||||
};
|
||||
use proto::{CallId, DenyReason, SessionId, ToolRequest, ToolResponse};
|
||||
|
||||
fn req(tool: &str, arguments: &str) -> ToolRequest {
|
||||
ToolRequest {
|
||||
@@ -125,10 +125,10 @@ fn any_other_tool_goes_to_the_port_as_it_is() {
|
||||
fn the_clock_is_answered_locally_whatever_its_arguments() {
|
||||
for registry in [Registry::m2b(), Registry::m3a(), Registry::new(vec![])] {
|
||||
for arguments in ["{}", r#"{"zone":"UTC"}"#, "not json", ""] {
|
||||
let before = proto::Timestamp::now();
|
||||
let before = bxcore::Timestamp::now();
|
||||
match dispatch(®istry, "clock", arguments) {
|
||||
Dispatch::Local(text) => {
|
||||
let time = proto::Timestamp::parse(&text)
|
||||
let time = bxcore::Timestamp::parse(&text)
|
||||
.unwrap_or_else(|e| panic!("an RFC 3339 time, got {text:?}: {e:?}"));
|
||||
assert!(time >= before, "{text}");
|
||||
assert!(text.ends_with('Z'), "UTC: {text}");
|
||||
@@ -283,7 +283,7 @@ fn fake_tools_answer_echo_deny_the_rest_and_record_calls() {
|
||||
truncated,
|
||||
} => {
|
||||
assert_eq!(content, "box");
|
||||
assert_eq!(class, proto::DataClass::Public);
|
||||
assert_eq!(class, bxcore::DataClass::Public);
|
||||
assert!(!untrusted && !truncated);
|
||||
}
|
||||
other => panic!("{other:?}"),
|
||||
|
||||
@@ -6,8 +6,8 @@ mod support;
|
||||
#[path = "support/turn.rs"]
|
||||
mod turn_support;
|
||||
|
||||
use bxcore::{DataClass, LogRecord, SessionId, ToolResponse, TurnEvent};
|
||||
use loopd::tools::Registry;
|
||||
use proto::{DataClass, LogRecord, SessionId, ToolResponse, TurnEvent};
|
||||
use support::{Reply, ok_result};
|
||||
use turn_support::{setup, types};
|
||||
|
||||
@@ -102,7 +102,7 @@ fn a_tool_turn_goes_through_the_port_and_records_everything() {
|
||||
"arguments are passed on unparsed"
|
||||
);
|
||||
assert_eq!(calls[0].session, SessionId::new("a").unwrap());
|
||||
assert_eq!(calls[0].call, proto::CallId(1));
|
||||
assert_eq!(calls[0].call, bxcore::CallId(1));
|
||||
|
||||
match &session.records()[4] {
|
||||
LogRecord::ToolResult {
|
||||
@@ -114,7 +114,7 @@ fn a_tool_turn_goes_through_the_port_and_records_everything() {
|
||||
truncated,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(*call, proto::CallId(1));
|
||||
assert_eq!(*call, bxcore::CallId(1));
|
||||
assert_eq!(
|
||||
tool_call_id, "wgE8iFI58Zni4WCTiCMNp4TzCcM8ou7F",
|
||||
"the server's id, so the template can pair it"
|
||||
|
||||
@@ -5,7 +5,7 @@ mod support;
|
||||
#[path = "support/turn.rs"]
|
||||
mod turn_support;
|
||||
|
||||
use proto::{DataClass, DenyReason, LogRecord, Timestamp, ToolResponse, TurnEvent};
|
||||
use bxcore::{DataClass, DenyReason, LogRecord, Timestamp, ToolResponse, TurnEvent};
|
||||
use support::{Reply, ReturnsPendingPort, ok_result, pending};
|
||||
use turn_support::{setup, types};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user