listModels
JavaScript · package toolnexus · SPEC §8 · js/src/models.ts
interface ModelInfo { id: string; name?: string; contextLength?: number }listModels( opts: Pick<ClientOptions, "baseUrl" | "style" | "apiKey" | "apiKeyEnv" | "headers" | "fetch">, ctx?: { signal?: AbortSignal },): Promise<ModelInfo[]>Lists the models a provider serves, sorted by id. openai style: GET {base}/models (OpenRouter’s
context_length becomes contextLength); anthropic: GET {base}/v1/models, following
has_more / last_id. One GET per page, no retries, and the same
key rules as the client. A non-2xx throws
list models: HTTP <status>: ….
When to use it
Section titled “When to use it”A model picker in a host UI, or checking at startup that the configured model exists before the first turn fails on it.
Why this and not the alternative
Section titled “Why this and not the alternative”Examples
Section titled “Examples”1. The smallest useful call
Section titled “1. The smallest useful call”import assert from "node:assert"import http from "node:http"import { listModels } from "toolnexus"
const server = http.createServer((req, res) => { assert.equal(req.url, "/v1/models") res.writeHead(200, { "content-type": "application/json" }) res.end(JSON.stringify({ data: [{ id: "b-model" }, { id: "a-model" }] }))})await new Promise<void>((r) => server.listen(0, "127.0.0.1", r))const models = await listModels({ baseUrl: `http://127.0.0.1:${(server.address() as any).port}/v1`, style: "openai", apiKey: "YOUR_KEY_HERE" })assert.deepEqual(models.map((m) => m.id), ["a-model", "b-model"])server.close()console.log("ok:", models.map((m) => m.id).join(","))2. The realistic case — OpenRouter-shaped context lengths for a picker
Section titled “2. The realistic case — OpenRouter-shaped context lengths for a picker”import assert from "node:assert"import http from "node:http"import { listModels } from "toolnexus"
const server = http.createServer((req, res) => { res.writeHead(200, { "content-type": "application/json" }) res.end(JSON.stringify({ data: [ { id: "openai/gpt-4o-mini", name: "GPT-4o mini", context_length: 128000 }, { id: "local/tiny" }, ] }))})await new Promise<void>((r) => server.listen(0, "127.0.0.1", r))const models = await listModels({ baseUrl: `http://127.0.0.1:${(server.address() as any).port}`, style: "openai", apiKey: "YOUR_KEY_HERE" })assert.deepEqual(models[1], { id: "openai/gpt-4o-mini", name: "GPT-4o mini", contextLength: 128000 })assert.deepEqual(models[0], { id: "local/tiny" })server.close()console.log("ok:", models.map((m) => `${m.id}:${m.contextLength ?? "?"}`).join(" "))3. The full surface — anthropic paging, and the key rule
Section titled “3. The full surface — anthropic paging, and the key rule”import assert from "node:assert"import http from "node:http"import { listModels } from "toolnexus"
const server = http.createServer((req, res) => { const after = new URL(req.url!, "http://x").searchParams.get("after_id") res.writeHead(200, { "content-type": "application/json" }) res.end(JSON.stringify(after ? { data: [{ id: "claude-b", display_name: "B" }], has_more: false } : { data: [{ id: "claude-a", display_name: "A" }], has_more: true, last_id: "claude-a" }))})await new Promise<void>((r) => server.listen(0, "127.0.0.1", r))const base = `http://127.0.0.1:${(server.address() as any).port}`const models = await listModels({ baseUrl: base, style: "anthropic", apiKey: "YOUR_KEY_HERE" })assert.deepEqual(models, [{ id: "claude-a", name: "A" }, { id: "claude-b", name: "B" }])// A local host with no apiKey/apiKeyEnv is refused, exactly like the client.await assert.rejects(listModels({ baseUrl: base, style: "anthropic" }), /apiKeyEnv/)server.close()console.log("ok:", models.length, "models over 2 pages")See also
Section titled “See also”createClient— The unified client: system prompt, skills injection, parallel and chained tool calls, retries, memory.Client.run— Send a prompt, let the loop call tools until the model stops, get a RunResult.Client.stream— The streaming loop: text deltas, tool-call events, and suspension events as they happen.Hooks— Intercept before/after model calls and tool calls: audit, redact, veto, or rewrite.