Provider: finalize dynamic Chutes models and TEE filtering
This commit is contained in:
parent
2bb5e73d51
commit
053c160b6b
@ -6,7 +6,9 @@ read_when:
|
|||||||
---
|
---
|
||||||
# Chutes AI
|
# Chutes AI
|
||||||
|
|
||||||
Chutes provides high-performance inference for open-weight models, including GLM 4.6 TEE. Clawdbot supports Chutes via both OAuth and API key authentication.
|
Chutes provides high-performance inference for open-weight models, including GLM 4.7 Flash. Clawdbot supports Chutes via both OAuth and API key authentication.
|
||||||
|
|
||||||
|
Models are fetched dynamically from the Chutes API, ensuring you always have access to the latest models, accurate pricing, and context window limits.
|
||||||
|
|
||||||
## CLI setup
|
## CLI setup
|
||||||
|
|
||||||
@ -47,13 +49,14 @@ If you wish to use your own OAuth application instead of the default, set these
|
|||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
env: { CHUTES_API_KEY: "sk-..." },
|
env: { CHUTES_API_KEY: "sk-..." },
|
||||||
agents: { defaults: { model: { primary: "chutes/zai-org/GLM-4.6-TEE" } } },
|
agents: { defaults: { model: { primary: "chutes/zai-org/GLM-4.7-Flash" } } },
|
||||||
models: {
|
models: {
|
||||||
providers: {
|
providers: {
|
||||||
chutes: {
|
chutes: {
|
||||||
baseUrl: "https://llm.chutes.ai/v1",
|
baseUrl: "https://llm.chutes.ai/v1",
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
apiKey: "${CHUTES_API_KEY}"
|
apiKey: "${CHUTES_API_KEY}",
|
||||||
|
teeOnly: false // Set to true to filter models by Trusted Execution Environment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,11 +66,12 @@ If you wish to use your own OAuth application instead of the default, set these
|
|||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Chutes models are available under the `chutes/` provider prefix.
|
- Chutes models are available under the `chutes/` provider prefix.
|
||||||
- The default model is `chutes/zai-org/GLM-4.6-TEE`.
|
- The default model is `chutes/zai-org/GLM-4.7-Flash`.
|
||||||
- Chutes uses OpenAI-compatible endpoints.
|
- Chutes uses OpenAI-compatible endpoints.
|
||||||
|
- **Trusted Execution Environment (TEE)**: Models running in a TEE are marked with a "TEE" badge in the model picker. You can filter for these models by setting `teeOnly: true` in your provider config.
|
||||||
- Many top models on Chutes support tool calling, including:
|
- Many top models on Chutes support tool calling, including:
|
||||||
- `Qwen/Qwen3-235B-A22B-Instruct-2507-TEE`
|
- `Qwen/Qwen3-235B-A22B-Instruct-2507-TEE` (TEE)
|
||||||
- `deepseek-ai/DeepSeek-V3.2-TEE`
|
- `deepseek-ai/DeepSeek-V3.2-TEE` (TEE)
|
||||||
- `chutesai/Mistral-Small-3.1-24B-Instruct-2503`
|
- `chutesai/Mistral-Small-3.1-24B-Instruct-2503`
|
||||||
- `NousResearch/Hermes-4-14B`
|
- `NousResearch/Hermes-4-14B`
|
||||||
- For a full list of available models, see the [Chutes Models API](https://llm.chutes.ai/v1/models). Popular models include:
|
- For a full list of available models, see the [Chutes Models API](https://llm.chutes.ai/v1/models). Popular models include:
|
||||||
|
|||||||
76
src/agents/chutes-models.ts
Normal file
76
src/agents/chutes-models.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import type { ModelDefinitionConfig } from "../config/types.models.js";
|
||||||
|
|
||||||
|
export const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
|
||||||
|
export const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.7-Flash";
|
||||||
|
export const CHUTES_DEFAULT_MODEL_REF = `chutes/${CHUTES_DEFAULT_MODEL_ID}`;
|
||||||
|
|
||||||
|
export interface ChutesModelEntry {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
context_length?: number;
|
||||||
|
max_output_length?: number;
|
||||||
|
confidential_compute?: boolean;
|
||||||
|
pricing?: { prompt: number; completion: number };
|
||||||
|
supported_features?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchChutesModels(): Promise<ChutesModelEntry[]> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${CHUTES_BASE_URL}/models`, {
|
||||||
|
signal: AbortSignal.timeout(5000),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch Chutes models: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
const data = (await response.json()) as { data: ChutesModelEntry[] };
|
||||||
|
return data.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`[chutes-models] Failed to fetch models: ${String(error)}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapChutesModelToDefinition(entry: ChutesModelEntry): ModelDefinitionConfig {
|
||||||
|
return {
|
||||||
|
id: entry.id,
|
||||||
|
name: entry.name || entry.id,
|
||||||
|
reasoning: entry.supported_features?.includes("reasoning") ?? false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: entry.pricing?.prompt ?? 0,
|
||||||
|
output: entry.pricing?.completion ?? 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: entry.context_length || 128000,
|
||||||
|
maxTokens: entry.max_output_length || 4096,
|
||||||
|
confidentialCompute: entry.confidential_compute,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function discoverChutesModels(opts?: {
|
||||||
|
teeOnly?: boolean;
|
||||||
|
}): Promise<ModelDefinitionConfig[]> {
|
||||||
|
const models = await fetchChutesModels();
|
||||||
|
if (models.length === 0) {
|
||||||
|
// Fallback to minimal list
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: CHUTES_DEFAULT_MODEL_ID,
|
||||||
|
name: "GLM 4.7 Flash",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
let filtered = models;
|
||||||
|
if (opts?.teeOnly) {
|
||||||
|
filtered = models.filter((m) => m.confidential_compute === true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered.map(mapChutesModelToDefinition);
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import {
|
|||||||
import { ensureAuthProfileStore, listProfilesForProvider } from "./auth-profiles.js";
|
import { ensureAuthProfileStore, listProfilesForProvider } from "./auth-profiles.js";
|
||||||
import { resolveAwsSdkEnvVarName, resolveEnvApiKey } from "./model-auth.js";
|
import { resolveAwsSdkEnvVarName, resolveEnvApiKey } from "./model-auth.js";
|
||||||
import { discoverBedrockModels } from "./bedrock-discovery.js";
|
import { discoverBedrockModels } from "./bedrock-discovery.js";
|
||||||
|
import { discoverChutesModels } from "./chutes-models.js";
|
||||||
import {
|
import {
|
||||||
buildSyntheticModelDefinition,
|
buildSyntheticModelDefinition,
|
||||||
SYNTHETIC_BASE_URL,
|
SYNTHETIC_BASE_URL,
|
||||||
@ -42,15 +43,6 @@ const MOONSHOT_DEFAULT_COST = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
|
const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
|
||||||
const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.6-TEE";
|
|
||||||
const CHUTES_DEFAULT_CONTEXT_WINDOW = 128000;
|
|
||||||
const CHUTES_DEFAULT_MAX_TOKENS = 4096;
|
|
||||||
const CHUTES_DEFAULT_COST = {
|
|
||||||
input: 0,
|
|
||||||
output: 0,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const KIMI_CODE_BASE_URL = "https://api.kimi.com/coding/v1";
|
const KIMI_CODE_BASE_URL = "https://api.kimi.com/coding/v1";
|
||||||
const KIMI_CODE_MODEL_ID = "kimi-for-coding";
|
const KIMI_CODE_MODEL_ID = "kimi-for-coding";
|
||||||
@ -298,57 +290,13 @@ function buildMoonshotProvider(): ProviderConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChutesProvider(): ProviderConfig {
|
async function buildChutesProvider(opts?: { teeOnly?: boolean }): Promise<ProviderConfig> {
|
||||||
|
const models = await discoverChutesModels(opts);
|
||||||
return {
|
return {
|
||||||
baseUrl: CHUTES_BASE_URL,
|
baseUrl: CHUTES_BASE_URL,
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
models: [
|
models,
|
||||||
{
|
teeOnly: opts?.teeOnly,
|
||||||
id: CHUTES_DEFAULT_MODEL_ID,
|
|
||||||
name: "GLM 4.6 TEE",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: CHUTES_DEFAULT_COST,
|
|
||||||
contextWindow: CHUTES_DEFAULT_CONTEXT_WINDOW,
|
|
||||||
maxTokens: CHUTES_DEFAULT_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "Qwen/Qwen3-235B-A22B-Instruct-2507-TEE",
|
|
||||||
name: "Qwen 3 235B (Tools)",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: CHUTES_DEFAULT_COST,
|
|
||||||
contextWindow: 262144,
|
|
||||||
maxTokens: 4096,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "deepseek-ai/DeepSeek-V3.2-TEE",
|
|
||||||
name: "DeepSeek V3.2 (Tools)",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: CHUTES_DEFAULT_COST,
|
|
||||||
contextWindow: 202752,
|
|
||||||
maxTokens: 4096,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "chutesai/Mistral-Small-3.1-24B-Instruct-2503",
|
|
||||||
name: "Mistral Small 3.1 (Tools)",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: CHUTES_DEFAULT_COST,
|
|
||||||
contextWindow: 131072,
|
|
||||||
maxTokens: 4096,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "NousResearch/Hermes-4-14B",
|
|
||||||
name: "Hermes 4 14B (Tools)",
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: CHUTES_DEFAULT_COST,
|
|
||||||
contextWindow: 40960,
|
|
||||||
maxTokens: 4096,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +399,7 @@ export async function resolveImplicitProviders(params: {
|
|||||||
resolveEnvApiKeyVarName("chutes") ??
|
resolveEnvApiKeyVarName("chutes") ??
|
||||||
resolveApiKeyFromProfiles({ provider: "chutes", store: authStore });
|
resolveApiKeyFromProfiles({ provider: "chutes", store: authStore });
|
||||||
if (chutesKey) {
|
if (chutesKey) {
|
||||||
providers.chutes = { ...buildChutesProvider(), apiKey: chutesKey };
|
providers.chutes = { ...(await buildChutesProvider()), apiKey: chutesKey };
|
||||||
}
|
}
|
||||||
|
|
||||||
const kimiCodeKey =
|
const kimiCodeKey =
|
||||||
|
|||||||
@ -214,6 +214,7 @@ export async function promptDefaultModel(
|
|||||||
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
|
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
|
||||||
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
|
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
|
||||||
if (entry.reasoning) hints.push("reasoning");
|
if (entry.reasoning) hints.push("reasoning");
|
||||||
|
if ((entry as any).confidentialCompute) hints.push("TEE");
|
||||||
const aliases = aliasIndex.byKey.get(key);
|
const aliases = aliasIndex.byKey.get(key);
|
||||||
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
|
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
|
||||||
if (!hasAuth(entry.provider)) hints.push("auth missing");
|
if (!hasAuth(entry.provider)) hints.push("auth missing");
|
||||||
@ -341,6 +342,7 @@ export async function promptModelAllowlist(params: {
|
|||||||
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
|
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
|
||||||
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
|
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
|
||||||
if (entry.reasoning) hints.push("reasoning");
|
if (entry.reasoning) hints.push("reasoning");
|
||||||
|
if ((entry as any).confidentialCompute) hints.push("TEE");
|
||||||
const aliases = aliasIndex.byKey.get(key);
|
const aliases = aliasIndex.byKey.get(key);
|
||||||
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
|
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
|
||||||
if (!hasAuth(entry.provider)) hints.push("auth missing");
|
if (!hasAuth(entry.provider)) hints.push("auth missing");
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import {
|
|||||||
MOONSHOT_DEFAULT_MODEL_ID,
|
MOONSHOT_DEFAULT_MODEL_ID,
|
||||||
MOONSHOT_DEFAULT_MODEL_REF,
|
MOONSHOT_DEFAULT_MODEL_REF,
|
||||||
CHUTES_BASE_URL,
|
CHUTES_BASE_URL,
|
||||||
CHUTES_DEFAULT_MODEL_ID,
|
|
||||||
CHUTES_DEFAULT_MODEL_REF,
|
CHUTES_DEFAULT_MODEL_REF,
|
||||||
buildChutesModelDefinition,
|
buildChutesModelDefinition,
|
||||||
} from "./onboard-auth.models.js";
|
} from "./onboard-auth.models.js";
|
||||||
@ -210,36 +209,16 @@ export function applyChutesProviderConfig(cfg: ClawdbotConfig): ClawdbotConfig {
|
|||||||
const models = { ...cfg.agents?.defaults?.models };
|
const models = { ...cfg.agents?.defaults?.models };
|
||||||
models[CHUTES_DEFAULT_MODEL_REF] = {
|
models[CHUTES_DEFAULT_MODEL_REF] = {
|
||||||
...models[CHUTES_DEFAULT_MODEL_REF],
|
...models[CHUTES_DEFAULT_MODEL_REF],
|
||||||
alias: models[CHUTES_DEFAULT_MODEL_REF]?.alias ?? "GLM 4.6",
|
alias: models[CHUTES_DEFAULT_MODEL_REF]?.alias ?? "GLM 4.7 Flash",
|
||||||
};
|
};
|
||||||
|
|
||||||
const providers = { ...cfg.models?.providers };
|
const providers = { ...cfg.models?.providers };
|
||||||
const existingProvider = providers.chutes;
|
const existingProvider = providers.chutes;
|
||||||
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
|
||||||
|
|
||||||
const toolCapableModelIds = [
|
|
||||||
"Qwen/Qwen3-235B-A22B-Instruct-2507-TEE",
|
|
||||||
"deepseek-ai/DeepSeek-V3.2-TEE",
|
|
||||||
"chutesai/Mistral-Small-3.1-24B-Instruct-2503",
|
|
||||||
"NousResearch/Hermes-4-14B",
|
|
||||||
];
|
|
||||||
|
|
||||||
const defaultModel = buildChutesModelDefinition();
|
|
||||||
const toolModels = toolCapableModelIds.map((id) => buildChutesModelDefinition(id));
|
|
||||||
|
|
||||||
const allChutesModels = [defaultModel, ...toolModels];
|
|
||||||
const mergedModels = [...existingModels];
|
|
||||||
|
|
||||||
for (const model of allChutesModels) {
|
|
||||||
if (!mergedModels.some((m) => m.id === model.id)) {
|
|
||||||
mergedModels.push(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
|
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
|
||||||
string,
|
string,
|
||||||
unknown
|
unknown
|
||||||
> as { apiKey?: string };
|
> as { apiKey?: string; teeOnly?: boolean };
|
||||||
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
|
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
|
||||||
const normalizedApiKey = resolvedApiKey?.trim();
|
const normalizedApiKey = resolvedApiKey?.trim();
|
||||||
providers.chutes = {
|
providers.chutes = {
|
||||||
@ -247,7 +226,9 @@ export function applyChutesProviderConfig(cfg: ClawdbotConfig): ClawdbotConfig {
|
|||||||
baseUrl: CHUTES_BASE_URL,
|
baseUrl: CHUTES_BASE_URL,
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
|
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
|
||||||
models: mergedModels,
|
// Models will be refreshed dynamically at startup,
|
||||||
|
// but we can pre-populate the default one for onboarding.
|
||||||
|
models: existingProvider?.models || [buildChutesModelDefinition()],
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -126,7 +126,7 @@ export async function setVeniceApiKey(key: string, agentDir?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7";
|
export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7";
|
||||||
export const CHUTES_DEFAULT_MODEL_REF = "chutes/zai-org/GLM-4.6-TEE";
|
export const CHUTES_DEFAULT_MODEL_REF = "chutes/zai-org/GLM-4.7-Flash";
|
||||||
export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto";
|
export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto";
|
||||||
export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF = "vercel-ai-gateway/anthropic/claude-opus-4.5";
|
export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF = "vercel-ai-gateway/anthropic/claude-opus-4.5";
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export const MOONSHOT_DEFAULT_CONTEXT_WINDOW = 256000;
|
|||||||
export const MOONSHOT_DEFAULT_MAX_TOKENS = 8192;
|
export const MOONSHOT_DEFAULT_MAX_TOKENS = 8192;
|
||||||
|
|
||||||
export const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
|
export const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
|
||||||
export const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.6-TEE";
|
export const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.7-Flash";
|
||||||
export const CHUTES_DEFAULT_MODEL_REF = `chutes/${CHUTES_DEFAULT_MODEL_ID}`;
|
export const CHUTES_DEFAULT_MODEL_REF = `chutes/${CHUTES_DEFAULT_MODEL_ID}`;
|
||||||
export const CHUTES_DEFAULT_CONTEXT_WINDOW = 128000;
|
export const CHUTES_DEFAULT_CONTEXT_WINDOW = 128000;
|
||||||
export const CHUTES_DEFAULT_MAX_TOKENS = 4096;
|
export const CHUTES_DEFAULT_MAX_TOKENS = 4096;
|
||||||
@ -165,7 +165,7 @@ export function buildChutesModelDefinition(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: CHUTES_DEFAULT_MODEL_ID,
|
id: CHUTES_DEFAULT_MODEL_ID,
|
||||||
name: "GLM 4.6 TEE",
|
name: "GLM 4.7 Flash",
|
||||||
reasoning: false,
|
reasoning: false,
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: CHUTES_DEFAULT_COST,
|
cost: CHUTES_DEFAULT_COST,
|
||||||
|
|||||||
@ -31,6 +31,8 @@ export type ModelDefinitionConfig = {
|
|||||||
maxTokens: number;
|
maxTokens: number;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
compat?: ModelCompatConfig;
|
compat?: ModelCompatConfig;
|
||||||
|
/** Chutes-only: indicates the model runs in a Trusted Execution Environment */
|
||||||
|
confidentialCompute?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModelProviderConfig = {
|
export type ModelProviderConfig = {
|
||||||
@ -41,6 +43,8 @@ export type ModelProviderConfig = {
|
|||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
authHeader?: boolean;
|
authHeader?: boolean;
|
||||||
models: ModelDefinitionConfig[];
|
models: ModelDefinitionConfig[];
|
||||||
|
/** Chutes-only: filter models by confidential_compute: true */
|
||||||
|
teeOnly?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BedrockDiscoveryConfig = {
|
export type BedrockDiscoveryConfig = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user