Skip to content

Commit 1b83eac

Browse files
jpbufe3Copilot
andcommitted
Make Rust allowlist codegen reproducible
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 40f9c80 commit 1b83eac

2 files changed

Lines changed: 114 additions & 4 deletions

File tree

rust/src/wire.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub(crate) struct SessionCreateWire {
5252
pub session_id: Option<SessionId>,
5353
#[serde(skip_serializing_if = "Option::is_none")]
5454
pub model: Option<String>,
55-
#[serde(skip_serializing_if = "Option::is_none")]
55+
#[serde(rename = "allowedModels", skip_serializing_if = "Option::is_none")]
5656
pub allowed_models: Option<Vec<String>>,
5757
#[serde(skip_serializing_if = "Option::is_none")]
5858
pub client_name: Option<String>,
@@ -212,7 +212,7 @@ pub(crate) struct SessionResumeWire {
212212
pub session_id: SessionId,
213213
#[serde(skip_serializing_if = "Option::is_none")]
214214
pub model: Option<String>,
215-
#[serde(skip_serializing_if = "Option::is_none")]
215+
#[serde(rename = "allowedModels", skip_serializing_if = "Option::is_none")]
216216
pub allowed_models: Option<Vec<String>>,
217217
#[serde(skip_serializing_if = "Option::is_none")]
218218
pub client_name: Option<String>,

scripts/codegen/rust.ts

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,114 @@ const EXTERNAL_SCHEMA_RUST_TYPE_MODULE: Record<string, Record<string, string>> =
6969
},
7070
};
7171

72+
/**
73+
* Add the live model-allowlist RPC until the pinned CLI schema includes it.
74+
*
75+
* This is Rust-only because the compatibility surface is currently exposed
76+
* only by the Rust SDK.
77+
*/
78+
function addModelSetAllowedModelsToApiSchema(schema: ApiSchema): ApiSchema {
79+
const session = (schema.session ??= {});
80+
const model = (session.model ??= {}) as Record<string, unknown>;
81+
if (model.setAllowedModels !== undefined) return schema;
82+
83+
const definitions = (schema.definitions ??= {});
84+
if (
85+
definitions.ModelSetAllowedModelsRequest !== undefined ||
86+
definitions.ModelSetAllowedModelsResult !== undefined
87+
) {
88+
throw new Error(
89+
"Model allowlist schema definitions exist without session.model.setAllowedModels",
90+
);
91+
}
92+
93+
const allowedModelsProperty = {
94+
anyOf: [
95+
{
96+
type: "array",
97+
items: {
98+
type: "string",
99+
},
100+
},
101+
{
102+
type: "null",
103+
},
104+
],
105+
description: "Exact model IDs to permit, or null to clear the host restriction.",
106+
};
107+
const requestDescription =
108+
"Host-supplied exact CAPI model IDs to allow for this running session. The runtime intersects the list with repository `.github/allowed_models.txt` policy. Omit or pass null to clear the host restriction; an explicit empty or disjoint list is rejected.";
109+
110+
definitions.ModelSetAllowedModelsRequest = {
111+
type: "object",
112+
properties: {
113+
allowedModels: allowedModelsProperty,
114+
},
115+
additionalProperties: false,
116+
description: requestDescription,
117+
title: "ModelSetAllowedModelsRequest",
118+
stability: "experimental",
119+
} as JSONSchema7Definition;
120+
definitions.ModelSetAllowedModelsResult = {
121+
type: "object",
122+
properties: {
123+
allowedModels: {
124+
type: "array",
125+
items: {
126+
type: "string",
127+
},
128+
description: "Normalized host allowlist. Omitted when the host restriction was cleared.",
129+
},
130+
effectiveAllowedModels: {
131+
type: "array",
132+
items: {
133+
type: "string",
134+
},
135+
description:
136+
"Effective exact IDs or repository policy patterns after applying the host restriction. Omitted by relay clients whose AHP host applies the policy asynchronously.",
137+
},
138+
fallbackModel: {
139+
type: "string",
140+
description: "Effective deterministic fallback model, when the policy defines one.",
141+
},
142+
modelId: {
143+
type: "string",
144+
description:
145+
"Selected session model after reconciling a now-disallowed concrete selection.",
146+
},
147+
},
148+
additionalProperties: false,
149+
description: "The applied host allowlist and effective session model policy after intersection.",
150+
title: "ModelSetAllowedModelsResult",
151+
} as JSONSchema7Definition;
152+
model.setAllowedModels = {
153+
rpcMethod: "session.model.setAllowedModels",
154+
description: "Replaces or clears the host-supplied model allowlist for a running session.",
155+
params: {
156+
type: "object",
157+
properties: {
158+
sessionId: {
159+
type: "string",
160+
description: "Target session identifier",
161+
},
162+
allowedModels: allowedModelsProperty,
163+
},
164+
required: ["sessionId"],
165+
additionalProperties: false,
166+
description: requestDescription,
167+
title: "ModelSetAllowedModelsRequest",
168+
stability: "experimental",
169+
},
170+
result: {
171+
$ref: "#/definitions/ModelSetAllowedModelsResult",
172+
description: "The applied host allowlist and effective session model policy after intersection.",
173+
},
174+
stability: "experimental",
175+
};
176+
177+
return schema;
178+
}
179+
72180
function rustDeprecatedAttributes(indent = ""): string[] {
73181
return [`${indent}#[doc(hidden)]`, `${indent}#[deprecated]`];
74182
}
@@ -2219,8 +2327,10 @@ async function generate(): Promise<void> {
22192327
const sessionEventsRaw = normalizeSchemaBrandCasing(
22202328
JSON.parse(await fs.readFile(sessionEventsSchemaPath, "utf-8")),
22212329
);
2222-
const apiRaw = normalizeSchemaBrandCasing(
2223-
JSON.parse(await fs.readFile(apiSchemaPath, "utf-8")) as ApiSchema,
2330+
const apiRaw = addModelSetAllowedModelsToApiSchema(
2331+
normalizeSchemaBrandCasing(
2332+
JSON.parse(await fs.readFile(apiSchemaPath, "utf-8")) as ApiSchema,
2333+
),
22242334
);
22252335

22262336
const sessionEventsSchema = propagateInternalVisibility(

0 commit comments

Comments
 (0)