Skip to content
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
5b455a1
chore(vendor): bump tinyinference submodule
senamakel Oct 24, 2026
8afb24d
chore(deps): add sha2 to lockfile
senamakel Oct 24, 2026
fd61026
chore(run-ledger-mongodb): add sha2 to lockfile
senamakel Oct 24, 2026
e42381a
Merge pull request #181 from senamakel/epic-8369-inference-pin-deliver
senamakel Oct 24, 2026
9765063
chore(vendor): bump tinyinference submodule
senamakel Oct 24, 2026
bc0a008
Merge pull request #182 from senamakel/epic-8369-inference-pin-refresh
senamakel Oct 24, 2026
67966b9
chore(vendor): bump tinytools submodule
senamakel Oct 26, 2026
edf9ec7
chore(vendor): bump tinytools submodule
senamakel Oct 26, 2026
c373524
Merge pull request #186 from senamakel/sec-10-url-guard
senamakel Oct 26, 2026
1f3273f
refactor(model_factory): make model building async
senamakel Oct 27, 2026
8145f0f
style: fix indentation and line wrapping in model factory assembly tests
senamakel Oct 27, 2026
091f807
docs(model_factory): document async factory and build awaiting
senamakel Oct 27, 2026
5765b01
Merge pull request #187 from senamakel/sec-656-model-factory
senamakel Oct 27, 2026
e50efd5
fix(model-factory): send async factory futures
senamakel Oct 27, 2026
a20b6b1
Merge pull request #188 from senamakel/sec-656-model-factory-send
senamakel Oct 27, 2026
9851ebc
chore(tinyinference): consume async bearer resolver API
senamakel Oct 27, 2026
72629e5
Merge pull request #189 from senamakel/sec-656-secret-cipher
senamakel Oct 27, 2026
ab33547
chore(vendor): bump tinyinference and tinytools submodules
senamakel Oct 30, 2026
05061f1
test: cover transcript adoption, prefix reset, and summary rendering
senamakel Oct 30, 2026
b93d1ff
chore(vendor): bump tinyinference and tinytools submodules
senamakel Oct 30, 2026
089e109
feat(transcript): add prefix_reset flag to transcript metadata
senamakel Oct 30, 2026
8324016
feat(session): add atomic adoption of imported transcript history
senamakel Oct 30, 2026
f1db73c
feat(summarization): add tool rendering modes and output token cap
senamakel Oct 30, 2026
6a6e4ba
fix(session): remove redundant map in transcript install
senamakel Oct 30, 2026
c50e4c3
test(session): cover adopting imported history only into empty sessions
senamakel Oct 30, 2026
a3beb9a
test(summarization): cover tool rendering markers and output token cap
senamakel Oct 30, 2026
641e20a
docs: document tool rendering, prefix reset, and adopt primitives
senamakel Oct 30, 2026
b3f83da
test: reformat assertions to satisfy line width limits
senamakel Oct 30, 2026
1da28ca
test(summarization): fix argument length assertion in marker renderin…
senamakel Oct 30, 2026
30d1860
feat(session): add reset_history to start a fresh model context
senamakel Oct 30, 2026
9aefe1f
test(runtime): add prefix freeze and reset fields to test fixtures
senamakel Oct 30, 2026
a207803
docs(runtime): document session history reset and frozen prefix state
senamakel Oct 30, 2026
ba79e94
feat(harness): add migrate_storage compatibility alias and expose run…
senamakel Oct 30, 2026
c453f42
feat(session): expose message metadata in transcript views and suppor…
senamakel Oct 30, 2026
f047853
fix(tinyagents-harness): construct subagent cost tally directly
senamakel Oct 30, 2026
0eea709
build(deps): add schemars dependency to harness, tools, and session c…
senamakel Oct 30, 2026
fb969e2
feat(types): derive JsonSchema on harness and session types
senamakel Oct 30, 2026
6cea202
build(deps): switch schemars chrono feature to chrono04
senamakel Oct 30, 2026
21f8b7b
refactor(middleware): drop JsonSchema derives from library types
senamakel Oct 30, 2026
1136aa2
chore(session): import serde_json Value in rewrite driver
senamakel Oct 30, 2026
14a68f8
refactor(threads): extract metadata merge into shared helper
senamakel Oct 30, 2026
1a10b2d
test: update tests for renamed cost source and reordered modules
senamakel Oct 30, 2026
196913f
test(threads): use default struct update in message patch tests
senamakel Oct 30, 2026
c3d7d32
test(storage): cover migrate_storage scope initialization
senamakel Oct 30, 2026
567dbc6
Merge upstream/main into epic/8369-security-migration
senamakel Oct 30, 2026
37bee91
chore(session): drop unused sha2 dependency and stale test field
senamakel Oct 30, 2026
9a5632b
chore(deps): sync run-ledger-mongodb lockfile with dependency changes
senamakel Oct 30, 2026
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
83 changes: 75 additions & 8 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 crates/tinyagents-harness-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ reqwest = { workspace = true, features = ["stream", "multipart"], optional = tru
sha2 = { version = "0.11", optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
schemars = "1.2.3"
tinyagents-harness = { path = "../tinyagents-harness", version = "3.0.0", default-features = false }
tinyagents-tasks = { path = "../tinyagents-tasks", version = "3.0.0", default-features = false, optional = true }
tinyinference-llm = { path = "../../vendor/tinyinference/crates/tinyinference-llm", version = "0.5.0", optional = true }
Expand Down
4 changes: 2 additions & 2 deletions crates/tinyagents-harness-tools/src/goals/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize};
/// [`BudgetLimited`](ThreadGoalStatus::BudgetLimited) are entered only by the
/// system (host control and accounting respectively), and clearing deletes the
/// row entirely rather than being a status.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ThreadGoalStatus {
/// The graph may make progress and (when driven) auto-continue.
Expand Down Expand Up @@ -60,7 +60,7 @@ impl ThreadGoalStatus {
}

/// A single thread-scoped goal.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ThreadGoal {
/// The thread this goal belongs to (one goal per thread).
Expand Down
8 changes: 4 additions & 4 deletions crates/tinyagents-harness-tools/src/todos/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use serde::{Deserialize, Serialize};

/// Lifecycle state of a todo item.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum TodoStatus {
/// Not started.
Expand Down Expand Up @@ -40,7 +40,7 @@ impl TodoStatus {
}

/// One item on a thread's todo list.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TodoItem {
/// The step, as the model wrote it.
Expand Down Expand Up @@ -74,7 +74,7 @@ impl TodoItem {
}

/// A per-thread list: the items in order plus a last-mutation stamp.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TodoList {
/// The thread this list belongs to.
Expand All @@ -97,7 +97,7 @@ impl TodoList {
}

/// A single store outcome: the post-mutation items plus a markdown rendering.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TodosSnapshot {
/// The thread the list belongs to.
Expand Down
1 change: 1 addition & 0 deletions crates/tinyagents-harness/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ regex = "1"
reqwest = { workspace = true, features = ["stream", "http2"], optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
schemars = "1.2.3"
sha2 = "0.11"
thiserror = "2"
tracing = { workspace = true }
Expand Down
12 changes: 8 additions & 4 deletions crates/tinyagents-harness/src/host/model_factory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ stable description of each requested route.
`types.rs` defines the serde-compatible `BuildOpts`, `ModelPurpose`, and
`ModelBuildRequest` values, plus the `ModelBuildGate` and `ModelFactory`
contracts. Hosts implement the gate to authorize each construction request and
the factory to return a model with its resolved provider/model route.
the async factory to return a model with its resolved provider/model route.
Both adapters are `Sync`, and factory futures are `Send`, so turn assembly can
run inside the host's sendable task boundaries.

`assembly.rs` owns `TurnModelSetBuilder` and `TurnModelSet`. It builds the
primary route, independently builds workload tiers (omitting unavailable or
gated tiers), builds the summarizer, and records the concrete routes and error
slots for later resolution. A primary pin does not implicitly pin workload
routes. An explicit summarization role with no summary pin uses that role's
configured default.
slots for later resolution. Await `TurnModelSetBuilder::build` or
`TurnModelSet::build`; each primary, workload, and summary factory request is
awaited before assembly continues. A primary pin does not implicitly pin
workload routes. An explicit summarization role with no summary pin uses that
role's configured default.

`subprocess.rs` adapts Claude Code and Claude Agent SDK route values to the
existing provider implementations. Hosts must run `ModelBuildGate` before
Expand Down
12 changes: 6 additions & 6 deletions crates/tinyagents-harness/src/host/model_factory/assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ impl<'a, State: Send + Sync + 'static, F: ModelFactory<State> + ?Sized, G: Model

/// Builds all requested models. Primary and summarization failures are
/// fatal; failed workload routes are logged and omitted.
pub fn build(self) -> Result<TurnModelSet<State>> {
pub async fn build(self) -> Result<TurnModelSet<State>> {
self.gate.check(&self.primary)?;
let (primary_model, primary_route) = self.factory.build(&self.primary)?;
let (primary_model, primary_route) = self.factory.build(&self.primary).await?;
let primary = Arc::new(RouteRecordingModel::new(
primary_model,
primary_route.clone(),
Expand Down Expand Up @@ -182,7 +182,7 @@ impl<'a, State: Send + Sync + 'static, F: ModelFactory<State> + ?Sized, G: Model
tracing::debug!(route = ?request.route, %error, "skipping gated workload model");
continue;
}
match self.factory.build(&request) {
match self.factory.build(&request).await {
Ok((model, route)) => {
let slot = Arc::new(Mutex::new(None));
let recorded = Arc::new(RouteRecordingModel::new(model, route))
Expand Down Expand Up @@ -215,7 +215,7 @@ impl<'a, State: Send + Sync + 'static, F: ModelFactory<State> + ?Sized, G: Model
opts: self.summarization_opts.unwrap_or(self.primary.opts),
};
self.gate.check(&summary_request)?;
let (summary_model, summary_route) = self.factory.build(&summary_request)?;
let (summary_model, summary_route) = self.factory.build(&summary_request).await?;
let summary_error_slot = Arc::new(Mutex::new(None));
let summarizer = Arc::new(RouteRecordingModel::new(
summary_model,
Expand Down Expand Up @@ -251,12 +251,12 @@ pub struct TurnModelSet<State: Send + Sync> {

impl<State: Send + Sync + 'static> TurnModelSet<State> {
/// Builds a turn's primary, canonical workload routes, and summarizer.
pub fn build<F, G>(factory: &F, gate: &G, primary_role: impl Into<String>) -> Result<Self>
pub async fn build<F, G>(factory: &F, gate: &G, primary_role: impl Into<String>) -> Result<Self>
where
F: ModelFactory<State> + ?Sized,
G: ModelBuildGate + ?Sized,
{
Self::builder(factory, gate, primary_role).build()
Self::builder(factory, gate, primary_role).build().await
}

/// Starts building a model set using the standard workload aliases.
Expand Down
14 changes: 11 additions & 3 deletions crates/tinyagents-harness/src/host/model_factory/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tinyinference_llm::model::{ChatModel, ResolvedModelRoute};

Expand Down Expand Up @@ -58,15 +59,22 @@ impl ModelBuildRequest {
}

/// Host policy hook called before every model construction.
pub trait ModelBuildGate {
///
/// Implementations are `Sync` so a turn-model assembly future may cross a
/// host task boundary while retaining the gate between model builds.
pub trait ModelBuildGate: Sync {
/// Authorize constructing the model described by `request`.
fn check(&self, request: &ModelBuildRequest) -> Result<()>;
}

/// Host implementation that selects and constructs a provider model.
pub trait ModelFactory<State: Send + Sync> {
///
/// Implementations are `Sync`, and [`build`](Self::build) returns a `Send`
/// future so the harness can assemble turn models inside sendable host tasks.
#[async_trait]
pub trait ModelFactory<State: Send + Sync>: Sync {
/// Construct a model and report the concrete route selected by the host.
fn build(
async fn build(
&self,
request: &ModelBuildRequest,
) -> Result<(Arc<dyn ChatModel<State>>, ResolvedModelRoute)>;
Expand Down
Loading