feat: add letta/auto and letta/auto-fast model support (#1259)
Co-authored-by: Letta Code <noreply@letta.com>
This commit is contained in:
57
src/tests/agent/models-auto.integration.test.ts
Normal file
57
src/tests/agent/models-auto.integration.test.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Live API regression test for Cloud model availability.
|
||||
*
|
||||
* Runs only when:
|
||||
* - LETTA_API_KEY is set
|
||||
* - LETTA_BASE_URL points to Letta Cloud (api.letta.com)
|
||||
*/
|
||||
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import Letta from "@letta-ai/letta-client";
|
||||
|
||||
const LETTA_API_KEY = process.env.LETTA_API_KEY;
|
||||
const LETTA_BASE_URL = process.env.LETTA_BASE_URL || "https://api.letta.com";
|
||||
|
||||
function isCloudBaseUrl(value: string): boolean {
|
||||
try {
|
||||
return new URL(value).hostname === "api.letta.com";
|
||||
} catch {
|
||||
return value.includes("api.letta.com");
|
||||
}
|
||||
}
|
||||
|
||||
const describeIntegration =
|
||||
LETTA_API_KEY && isCloudBaseUrl(LETTA_BASE_URL) ? describe : describe.skip;
|
||||
|
||||
async function listModelHandlesWithRetry(
|
||||
client: Letta,
|
||||
maxAttempts = 3,
|
||||
): Promise<string[]> {
|
||||
let lastError: unknown;
|
||||
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
||||
try {
|
||||
const models = await client.models.list();
|
||||
return models.map((m) => m.handle).filter((h): h is string => Boolean(h));
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (attempt < maxAttempts) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 500 * attempt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
describeIntegration("cloud models list", () => {
|
||||
test("includes letta/auto handle", async () => {
|
||||
const client = new Letta({
|
||||
baseURL: LETTA_BASE_URL,
|
||||
apiKey: LETTA_API_KEY,
|
||||
});
|
||||
|
||||
const handles = await listModelHandlesWithRetry(client);
|
||||
expect(handles).toContain("letta/auto");
|
||||
});
|
||||
});
|
||||
55
src/tests/cli/model-selector-availability.test.ts
Normal file
55
src/tests/cli/model-selector-availability.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { filterModelsByAvailabilityForSelector } from "../../cli/components/ModelSelector";
|
||||
|
||||
type StubModel = { handle: string; label: string };
|
||||
|
||||
const MODELS: StubModel[] = [
|
||||
{ handle: "letta/auto", label: "Auto" },
|
||||
{ handle: "letta/auto-fast", label: "Auto Fast" },
|
||||
{ handle: "anthropic/claude-sonnet-4-6", label: "Sonnet 4.6" },
|
||||
];
|
||||
|
||||
describe("ModelSelector availability gating", () => {
|
||||
test("includes letta/auto when API availability includes it", () => {
|
||||
const availableHandles = new Set([
|
||||
"letta/auto",
|
||||
"anthropic/claude-sonnet-4-6",
|
||||
]);
|
||||
|
||||
const result = filterModelsByAvailabilityForSelector(
|
||||
MODELS,
|
||||
availableHandles,
|
||||
Array.from(availableHandles),
|
||||
);
|
||||
|
||||
expect(result.map((m) => m.handle)).toContain("letta/auto");
|
||||
});
|
||||
|
||||
test("excludes letta/auto when API availability does not include it", () => {
|
||||
const availableHandles = new Set(["anthropic/claude-sonnet-4-6"]);
|
||||
|
||||
const result = filterModelsByAvailabilityForSelector(
|
||||
MODELS,
|
||||
availableHandles,
|
||||
Array.from(availableHandles),
|
||||
);
|
||||
|
||||
expect(result.map((m) => m.handle)).not.toContain("letta/auto");
|
||||
});
|
||||
|
||||
test("fallback mode hides letta/auto unless explicitly present in allApiHandles", () => {
|
||||
const hiddenResult = filterModelsByAvailabilityForSelector(MODELS, null, [
|
||||
"anthropic/claude-sonnet-4-6",
|
||||
]);
|
||||
expect(hiddenResult.map((m) => m.handle)).not.toContain("letta/auto");
|
||||
expect(hiddenResult.map((m) => m.handle)).toContain(
|
||||
"anthropic/claude-sonnet-4-6",
|
||||
);
|
||||
|
||||
const shownResult = filterModelsByAvailabilityForSelector(MODELS, null, [
|
||||
"letta/auto",
|
||||
"anthropic/claude-sonnet-4-6",
|
||||
]);
|
||||
expect(shownResult.map((m) => m.handle)).toContain("letta/auto");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user