@wy-ai-labs/llm-profiles
v0.1.0
Published
LLM endpoint-profile resolver implementing the cross-language profile schema v1 (hand-written validator): env > LLM_PROFILES_DIR/<name>.json > repo profiles > builtins (dev / gateway / hosted); secrets never enter a profile — env var names only.
Maintainers
Readme
@wy-ai-labs/llm-profiles
Endpoint-profile resolver that implements the cross-language LLM endpoint profile schema (v1, hand-written validator), resolves env > profile dir > repo profiles > built-ins, and never lets a secret into a profile — only env var names.
Part of the wy-ai-labs parts monorepo (packages/llm-profiles) · contract v1 · Python twin wy-llm-profiles planned (same CONTRACT.md)
Install
npm install @wy-ai-labs/llm-profiles # Node ≥22.11, ESM only (import — no require)30-second usage
import { resolveProfile, describeProfile, CONTRACT_VERSION } from '@wy-ai-labs/llm-profiles';
// env > $LLM_PROFILES_DIR/<name>.json > ./profiles/<name>.json > built-ins (dev / gateway / hosted)
const { profile, source, overrides, warnings } = resolveProfile({
repoProfilesDir: new URL('./profiles/', import.meta.url).pathname, // profiles your app ships (optional)
legacy: { LLM_BASE_URL: ['OPENAI_BASE_URL'] }, // old names still honored, with a warning
});
console.log(CONTRACT_VERSION, source, describeProfile(profile));
// 1 builtin dev (lmstudio) · chat http://127.0.0.1:1234/v1 [qwen2.5-7b-instruct] · embeddings http://127.0.0.1:1234/v1 [text-embedding-bge-m3] · auth none
for (const w of warnings) console.warn(w); // e.g. LLM_PROFILE is not set — using the default profile "dev"
const apiKey = profile.auth?.env_var ? process.env[profile.auth.env_var] : undefined; // the profile holds the NAME onlyWith nothing set you get the loopback dev profile (LM Studio). LLM_PROFILE=gateway routes through a local llm-gateway (GATEWAY_CLIENT_ID / clientId sets the per-client id); LLM_PROFILE=hosted LLM_BASE_URL=https://… LLM_MODEL=… LLM_API_KEY=… targets any hosted OpenAI-compatible API; LLM_BASE_URL + LLM_MODEL alone (no profile name) synthesize an env profile. Employer-specific profiles live in a private LLM_PROFILES_DIR and are selected by name — never in this package.
Contract
Public API, invariants and error model are fixed in CONTRACT.md; the tests in test/ are the contract suite (one test per numbered invariant). Three invariants to know before depending on this part:
- Secrets never enter a profile —
LLM_API_KEY/EMBEDDINGS_API_KEYonly produceauth = { type: 'bearer', env_var: '<NAME>' }; no value ever appears in a profile, a description,profileToEnv, a warning or an error message. - Precedence is fixed and explicit — env >
<LLM_PROFILES_DIR>/<name>.json><repoProfilesDir>/<name>.json> built-ins;source/overrides/warningstell you what happened; an invalid profile file or env value fails loudly (invalid_profile/invalid_env), never silently. - Strict schema, loopback built-ins, pure resolution — unknown keys and wrong enums are rejected; built-ins are
127.0.0.1/example.comonly and deep-frozen;process.env, yourenvobject and the built-ins are never mutated.
An incompatible change bumps CONTRACT_VERSION and the major version together (CONTRACT.md → Compatibility).
Mined from
Extracted from four private source repositories — MyWork (MailDoAI) (src/maildoai/config.py: profiles, env precedence, legacy-name inheritance), AgentRAGKnowledge (src/env/loadEnv.js, package.json#arkUx, env names of the embedding / rerank clients), LLM_GATEWAY (server/connection-profile.mjs), CodeReviewWar (server/runtime/server-runtime.ts, gateway URL handling) — developed 2026-06-30 – 2026-08-17, generalized onto the hub profile schema and re-tested for publication. What was kept, generalized and stripped: PROVENANCE.md.
Used by
| Client | Role of this part there |
|---|---|
| llm-gateway | upstream endpoint selection for the gateway's own providers and its CLI |
| code-review-war | which gateway / hosted API the review workers talk to (gateway profile + GATEWAY_URL) |
| ark | chat + embeddings + rerank endpoints of the local RAG workbench, overridable per install |
| pr-digest | endpoint of the weekly digest's contract-bound LLM calls |
Dependencies & budget
- Runtime dependencies: 0 (budget 0, default 0) — enforced by
scripts/check-budget.mjs; imports arenode:fsandnode:pathonly. - Allowed: other
@wy-ai-labs/*parts, pinned as caret ranges from the registry. Never a client, neverfile:/link:/ git URLs /../..envloading is@wy-ai-labs/env-config's job — compose them, this part reads only theenvobject it is given. - No private host, model id or key as a default: built-ins are loopback /
example.com; endpoints come from env vars, a profile directory (LLM_PROFILE/LLM_PROFILES_DIR) or the app's shipped profiles.
Gates
| Command | What | When |
|---|---|---|
| npm test | contract suite (node:test), offline, seconds | every save |
| npm run gates:core | dependency budget + independence + engines.node + tests | before every commit / PR |
| npm run gates:full | everything above | nightly / before release |
CI only calls these scripts (wy-ai-labs/.github → node-gates.yml). Releases: Keep a Changelog + npm publish --provenance.
License
MIT © 2026 waneekim
한국어 요약
- @wy-ai-labs/llm-profiles — LLM 엔드포인트 프로필 스키마(v1)를 직접 작성한 검증기로 구현하고, 환경변수 > 프로필 디렉터리 > repo 프로필 > 내장(dev/gateway/hosted) 순서로 해석하며, 시크릿은 절대 프로필에 넣지 않는(환경변수 이름만) 부품입니다. 공개 API·불변식·오류 모델은 CONTRACT.md에 고정되어 있고, 테스트가 곧 계약 스위트입니다.
- 설치
npm install @wy-ai-labs/llm-profiles(Node ≥22, ESM). 런타임 의존성 0, 다른 part에만 핀 버전으로 의존, 내장 프로필은 루프백/example.com 뿐 — 사설 호스트 기본값 없음. - 비공개 저장소
MyWork (MailDoAI)·AgentRAGKnowledge·LLM_GATEWAY·CodeReviewWar에서 추출·일반화했습니다(PROVENANCE.md). 커밋 전npm run gates:core.
