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
2 changes: 1 addition & 1 deletion Cargo.lock

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

9 changes: 9 additions & 0 deletions crates/graphql-orm-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ checkpoint facts. For the current workspace baseline and active gates, use the
[implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## [0.106.1] - 2026-10-01

### Fixed

- Raise the finite provider-session static bootstrap and Grok SDK definition
bounds from 64 to 128. Larger reviewed catalogues can start native sessions
without omitting tools; exact fingerprints, duplicate/schema rejection,
provider frame/byte limits and callback bounds remain mandatory.

## [Unreleased]

### Added
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-ai"
version = "0.106.0"
version = "0.106.1"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
16 changes: 16 additions & 0 deletions crates/graphql-orm-ai/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ they describe. For the current workspace baseline and active delivery gates,
use [implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## 0.106.0 to 0.106.1

Provider-session bindings now admit up to 128 static bootstrap fingerprints;
the Grok SDK broker admits up to 128 exact definitions. Count the complete
projected provider surface, including fixed broker definitions, against its
own limit. This fixes admission of reviewed catalogues above the former 64-tool
ceiling without granting discovery or execution authority. Existing session
fingerprints remain byte-identical for unchanged inputs.

No data migration, DDL, GraphQL SDL, protected payload or schema-module change
is required. The widened bound affects construction only; the persisted format
and fingerprint computation are unchanged. Older readers cannot construct a
new session with more than 64 bootstrap fingerprints, so retain this release
when configuring such a catalogue. All current-principal, approval, egress,
budget, provider byte/frame and callback checks remain authoritative.

## 0.105.2 to 0.106.0

Hosts can return `AiToolAuthorizationDecision::require_authentication` for an
Expand Down
6 changes: 6 additions & 0 deletions crates/graphql-orm-ai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ supersedes: []

# graphql-orm-ai

Version `0.106.1` admits up to 128 exact static bootstrap fingerprints and
Grok SDK definitions, matching the existing Codex definition ceiling. Hosts
with larger reviewed tool catalogues no longer fail provider-session admission
at the former 64-tool limit. Complete projected surfaces, including broker tools,
still obey each provider’s definition and byte limits.

Version `0.106.0` lets trusted host policy distinguish required authentication
renewal from permission denial before native tool admission. The model receives
a protected, audited, non-retryable preflight failure and can continue permitted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ negotiation metadata, never authority.
| `ProviderDeferred` | Already-filtered definitions marked for reviewed native deferred loading | Native provider tool search |
| `FixedBroker` | Exact static bootstrap plus frozen discover/describe/execute definitions | Retained sessions whose generated definitions cannot change |

Provider-session bindings admit at most 128 exact static bootstrap fingerprints.
Grok SDK and Codex dynamic tools independently enforce 128-definition ceilings
on the **complete** surface, including fixed broker definitions. Fingerprint
admission does not relax provider byte/frame limits or application authority.

`prepare_client_deferred_continuation` accepts only definitions matching the
crate-owned loaded bindings and the configured selection count. Fixed broker
arguments use a closed scalar argument list and public selection paths; the
Expand Down
30 changes: 28 additions & 2 deletions crates/graphql-orm-ai/src/capability_delivery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,9 @@ impl AiProviderCapabilitySessionBinding {
///
/// # Errors
///
/// Rejects missing, unbounded, or control-character-bearing values.
/// Rejects missing, unbounded, or control-character-bearing values and more
/// than 128 static bootstrap fingerprints. Provider-specific definition and
/// byte limits still apply independently to the complete projected surface.
#[allow(clippy::too_many_arguments)]
pub fn new(
delivery_mode: AiCapabilityDeliveryMode,
Expand All @@ -505,7 +507,7 @@ impl AiProviderCapabilitySessionBinding {
}
if !crate::valid_sha256(&capability_index_fingerprint)
|| !crate::valid_sha256(&registration_identity)
|| static_bootstrap_tool_fingerprints.len() > 64
|| static_bootstrap_tool_fingerprints.len() > 128
|| static_bootstrap_tool_fingerprints
.iter()
.any(|value| !crate::valid_sha256(value))
Expand Down Expand Up @@ -2787,6 +2789,30 @@ mod tests {
));
}

#[test]
fn provider_binding_accepts_large_exact_bootstrap_and_keeps_a_finite_limit() {
let make = |count: usize| {
AiProviderCapabilitySessionBinding::new(
AiCapabilityDeliveryMode::FixedBroker,
"a".repeat(64),
(0..count).map(|index| format!("{index:064x}")).collect(),
"test-projection/v1",
"test-model",
ModelReasoningEffort::Low,
"b".repeat(64),
)
};
for count in [64, 65, 86, 128] {
let binding = make(count).expect("bounded larger host bootstrap should be admitted");
assert_eq!(binding.static_bootstrap_tool_fingerprints().len(), count);
}
assert!(make(129).is_err());
assert_ne!(
make(85).unwrap().fingerprint(),
make(86).unwrap().fingerprint()
);
}

#[test]
fn retained_binding_changes_for_every_execution_relevant_dimension() {
let make = |mode, effort, model: &str| {
Expand Down
37 changes: 35 additions & 2 deletions crates/graphql-orm-ai/src/providers/grok_acp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
};

const MAX_FRAME_BYTES: usize = 16 * 1024 * 1024;
const MAX_DEFINITIONS: usize = 64;
const MAX_DEFINITIONS: usize = 128;
pub(super) const MAX_SDK_CALLS: usize = 4096;

fn rejected() -> ProviderError {
Expand Down Expand Up @@ -81,7 +81,7 @@ impl AiGrokAcpSdkBroker {
///
/// # Errors
/// Rejects malformed identities, duplicate or invalid definitions, more
/// than 64 definitions or 4096 callbacks, frames over 16 MiB, or total
/// than 128 definitions or 4096 callbacks, frames over 16 MiB, or total
/// bytes over 64 MiB.
pub fn new(
server_id: String,
Expand Down Expand Up @@ -475,6 +475,39 @@ mod tests {
));
}

#[test]
fn exact_definition_capacity_admits_large_bootstrap_and_rejects_overflow() {
let make = |count: usize| {
let tools = (0..count)
.map(|index| {
let mut tool = definition();
tool.tool_id = format!("test.tool.{index}");
tool.provider_name = format!("tool_{index}");
tool.fingerprint = format!("{index:064x}");
tool
})
.collect();
AiGrokAcpSdkBroker::new(
"sdk-1".into(),
"prompt-1".into(),
tools,
1,
1024 * 1024,
4 * 1024 * 1024,
)
};
for count in [65, 90, 128] {
let mut broker = make(count).expect("bounded exact definitions should be admitted");
initialize(&mut broker);
assert!(matches!(
broker.accept(&request(2, "tools/list", json!({}))),
Ok(AiGrokAcpSdkInbound::Response(_))
));
assert_eq!(broker.tools.len(), count);
}
assert!(matches!(make(129), Err(ProviderError::InvalidRequest)));
}

#[test]
fn callback_capacity_is_independent_of_definition_count_and_remains_bounded() {
let mut broker = AiGrokAcpSdkBroker::new(
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/workspace-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ changes.
| Package | Version | Path | Default features | Direct internal dependencies |
| --- | --- | --- | --- | --- |
| `graphql-orm` | `0.33.3` | `crates/graphql-orm` | `sqlite` | `graphql-orm-macros`, `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-ai` | `0.106.0` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai` | `0.106.1` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai-tool-profiles` | `0.15.0` | `crates/graphql-orm-ai-tool-profiles` | none | `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-backup` | `0.7.2` | `crates/graphql-orm-backup` | `local` | `graphql-orm` (optional), `graphql-orm-storage` |
| `graphql-orm-macros` | `0.33.3` | `crates/graphql-orm-macros` | `sqlite` | none |
Expand Down
Loading