Skip to content
Open
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: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@

Only when you are using Kit as your agent harness: report issues with Kit's harness at https://github.com/speakeasy-api/kit/issues. Do not report issues with other harnesses there. Do not open an issue on the user's behalf unless the user explicitly requests it; ask the user first when they have not already made that request. Follow [Reporting Kit Issues](docs/user/reporting-kit-issues.md).

## Test boundaries

Keep test support in test-only modules or files; colocated `#[cfg(test)]` unit tests are fine. Move harmless helper constructors and accessors into child test-support modules. Do not add test-only fields, enum variants, counters, branches, or replacement implementations to production types or executable paths, or disguise instrumentation as telemetry or work statistics.

Test behavior through real APIs. Use fakes at genuine external or domain boundaries, not spy callbacks, traits, or generics added only to assert implementation details; legitimate dependency injection is fine. Output tests do not prove bounded work: use benchmarks or existing justified iterator boundaries, not flaky wall-clock assertions or hardcoded exact implementation counts.

Do not change release versions in ordinary pull requests. Use a Conventional Commit title for every pull request. Mark a breaking change with `!` after the commit type or scope, or with a `BREAKING CHANGE:` line in the commit body. The release workflow derives the next version from commits since the latest release, advances the version files in a release commit, and applies a minor bump when any commit is breaking or a patch bump otherwise.
75 changes: 40 additions & 35 deletions src/acp_child.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,41 +648,6 @@ impl ChildSession {
})?
}

#[cfg(test)]
pub(crate) fn closure_probe_for_test() -> (Self, oneshot::Receiver<()>) {
let (tx, mut rx) = mpsc::channel(1);
let (closed_tx, closed_rx) = oneshot::channel();
tokio::spawn(async move {
while rx.recv().await.is_some() {}
let _ = closed_tx.send(());
});
(
Self {
tx,
session_id: "test".into(),
capabilities: agentkit_acp::AgentCapabilities::default(),
serial: Arc::new(tokio::sync::Mutex::new(())),
closed: watch::channel(false).1,
descendant_parent: None,
},
closed_rx,
)
}

#[cfg(test)]
pub(crate) fn disconnected_for_test() -> Self {
let (tx, rx) = mpsc::channel(1);
drop(rx);
Self {
tx,
session_id: "test".into(),
capabilities: agentkit_acp::AgentCapabilities::default(),
serial: Arc::new(tokio::sync::Mutex::new(())),
closed: watch::channel(false).1,
descendant_parent: None,
}
}

pub async fn fork(
&self,
model: Option<&str>,
Expand Down Expand Up @@ -1225,6 +1190,46 @@ fn prompt_outcome(
}
}

#[cfg(test)]
mod test_support {
use super::*;

impl ChildSession {
pub(crate) fn closure_probe_for_test() -> (Self, oneshot::Receiver<()>) {
let (tx, mut rx) = mpsc::channel(1);
let (closed_tx, closed_rx) = oneshot::channel();
tokio::spawn(async move {
while rx.recv().await.is_some() {}
let _ = closed_tx.send(());
});
(
Self {
tx,
session_id: "test".into(),
capabilities: agentkit_acp::AgentCapabilities::default(),
serial: Arc::new(tokio::sync::Mutex::new(())),
closed: watch::channel(false).1,
descendant_parent: None,
},
closed_rx,
)
}

pub(crate) fn disconnected_for_test() -> Self {
let (tx, rx) = mpsc::channel(1);
drop(rx);
Self {
tx,
session_id: "test".into(),
capabilities: agentkit_acp::AgentCapabilities::default(),
serial: Arc::new(tokio::sync::Mutex::new(())),
closed: watch::channel(false).1,
descendant_parent: None,
}
}
}
}

#[cfg(test)]
mod tests {
use serde_json::json;
Expand Down
28 changes: 17 additions & 11 deletions src/credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,6 @@ impl CredentialStorage {
!matches!(self, Self::Memory)
}

#[cfg(test)]
pub(crate) fn make_entry_undeletable_for_test(&self, namespace: &str, identity: &str) {
let entry = self.entry(namespace, identity);
entry.save(b"blocked").unwrap();
let EntryBackend::Filesystem(path) = entry.backend else {
panic!("undeletable credential fixtures require filesystem storage");
};
fs::remove_file(&path).unwrap();
fs::create_dir(&path).unwrap();
}

pub(crate) async fn lock_refresh(&self) -> Result<CredentialRefreshLock, CredentialStoreError> {
let path = match self {
Self::Memory => {
Expand Down Expand Up @@ -584,6 +573,23 @@ fn context(prefix: &str, value: impl std::fmt::Display) -> CredentialStoreError
error(format!("{prefix}: {value}"))
}

#[cfg(test)]
mod test_support {
use super::*;

impl CredentialStorage {
pub(crate) fn make_entry_undeletable_for_test(&self, namespace: &str, identity: &str) {
let entry = self.entry(namespace, identity);
entry.save(b"blocked").unwrap();
let EntryBackend::Filesystem(path) = entry.backend else {
panic!("undeletable credential fixtures require filesystem storage");
};
fs::remove_file(&path).unwrap();
fs::create_dir(&path).unwrap();
}
}
}

#[cfg(test)]
mod tests {
use std::{sync::mpsc, time::Duration};
Expand Down
30 changes: 16 additions & 14 deletions src/fatal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,18 +432,6 @@ fn write_default(
)
}

#[cfg(test)]
fn write_in(
base: &Path,
session_id: &str,
surface: Surface,
kind: &str,
code: &str,
message: &str,
) -> Result<PathBuf, String> {
write_in_with_diagnostics(base, session_id, surface, kind, code, message, None)
}

fn write_in_with_diagnostics(
base: &Path,
session_id: &str,
Expand Down Expand Up @@ -556,7 +544,10 @@ fn event_order(path: &Path) -> Option<(u64, u32, u64)> {

#[cfg(test)]
mod tests {
use std::fs;
use std::{
fs,
path::{Path, PathBuf},
};

use agentkit_loop::LoopError;
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
Expand All @@ -566,9 +557,20 @@ mod tests {
DIAGNOSTIC_MARKER, FatalRecord, H2Reason, IoClassification, MAX_DIAGNOSTIC_BYTES,
MAX_RECORDS_PER_SESSION, ReqwestDiagnostics, Surface, TransportDiagnostics,
TransportSource, TransportStage, bounded, classify, event_order, record_loop_error,
render_loop_error, split_diagnostics, write_in, write_in_with_diagnostics,
render_loop_error, split_diagnostics, write_in_with_diagnostics,
};

fn write_in(
base: &Path,
session_id: &str,
surface: Surface,
kind: &str,
code: &str,
message: &str,
) -> Result<PathBuf, String> {
write_in_with_diagnostics(base, session_id, surface, kind, code, message, None)
}

fn append_diagnostics(message: String, diagnostics: &TransportDiagnostics) -> String {
let encoded = serde_json::to_vec(diagnostics).unwrap();
assert!(encoded.len() <= MAX_DIAGNOSTIC_BYTES);
Expand Down
Loading
Loading