config(pi): execute pinned native schema and composer oracles

Evaluate raw Pi documents with the vendored upstream TypeBox schema and replay composer/transport expectations captured by actually executing Pi ab366ebe94cacd419d986be454f12b1b9913aaca.

Bind all 252 canonical fields to successful raw and own-layer composer evidence (70 provider, 92 model, 90 override), fail closed where pinned runtime context is unavailable, expose structured inspection, and enforce module/write/restore boundaries with negative fixtures.
This commit is contained in:
SaladDay
2026-07-31 17:59:35 +00:00
parent 4f78451405
commit 10f2dacbe4
18 changed files with 13595 additions and 1 deletions
File diff suppressed because it is too large Load Diff
+12 -1
View File
@@ -783,6 +783,7 @@ dependencies = [
"indexmap 2.13.0",
"json-five",
"json5",
"jsonc-parser",
"libc",
"log",
"objc2 0.5.2",
@@ -800,6 +801,7 @@ dependencies = [
"serde_yaml",
"serial_test",
"sha2",
"syn 2.0.117",
"sys-locale",
"tauri",
"tauri-build",
@@ -2799,6 +2801,15 @@ dependencies = [
"serde",
]
[[package]]
name = "jsonc-parser"
version = "0.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0560e3f9a9a03ea6b6e90b41138c5db9e21526c99eb192c1a26c68176593285"
dependencies = [
"serde_json",
]
[[package]]
name = "jsonptr"
version = "0.6.3"
@@ -4687,7 +4698,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
+2
View File
@@ -24,6 +24,7 @@ tauri-build = { version = "2.4.0", features = [] }
[dependencies]
serde_json = { version = "1.0", features = ["preserve_order"] }
jsonc-parser = { version = "0.33", features = ["cst", "serde_json"] }
serde = { version = "1.0", features = ["derive"] }
log = "0.4"
chrono = { version = "0.4", features = ["serde"] }
@@ -117,3 +118,4 @@ strip = "symbols"
[dev-dependencies]
serial_test = "3"
tempfile = "3"
syn = { version = "2", features = ["full", "visit"] }
+554
View File
@@ -0,0 +1,554 @@
use regex::Regex;
use serde_json::json;
use std::collections::{BTreeMap, BTreeSet};
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use syn::visit::{self, Visit};
use syn::{
Attribute, ExprLit, ImplItem, Item, ItemImpl, ItemStruct, ItemUse, Lit, Meta, Path as SynPath,
Type, UseTree,
};
static PROVIDER_DML: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r#"(?is)\b(?:INSERT(?:\s+OR\s+(?:ABORT|FAIL|IGNORE|REPLACE|ROLLBACK))?\s+INTO|UPDATE(?:\s+OR\s+(?:ABORT|FAIL|IGNORE|REPLACE|ROLLBACK))?|DELETE\s+FROM)\s+["`\[]?(providers|provider_endpoints)\b"#,
)
.expect("compile provider DML classifier")
});
static RESTORE_CREATE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"(?is)\bCREATE\s+(?:TEMP(?:ORARY)?\s+)?(?:TABLE|INDEX|TRIGGER|VIEW)\b")
.expect("compile restore DDL classifier")
});
#[derive(Debug, Clone, PartialEq, Eq)]
struct Violation {
kind: &'static str,
path: String,
detail: String,
}
fn is_cfg_test(attrs: &[Attribute]) -> bool {
attrs.iter().any(|attribute| {
if !attribute.path().is_ident("cfg") {
return false;
}
match &attribute.meta {
Meta::List(list) => list
.tokens
.to_string()
.split(|character: char| !character.is_ascii_alphanumeric() && character != '_')
.any(|token| token == "test"),
_ => false,
}
})
}
fn flatten_use(tree: &UseTree, prefix: &mut Vec<String>, output: &mut Vec<Vec<String>>) {
match tree {
UseTree::Path(path) => {
prefix.push(path.ident.to_string());
flatten_use(&path.tree, prefix, output);
prefix.pop();
}
UseTree::Name(name) => {
let mut path = prefix.clone();
path.push(name.ident.to_string());
output.push(path);
}
UseTree::Rename(rename) => {
let mut path = prefix.clone();
path.push(rename.ident.to_string());
output.push(path);
}
UseTree::Group(group) => {
for item in &group.items {
flatten_use(item, prefix, output);
}
}
UseTree::Glob(_) => output.push(prefix.clone()),
}
}
fn path_segments(path: &SynPath) -> Vec<String> {
path.segments
.iter()
.map(|segment| segment.ident.to_string())
.collect()
}
struct ArchitectureVisitor<'a> {
path: &'a str,
violations: Vec<Violation>,
internal_edges: BTreeSet<String>,
}
impl ArchitectureVisitor<'_> {
fn record_dependency(&mut self, segments: &[String]) {
let source_module = if self.path.ends_with("pi_config/raw_schema.rs") {
Some("raw_schema")
} else if self.path.ends_with("pi_config/composer.rs") {
Some("composer")
} else if self.path.ends_with("pi_config/gateway.rs") {
Some("gateway")
} else if self.path.ends_with("pi_config/native.rs") {
Some("native")
} else if self.path.ends_with("pi_config/model.rs") {
Some("model")
} else {
None
};
let Some(source_module) = source_module else {
return;
};
let qualified_internal_path = segments.len() > 1
&& segments.iter().any(|segment| {
matches!(segment.as_str(), "super" | "self" | "crate" | "pi_config")
});
if qualified_internal_path {
for module in [
"raw_schema",
"composer",
"gateway",
"native",
"model",
"document",
] {
if module != source_module && segments.iter().any(|segment| segment == module) {
self.internal_edges
.insert(format!("{source_module}->{module}"));
}
}
}
let imports_gateway = segments
.iter()
.any(|segment| segment == "gateway" || segment.starts_with("PiGateway"));
let imports_model_module = segments.len() > 1
&& segments.iter().any(|segment| segment == "model")
&& segments.iter().any(|segment| {
matches!(segment.as_str(), "super" | "self" | "crate" | "pi_config")
});
let imports_managed = imports_model_module
|| segments.iter().any(|segment| {
segment == "PiApiFamily"
|| segment.starts_with("PiManaged")
|| segment == "PiEffectiveModel"
});
if matches!(source_module, "raw_schema" | "composer")
&& (imports_gateway || imports_managed)
{
self.violations.push(Violation {
kind: "cross_layer_import",
path: self.path.to_string(),
detail: format!(
"{source_module} imports managed/gateway path {}",
segments.join("::")
),
});
}
let imports_raw_valid = segments
.iter()
.any(|segment| segment == "raw_schema" || segment == "PiRawValidProvider");
if source_module == "gateway" && imports_raw_valid {
self.violations.push(Violation {
kind: "cross_layer_import",
path: self.path.to_string(),
detail: format!(
"gateway constructs or imports raw-valid path {}",
segments.join("::")
),
});
}
}
fn inspect_string(&mut self, literal: &str) {
if PROVIDER_DML.is_match(literal) && !provider_dml_path_allowed(self.path) {
self.violations.push(Violation {
kind: "provider_dml",
path: self.path.to_string(),
detail: "provider table DML exists outside typed row/state, endpoint, migration, or canonical-copy authority".to_string(),
});
}
if self.path.ends_with("database/backup.rs") && RESTORE_CREATE.is_match(literal) {
self.violations.push(Violation {
kind: "restore_create",
path: self.path.to_string(),
detail: "restore production code contains CREATE TABLE/INDEX/TRIGGER/VIEW"
.to_string(),
});
}
}
}
impl<'ast> Visit<'ast> for ArchitectureVisitor<'_> {
fn visit_item(&mut self, item: &'ast Item) {
let attrs = match item {
Item::Const(item) => &item.attrs,
Item::Enum(item) => &item.attrs,
Item::ExternCrate(item) => &item.attrs,
Item::Fn(item) => &item.attrs,
Item::ForeignMod(item) => &item.attrs,
Item::Impl(item) => &item.attrs,
Item::Macro(item) => &item.attrs,
Item::Mod(item) => &item.attrs,
Item::Static(item) => &item.attrs,
Item::Struct(item) => &item.attrs,
Item::Trait(item) => &item.attrs,
Item::TraitAlias(item) => &item.attrs,
Item::Type(item) => &item.attrs,
Item::Union(item) => &item.attrs,
Item::Use(item) => &item.attrs,
Item::Verbatim(_) => {
visit::visit_item(self, item);
return;
}
_ => {
visit::visit_item(self, item);
return;
}
};
if !is_cfg_test(attrs) {
visit::visit_item(self, item);
}
}
fn visit_impl_item(&mut self, item: &'ast ImplItem) {
let attrs = match item {
ImplItem::Const(item) => &item.attrs,
ImplItem::Fn(item) => &item.attrs,
ImplItem::Type(item) => &item.attrs,
ImplItem::Macro(item) => &item.attrs,
ImplItem::Verbatim(_) => {
visit::visit_impl_item(self, item);
return;
}
_ => {
visit::visit_impl_item(self, item);
return;
}
};
if !is_cfg_test(attrs) {
visit::visit_impl_item(self, item);
}
}
fn visit_ident(&mut self, identifier: &'ast syn::Ident) {
let identifier = identifier.to_string();
if matches!(
identifier.as_str(),
"save_provider" | "save_provider_row_on_tx" | "save_provider_aggregate"
) || identifier.starts_with("upsert_provider")
{
self.violations.push(Violation {
kind: "forbidden_provider_symbol",
path: self.path.to_string(),
detail: format!("forbidden provider write symbol '{identifier}'"),
});
}
}
fn visit_expr_lit(&mut self, expression: &'ast ExprLit) {
if let Lit::Str(literal) = &expression.lit {
self.inspect_string(&literal.value());
}
visit::visit_expr_lit(self, expression);
}
fn visit_item_use(&mut self, item: &'ast ItemUse) {
let mut paths = Vec::new();
flatten_use(&item.tree, &mut Vec::new(), &mut paths);
for path in paths {
self.record_dependency(&path);
}
visit::visit_item_use(self, item);
}
fn visit_path(&mut self, path: &'ast SynPath) {
self.record_dependency(&path_segments(path));
visit::visit_path(self, path);
}
}
fn provider_dml_path_allowed(path: &str) -> bool {
[
"database/dao/provider_write.rs",
"database/dao/providers.rs",
"database/dao/failover.rs",
"database/schema.rs",
"database/migration.rs",
"database/backup.rs",
]
.iter()
.any(|allowed| path.ends_with(allowed))
}
fn scan_source(path: &str, source: &str) -> (Vec<Violation>, BTreeSet<String>) {
let syntax = match syn::parse_file(source) {
Ok(syntax) => syntax,
Err(error) => {
return (
vec![Violation {
kind: "parse_error",
path: path.to_string(),
detail: error.to_string(),
}],
BTreeSet::new(),
)
}
};
let mut visitor = ArchitectureVisitor {
path,
violations: Vec::new(),
internal_edges: BTreeSet::new(),
};
visitor.visit_file(&syntax);
(visitor.violations, visitor.internal_edges)
}
fn rust_sources(root: &Path) -> Vec<PathBuf> {
fn walk(directory: &Path, output: &mut Vec<PathBuf>) {
let mut entries = fs::read_dir(directory)
.unwrap_or_else(|error| panic!("read {}: {error}", directory.display()))
.collect::<Result<Vec<_>, _>>()
.unwrap_or_else(|error| panic!("read entry in {}: {error}", directory.display()));
entries.sort_by_key(|entry| entry.path());
for entry in entries {
let path = entry.path();
if path.is_dir() {
walk(&path, output);
} else if path.extension().is_some_and(|extension| extension == "rs") {
output.push(path);
}
}
}
let mut output = Vec::new();
walk(root, &mut output);
output
}
fn type_leaf(ty: &Type) -> String {
match ty {
Type::Path(path) => path
.path
.segments
.last()
.map(|segment| segment.ident.to_string())
.unwrap_or_else(|| "unknown".to_string()),
Type::Reference(reference) => type_leaf(&reference.elem),
_ => "other".to_string(),
}
}
fn provider_write_api_snapshot(source: &str) -> serde_json::Value {
let syntax = syn::parse_file(source).expect("parse provider write authority");
let type_names = [
"ProviderKey",
"ProviderRowUpdate",
"NewEndpoint",
"NewProviderAggregate",
"RenameProvider",
];
let method_names = [
"create_provider",
"update_provider",
"rename_db_only_additive_provider",
"add_provider_endpoint",
"remove_provider_endpoint",
"touch_provider_endpoint",
];
let mut types = BTreeMap::<String, Vec<String>>::new();
let mut methods = BTreeMap::<String, Vec<String>>::new();
for item in syntax.items {
if let Item::Struct(ItemStruct { ident, fields, .. }) = &item {
if type_names.contains(&ident.to_string().as_str()) {
types.insert(
ident.to_string(),
fields
.iter()
.filter_map(|field| field.ident.as_ref().map(ToString::to_string))
.collect(),
);
}
}
if let Item::Impl(ItemImpl { self_ty, items, .. }) = item {
if type_leaf(&self_ty) != "Database" {
continue;
}
for item in items {
let ImplItem::Fn(function) = item else {
continue;
};
let name = function.sig.ident.to_string();
if !method_names.contains(&name.as_str()) {
continue;
}
let inputs = function
.sig
.inputs
.iter()
.filter_map(|argument| match argument {
syn::FnArg::Receiver(_) => None,
syn::FnArg::Typed(argument) => Some(type_leaf(&argument.ty)),
})
.collect();
methods.insert(name, inputs);
}
}
}
json!({
"manifestVersion": 1,
"codeAuthority": "src-tauri/src/database/dao/provider_write.rs",
"types": types,
"databaseMethods": methods,
})
}
#[test]
fn architecture_scanner_accepts_production_tree_and_matches_machine_snapshots() {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let source_root = manifest_dir.join("src");
let mut violations = Vec::new();
let mut edges = BTreeSet::new();
for path in rust_sources(&source_root) {
let relative = path
.strip_prefix(manifest_dir)
.expect("source is under manifest")
.to_string_lossy()
.replace('\\', "/");
if relative.ends_with("architecture_tests.rs")
|| relative.ends_with("/tests.rs")
|| relative.contains("/tests/")
{
continue;
}
let source = fs::read_to_string(&path)
.unwrap_or_else(|error| panic!("read {}: {error}", path.display()));
let (mut source_violations, source_edges) = scan_source(&relative, &source);
violations.append(&mut source_violations);
edges.extend(source_edges);
}
assert!(
violations.is_empty(),
"architecture violations:\n{}",
violations
.iter()
.map(|violation| format!(
"{} {}: {}",
violation.kind, violation.path, violation.detail
))
.collect::<Vec<_>>()
.join("\n")
);
// Integration tests compile as external consumers and used to retain
// calls to the deleted generic writer even after `cargo test --lib`
// passed. They may contain deliberate SQL fixtures, so this pass checks
// only that the forbidden API surface is absent from actual Rust syntax.
let mut forbidden_test_symbols = Vec::new();
for path in rust_sources(&manifest_dir.join("tests")) {
let relative = path
.strip_prefix(manifest_dir)
.expect("integration test is under manifest")
.to_string_lossy()
.replace('\\', "/");
let source = fs::read_to_string(&path)
.unwrap_or_else(|error| panic!("read {}: {error}", path.display()));
let (source_violations, _) = scan_source(&relative, &source);
forbidden_test_symbols.extend(
source_violations
.into_iter()
.filter(|violation| violation.kind == "forbidden_provider_symbol"),
);
}
assert!(
forbidden_test_symbols.is_empty(),
"forbidden provider write symbols remain in integration tests:\n{}",
forbidden_test_symbols
.iter()
.map(|violation| format!("{}: {}", violation.path, violation.detail))
.collect::<Vec<_>>()
.join("\n")
);
let module_snapshot: serde_json::Value = serde_json::from_str(include_str!(
"../../tests/fixtures/pi/module-boundaries-v1.json"
))
.expect("parse module boundary snapshot");
assert_eq!(
json!({
"manifestVersion": 1,
"codeAuthority": "src-tauri/src/architecture_tests.rs",
"edges": edges,
}),
module_snapshot
);
let provider_source = fs::read_to_string(source_root.join("database/dao/provider_write.rs"))
.expect("read provider write authority");
let provider_snapshot: serde_json::Value = serde_json::from_str(include_str!(
"../../tests/fixtures/pi/provider-write-api-v1.json"
))
.expect("parse provider write API snapshot");
assert_eq!(
provider_write_api_snapshot(&provider_source),
provider_snapshot
);
}
#[test]
fn architecture_scanner_negative_fixtures_prove_each_guard_fires() {
let cases = [
(
"src/services/forbidden.rs",
"fn call() { save_provider(); }",
"forbidden_provider_symbol",
),
(
"src/services/rogue.rs",
r#"fn write(conn: &Db) { conn.execute("UPDATE OR REPLACE providers SET name = 'x'", []); }"#,
"provider_dml",
),
(
"src/database/backup.rs",
r#"fn stage(conn: &Db) { conn.execute("CREATE TABLE leaked (id INTEGER)", []); }"#,
"restore_create",
),
(
"src/pi_config/composer.rs",
"use super::gateway::PiGatewayApiFamily;",
"cross_layer_import",
),
(
"src/pi_config/gateway.rs",
"use super::raw_schema::PiRawValidProvider;",
"cross_layer_import",
),
];
for (path, source, expected_kind) in cases {
let (violations, _) = scan_source(path, source);
assert!(
violations
.iter()
.any(|violation| violation.kind == expected_kind),
"negative fixture {path} did not trigger {expected_kind}: {violations:?}"
);
}
let ignored_test_fixture = r#"
#[cfg(test)]
mod tests {
fn legacy() {
save_provider();
let _ = "CREATE TABLE ignored (id INTEGER)";
let _ = "DELETE FROM providers";
}
}
"#;
let (violations, _) = scan_source("src/services/ignored.rs", ignored_test_fixture);
assert!(
violations.is_empty(),
"#[cfg(test)] content must be excluded: {violations:?}"
);
}
+3
View File
@@ -39,6 +39,9 @@ mod tray;
mod usage_events;
mod usage_script;
#[cfg(test)]
mod architecture_tests;
pub use app_config::{AppType, InstalledSkill, McpApps, McpServer, MultiAppConfig, SkillApps};
pub use codex_config::{get_codex_auth_path, get_codex_config_path, write_codex_live_atomic};
pub use commands::open_provider_terminal;
+752
View File
@@ -0,0 +1,752 @@
//! Credential-blind Pi native model composition.
//!
//! The only Pi-layer input is [`PiRawValidProvider`]. This module does not
//! import managed DTOs or gateway families, and it never resolves credentials,
//! environment variables, commands, files, or network resources.
#![allow(dead_code)]
use super::raw_schema::{PiRawApiId, PiRawValidProvider};
use serde_json::{json, Map, Value};
use std::collections::{BTreeMap, HashSet};
const PROVIDER_FIELDS: &[&str] = &[
"name",
"baseUrl",
"apiKey",
"api",
"oauth",
"headers",
"compat",
"authHeader",
"models",
"modelOverrides",
];
const MODEL_FIELDS: &[&str] = &[
"id",
"name",
"baseUrl",
"api",
"reasoning",
"thinkingLevelMap",
"input",
"cost",
"contextWindow",
"maxTokens",
"headers",
"compat",
];
const OVERRIDE_FIELDS: &[&str] = &[
"name",
"reasoning",
"thinkingLevelMap",
"input",
"cost",
"contextWindow",
"maxTokens",
"headers",
"compat",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PiComposerStatus {
Composed,
Failed,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PiComposerReasonCode {
CatalogRequired,
MissingExplicitModels,
MissingEffectiveApi,
MissingEffectiveEndpoint,
NonPositiveModelLimit,
CompositionFailed,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct PiComposerReason {
pub code: PiComposerReasonCode,
pub json_pointer: String,
}
/// The lossless native result of pinned Pi composition.
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct PiComposedNativeModel {
pub id: String,
pub name: String,
pub api: PiRawApiId,
pub provider: String,
pub base_url: String,
pub reasoning: bool,
pub thinking_level_map: Option<Value>,
pub input: Value,
pub cost: Value,
pub context_window: Value,
pub max_tokens: Value,
pub headers: BTreeMap<String, String>,
pub compat: Option<Value>,
pub api_key: Option<String>,
pub oauth: Option<Value>,
pub auth_header: bool,
pub provider_extra: BTreeMap<String, Value>,
pub model_extra: BTreeMap<String, Value>,
pub override_extra: BTreeMap<String, Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct PiNativeComposition {
pub status: PiComposerStatus,
pub provider_id: Option<String>,
pub provider_name: Option<String>,
pub provider_base_url: Option<String>,
pub models: Vec<PiComposedNativeModel>,
pub ignored_override_keys: Vec<String>,
pub reasons: Vec<PiComposerReason>,
}
impl PiNativeComposition {
pub(super) fn unavailable_without_valid_raw() -> Self {
Self {
status: PiComposerStatus::Unknown,
provider_id: None,
provider_name: None,
provider_base_url: None,
models: Vec::new(),
ignored_override_keys: Vec::new(),
reasons: Vec::new(),
}
}
pub(super) fn catalog_required(pointer: &str) -> Self {
Self {
status: PiComposerStatus::Unknown,
provider_id: None,
provider_name: None,
provider_base_url: None,
models: Vec::new(),
ignored_override_keys: Vec::new(),
reasons: vec![PiComposerReason {
code: PiComposerReasonCode::CatalogRequired,
json_pointer: pointer.to_string(),
}],
}
}
fn failed(code: PiComposerReasonCode, pointer: impl Into<String>) -> Self {
Self {
status: PiComposerStatus::Failed,
provider_id: None,
provider_name: None,
provider_base_url: None,
models: Vec::new(),
ignored_override_keys: Vec::new(),
reasons: vec![PiComposerReason {
code,
json_pointer: pointer.into(),
}],
}
}
}
pub(super) fn compose_explicit_custom_catalog(
provider_id: &str,
provider: &PiRawValidProvider,
) -> PiNativeComposition {
let Some(provider_object) = provider.raw().as_object() else {
return PiNativeComposition::failed(PiComposerReasonCode::CompositionFailed, "");
};
let Some(definitions) = provider_object
.get("models")
.and_then(Value::as_array)
.filter(|models| !models.is_empty())
else {
return PiNativeComposition::failed(PiComposerReasonCode::MissingExplicitModels, "/models");
};
let provider_api = provider_object.get("api").and_then(Value::as_str);
let provider_base_url = provider_object.get("baseUrl").and_then(Value::as_str);
if provider_object.get("oauth").and_then(Value::as_str) == Some("radius")
&& provider_base_url.is_none()
{
return PiNativeComposition::failed(
PiComposerReasonCode::MissingEffectiveEndpoint,
"/baseUrl",
);
}
let provider_compat = provider_object.get("compat").cloned();
let provider_headers = string_map(provider_object.get("headers"));
let provider_extra = unknown_fields(provider_object, PROVIDER_FIELDS);
let api_key = provider_object
.get("apiKey")
.and_then(Value::as_str)
.map(ToOwned::to_owned);
let oauth = provider_object.get("oauth").cloned();
let auth_header = provider_object
.get("authHeader")
.and_then(Value::as_bool)
.unwrap_or(false);
let overrides = provider_object
.get("modelOverrides")
.and_then(Value::as_object);
let mut models: Vec<PiComposedNativeModel> = Vec::with_capacity(definitions.len());
for (index, definition_value) in definitions.iter().enumerate() {
let Some(definition) = definition_value.as_object() else {
return PiNativeComposition::failed(
PiComposerReasonCode::CompositionFailed,
format!("/models/{index}"),
);
};
let Some(id) = definition.get("id").and_then(Value::as_str) else {
return PiNativeComposition::failed(
PiComposerReasonCode::CompositionFailed,
format!("/models/{index}/id"),
);
};
let existing_index = models.iter().position(|model| model.id == id);
let defaults = existing_index
.and_then(|position| models.get(position))
.or_else(|| models.first());
let api_value = definition
.get("api")
.and_then(Value::as_str)
.or(provider_api)
.or_else(|| defaults.map(|model| model.api.as_str()));
let Some(api_value) = api_value else {
return PiNativeComposition::failed(
PiComposerReasonCode::MissingEffectiveApi,
format!("/models/{index}/api"),
);
};
let Some(api) = PiRawApiId::new(api_value) else {
return PiNativeComposition::failed(
PiComposerReasonCode::MissingEffectiveApi,
format!("/models/{index}/api"),
);
};
let base_url = definition
.get("baseUrl")
.and_then(Value::as_str)
.or(provider_base_url)
.or_else(|| defaults.map(|model| model.base_url.as_str()));
let Some(base_url) = base_url.filter(|value| !value.is_empty()) else {
return PiNativeComposition::failed(
PiComposerReasonCode::MissingEffectiveEndpoint,
format!("/models/{index}/baseUrl"),
);
};
for (field, code) in [
("contextWindow", PiComposerReasonCode::NonPositiveModelLimit),
("maxTokens", PiComposerReasonCode::NonPositiveModelLimit),
] {
if definition
.get(field)
.and_then(Value::as_f64)
.is_some_and(|value| value <= 0.0)
{
return PiNativeComposition::failed(code, format!("/models/{index}/{field}"));
}
}
let model = PiComposedNativeModel {
id: id.to_string(),
name: definition
.get("name")
.and_then(Value::as_str)
.unwrap_or(id)
.to_string(),
api,
provider: provider_id.to_string(),
base_url: base_url.to_string(),
reasoning: definition
.get("reasoning")
.and_then(Value::as_bool)
.unwrap_or(false),
thinking_level_map: definition.get("thinkingLevelMap").cloned(),
input: definition
.get("input")
.cloned()
.unwrap_or_else(|| json!(["text"])),
cost: definition.get("cost").cloned().unwrap_or_else(default_cost),
context_window: definition
.get("contextWindow")
.cloned()
.unwrap_or_else(|| json!(128000)),
max_tokens: definition
.get("maxTokens")
.cloned()
.unwrap_or_else(|| json!(16384)),
headers: BTreeMap::new(),
compat: merge_compat(provider_compat.clone(), definition.get("compat").cloned()),
api_key: api_key.clone(),
oauth: oauth.clone(),
auth_header,
provider_extra: provider_extra.clone(),
model_extra: unknown_fields(definition, MODEL_FIELDS),
override_extra: BTreeMap::new(),
};
if let Some(existing_index) = existing_index {
models[existing_index] = model;
} else {
models.push(model);
}
}
for model in &mut models {
// Pinned Pi's rawModelHeaders uses Array.find, so duplicate model
// definitions obtain request headers from the first definition even
// though the later definition replaces the composed model slot.
let definition = definitions
.iter()
.filter_map(Value::as_object)
.find(|definition| {
definition.get("id").and_then(Value::as_str) == Some(model.id.as_str())
})
.expect("raw-valid composed model has a source definition");
let model_override =
overrides.and_then(|overrides| overrides.get(&model.id).and_then(Value::as_object));
let mut headers = provider_headers.clone();
if let Some(model_override) = model_override {
headers.extend(string_map(model_override.get("headers")));
}
headers.extend(string_map(definition.get("headers")));
model.headers = headers;
if let Some(model_override) = model_override {
if let Some(name) = model_override.get("name").and_then(Value::as_str) {
model.name = name.to_string();
}
if let Some(reasoning) = model_override.get("reasoning").and_then(Value::as_bool) {
model.reasoning = reasoning;
}
if let Some(override_map) = model_override
.get("thinkingLevelMap")
.and_then(Value::as_object)
{
let mut merged = model
.thinking_level_map
.take()
.and_then(|value| value.as_object().cloned())
.unwrap_or_default();
merged.extend(override_map.clone());
model.thinking_level_map = Some(Value::Object(merged));
}
if let Some(input) = model_override.get("input") {
model.input = input.clone();
}
if let Some(cost) = model_override.get("cost").and_then(Value::as_object) {
model.cost = merge_cost(&model.cost, cost);
}
if let Some(context_window) = model_override.get("contextWindow") {
model.context_window = context_window.clone();
}
if let Some(max_tokens) = model_override.get("maxTokens") {
model.max_tokens = max_tokens.clone();
}
model.compat =
merge_compat(model.compat.clone(), model_override.get("compat").cloned());
model.override_extra = unknown_fields(model_override, OVERRIDE_FIELDS);
}
}
let model_ids = models
.iter()
.map(|model| model.id.as_str())
.collect::<HashSet<_>>();
let ignored_override_keys = overrides
.into_iter()
.flat_map(|overrides| overrides.keys())
.filter(|model_id| !model_ids.contains(model_id.as_str()))
.cloned()
.collect();
PiNativeComposition {
status: PiComposerStatus::Composed,
provider_id: Some(provider_id.to_string()),
provider_name: Some(
provider_object
.get("name")
.and_then(Value::as_str)
.unwrap_or(provider_id)
.to_string(),
),
provider_base_url: provider_base_url.map(ToOwned::to_owned),
models,
ignored_override_keys,
reasons: Vec::new(),
}
}
fn default_cost() -> Value {
json!({
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
})
}
fn merge_cost(base: &Value, overlay: &Map<String, Value>) -> Value {
let mut merged = base.as_object().cloned().unwrap_or_default();
for key in ["input", "output", "cacheRead", "cacheWrite", "tiers"] {
if let Some(value) = overlay.get(key) {
merged.insert(key.to_string(), value.clone());
}
}
Value::Object(merged)
}
fn merge_compat(base: Option<Value>, overlay: Option<Value>) -> Option<Value> {
let Some(overlay) = overlay else {
return base;
};
let mut merged = base
.as_ref()
.and_then(Value::as_object)
.cloned()
.unwrap_or_default();
let Some(overlay_object) = overlay.as_object() else {
return Some(overlay);
};
for (key, value) in overlay_object {
if matches!(
key.as_str(),
"openRouterRouting" | "vercelGatewayRouting" | "chatTemplateKwargs"
) {
let base_nested = merged.get(key).and_then(Value::as_object);
let override_nested = value.as_object();
if base_nested.is_some() || override_nested.is_some() {
let mut nested = base_nested.cloned().unwrap_or_default();
if let Some(override_nested) = override_nested {
nested.extend(override_nested.clone());
}
merged.insert(key.clone(), Value::Object(nested));
continue;
}
}
merged.insert(key.clone(), value.clone());
}
Some(Value::Object(merged))
}
fn string_map(value: Option<&Value>) -> BTreeMap<String, String> {
value
.and_then(Value::as_object)
.into_iter()
.flat_map(|object| object.iter())
.filter_map(|(key, value)| value.as_str().map(|value| (key.clone(), value.to_string())))
.collect()
}
fn unknown_fields(object: &Map<String, Value>, recognized: &[&str]) -> BTreeMap<String, Value> {
object
.iter()
.filter(|(key, _)| !recognized.contains(&key.as_str()))
.map(|(key, value)| (key.clone(), value.clone()))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pi_config::raw_schema::{evaluate_provider_value, PiRawValidity};
use serde::Deserialize;
const COMPOSER_ORACLE_SOURCE: &str =
include_str!("../../../tests/fixtures/pi/native-oracle/composer-oracle-v1.json");
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComposerOracle {
cases: Vec<ComposerOracleCase>,
fail_closed_cases: Vec<FailClosedCase>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComposerOracleCase {
id: String,
provider_id: String,
input: Value,
execution: Execution,
#[serde(default)]
auth_execution: Option<Value>,
#[serde(default)]
expected: Option<Value>,
#[serde(default)]
expected_error: Option<String>,
}
#[derive(Deserialize)]
struct Execution {
status: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct FailClosedCase {
id: String,
rust_expected_status: String,
reason_code: String,
}
fn model_as_oracle_value(model: &PiComposedNativeModel) -> Value {
let mut object = Map::new();
object.insert("id".into(), json!(model.id));
object.insert("name".into(), json!(model.name));
object.insert("api".into(), json!(model.api.as_str()));
object.insert("provider".into(), json!(model.provider));
object.insert("baseUrl".into(), json!(model.base_url));
object.insert("reasoning".into(), json!(model.reasoning));
if let Some(thinking) = &model.thinking_level_map {
object.insert("thinkingLevelMap".into(), thinking.clone());
}
object.insert("input".into(), model.input.clone());
object.insert("cost".into(), model.cost.clone());
object.insert("contextWindow".into(), model.context_window.clone());
object.insert("maxTokens".into(), model.max_tokens.clone());
object.insert("authHeader".into(), json!(model.auth_header));
if let Some(compat) = &model.compat {
object.insert("compat".into(), compat.clone());
}
if !model.headers.is_empty() {
object.insert("headers".into(), json!(model.headers));
}
Value::Object(object)
}
fn provider_as_oracle_value(composition: &PiNativeComposition) -> Value {
let mut object = Map::new();
object.insert(
"id".into(),
json!(composition
.provider_id
.as_ref()
.expect("composed provider id")),
);
object.insert(
"name".into(),
json!(composition
.provider_name
.as_ref()
.expect("composed provider name")),
);
if let Some(base_url) = &composition.provider_base_url {
object.insert("baseUrl".into(), json!(base_url));
}
Value::Object(object)
}
fn json_numbers_equal(left: &Value, right: &Value) -> bool {
match (left, right) {
(Value::Number(left), Value::Number(right)) => left.as_f64() == right.as_f64(),
(Value::Array(left), Value::Array(right)) => {
left.len() == right.len()
&& left
.iter()
.zip(right)
.all(|(left, right)| json_numbers_equal(left, right))
}
(Value::Object(left), Value::Object(right)) => {
left.len() == right.len()
&& left.iter().all(|(key, left)| {
right
.get(key)
.is_some_and(|right| json_numbers_equal(left, right))
})
}
_ => left == right,
}
}
#[test]
fn rust_composer_matches_actual_pinned_upstream_execution() {
let oracle: ComposerOracle =
serde_json::from_str(COMPOSER_ORACLE_SOURCE).expect("parse composer oracle");
for case in oracle.cases {
let raw = evaluate_provider_value(&case.input);
if case.execution.status == "error" {
assert!(
case.expected_error.is_some(),
"upstream error vector '{}' records its actual error",
case.id
);
match raw.validity {
PiRawValidity::Invalid => {}
PiRawValidity::Valid => {
let result = compose_explicit_custom_catalog(
&case.provider_id,
raw.valid_provider.as_ref().expect("raw-valid provider"),
);
assert_eq!(
result.status,
PiComposerStatus::Failed,
"raw-valid upstream error case '{}'",
case.id
);
}
PiRawValidity::Unknown => {
panic!("oracle case '{}' unexpectedly became Unknown", case.id)
}
}
continue;
}
assert_eq!(raw.validity, PiRawValidity::Valid, "case '{}'", case.id);
let result = compose_explicit_custom_catalog(
&case.provider_id,
raw.valid_provider.as_ref().expect("raw-valid provider"),
);
assert_eq!(
result.status,
PiComposerStatus::Composed,
"case '{}'",
case.id
);
let auth_execution = case
.auth_execution
.as_ref()
.expect("successful composer case records actual auth execution");
assert_eq!(
auth_execution.pointer("/status").and_then(Value::as_str),
Some("success"),
"case '{}'",
case.id
);
let actual_resolved_key = auth_execution
.pointer("/result/auth/apiKey")
.and_then(Value::as_str)
.expect("successful literal composer vector resolves an API key");
assert!(
result
.models
.iter()
.all(|model| { model.api_key.as_deref() == Some(actual_resolved_key) }),
"case '{}' preserves the same literal key that pinned Pi resolved",
case.id
);
if case
.input
.get("authHeader")
.and_then(Value::as_bool)
.unwrap_or(false)
{
let expected_bearer = format!("Bearer {actual_resolved_key}");
assert_eq!(
auth_execution
.pointer("/result/auth/headers/Authorization")
.and_then(Value::as_str),
Some(expected_bearer.as_str()),
"case '{}' uses pinned Pi authHeader behavior",
case.id
);
}
let actual = json!({
"provider": provider_as_oracle_value(&result),
"models": result
.models
.iter()
.map(model_as_oracle_value)
.collect::<Vec<_>>(),
"ignoredOverrideKeys": result.ignored_override_keys,
});
let expected = case.expected.expect("successful upstream expected output");
assert!(
json_numbers_equal(&actual, &expected),
"oracle case '{}'\nactual: {actual:#}\nexpected: {expected:#}",
case.id
);
}
}
#[test]
fn unavailable_upstream_catalog_semantics_are_explicitly_unknown() {
let oracle: ComposerOracle =
serde_json::from_str(COMPOSER_ORACLE_SOURCE).expect("parse composer oracle");
assert_eq!(oracle.fail_closed_cases.len(), 2);
for case in oracle.fail_closed_cases {
assert_eq!(case.rust_expected_status, "unknown", "case '{}'", case.id);
assert_eq!(case.reason_code, "catalog_required", "case '{}'", case.id);
let result = PiNativeComposition::catalog_required("/models");
assert_eq!(result.status, PiComposerStatus::Unknown);
assert_eq!(
result.reasons[0].code,
PiComposerReasonCode::CatalogRequired
);
}
}
#[test]
fn credential_expressions_are_preserved_without_execution() {
let value = json!({
"api": "openai-responses",
"baseUrl": "https://example.test/v1",
"apiKey": "!read-secret",
"oauth": "radius",
"authHeader": true,
"headers": {"x-tenant": "${TENANT}"},
"models": [{"id": "m"}]
});
let raw = evaluate_provider_value(&value);
let composed = compose_explicit_custom_catalog(
"deferred",
raw.valid_provider.as_ref().expect("raw-valid"),
);
assert_eq!(composed.status, PiComposerStatus::Composed);
assert_eq!(composed.models[0].api_key.as_deref(), Some("!read-secret"));
assert_eq!(composed.models[0].oauth, Some(json!("radius")));
assert!(composed.models[0].auth_header);
assert_eq!(composed.models[0].headers["x-tenant"], "${TENANT}");
}
#[test]
fn unknown_provider_model_and_override_fields_are_retained_losslessly() {
let value = json!({
"api": "future-wire-v9",
"baseUrl": "https://example.test/v9",
"apiKey": "literal",
"futureProviderShape": {
"nested": [1, {"flag": true}]
},
"models": [{
"id": "m",
"futureModelShape": {
"mode": "novel",
"threshold": 0.125
}
}],
"modelOverrides": {
"m": {
"futureOverrideShape": [
null,
{"preserve": "exactly"}
]
}
}
});
let raw = evaluate_provider_value(&value);
let composed = compose_explicit_custom_catalog(
"lossless",
raw.valid_provider.as_ref().expect("raw-valid"),
);
assert_eq!(composed.status, PiComposerStatus::Composed);
let model = &composed.models[0];
assert_eq!(
model.provider_extra["futureProviderShape"],
json!({"nested": [1, {"flag": true}]})
);
assert_eq!(
model.model_extra["futureModelShape"],
json!({"mode": "novel", "threshold": 0.125})
);
assert_eq!(
model.override_extra["futureOverrideShape"],
json!([null, {"preserve": "exactly"}])
);
}
}
+334
View File
@@ -0,0 +1,334 @@
//! Read-only access to Pi's shared `models.json` document.
//!
//! The semantic parse mirrors Pi's pinned `stripJsonComments()` behavior.
//! A CST parse is additionally required so callers can fingerprint one exact
//! provider value without making unrelated entries part of the revision.
use crate::error::AppError;
use indexmap::IndexMap;
use jsonc_parser::cst::{CstContainerNode, CstNode, CstObject, CstObjectProp, CstRootNode};
use jsonc_parser::ParseOptions;
use regex::Regex;
use serde_json::Value;
use std::fs::{self, File, Metadata, OpenOptions};
use std::io::{Read, Take};
use std::path::Path;
use std::sync::LazyLock;
const MAX_PI_MODELS_BYTES: u64 = 8 * 1024 * 1024;
const EMPTY_MODELS_DOCUMENT: &str = "{\"providers\":{}}";
static PI_JSON_LINE_COMMENTS: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#""(?:\\.|[^"\\])*"|//[^\n]*"#).expect("Pi JSON line-comment regex must compile")
});
static PI_JSON_TRAILING_COMMAS: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#""(?:\\.|[^"\\])*"|,(\s*[}\]])"#)
.expect("Pi JSON trailing-comma regex must compile")
});
#[derive(Debug, Clone)]
pub(super) struct PiRawProviderEntry {
pub value: Value,
pub raw_source: String,
}
#[derive(Debug, Clone)]
pub(super) struct PiModelsDocument {
providers: IndexMap<String, PiRawProviderEntry>,
}
impl PiModelsDocument {
pub fn providers(&self) -> &IndexMap<String, PiRawProviderEntry> {
&self.providers
}
}
fn pi_models_parse_options() -> ParseOptions {
// Pinned Pi accepts standard double-quoted JSON with `//` comments and
// trailing commas. jsonc-parser is broader by default, so all other
// extensions stay disabled.
ParseOptions {
allow_comments: true,
allow_loose_object_property_names: false,
allow_trailing_commas: true,
allow_missing_commas: false,
allow_single_quoted_strings: false,
allow_hexadecimal_numbers: false,
allow_unary_plus_numbers: false,
}
}
fn jsonc_error(path: &Path, message: impl std::fmt::Display) -> AppError {
AppError::Config(format!(
"JSON parse error in Pi models file {}: {message}",
path.display()
))
}
/// Mirrors Pi commit `ab366ebe94cacd419d986be454f12b1b9913aaca`
/// (`packages/coding-agent/src/utils/json.ts`).
fn strip_pi_json_comments(input: &str) -> String {
let without_comments =
PI_JSON_LINE_COMMENTS.replace_all(input, |captures: &regex::Captures<'_>| {
let matched = captures
.get(0)
.expect("the full regex match is always present")
.as_str();
if matched.starts_with('"') {
matched.to_string()
} else {
String::new()
}
});
PI_JSON_TRAILING_COMMAS
.replace_all(&without_comments, |captures: &regex::Captures<'_>| {
captures
.get(1)
.or_else(|| captures.get(0))
.expect("the full regex match is always present")
.as_str()
.to_string()
})
.into_owned()
}
fn cst_property_name(property: &CstObjectProp) -> Option<String> {
property.name()?.decoded_value().ok()
}
fn last_cst_property(object: &CstObject, name: &str) -> Option<CstObjectProp> {
object
.properties()
.into_iter()
.rev()
.find(|property| cst_property_name(property).as_deref() == Some(name))
}
fn cst_object(node: CstNode, path: &Path, label: &str) -> Result<CstObject, AppError> {
match node {
CstNode::Container(CstContainerNode::Object(object)) => Ok(object),
_ => Err(jsonc_error(path, format!("{label} must be an object"))),
}
}
fn parse_models_source(path: &Path, source: &str) -> Result<PiModelsDocument, AppError> {
let document: Value = serde_json::from_str(&strip_pi_json_comments(source))
.map_err(|error| AppError::json(path, error))?;
let root = CstRootNode::parse(source, &pi_models_parse_options())
.map_err(|error| jsonc_error(path, error))?;
if root.to_serde_value().as_ref() != Some(&document) {
return Err(jsonc_error(path, "CST does not match Pi's parsed document"));
}
let semantic_providers = document
.as_object()
.and_then(|root| root.get("providers"))
.and_then(Value::as_object)
.ok_or_else(|| jsonc_error(path, "root must contain a providers object"))?;
let root_object = cst_object(
root.value()
.ok_or_else(|| jsonc_error(path, "document must contain a JSON value"))?,
path,
"root",
)?;
let providers_node = last_cst_property(&root_object, "providers")
.and_then(|property| property.value())
.ok_or_else(|| jsonc_error(path, "CST is missing the providers value"))?;
let providers_object = cst_object(providers_node, path, "providers")?;
let mut providers = IndexMap::with_capacity(semantic_providers.len());
for (provider_key, value) in semantic_providers {
let raw_source = last_cst_property(&providers_object, provider_key)
.and_then(|property| property.value())
.ok_or_else(|| {
jsonc_error(
path,
format!("CST is missing provider entry '{provider_key}'"),
)
})?
.to_string();
providers.insert(
provider_key.clone(),
PiRawProviderEntry {
value: value.clone(),
raw_source,
},
);
}
Ok(PiModelsDocument { providers })
}
#[cfg(unix)]
fn open_read_only(path: &Path) -> std::io::Result<File> {
use std::os::unix::fs::OpenOptionsExt;
OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW)
.open(path)
}
#[cfg(not(unix))]
fn open_read_only(path: &Path) -> std::io::Result<File> {
OpenOptions::new().read(true).open(path)
}
#[cfg(unix)]
fn same_file(opened: &Metadata, current: &Metadata) -> bool {
use std::os::unix::fs::MetadataExt;
opened.dev() == current.dev() && opened.ino() == current.ino()
}
#[cfg(not(unix))]
fn same_file(opened: &Metadata, current: &Metadata) -> bool {
opened.len() == current.len() && opened.modified().ok() == current.modified().ok()
}
fn read_limited(mut reader: Take<&mut File>, path: &Path) -> Result<Vec<u8>, AppError> {
let mut bytes = Vec::new();
reader
.read_to_end(&mut bytes)
.map_err(|error| AppError::io(path, error))?;
if bytes.len() as u64 > MAX_PI_MODELS_BYTES {
return Err(AppError::Config(format!(
"Pi models file exceeds {} bytes: {}",
MAX_PI_MODELS_BYTES,
path.display()
)));
}
Ok(bytes)
}
fn read_models_bytes(path: &Path) -> Result<Option<Vec<u8>>, AppError> {
let initial = match fs::symlink_metadata(path) {
Ok(metadata) => metadata,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(error) => return Err(AppError::io(path, error)),
};
if !initial.file_type().is_file() {
return Err(AppError::Config(format!(
"Pi models path must be a regular file, not a symlink or special file: {}",
path.display()
)));
}
if initial.len() > MAX_PI_MODELS_BYTES {
return Err(AppError::Config(format!(
"Pi models file exceeds {} bytes: {}",
MAX_PI_MODELS_BYTES,
path.display()
)));
}
let mut file = open_read_only(path).map_err(|error| AppError::io(path, error))?;
let opened = file.metadata().map_err(|error| AppError::io(path, error))?;
if !opened.file_type().is_file() || opened.len() > MAX_PI_MODELS_BYTES {
return Err(AppError::Config(format!(
"Pi models path changed or exceeded its size limit: {}",
path.display()
)));
}
let bytes = read_limited(file.by_ref().take(MAX_PI_MODELS_BYTES + 1), path)?;
let completed = file.metadata().map_err(|error| AppError::io(path, error))?;
let current = fs::symlink_metadata(path).map_err(|error| AppError::io(path, error))?;
if !current.file_type().is_file()
|| !same_file(&completed, &current)
|| opened.len() != bytes.len() as u64
|| completed.len() != bytes.len() as u64
|| current.len() != bytes.len() as u64
|| opened.modified().ok() != completed.modified().ok()
{
return Err(AppError::Config(format!(
"Pi models file changed during inspection: {}",
path.display()
)));
}
Ok(Some(bytes))
}
pub(super) fn read_pi_models_document(path: &Path) -> Result<PiModelsDocument, AppError> {
let bytes =
read_models_bytes(path)?.unwrap_or_else(|| EMPTY_MODELS_DOCUMENT.as_bytes().to_vec());
let source = std::str::from_utf8(&bytes)
.map_err(|error| jsonc_error(path, format!("file is not UTF-8: {error}")))?;
parse_models_source(path, source)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn reads_exact_pi_jsonc_dialect_and_retains_entry_cst() {
let temp = tempfile::tempdir().expect("tempdir");
let path = temp.path().join("models.json");
fs::write(
&path,
r#"{
// root
"providers": {
"custom": {
// nested comment
"baseUrl": "https://example.test/v1",
"models": [{"id": "model//literal",},],
},
},
}
"#,
)
.expect("write");
let document = read_pi_models_document(&path).expect("read");
let entry = &document.providers()["custom"];
assert_eq!(entry.value["models"][0]["id"], "model//literal");
assert!(entry.raw_source.contains("// nested comment"));
assert!(entry.raw_source.contains("\"model//literal\""));
}
#[test]
fn rejects_json_extensions_that_pinned_pi_rejects() {
let temp = tempfile::tempdir().expect("tempdir");
for (case, source) in [
("single-quoted", "{'providers': {}}"),
("bare-key", "{providers: {}}"),
("block-comment", "{\"providers\": {/* nope */}}"),
("missing-comma", "{\"providers\": {} \"other\": 1}"),
] {
let path = temp.path().join(format!("{case}.json"));
fs::write(&path, source).expect("write");
assert!(read_pi_models_document(&path).is_err(), "{case} must fail");
}
}
#[test]
fn missing_file_is_an_empty_catalog_and_oversized_file_fails() {
let temp = tempfile::tempdir().expect("tempdir");
let missing = temp.path().join("missing-models.json");
assert!(read_pi_models_document(&missing)
.expect("missing")
.providers()
.is_empty());
let oversized = temp.path().join("oversized-models.json");
let mut file = File::create(&oversized).expect("create");
file.write_all(b"{").expect("seed");
file.set_len(MAX_PI_MODELS_BYTES + 1).expect("extend");
assert!(read_pi_models_document(&oversized).is_err());
}
#[cfg(unix)]
#[test]
fn symlink_is_never_followed() {
use std::os::unix::fs::symlink;
let temp = tempfile::tempdir().expect("tempdir");
let target = temp.path().join("target.json");
let link = temp.path().join("models.json");
fs::write(&target, EMPTY_MODELS_DOCUMENT).expect("target");
symlink(&target, &link).expect("symlink");
assert!(read_pi_models_document(&link).is_err());
}
}
+767
View File
@@ -0,0 +1,767 @@
//! Gateway-only Pi API families and candidate header planning.
//!
//! The four-family enum is intentionally confined to this module. Raw and
//! managed layers retain opaque API identifiers and cannot accidentally reject
//! a future Pi family merely because the gateway has not implemented it.
#![allow(dead_code)]
use super::composer::{PiComposedNativeModel, PiComposerStatus, PiNativeComposition};
use http::{HeaderMap, HeaderName, HeaderValue};
use url::Url;
const PROTECTED_HEADERS: &[&str] = &[
"authorization",
"connection",
"content-length",
"host",
"keep-alive",
"proxy-authenticate",
"proxy-authorization",
"te",
"trailer",
"transfer-encoding",
"upgrade",
"x-api-key",
"x-goog-api-key",
];
const PROTOCOL_HEADERS: &[&str] = &[
"anthropic-version",
"anthropic-beta",
"openai-beta",
"openai-version",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum PiGatewayApiFamily {
AnthropicMessages,
OpenAiCompletions,
OpenAiResponses,
GoogleGenerativeAi,
}
impl PiGatewayApiFamily {
pub(super) const ALL: [Self; 4] = [
Self::AnthropicMessages,
Self::OpenAiCompletions,
Self::OpenAiResponses,
Self::GoogleGenerativeAi,
];
pub(super) const fn as_str(self) -> &'static str {
match self {
Self::AnthropicMessages => "anthropic-messages",
Self::OpenAiCompletions => "openai-completions",
Self::OpenAiResponses => "openai-responses",
Self::GoogleGenerativeAi => "google-generative-ai",
}
}
fn parse(value: &str) -> Option<Self> {
Self::ALL
.into_iter()
.find(|family| family.as_str() == value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum PiGatewayCapability {
Proxyable,
DirectOnly,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum PiGatewayReasonCode {
UnsupportedFamily,
InvalidEndpoint,
MissingCredential,
InvalidHeaderName,
InvalidHeaderValue,
ProtectedHeader,
DeferredValueUnavailable,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct PiGatewayReason {
pub code: PiGatewayReasonCode,
pub json_pointer: String,
}
#[derive(Debug, Clone)]
pub(super) struct PiGatewayAssessment {
pub capability: PiGatewayCapability,
pub reasons: Vec<PiGatewayReason>,
pub plans: Vec<CandidateHeaderPlan>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct DeferredHeaderValue {
raw: String,
}
impl DeferredHeaderValue {
fn new(raw: impl Into<String>) -> Self {
Self { raw: raw.into() }
}
fn materialize(
&self,
resolver: &impl DeferredValueResolver,
pointer: &str,
) -> Result<HeaderValue, PiGatewayReason> {
let materialized = if is_deferred(&self.raw) {
resolver.resolve(&self.raw).ok_or_else(|| PiGatewayReason {
code: PiGatewayReasonCode::DeferredValueUnavailable,
json_pointer: pointer.to_string(),
})?
} else {
self.raw.clone()
};
HeaderValue::from_str(&materialized).map_err(|_| PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: pointer.to_string(),
})
}
}
#[derive(Debug, Clone)]
pub(super) struct CandidateHeaderPlan {
family: PiGatewayApiFamily,
endpoint: Url,
credential: DeferredHeaderValue,
auth_header: bool,
custom_headers: Vec<(HeaderName, String, DeferredHeaderValue)>,
protocol_headers: Vec<(HeaderName, String, DeferredHeaderValue)>,
protocol_identity_predictable: bool,
}
#[derive(Debug, Clone)]
pub(super) struct MaterializedCandidate {
pub endpoint: Url,
pub headers: HeaderMap,
family: PiGatewayApiFamily,
protocol_headers: HeaderMap,
protocol_identity_predictable: bool,
}
pub(super) trait DeferredValueResolver {
fn resolve(&self, expression: &str) -> Option<String>;
}
impl<F> DeferredValueResolver for F
where
F: Fn(&str) -> Option<String>,
{
fn resolve(&self, expression: &str) -> Option<String> {
self(expression)
}
}
impl CandidateHeaderPlan {
fn build(
model: &PiComposedNativeModel,
model_index: usize,
) -> Result<Self, Vec<PiGatewayReason>> {
let mut reasons = Vec::new();
let Some(family) = PiGatewayApiFamily::parse(model.api.as_str()) else {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::UnsupportedFamily,
json_pointer: format!("/models/{model_index}/api"),
});
return Err(reasons);
};
let endpoint = match Url::parse(&model.base_url) {
Ok(endpoint)
if matches!(endpoint.scheme(), "http" | "https") && endpoint.host().is_some() =>
{
endpoint
}
_ => {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::InvalidEndpoint,
json_pointer: format!("/models/{model_index}/baseUrl"),
});
return Err(reasons);
}
};
let Some(credential) = model.api_key.as_ref() else {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::MissingCredential,
json_pointer: "/apiKey".to_string(),
});
return Err(reasons);
};
let mut custom_headers = Vec::new();
let mut protocol_headers = Vec::new();
let mut protocol_identity_predictable = true;
for (name, value) in &model.headers {
let pointer = format!(
"/models/{model_index}/headers/{}",
escape_json_pointer(name)
);
let Ok(parsed_name) = HeaderName::from_bytes(name.as_bytes()) else {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderName,
json_pointer: pointer,
});
continue;
};
if PROTECTED_HEADERS.contains(&parsed_name.as_str()) {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::ProtectedHeader,
json_pointer: pointer,
});
continue;
}
if HeaderValue::from_str(value).is_err() {
reasons.push(PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: pointer,
});
continue;
}
let planned = (
parsed_name,
pointer,
DeferredHeaderValue::new(value.clone()),
);
if PROTOCOL_HEADERS.contains(&planned.0.as_str()) {
protocol_identity_predictable &= !value.starts_with('!');
protocol_headers.push(planned);
} else {
custom_headers.push(planned);
}
}
if !reasons.is_empty() {
return Err(reasons);
}
Ok(Self {
family,
endpoint,
credential: DeferredHeaderValue::new(credential.clone()),
auth_header: model.auth_header,
custom_headers,
protocol_headers,
protocol_identity_predictable,
})
}
pub(super) fn materialize(
&self,
resolver: &impl DeferredValueResolver,
) -> Result<MaterializedCandidate, PiGatewayReason> {
// A new map is allocated for every candidate. No value from a prior
// candidate can survive failover.
let mut headers = HeaderMap::new();
let mut protocol_headers = HeaderMap::new();
let credential = self.credential.materialize(resolver, "/apiKey")?;
let bearer_credential = credential.clone();
let (auth_name, auth_value) = match self.family {
PiGatewayApiFamily::AnthropicMessages => {
(HeaderName::from_static("x-api-key"), credential)
}
PiGatewayApiFamily::GoogleGenerativeAi => {
(HeaderName::from_static("x-goog-api-key"), credential)
}
PiGatewayApiFamily::OpenAiCompletions | PiGatewayApiFamily::OpenAiResponses => {
let credential = credential.to_str().map_err(|_| PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: "/apiKey".to_string(),
})?;
let bearer =
HeaderValue::from_str(&format!("Bearer {credential}")).map_err(|_| {
PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: "/apiKey".to_string(),
}
})?;
(HeaderName::from_static("authorization"), bearer)
}
};
headers.insert(auth_name, auth_value);
if self.auth_header {
let credential = bearer_credential.to_str().map_err(|_| PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: "/apiKey".to_string(),
})?;
let bearer = HeaderValue::from_str(&format!("Bearer {credential}")).map_err(|_| {
PiGatewayReason {
code: PiGatewayReasonCode::InvalidHeaderValue,
json_pointer: "/apiKey".to_string(),
}
})?;
headers.insert(HeaderName::from_static("authorization"), bearer);
}
for (name, pointer, value) in &self.custom_headers {
headers.insert(name.clone(), value.materialize(resolver, pointer)?);
}
for (name, pointer, value) in &self.protocol_headers {
let value = value.materialize(resolver, pointer)?;
protocol_headers.insert(name.clone(), value.clone());
headers.insert(name.clone(), value);
}
let host = authority_header(&self.endpoint).ok_or_else(|| PiGatewayReason {
code: PiGatewayReasonCode::InvalidEndpoint,
json_pointer: "/baseUrl".to_string(),
})?;
headers.insert(HeaderName::from_static("host"), host);
Ok(MaterializedCandidate {
endpoint: self.endpoint.clone(),
headers,
family: self.family,
protocol_headers,
protocol_identity_predictable: self.protocol_identity_predictable,
})
}
}
impl MaterializedCandidate {
pub(super) fn failover_protocol_identity(&self) -> Option<(PiGatewayApiFamily, &HeaderMap)> {
// Auth, tenant and arbitrary custom headers are deliberately excluded.
self.protocol_identity_predictable
.then_some((self.family, &self.protocol_headers))
}
}
pub(super) fn assess_composition(composition: &PiNativeComposition) -> PiGatewayAssessment {
if composition.status != PiComposerStatus::Composed {
return PiGatewayAssessment {
capability: PiGatewayCapability::Unknown,
reasons: Vec::new(),
plans: Vec::new(),
};
}
let mut plans = Vec::with_capacity(composition.models.len());
let mut reasons = Vec::new();
for (index, model) in composition.models.iter().enumerate() {
match CandidateHeaderPlan::build(model, index) {
Ok(plan) => plans.push(plan),
Err(mut model_reasons) => reasons.append(&mut model_reasons),
}
}
if reasons.is_empty() && plans.len() == composition.models.len() {
PiGatewayAssessment {
capability: PiGatewayCapability::Proxyable,
reasons,
plans,
}
} else {
PiGatewayAssessment {
capability: PiGatewayCapability::DirectOnly,
reasons,
plans: Vec::new(),
}
}
}
fn authority_header(url: &Url) -> Option<HeaderValue> {
let host = url.host_str()?;
let authority = match url.port() {
Some(port) => format!("{host}:{port}"),
None => host.to_string(),
};
HeaderValue::from_str(&authority).ok()
}
fn is_deferred(value: &str) -> bool {
value.starts_with('!') || value.contains('$')
}
fn escape_json_pointer(value: &str) -> String {
value.replace('~', "~0").replace('/', "~1")
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pi_config::composer::compose_explicit_custom_catalog;
use crate::pi_config::raw_schema::evaluate_provider_value;
use serde_json::{json, Value};
use std::collections::BTreeMap;
const TRANSPORT_ORACLE_SOURCE: &str =
include_str!("../../../tests/fixtures/pi/native-oracle/transport-oracle-v1.json");
fn composed(input: serde_json::Value) -> PiNativeComposition {
let raw = evaluate_provider_value(&input);
compose_explicit_custom_catalog(
"candidate",
raw.valid_provider.as_ref().expect("raw-valid input"),
)
}
#[test]
fn only_gateway_module_closes_the_four_family_set() {
assert_eq!(
PiGatewayApiFamily::ALL.map(PiGatewayApiFamily::as_str),
[
"anthropic-messages",
"openai-completions",
"openai-responses",
"google-generative-ai",
]
);
}
#[test]
fn unknown_api_is_composed_but_direct_only() {
let composition = composed(json!({
"api": "future-wire-v9",
"baseUrl": "https://future.example/v9",
"apiKey": "literal",
"models": [{"id": "future"}]
}));
assert_eq!(composition.status, PiComposerStatus::Composed);
let gateway = assess_composition(&composition);
assert_eq!(gateway.capability, PiGatewayCapability::DirectOnly);
assert_eq!(
gateway.reasons[0].code,
PiGatewayReasonCode::UnsupportedFamily
);
}
#[test]
fn capability_plan_rejects_invalid_protected_and_hop_headers() {
for (name, expected) in [
("bad header", PiGatewayReasonCode::InvalidHeaderName),
("Host", PiGatewayReasonCode::ProtectedHeader),
("Content-Length", PiGatewayReasonCode::ProtectedHeader),
("Connection", PiGatewayReasonCode::ProtectedHeader),
] {
let composition = composed(json!({
"api": "openai-responses",
"baseUrl": "https://example.test/v1",
"apiKey": "literal",
"headers": {name: "value"},
"models": [{"id": "m"}]
}));
let gateway = assess_composition(&composition);
assert_eq!(
gateway.capability,
PiGatewayCapability::DirectOnly,
"{name}"
);
assert_eq!(gateway.reasons[0].code, expected, "{name}");
}
let composition = composed(json!({
"api": "openai-responses",
"baseUrl": "https://example.test/v1",
"apiKey": "literal",
"headers": {"x-inject": "ok\r\nbad: value"},
"models": [{"id": "m"}]
}));
// TypeBox rejects non-header string syntax only at the gateway layer;
// the raw schema intentionally accepts arbitrary strings.
let gateway = assess_composition(&composition);
assert_eq!(
gateway.reasons[0].code,
PiGatewayReasonCode::InvalidHeaderValue
);
}
#[test]
fn deferred_materialization_is_per_candidate_and_precedes_network_io() {
let first = composed(json!({
"api": "openai-responses",
"baseUrl": "https://first.example:8443/v1",
"apiKey": "${FIRST_KEY}",
"headers": {"x-tenant": "${FIRST_TENANT}"},
"models": [{"id": "m"}]
}));
let second = composed(json!({
"api": "openai-responses",
"baseUrl": "https://second.example/v1",
"apiKey": "${SECOND_KEY}",
"headers": {"x-tenant": "${SECOND_TENANT}"},
"models": [{"id": "m"}]
}));
let first_plan = assess_composition(&first).plans.remove(0);
let second_plan = assess_composition(&second).plans.remove(0);
let first_values = BTreeMap::from([
("${FIRST_KEY}".to_string(), "first-secret".to_string()),
("${FIRST_TENANT}".to_string(), "tenant-a".to_string()),
]);
let first_materialized = first_plan
.materialize(&|expression: &str| first_values.get(expression).cloned())
.expect("first materialization");
assert_eq!(
first_materialized.headers[&HeaderName::from_static("host")],
"first.example:8443"
);
assert_eq!(
first_materialized.headers[&HeaderName::from_static("authorization")],
"Bearer first-secret"
);
let missing = second_plan.materialize(&|_expression: &str| None);
assert_eq!(
missing.expect_err("missing deferred value").code,
PiGatewayReasonCode::DeferredValueUnavailable
);
let second_values = BTreeMap::from([
("${SECOND_KEY}".to_string(), "second-secret".to_string()),
("${SECOND_TENANT}".to_string(), "tenant-b".to_string()),
]);
let second_materialized = second_plan
.materialize(&|expression: &str| second_values.get(expression).cloned())
.expect("second materialization");
assert_eq!(
second_materialized.headers[&HeaderName::from_static("host")],
"second.example"
);
assert_eq!(
second_materialized.headers[&HeaderName::from_static("authorization")],
"Bearer second-secret"
);
assert_eq!(
second_materialized.headers[&HeaderName::from_static("x-tenant")],
"tenant-b"
);
assert_ne!(
first_materialized.headers[&HeaderName::from_static("authorization")],
second_materialized.headers[&HeaderName::from_static("authorization")]
);
assert_eq!(
first_materialized.failover_protocol_identity(),
second_materialized.failover_protocol_identity()
);
}
#[test]
fn protocol_identity_uses_final_values_but_excludes_auth_tenant_and_custom_headers() {
let first = composed(json!({
"api": "anthropic-messages",
"baseUrl": "https://first.example/v1",
"apiKey": "first-secret",
"headers": {
"anthropic-version": "${VERSION_A}",
"x-tenant": "tenant-a",
"x-private": "private-a"
},
"models": [{"id": "m"}]
}));
let second = composed(json!({
"api": "anthropic-messages",
"baseUrl": "https://second.example/v1",
"apiKey": "second-secret",
"headers": {
"anthropic-version": "${VERSION_B}",
"x-tenant": "tenant-b",
"x-private": "private-b"
},
"models": [{"id": "m"}]
}));
let first = assess_composition(&first)
.plans
.remove(0)
.materialize(&|expression: &str| {
(expression == "${VERSION_A}").then(|| "2023-06-01".to_string())
})
.expect("first protocol materialization");
let same_protocol = assess_composition(&second)
.plans
.remove(0)
.materialize(&|expression: &str| {
(expression == "${VERSION_B}").then(|| "2023-06-01".to_string())
})
.expect("second protocol materialization");
assert_eq!(
first.failover_protocol_identity(),
same_protocol.failover_protocol_identity(),
"auth, origin, tenant and arbitrary custom headers do not affect wire identity"
);
let changed = composed(json!({
"api": "anthropic-messages",
"baseUrl": "https://third.example/v1",
"apiKey": "third-secret",
"headers": {"anthropic-version": "2024-01-01"},
"models": [{"id": "m"}]
}));
let changed = assess_composition(&changed)
.plans
.remove(0)
.materialize(&|_expression: &str| None)
.expect("changed protocol materialization");
assert_ne!(
first.failover_protocol_identity(),
changed.failover_protocol_identity()
);
}
#[test]
fn deferred_protocol_headers_fail_before_candidate_use_and_commands_are_ineligible() {
let composition = composed(json!({
"api": "openai-responses",
"baseUrl": "https://candidate.example/v1",
"apiKey": "literal",
"headers": {"openai-version": "${OPENAI_VERSION}"},
"models": [{"id": "m"}]
}));
let plan = assess_composition(&composition).plans.remove(0);
assert_eq!(
plan.materialize(&|_expression: &str| None)
.expect_err("unresolved protocol material")
.code,
PiGatewayReasonCode::DeferredValueUnavailable
);
let command = composed(json!({
"api": "openai-responses",
"baseUrl": "https://candidate.example/v1",
"apiKey": "literal",
"headers": {"openai-version": "!resolve-version"},
"models": [{"id": "m"}]
}));
let command = assess_composition(&command)
.plans
.remove(0)
.materialize(&|expression: &str| {
(expression == "!resolve-version").then(|| "2024-01-01".to_string())
})
.expect("command materializes for direct candidate use");
assert!(
command.failover_protocol_identity().is_none(),
"unpredictable protocol commands are failover-ineligible"
);
}
#[test]
fn auth_header_adds_candidate_local_bearer_without_reusing_another_candidate() {
let composition = composed(json!({
"api": "anthropic-messages",
"baseUrl": "https://candidate.example/v1",
"apiKey": "${KEY}",
"authHeader": true,
"models": [{"id": "m"}]
}));
let materialized = assess_composition(&composition)
.plans
.remove(0)
.materialize(&|expression: &str| {
(expression == "${KEY}").then(|| "candidate-secret".to_string())
})
.expect("authHeader materialization");
assert_eq!(
materialized.headers[&HeaderName::from_static("x-api-key")],
"candidate-secret"
);
assert_eq!(
materialized.headers[&HeaderName::from_static("authorization")],
"Bearer candidate-secret"
);
}
#[test]
fn four_families_materialize_their_own_auth_headers() {
for (family, auth_name, expected_value) in [
("anthropic-messages", "x-api-key", "secret"),
("openai-completions", "authorization", "Bearer secret"),
("openai-responses", "authorization", "Bearer secret"),
("google-generative-ai", "x-goog-api-key", "secret"),
] {
let composition = composed(json!({
"api": family,
"baseUrl": "https://candidate.example/v1",
"apiKey": "secret",
"models": [{"id": "m"}]
}));
let mut assessment = assess_composition(&composition);
assert_eq!(assessment.capability, PiGatewayCapability::Proxyable);
let materialized = assessment
.plans
.remove(0)
.materialize(&|_expression: &str| None)
.expect("literal materialization");
assert_eq!(
materialized.headers[&HeaderName::from_bytes(auth_name.as_bytes()).unwrap()],
expected_value
);
}
}
#[test]
fn deferred_values_replay_actual_pinned_pi_transport_results() {
let oracle: Value =
serde_json::from_str(TRANSPORT_ORACLE_SOURCE).expect("parse transport oracle");
for case in oracle["cases"].as_array().expect("transport cases") {
let input = case["input"].as_str().expect("transport input");
let composition = composed(json!({
"api": "openai-responses",
"baseUrl": "https://candidate.example/v1",
"apiKey": input,
"models": [{"id": "m"}]
}));
let plan = assess_composition(&composition).plans.remove(0);
match case.pointer("/execution/status").and_then(Value::as_str) {
Some("success") => {
let expected = case["expected"].as_str().expect("actual Pi result");
let materialized = plan
.materialize(&|expression: &str| {
(expression == input).then(|| expected.to_string())
})
.expect("replay actual Pi resolver result");
let expected_bearer = format!("Bearer {expected}");
assert_eq!(
materialized.headers[&HeaderName::from_static("authorization")],
expected_bearer,
"transport case '{}'",
case["id"]
);
}
Some("error") => {
assert!(case["expectedError"].is_string());
assert_eq!(
plan.materialize(&|_expression: &str| None)
.expect_err("actual Pi resolver failure must discard candidate")
.code,
PiGatewayReasonCode::DeferredValueUnavailable,
"transport case '{}'",
case["id"]
);
}
status => panic!("unexpected transport status {status:?}"),
}
}
let header_case = &oracle["headerCase"];
let input_headers = header_case["input"]
.as_object()
.expect("transport header input");
let expected_headers = header_case["expected"]
.as_object()
.expect("actual Pi header output");
let composition = composed(json!({
"api": "openai-responses",
"baseUrl": "https://candidate.example/v1",
"apiKey": "literal-key",
"headers": input_headers,
"models": [{"id": "m"}]
}));
let materialized = assess_composition(&composition)
.plans
.remove(0)
.materialize(&|expression: &str| {
input_headers.iter().find_map(|(name, configured)| {
(configured.as_str() == Some(expression))
.then(|| expected_headers[name].as_str().map(ToOwned::to_owned))
.flatten()
})
})
.expect("replay actual Pi header resolver results");
for (name, expected) in expected_headers {
let name = HeaderName::from_bytes(name.as_bytes()).expect("oracle header name");
assert_eq!(
materialized.headers[&name],
expected.as_str().expect("oracle header value")
);
}
}
}
+5
View File
@@ -4,4 +4,9 @@
//! Pi's shared files and from the proxy data plane. Callers must use the
//! typed model resolver rather than reimplementing provider/model inheritance.
mod composer;
mod document;
mod gateway;
pub(crate) mod model;
pub(crate) mod native;
mod raw_schema;
+968
View File
@@ -0,0 +1,968 @@
//! Public, side-effect-free inspection service for Pi's native catalog.
//!
//! This module orchestrates independent raw, managed, composer and gateway
//! assessments. No assessment is allowed to gate execution of a sibling layer.
#![allow(dead_code)]
use super::composer::{
compose_explicit_custom_catalog, PiComposerReasonCode, PiComposerStatus, PiNativeComposition,
};
use super::document::{read_pi_models_document, PiRawProviderEntry};
use super::gateway::{
assess_composition, PiGatewayAssessment, PiGatewayCapability, PiGatewayReasonCode,
};
use super::model::{
validate_pi_managed_provider, PiCompositionStatus, PiConfigError, PiDiagnosticLayer,
PiDiagnosticReason, PiGatewayStatus, PiManagedAssessment, PiManagedProviderConfig,
PiManagementStatus, PiNativeDiagnostic, PiNativeEntryKind, PiRawNativeValidity, PiReasonCode,
};
use super::raw_schema::{
evaluate_provider_value, PiRawReasonCode, PiRawSchemaEvaluation, PiRawValidity,
};
use crate::config::get_home_dir;
use crate::error::AppError;
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::collections::{BTreeMap, HashSet};
use std::path::{Path, PathBuf};
use url::Url;
/// Built-in provider IDs at Pi commit
/// `ab366ebe94cacd419d986be454f12b1b9913aaca`.
const PI_BUILTIN_PROVIDER_KEYS: &[&str] = &[
"amazon-bedrock",
"ant-ling",
"anthropic",
"azure-openai-responses",
"cerebras",
"cloudflare-ai-gateway",
"cloudflare-workers-ai",
"deepseek",
"fireworks",
"github-copilot",
"google",
"google-vertex",
"groq",
"huggingface",
"kimi-coding",
"minimax",
"minimax-cn",
"mistral",
"moonshotai",
"moonshotai-cn",
"nvidia",
"openai",
"openai-codex",
"opencode",
"opencode-go",
"openrouter",
"qwen-token-plan",
"qwen-token-plan-cn",
"radius",
"together",
"vercel-ai-gateway",
"xai",
"xiaomi",
"xiaomi-token-plan-ams",
"xiaomi-token-plan-cn",
"xiaomi-token-plan-sgp",
"zai",
"zai-coding-cn",
];
const RECOGNIZED_PROVIDER_FIELDS: &[&str] = &[
"name",
"baseUrl",
"apiKey",
"api",
"oauth",
"headers",
"compat",
"authHeader",
"models",
"modelOverrides",
];
#[derive(Debug, Clone)]
pub(crate) struct PiNativeEntryInspection {
pub diagnostic: PiNativeDiagnostic,
pub managed_config: Option<PiManagedProviderConfig>,
pub composition: PiNativeComposition,
}
#[derive(Debug)]
struct ManagedResult {
assessment: PiManagedAssessment,
config: Option<PiManagedProviderConfig>,
reasons: Vec<PiDiagnosticReason>,
}
/// The public read-only service entry used by commands and certification tests.
pub(crate) struct PiNativeInspectionService;
impl PiNativeInspectionService {
pub(crate) fn inspect_current(
managed_claims: &BTreeMap<String, String>,
) -> Result<Vec<PiNativeDiagnostic>, AppError> {
Self::inspect_catalog(&get_pi_models_path()?, managed_claims)
}
pub(crate) fn inspect_catalog(
path: &Path,
managed_claims: &BTreeMap<String, String>,
) -> Result<Vec<PiNativeDiagnostic>, AppError> {
let document = read_pi_models_document(path)?;
Ok(document
.providers()
.iter()
.map(|(provider_key, entry)| {
analyze_native_entry(provider_key, entry, managed_claims).diagnostic
})
.collect())
}
pub(crate) fn inspect_entry(
path: &Path,
provider_key: &str,
managed_claims: &BTreeMap<String, String>,
) -> Result<Option<PiNativeEntryInspection>, AppError> {
let document = read_pi_models_document(path)?;
Ok(document
.providers()
.get(provider_key)
.map(|entry| analyze_native_entry(provider_key, entry, managed_claims)))
}
}
pub(crate) fn inspect_current_pi_native_catalog(
managed_claims: &BTreeMap<String, String>,
) -> Result<Vec<PiNativeDiagnostic>, AppError> {
PiNativeInspectionService::inspect_current(managed_claims)
}
pub(crate) fn inspect_pi_native_catalog(
path: &Path,
managed_claims: &BTreeMap<String, String>,
) -> Result<Vec<PiNativeDiagnostic>, AppError> {
PiNativeInspectionService::inspect_catalog(path, managed_claims)
}
pub(crate) fn inspect_pi_native_entry(
path: &Path,
provider_key: &str,
managed_claims: &BTreeMap<String, String>,
) -> Result<Option<PiNativeEntryInspection>, AppError> {
PiNativeInspectionService::inspect_entry(path, provider_key, managed_claims)
}
fn normalize_pi_agent_dir(value: &str, home: &Path) -> Result<PathBuf, AppError> {
if value == "~" {
return Ok(home.to_path_buf());
}
if let Some(suffix) = value.strip_prefix("~/") {
return Ok(home.join(suffix));
}
#[cfg(windows)]
if let Some(suffix) = value.strip_prefix("~\\") {
return Ok(home.join(suffix));
}
if value.starts_with("file://") {
let url = Url::parse(value).map_err(|error| {
AppError::Config(format!("invalid Pi agent directory URL: {error}"))
})?;
return url.to_file_path().map_err(|_| {
AppError::Config(format!(
"Pi agent directory URL is not a local file path: {value}"
))
});
}
Ok(PathBuf::from(value))
}
pub(crate) fn get_pi_agent_dir() -> Result<PathBuf, AppError> {
let Some(raw) = std::env::var_os("PI_CODING_AGENT_DIR") else {
return Ok(get_home_dir().join(".pi").join("agent"));
};
if raw.is_empty() {
return Ok(get_home_dir().join(".pi").join("agent"));
}
normalize_pi_agent_dir(&raw.to_string_lossy(), &get_home_dir())
}
pub(crate) fn get_pi_models_path() -> Result<PathBuf, AppError> {
Ok(get_pi_agent_dir()?.join("models.json"))
}
fn analyze_native_entry(
provider_key: &str,
entry: &PiRawProviderEntry,
managed_claims: &BTreeMap<String, String>,
) -> PiNativeEntryInspection {
// Raw, composition and managed conversion are deliberately invoked from
// the same immutable JSON value. Neither result controls whether a sibling
// assessment is attempted.
let raw = evaluate_provider_value(&entry.value);
let raw_validity = map_raw_validity(raw.validity);
let kind = classify_kind(provider_key, &entry.value, raw.validity);
let composition = match (raw.valid_provider.as_ref(), kind) {
(Some(provider), PiNativeEntryKind::CustomCatalog) => {
compose_explicit_custom_catalog(provider_key, provider)
}
(Some(_), _) => PiNativeComposition::catalog_required("/models"),
(None, _) => PiNativeComposition::unavailable_without_valid_raw(),
};
let managed = assess_managed(raw.validity, kind, &entry.value);
let gateway = if raw.validity == PiRawValidity::Valid {
assess_composition(&composition)
} else {
PiGatewayAssessment {
capability: PiGatewayCapability::Unknown,
reasons: Vec::new(),
plans: Vec::new(),
}
};
let management_status = managed_claims
.get(provider_key)
.map(|provider_id| PiManagementStatus::Managed {
provider_id: provider_id.clone(),
})
.unwrap_or_else(|| {
if raw.validity == PiRawValidity::Valid
&& managed.assessment == PiManagedAssessment::Manageable
{
PiManagementStatus::Importable
} else {
PiManagementStatus::Unsupported
}
});
let mut reasons = map_raw_reasons(&raw);
extend_reasons(&mut reasons, managed.reasons.clone());
extend_reasons(&mut reasons, map_composer_reasons(&composition));
extend_reasons(&mut reasons, map_gateway_reasons(&gateway));
PiNativeEntryInspection {
diagnostic: PiNativeDiagnostic {
provider_key: provider_key.to_string(),
display_name: entry
.value
.get("name")
.and_then(Value::as_str)
.map(ToOwned::to_owned),
fingerprint: fingerprint(&entry.raw_source),
kind,
raw_validity,
managed_assessment: managed.assessment,
composition_status: map_composition_status(composition.status),
management_status,
gateway_status: map_gateway_status(gateway.capability),
reasons,
},
managed_config: managed.config,
composition,
}
}
fn assess_managed(
raw_validity: PiRawValidity,
kind: PiNativeEntryKind,
value: &Value,
) -> ManagedResult {
if raw_validity != PiRawValidity::Valid {
return ManagedResult {
assessment: PiManagedAssessment::Unsupported,
config: None,
reasons: Vec::new(),
};
}
if kind != PiNativeEntryKind::CustomCatalog {
let mut reasons = vec![diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::CatalogRequired,
"/models",
)];
if value
.get("modelOverrides")
.and_then(Value::as_object)
.is_some_and(|overrides| !overrides.is_empty())
{
reasons.push(diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::ModelOverridesOnly,
"/modelOverrides",
));
}
return ManagedResult {
assessment: PiManagedAssessment::Unsupported,
config: None,
reasons,
};
}
let config = match serde_json::from_value::<PiManagedProviderConfig>(value.clone()) {
Ok(config) => config,
Err(_) => {
return ManagedResult {
assessment: PiManagedAssessment::Unsupported,
config: None,
reasons: vec![diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::ManagedTypeConversionFailed,
&managed_conversion_pointer(value),
)],
};
}
};
let mut reasons = collect_managed_reasons(&config);
if reasons.is_empty() {
if let Err(error) = validate_pi_managed_provider(&config) {
reasons.push(managed_validation_reason(error));
}
}
if !reasons.is_empty() {
return ManagedResult {
assessment: PiManagedAssessment::Unsupported,
config: None,
reasons,
};
}
ManagedResult {
assessment: PiManagedAssessment::Manageable,
config: Some(config),
reasons,
}
}
fn collect_managed_reasons(config: &PiManagedProviderConfig) -> Vec<PiDiagnosticReason> {
let mut reasons = Vec::new();
let mut ids = HashSet::with_capacity(config.models.len());
if config.models.is_empty() {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::MissingExplicitModels,
"/models",
),
);
}
if config
.base_url
.as_deref()
.is_some_and(|value| !valid_http_endpoint(value))
{
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::InvalidEndpoint,
"/baseUrl",
),
);
}
for (index, model) in config.models.iter().enumerate() {
let pointer = format!("/models/{index}");
if model.id.trim().is_empty() {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::EmptyModelId,
&format!("{pointer}/id"),
),
);
} else if !ids.insert(model.id.as_str()) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::DuplicateModelId,
&format!("{pointer}/id"),
),
);
}
if model
.base_url
.as_deref()
.is_some_and(|value| !valid_http_endpoint(value))
{
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::InvalidEndpoint,
&format!("{pointer}/baseUrl"),
),
);
}
if model.api.is_none() && config.api.is_none() {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::MissingEffectiveApi,
&format!("{pointer}/api"),
),
);
}
if model.base_url.is_none() && config.base_url.is_none() {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::MissingEffectiveEndpoint,
&format!("{pointer}/baseUrl"),
),
);
}
for (field, value) in [
("contextWindow", model.context_window),
("maxTokens", model.max_tokens),
] {
if value.is_some_and(|value| value.get() <= 0.0) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::NonPositiveModelLimit,
&format!("{pointer}/{field}"),
),
);
}
}
for level in model.thinking_level_map.keys() {
if !is_managed_thinking_level(level) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::InvalidThinkingLevel,
&format!("{pointer}/thinkingLevelMap/{}", escape_json_pointer(level)),
),
);
}
}
}
for (model_id, model_override) in &config.model_overrides {
let pointer = format!("/modelOverrides/{}", escape_json_pointer(model_id));
if !ids.contains(model_id.as_str()) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::UnknownModelOverride,
&pointer,
),
);
}
for (field, value) in [
("contextWindow", model_override.context_window),
("maxTokens", model_override.max_tokens),
] {
if value.is_some_and(|value| value.get() <= 0.0) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::NonPositiveModelLimit,
&format!("{pointer}/{field}"),
),
);
}
}
for level in model_override.thinking_level_map.keys() {
if !is_managed_thinking_level(level) {
add_reason(
&mut reasons,
diagnostic_reason(
PiDiagnosticLayer::Managed,
PiReasonCode::InvalidThinkingLevel,
&format!("{pointer}/thinkingLevelMap/{}", escape_json_pointer(level)),
),
);
}
}
}
reasons
}
fn managed_conversion_pointer(value: &Value) -> String {
if let Some(models) = value.get("models").and_then(Value::as_array) {
for (index, model) in models.iter().enumerate() {
if let Some(map) = model.get("thinkingLevelMap").and_then(Value::as_object) {
for (key, value) in map {
if !(value.is_string() || value.is_null()) {
return format!(
"/models/{index}/thinkingLevelMap/{}",
escape_json_pointer(key)
);
}
}
}
}
}
if let Some(overrides) = value.get("modelOverrides").and_then(Value::as_object) {
for (model_id, model_override) in overrides {
if let Some(map) = model_override
.get("thinkingLevelMap")
.and_then(Value::as_object)
{
for (key, value) in map {
if !(value.is_string() || value.is_null()) {
return format!(
"/modelOverrides/{}/thinkingLevelMap/{}",
escape_json_pointer(model_id),
escape_json_pointer(key)
);
}
}
}
}
}
String::new()
}
fn managed_validation_reason(error: PiConfigError) -> PiDiagnosticReason {
let (code, pointer) = match error {
PiConfigError::ProviderHasNoModels => (PiReasonCode::MissingExplicitModels, "/models"),
PiConfigError::EmptyApiId => (PiReasonCode::ManagedTypeConversionFailed, "/api"),
PiConfigError::EmptyModelId => (PiReasonCode::EmptyModelId, "/models"),
PiConfigError::DuplicateModelId(_) => (PiReasonCode::DuplicateModelId, "/models"),
PiConfigError::ModelNotFound(_) => (PiReasonCode::ManagedTypeConversionFailed, "/models"),
PiConfigError::MissingEffectiveApi { .. } => (PiReasonCode::MissingEffectiveApi, "/models"),
PiConfigError::MissingEffectiveEndpoint { .. } => {
(PiReasonCode::MissingEffectiveEndpoint, "/models")
}
PiConfigError::InvalidEndpoint { .. } => (PiReasonCode::InvalidEndpoint, "/baseUrl"),
PiConfigError::UnknownModelOverride(_) => {
(PiReasonCode::UnknownModelOverride, "/modelOverrides")
}
PiConfigError::InvalidCompat { .. } => (PiReasonCode::InvalidCompat, "/compat"),
PiConfigError::EmptyOptionalField { .. } => (PiReasonCode::EmptyOptionalField, ""),
PiConfigError::NonPositiveModelLimit { .. } => {
(PiReasonCode::NonPositiveModelLimit, "/models")
}
PiConfigError::InvalidThinkingLevel { .. } => {
(PiReasonCode::InvalidThinkingLevel, "/models")
}
};
diagnostic_reason(PiDiagnosticLayer::Managed, code, pointer)
}
fn classify_kind(
provider_key: &str,
value: &Value,
raw_validity: PiRawValidity,
) -> PiNativeEntryKind {
if PI_BUILTIN_PROVIDER_KEYS.contains(&provider_key) {
return PiNativeEntryKind::BuiltInOverlay;
}
if raw_validity != PiRawValidity::Valid {
return PiNativeEntryKind::UnknownShape;
}
let Some(object) = value.as_object() else {
return PiNativeEntryKind::UnknownShape;
};
if object
.get("models")
.and_then(Value::as_array)
.is_some_and(|models| !models.is_empty())
{
PiNativeEntryKind::CustomCatalog
} else if object
.keys()
.any(|key| RECOGNIZED_PROVIDER_FIELDS.contains(&key.as_str()))
{
PiNativeEntryKind::ExtensionOverlay
} else {
PiNativeEntryKind::UnknownShape
}
}
fn map_raw_validity(validity: PiRawValidity) -> PiRawNativeValidity {
match validity {
PiRawValidity::Valid => PiRawNativeValidity::Valid,
PiRawValidity::Invalid => PiRawNativeValidity::Invalid,
PiRawValidity::Unknown => PiRawNativeValidity::Unknown,
}
}
fn map_composition_status(status: PiComposerStatus) -> PiCompositionStatus {
match status {
PiComposerStatus::Composed => PiCompositionStatus::Composed,
PiComposerStatus::Failed => PiCompositionStatus::Failed,
PiComposerStatus::Unknown => PiCompositionStatus::Unknown,
}
}
fn map_gateway_status(capability: PiGatewayCapability) -> PiGatewayStatus {
match capability {
PiGatewayCapability::Proxyable => PiGatewayStatus::Proxyable,
PiGatewayCapability::DirectOnly => PiGatewayStatus::DirectOnly,
PiGatewayCapability::Unknown => PiGatewayStatus::Unknown,
}
}
fn map_raw_reasons(raw: &PiRawSchemaEvaluation) -> Vec<PiDiagnosticReason> {
raw.reasons
.iter()
.map(|reason| {
diagnostic_reason(
PiDiagnosticLayer::RawSchema,
match reason.code {
PiRawReasonCode::SchemaMismatch => PiReasonCode::RawSchemaMismatch,
PiRawReasonCode::UnsupportedOperator => {
PiReasonCode::RawSchemaUnsupportedOperator
}
PiRawReasonCode::PinDrift => PiReasonCode::RawSchemaPinDrift,
PiRawReasonCode::AmbiguousSchema => PiReasonCode::RawSchemaAmbiguous,
},
&reason.json_pointer,
)
})
.collect()
}
fn map_composer_reasons(composition: &PiNativeComposition) -> Vec<PiDiagnosticReason> {
composition
.reasons
.iter()
.map(|reason| {
diagnostic_reason(
PiDiagnosticLayer::Composition,
match reason.code {
PiComposerReasonCode::CatalogRequired => PiReasonCode::CatalogRequired,
PiComposerReasonCode::MissingExplicitModels => {
PiReasonCode::MissingExplicitModels
}
PiComposerReasonCode::MissingEffectiveApi => PiReasonCode::MissingEffectiveApi,
PiComposerReasonCode::MissingEffectiveEndpoint => {
PiReasonCode::MissingEffectiveEndpoint
}
PiComposerReasonCode::NonPositiveModelLimit => {
PiReasonCode::NonPositiveModelLimit
}
PiComposerReasonCode::CompositionFailed => PiReasonCode::CompositionFailed,
},
&reason.json_pointer,
)
})
.collect()
}
fn map_gateway_reasons(gateway: &PiGatewayAssessment) -> Vec<PiDiagnosticReason> {
gateway
.reasons
.iter()
.map(|reason| {
diagnostic_reason(
PiDiagnosticLayer::Gateway,
match reason.code {
PiGatewayReasonCode::UnsupportedFamily => {
PiReasonCode::UnsupportedGatewayFamily
}
PiGatewayReasonCode::InvalidEndpoint => PiReasonCode::InvalidEndpoint,
PiGatewayReasonCode::MissingCredential => {
PiReasonCode::GatewayCredentialUnavailable
}
PiGatewayReasonCode::InvalidHeaderName => PiReasonCode::InvalidHeaderName,
PiGatewayReasonCode::InvalidHeaderValue => PiReasonCode::InvalidHeaderValue,
PiGatewayReasonCode::ProtectedHeader => PiReasonCode::ProtectedHeader,
PiGatewayReasonCode::DeferredValueUnavailable => {
PiReasonCode::DeferredValueUnavailable
}
},
&reason.json_pointer,
)
})
.collect()
}
fn diagnostic_reason(
layer: PiDiagnosticLayer,
code: PiReasonCode,
pointer: &str,
) -> PiDiagnosticReason {
PiDiagnosticReason::new(layer, code, Some(pointer.to_string()))
}
fn add_reason(reasons: &mut Vec<PiDiagnosticReason>, reason: PiDiagnosticReason) {
if !reasons.contains(&reason) {
reasons.push(reason);
}
}
fn extend_reasons(
reasons: &mut Vec<PiDiagnosticReason>,
candidates: impl IntoIterator<Item = PiDiagnosticReason>,
) {
for reason in candidates {
add_reason(reasons, reason);
}
}
fn valid_http_endpoint(value: &str) -> bool {
Url::parse(value)
.ok()
.is_some_and(|url| matches!(url.scheme(), "http" | "https") && url.host().is_some())
}
fn is_managed_thinking_level(value: &str) -> bool {
matches!(
value,
"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"
)
}
fn escape_json_pointer(value: &str) -> String {
value.replace('~', "~0").replace('/', "~1")
}
fn fingerprint(raw_source: &str) -> String {
format!("sha256:{:x}", Sha256::digest(raw_source.as_bytes()))
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
use std::fs;
fn by_key<'a>(diagnostics: &'a [PiNativeDiagnostic], key: &str) -> &'a PiNativeDiagnostic {
diagnostics
.iter()
.find(|diagnostic| diagnostic.provider_key == key)
.expect("diagnostic")
}
fn has_reason(
diagnostic: &PiNativeDiagnostic,
layer: PiDiagnosticLayer,
code: PiReasonCode,
pointer: &str,
) -> bool {
diagnostic.reasons.iter().any(|reason| {
reason.layer == layer
&& reason.code == code
&& reason.json_pointer.as_deref() == Some(pointer)
})
}
#[test]
fn public_inspection_service_certifies_the_native_state_matrix() {
let temp = tempfile::tempdir().expect("tempdir");
let path = temp.path().join("models.json");
fs::write(
&path,
r#"{
"providers": {
"anthropic": {"baseUrl": "https://builtin.example"},
"extension": {"api": "openai-responses"},
"future-custom": {
"api": "future-wire-v9",
"baseUrl": "https://future.example/v9",
"apiKey": "$FUTURE_KEY",
"models": [{"id": "future"}]
},
"known-custom": {
"api": "openai-responses",
"baseUrl": "https://known.example/v1",
"apiKey": "!read-secret",
"headers": {"x-tenant": "${TENANT}"},
"models": [{"id": "known"}]
},
"malformed": {"models": "not-an-array"}
}
}"#,
)
.expect("write fixture");
let bytes_before = fs::read(&path).expect("before");
let claims = BTreeMap::new();
let diagnostics =
PiNativeInspectionService::inspect_catalog(&path, &claims).expect("inspect service");
assert_eq!(fs::read(&path).expect("after"), bytes_before);
assert_eq!(diagnostics.len(), 5);
for key in ["anthropic", "extension"] {
let diagnostic = by_key(&diagnostics, key);
assert_eq!(diagnostic.raw_validity, PiRawNativeValidity::Valid);
assert_eq!(diagnostic.composition_status, PiCompositionStatus::Unknown);
assert_eq!(diagnostic.gateway_status, PiGatewayStatus::Unknown);
assert!(has_reason(
diagnostic,
PiDiagnosticLayer::Composition,
PiReasonCode::CatalogRequired,
"/models"
));
}
let future = by_key(&diagnostics, "future-custom");
assert_eq!(future.raw_validity, PiRawNativeValidity::Valid);
assert_eq!(future.composition_status, PiCompositionStatus::Composed);
assert_eq!(future.managed_assessment, PiManagedAssessment::Manageable);
assert_eq!(future.management_status, PiManagementStatus::Importable);
assert_eq!(future.gateway_status, PiGatewayStatus::DirectOnly);
assert!(has_reason(
future,
PiDiagnosticLayer::Gateway,
PiReasonCode::UnsupportedGatewayFamily,
"/models/0/api"
));
let known = by_key(&diagnostics, "known-custom");
assert_eq!(known.composition_status, PiCompositionStatus::Composed);
assert_eq!(known.management_status, PiManagementStatus::Importable);
assert_eq!(known.gateway_status, PiGatewayStatus::Proxyable);
let malformed = by_key(&diagnostics, "malformed");
assert_eq!(malformed.raw_validity, PiRawNativeValidity::Invalid);
assert_eq!(malformed.composition_status, PiCompositionStatus::Unknown);
assert_eq!(malformed.gateway_status, PiGatewayStatus::Unknown);
}
#[test]
fn managed_rejection_does_not_control_raw_composition() {
let temp = tempfile::tempdir().expect("tempdir");
let path = temp.path().join("models.json");
fs::write(
&path,
r#"{"providers":{"duplicate":{
"apiKey":"literal",
"models":[
{"id":"same","api":"openai-responses","baseUrl":"https://one.example"},
{"id":"same","api":"future-wire","baseUrl":"https://two.example"}
],
"modelOverrides":{"missing":{"maxTokens":7.5}}
}}}"#,
)
.expect("write");
let diagnostic =
&PiNativeInspectionService::inspect_catalog(&path, &BTreeMap::new()).unwrap()[0];
assert_eq!(diagnostic.raw_validity, PiRawNativeValidity::Valid);
assert_eq!(
diagnostic.managed_assessment,
PiManagedAssessment::Unsupported
);
assert_eq!(diagnostic.composition_status, PiCompositionStatus::Composed);
assert!(has_reason(
diagnostic,
PiDiagnosticLayer::Managed,
PiReasonCode::DuplicateModelId,
"/models/1/id"
));
assert!(has_reason(
diagnostic,
PiDiagnosticLayer::Managed,
PiReasonCode::UnknownModelOverride,
"/modelOverrides/missing"
));
}
#[test]
fn unknown_thinking_shape_is_lossless_for_composer_and_narrowed_separately() {
let temp = tempfile::tempdir().expect("tempdir");
let path = temp.path().join("models.json");
fs::write(
&path,
r#"{"providers":{"thinking":{
"api":"anthropic-messages",
"baseUrl":"https://thinking.example",
"apiKey":"literal",
"models":[{
"id":"m",
"thinkingLevelMap":{"high":"future-high","future":{"opaque":true}}
}]
}}}"#,
)
.expect("write");
let inspection =
PiNativeInspectionService::inspect_entry(&path, "thinking", &BTreeMap::new())
.expect("inspect")
.expect("entry");
assert_eq!(
inspection.diagnostic.raw_validity,
PiRawNativeValidity::Valid
);
assert_eq!(
inspection.diagnostic.composition_status,
PiCompositionStatus::Composed
);
assert_eq!(
inspection.composition.models[0]
.thinking_level_map
.as_ref()
.expect("opaque thinking")["future"],
json!({"opaque": true})
);
assert_eq!(
inspection.diagnostic.managed_assessment,
PiManagedAssessment::Unsupported
);
assert!(has_reason(
&inspection.diagnostic,
PiDiagnosticLayer::Managed,
PiReasonCode::ManagedTypeConversionFailed,
"/models/0/thinkingLevelMap/future"
));
}
#[test]
fn exact_entry_fingerprint_changes_only_when_that_raw_entry_changes() {
let temp = tempfile::tempdir().expect("tempdir");
let path = temp.path().join("models.json");
let claims = BTreeMap::new();
fs::write(
&path,
r#"{"providers":{
"target":{"api":"openai-responses","baseUrl":"https://target","apiKey":"x","models":[{"id":"m"}]},
"sibling":{"api":"openai-responses","baseUrl":"https://sibling","apiKey":"x","models":[{"id":"m"}]}
}}"#,
)
.expect("write");
let first = PiNativeInspectionService::inspect_entry(&path, "target", &claims)
.unwrap()
.unwrap()
.diagnostic
.fingerprint;
fs::write(
&path,
r#"{"providers":{
"target":{"api":"openai-responses","baseUrl":"https://target","apiKey":"x","models":[{"id":"m"}]},
"sibling":{"api":"openai-responses","baseUrl":"https://changed","apiKey":"x","models":[{"id":"m"}]}
}}"#,
)
.expect("write sibling");
let after_sibling = PiNativeInspectionService::inspect_entry(&path, "target", &claims)
.unwrap()
.unwrap()
.diagnostic
.fingerprint;
assert_eq!(first, after_sibling);
}
#[test]
fn agent_dir_normalization_matches_pi_path_semantics() {
let temp = tempfile::tempdir().expect("tempdir");
let file_url = Url::from_file_path(temp.path())
.expect("absolute temp path")
.to_string();
assert_eq!(
normalize_pi_agent_dir(&file_url, Path::new("/unused")).expect("file URL"),
temp.path()
);
let spaced = " relative agent dir ";
assert_eq!(
normalize_pi_agent_dir(spaced, Path::new("/unused")).expect("spaced path"),
PathBuf::from(spaced)
);
}
#[test]
fn pi_config_error_stays_managed_only() {
let error = PiConfigError::EmptyApiId;
assert_eq!(error.to_string(), "Pi API id cannot be empty");
}
}
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
{
"manifestVersion": 1,
"codeAuthority": "src-tauri/src/architecture_tests.rs",
"edges": [
"composer->raw_schema",
"gateway->composer",
"native->composer",
"native->document",
"native->gateway",
"native->model",
"native->raw_schema"
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+96
View File
@@ -0,0 +1,96 @@
{
"version": 1,
"pi": {
"repository": "https://github.com/earendil-works/pi.git",
"commit": "ab366ebe94cacd419d986be454f12b1b9913aaca"
},
"typeboxVersion": "1.3.7",
"sources": {
"modelConfig": {
"path": "packages/coding-agent/src/core/model-config.ts",
"sha256": "62141770d675ad6357a72e07354355f0eda29281c0e5be1b48d2360f341c7360"
},
"providerComposer": {
"path": "packages/coding-agent/src/core/provider-composer.ts",
"sha256": "17308a4179b330526eabf6c917fa13e9dbd9ece90d1555b870e87d39b5b60d9d"
},
"resolveConfigValue": {
"path": "packages/coding-agent/src/core/resolve-config-value.ts",
"sha256": "0f53dad47fe5d5d8837c022b7951ccd3bd5a9b577bd662f0986272110e83bcc7"
}
},
"artifacts": {
"provider-schema.snapshot.json": "e498c9f1b344eee1bd3c3ba74d1b648dcb835378cfad92800ec80078b825745c",
"raw-oracle-v1.json": "5aaa37160f96a0fe50867d900ca38c73f13aba769e156a883324368d9dbeeb9a",
"composer-oracle-v1.json": "f7e54bb84e5fd6d50e5762dc304834410fa73ef608c2f9c42475c5983f8e0cf5",
"transport-oracle-v1.json": "b2c816e53b60da5cd6352d2c23934939e9f6dd0077971488fe9dd36fa723e855",
"field-coverage-v1.json": "b8b85e611cf1dbef86c611df185ba8ac2d64160087d0c6e47747f838a0fafe42"
},
"harness": {
"path": "scripts/generate-pi-native-oracle.mjs",
"sha256": "f7a138831284b48ef655ef500a63313f0fc89cf08d319094895027ba4777cc20",
"upstreamEntry": "packages/coding-agent/src/core/provider-composer.ts",
"entryFunctions": [
"composeModelProvider",
"Provider.getModels",
"resolveCompatibilityRequestConfig",
"Provider.auth.apiKey.resolve"
],
"bundler": "esbuild@0.28.1",
"transportShims": {
"pi-ai": "debdf80a40ad2086467c7c3ed6fe43d6167caa85e5bff86e10f28cc36d8fcc53",
"pi-ai/compat": "533cd8f8a242bb25b42db8249abcb539daf30889ea748b5114c177e44c3849d2"
},
"assertion": "expected composer outputs were captured by executing the pinned upstream entry functions; transport shims are unreachable during credential-blind model composition",
"transportResolver": {
"upstreamEntry": "packages/coding-agent/src/core/resolve-config-value.ts",
"entryFunctions": [
"resolveConfigValueOrThrow",
"resolveHeadersOrThrow"
],
"bundler": "esbuild@0.28.1",
"platform": "linux"
}
},
"uncoveredSemantics": [
{
"id": "builtin-overlay-without-pinned-base-catalog",
"unavailableContext": "pinned built-in Provider instance and model catalog",
"rustExpectedStatus": "unknown",
"reasonCode": "catalog_required"
},
{
"id": "extension-overlay-without-extension-registration",
"unavailableContext": "extension ProviderConfigInput and registered model catalog",
"rustExpectedStatus": "unknown",
"reasonCode": "catalog_required"
},
{
"id": "radius-oauth-credential-lifecycle",
"unavailableContext": "interactive Radius login, refresh credentials, and network exchange",
"rustExpectedStatus": "direct_only",
"reasonCode": "missing_gateway_credential"
}
],
"schemaOperatorInventory": [
"anyOf",
"const",
"items",
"minLength",
"patternProperties",
"properties",
"required",
"type"
],
"evaluatorOperatorAllowlist": [
"additionalProperties",
"anyOf",
"const",
"items",
"minLength",
"patternProperties",
"properties",
"required",
"type"
]
}
File diff suppressed because it is too large Load Diff
+723
View File
@@ -0,0 +1,723 @@
{
"version": 1,
"execution": {
"engine": "typebox Value.Check",
"typeboxVersion": "1.3.7",
"schemaTarget": "ModelsConfigSchema.properties.providers.patternProperties['^.*$']"
},
"cases": [
{
"id": "all-schema-fields-valid",
"input": {
"name": "All Fields Provider",
"baseUrl": "https://all-fields.example/v1",
"apiKey": "literal-all-fields-key",
"api": "openai-responses",
"oauth": "radius",
"headers": {
"x-provider-field": "provider-value"
},
"compat": {
"supportsStore": true,
"supportsDeveloperRole": true,
"supportsReasoningEffort": true,
"supportsUsageInStreaming": true,
"maxTokensField": "max_completion_tokens",
"requiresToolResultName": true,
"requiresAssistantAfterToolResult": true,
"requiresThinkingAsText": true,
"requiresReasoningContentOnAssistantMessages": true,
"thinkingFormat": "chat-template",
"chatTemplateKwargs": {
"stringValue": "literal",
"numberValue": 1.25,
"booleanValue": true,
"nullValue": null,
"variableValue": {
"$var": "thinking.effort",
"omitWhenOff": true
}
},
"cacheControlFormat": "anthropic",
"openRouterRouting": {
"allow_fallbacks": true,
"require_parameters": true,
"data_collection": "deny",
"zdr": true,
"enforce_distillable_text": true,
"order": [
"provider-a",
"provider-b"
],
"only": [
"provider-a"
],
"ignore": [
"provider-z"
],
"quantizations": [
"fp8"
],
"sort": {
"by": "price",
"partition": null
},
"max_price": {
"prompt": 1.1,
"completion": "2.2",
"image": 3.3,
"audio": "4.4",
"request": 5.5
},
"preferred_min_throughput": {
"p50": 10.5,
"p75": 9.5,
"p90": 8.5,
"p99": 7.5
},
"preferred_max_latency": {
"p50": 100.5,
"p75": 200.5,
"p90": 300.5,
"p99": 400.5
}
},
"vercelGatewayRouting": {
"only": [
"provider-a"
],
"order": [
"provider-a",
"provider-b"
]
},
"supportsOpenAIGrammarTools": true,
"supportsStrictMode": true,
"sendSessionAffinityHeaders": true,
"deferredToolsMode": "kimi",
"sessionAffinityFormat": "openrouter",
"supportsLongCacheRetention": true,
"supportsToolSearch": true,
"supportsEagerToolInputStreaming": true,
"supportsCacheControlOnTools": true,
"supportsTemperature": true,
"forceAdaptiveThinking": true,
"allowEmptySignature": true,
"supportsStrictTools": true,
"supportsToolReferences": true
},
"authHeader": true,
"models": [
{
"id": "all-fields-model",
"name": "All Fields Model",
"api": "anthropic-messages",
"baseUrl": "https://all-fields-model.example/v1",
"reasoning": true,
"thinkingLevelMap": {
"off": null,
"minimal": "minimal-effort",
"low": "low-effort",
"medium": "medium-effort",
"high": "high-effort",
"xhigh": "xhigh-effort",
"max": "max-effort"
},
"input": [
"text",
"image"
],
"cost": {
"input": 0.11,
"output": 0.22,
"cacheRead": 0.033,
"cacheWrite": 0.044,
"tiers": [
{
"inputTokensAbove": 1000.5,
"input": 0.55,
"output": 0.66,
"cacheRead": 0.077,
"cacheWrite": 0.088
}
]
},
"contextWindow": 128000.5,
"maxTokens": 16384.25,
"headers": {
"x-model-field": "model-value"
},
"compat": {
"supportsStore": true,
"supportsDeveloperRole": true,
"supportsReasoningEffort": true,
"supportsUsageInStreaming": true,
"maxTokensField": "max_completion_tokens",
"requiresToolResultName": true,
"requiresAssistantAfterToolResult": true,
"requiresThinkingAsText": true,
"requiresReasoningContentOnAssistantMessages": true,
"thinkingFormat": "chat-template",
"chatTemplateKwargs": {
"stringValue": "literal",
"numberValue": 1.25,
"booleanValue": true,
"nullValue": null,
"variableValue": {
"$var": "thinking.effort",
"omitWhenOff": true
}
},
"cacheControlFormat": "anthropic",
"openRouterRouting": {
"allow_fallbacks": true,
"require_parameters": true,
"data_collection": "deny",
"zdr": true,
"enforce_distillable_text": true,
"order": [
"provider-a",
"provider-b"
],
"only": [
"provider-a"
],
"ignore": [
"provider-z"
],
"quantizations": [
"fp8"
],
"sort": {
"by": "price",
"partition": null
},
"max_price": {
"prompt": 1.1,
"completion": "2.2",
"image": 3.3,
"audio": "4.4",
"request": 5.5
},
"preferred_min_throughput": {
"p50": 10.5,
"p75": 9.5,
"p90": 8.5,
"p99": 7.5
},
"preferred_max_latency": {
"p50": 100.5,
"p75": 200.5,
"p90": 300.5,
"p99": 400.5
}
},
"vercelGatewayRouting": {
"only": [
"provider-a"
],
"order": [
"provider-a",
"provider-b"
]
},
"supportsOpenAIGrammarTools": true,
"supportsStrictMode": true,
"sendSessionAffinityHeaders": true,
"deferredToolsMode": "kimi",
"sessionAffinityFormat": "openrouter",
"supportsLongCacheRetention": true,
"supportsToolSearch": true,
"supportsEagerToolInputStreaming": true,
"supportsCacheControlOnTools": true,
"supportsTemperature": true,
"forceAdaptiveThinking": true,
"allowEmptySignature": true,
"supportsStrictTools": true,
"supportsToolReferences": true
}
}
],
"modelOverrides": {
"all-fields-model": {
"name": "All Fields Override",
"reasoning": false,
"thinkingLevelMap": {
"off": null,
"minimal": "minimal-effort",
"low": "low-effort",
"medium": "medium-effort",
"high": "high-effort",
"xhigh": "xhigh-effort",
"max": "max-effort"
},
"input": [
"image",
"text"
],
"cost": {
"input": 0.11,
"output": 0.22,
"cacheRead": 0.033,
"cacheWrite": 0.044,
"tiers": [
{
"inputTokensAbove": 1000.5,
"input": 0.55,
"output": 0.66,
"cacheRead": 0.077,
"cacheWrite": 0.088
}
]
},
"contextWindow": 256000.75,
"maxTokens": 32768.5,
"headers": {
"x-override-field": "override-value"
},
"compat": {
"supportsStore": true,
"supportsDeveloperRole": true,
"supportsReasoningEffort": true,
"supportsUsageInStreaming": true,
"maxTokensField": "max_completion_tokens",
"requiresToolResultName": true,
"requiresAssistantAfterToolResult": true,
"requiresThinkingAsText": true,
"requiresReasoningContentOnAssistantMessages": true,
"thinkingFormat": "chat-template",
"chatTemplateKwargs": {
"stringValue": "literal",
"numberValue": 1.25,
"booleanValue": true,
"nullValue": null,
"variableValue": {
"$var": "thinking.effort",
"omitWhenOff": true
}
},
"cacheControlFormat": "anthropic",
"openRouterRouting": {
"allow_fallbacks": true,
"require_parameters": true,
"data_collection": "deny",
"zdr": true,
"enforce_distillable_text": true,
"order": [
"provider-a",
"provider-b"
],
"only": [
"provider-a"
],
"ignore": [
"provider-z"
],
"quantizations": [
"fp8"
],
"sort": {
"by": "price",
"partition": null
},
"max_price": {
"prompt": 1.1,
"completion": "2.2",
"image": 3.3,
"audio": "4.4",
"request": 5.5
},
"preferred_min_throughput": {
"p50": 10.5,
"p75": 9.5,
"p90": 8.5,
"p99": 7.5
},
"preferred_max_latency": {
"p50": 100.5,
"p75": 200.5,
"p90": 300.5,
"p99": 400.5
}
},
"vercelGatewayRouting": {
"only": [
"provider-a"
],
"order": [
"provider-a",
"provider-b"
]
},
"supportsOpenAIGrammarTools": true,
"supportsStrictMode": true,
"sendSessionAffinityHeaders": true,
"deferredToolsMode": "kimi",
"sessionAffinityFormat": "openrouter",
"supportsLongCacheRetention": true,
"supportsToolSearch": true,
"supportsEagerToolInputStreaming": true,
"supportsCacheControlOnTools": true,
"supportsTemperature": true,
"forceAdaptiveThinking": true,
"allowEmptySignature": true,
"supportsStrictTools": true,
"supportsToolReferences": true
}
}
}
},
"expectedValid": true
},
{
"id": "empty-provider-object",
"input": {},
"expectedValid": true
},
{
"id": "null-provider",
"input": null,
"expectedValid": false
},
{
"id": "additional-provider-property",
"input": {
"futureProviderField": {
"nested": true
}
},
"expectedValid": true
},
{
"id": "empty-present-base-url",
"input": {
"baseUrl": ""
},
"expectedValid": false
},
{
"id": "non-url-base-url-is-raw-string",
"input": {
"baseUrl": "not a URL"
},
"expectedValid": true
},
{
"id": "radius-oauth",
"input": {
"oauth": "radius"
},
"expectedValid": true
},
{
"id": "unknown-oauth-literal",
"input": {
"oauth": "other"
},
"expectedValid": false
},
{
"id": "models-null",
"input": {
"models": null
},
"expectedValid": false
},
{
"id": "model-missing-id",
"input": {
"models": [
{
"api": "openai-responses"
}
]
},
"expectedValid": false
},
{
"id": "model-empty-id",
"input": {
"models": [
{
"id": ""
}
]
},
"expectedValid": false
},
{
"id": "integer-model-numbers",
"input": {
"models": [
{
"id": "integer",
"contextWindow": 128000,
"maxTokens": 16384
}
]
},
"expectedValid": true
},
{
"id": "fractional-model-numbers",
"input": {
"models": [
{
"id": "fractional",
"contextWindow": 128000.5,
"maxTokens": 16384.25
}
]
},
"expectedValid": true
},
{
"id": "negative-number-is-still-typebox-number",
"input": {
"models": [
{
"id": "negative",
"maxTokens": -1.5
}
]
},
"expectedValid": true
},
{
"id": "string-is-not-number",
"input": {
"models": [
{
"id": "string-limit",
"maxTokens": "16384"
}
]
},
"expectedValid": false
},
{
"id": "complete-cost-with-fractions",
"input": {
"models": [
{
"id": "priced",
"cost": {
"input": 0.1,
"output": 0.2,
"cacheRead": 0.03,
"cacheWrite": 0.04,
"tiers": [
{
"inputTokensAbove": 1000.5,
"input": 0.5,
"output": 0.6,
"cacheRead": 0.07,
"cacheWrite": 0.08
}
]
}
}
]
},
"expectedValid": true
},
{
"id": "incomplete-model-cost",
"input": {
"models": [
{
"id": "priced",
"cost": {
"input": 0.1,
"output": 0.2,
"cacheRead": 0.03
}
}
]
},
"expectedValid": false
},
{
"id": "compat-openrouter-recursive-valid",
"input": {
"compat": {
"thinkingFormat": "chat-template",
"chatTemplateKwargs": {
"temperature": 0.25,
"thinking": {
"$var": "thinking.effort",
"omitWhenOff": true
},
"nullable": null
},
"openRouterRouting": {
"data_collection": "deny",
"sort": {
"by": "price",
"partition": null
},
"max_price": {
"prompt": 1.5,
"completion": "2.0"
},
"preferred_min_throughput": {
"p50": 10.5,
"p99": 2
}
}
}
},
"expectedValid": true
},
{
"id": "compat-nested-union-invalid-in-every-branch",
"input": {
"compat": {
"openRouterRouting": {
"preferred_min_throughput": {
"p50": "fast"
}
},
"supportsToolSearch": "yes",
"supportsTemperature": 1
}
},
"expectedValid": false
},
{
"id": "compat-union-additional-field",
"input": {
"compat": {
"futureCompatField": [
1,
2,
3
]
}
},
"expectedValid": true
},
{
"id": "compat-null",
"input": {
"compat": null
},
"expectedValid": false
},
{
"id": "thinking-map-unknown-key-and-string-value",
"input": {
"models": [
{
"id": "thinking",
"thinkingLevelMap": {
"low": null,
"max": "future-effort",
"future": {
"nested": true
}
}
}
]
},
"expectedValid": true
},
{
"id": "thinking-map-known-key-invalid-value",
"input": {
"models": [
{
"id": "thinking",
"thinkingLevelMap": {
"low": 2
}
}
]
},
"expectedValid": false
},
{
"id": "compat-sort-string-union-branch",
"input": {
"compat": {
"openRouterRouting": {
"sort": "price"
}
}
},
"expectedValid": true
},
{
"id": "compat-sort-object-union-branch",
"input": {
"compat": {
"openRouterRouting": {
"sort": {
"by": "price",
"partition": null
}
}
}
},
"expectedValid": true
},
{
"id": "compat-sort-invalid-union-boundary",
"input": {
"compat": {
"openRouterRouting": {
"sort": false
}
}
},
"expectedValid": true
},
{
"id": "headers-record-valid",
"input": {
"headers": {
"Authorization": "Bearer literal",
"x-count": "2"
}
},
"expectedValid": true
},
{
"id": "headers-record-invalid-value",
"input": {
"headers": {
"x-count": 2
}
},
"expectedValid": false
},
{
"id": "model-override-fractional-and-extra",
"input": {
"modelOverrides": {
"model/a": {
"contextWindow": 10.5,
"maxTokens": 2.25,
"futureOverrideField": true
}
}
},
"expectedValid": true
},
{
"id": "input-union-invalid",
"input": {
"models": [
{
"id": "input",
"input": [
"text",
"audio"
]
}
]
},
"expectedValid": false
}
]
}
@@ -0,0 +1,82 @@
{
"version": 1,
"piCommit": "ab366ebe94cacd419d986be454f12b1b9913aaca",
"engine": "pinned upstream TypeScript",
"bundler": "esbuild@0.28.1",
"upstreamEntry": "packages/coding-agent/src/core/resolve-config-value.ts",
"platform": "linux",
"cases": [
{
"id": "literal-value",
"input": "literal-secret",
"environment": {},
"execution": {
"status": "success",
"entryFunction": "resolveConfigValueOrThrow"
},
"expected": "literal-secret"
},
{
"id": "environment-template",
"input": "prefix-${PI_ORACLE_VALUE}-suffix",
"environment": {
"PI_ORACLE_VALUE": "environment-secret"
},
"execution": {
"status": "success",
"entryFunction": "resolveConfigValueOrThrow"
},
"expected": "prefix-environment-secret-suffix"
},
{
"id": "escaped-dollar-and-bang",
"input": "$$literal-$!bang",
"environment": {},
"execution": {
"status": "success",
"entryFunction": "resolveConfigValueOrThrow"
},
"expected": "$literal-!bang"
},
{
"id": "shell-command",
"input": "!printf pi-command-value",
"environment": {},
"execution": {
"status": "success",
"entryFunction": "resolveConfigValueOrThrow"
},
"expected": "pi-command-value"
},
{
"id": "missing-environment",
"input": "${PI_ORACLE_MISSING}",
"environment": {},
"execution": {
"status": "error",
"entryFunction": "resolveConfigValueOrThrow"
},
"expectedError": "Failed to resolve oracle missing-environment from environment variable: PI_ORACLE_MISSING"
}
],
"headerCase": {
"id": "provider-header-materialization",
"input": {
"x-literal": "literal-header",
"x-environment": "${PI_ORACLE_HEADER}",
"x-command": "!printf pi-command-header"
},
"environment": {
"PI_ORACLE_HEADER": "environment-header"
},
"execution": {
"status": "success",
"entryFunction": "resolveHeadersOrThrow"
},
"expected": {
"x-literal": "literal-header",
"x-environment": "environment-header",
"x-command": "pi-command-header"
}
}
}