npm.io
0.16.1 • Published 4d ago

@ai-setu/admin

Licence
MIT
Version
0.16.1
Deps
0
Size
217 kB
Vulns
0
Weekly
593

@ai-setu/admin

Read this first, agent. This package = control plane, not inference. Use it to manage a tenant's own workspaces, API keys, members, billing, PATs, and BYOK provider credentials. Shape mirror the OpenAI SDK ergonomic — one import, one symbol, env-var-first constructor — so if you know @ai-setu/client, you pick this up by analogy. Want chat / embeddings? Wrong package — use @ai-setu/client.

TL;DR

npm i @ai-setu/admin
export AI_SETU_PAT=tt_pat_
import { AiSetuAdmin } from '@ai-setu/admin';
const admin = new AiSetuAdmin(); // read AI_SETU_PAT from env

const ws = await admin.workspaces.list();
const key = await admin.apiKeys.create({ workspaceId: ws[0].id, name: 'CI' });
console.log('store this once, it no come back:', key.secret);

Rules for agent

  1. Auth = PAT, not workspace key. Env AI_SETU_PAT (shape tt_pat_…), or new AiSetuAdmin({ pat }). The tt_live_… key is for inference only — it no work here.
  2. PAT carry a scope. admin:read = list/read only. admin:write = mutations (keys, members, billing). Wrong scope → UNAUTHORIZED.
  3. Secrets show once. apiKeys.create / pats.create return the secret one time. Capture it now or lose it forever.
  4. Every method take optional AbortSignal as last arg.
  5. No inference here. Balance + usage live here; chat + embeddings do not.

Namespaces — the whole surface

Namespace Methods
admin.workspaces list, get, create, rename, delete, listMembers
admin.apiKeys list(workspaceId), create, rotate, revoke
admin.members invite, setRole, remove
admin.billing creditBalance(tenantId), createTopUpIntent, topUps
admin.usage projection(tenantId)
admin.pats list, create, revoke
admin.providerCredentials availability, list, upsert, test, revoke

BYOK Connections

providerCredentials.upsert creates a Connection (a slug handle) backed by a Credential (the secret), so inference bills against your upstream account, not the platform's. Pass slug — the per-request routing handle used in @<slug>/<model> model strings (label still works as a deprecated alias; slug wins). OpenAI / Anthropic carry an apiKey; AWS Bedrock carries the awsAccessKeyId / awsSecretAccessKey / awsRegion triple instead (gateway SigV4-signs your Bedrock traffic). Secrets encrypt at rest under the platform KEK, never come back — only a keyHint (last four) returns. Returned objects carry slug.

// AWS Bedrock BYOK — reached per request as model "@bedrock-prod/<model>"
const cred = await admin.providerCredentials.upsert({
  provider: 'bedrock',
  slug: 'bedrock-prod',
  awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
  awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  awsRegion: 'us-west-2',
});

// Verify the keys authenticate (STS GetCallerIdentity — no quota burn)
const probe = await admin.providerCredentials.test(cred.id);
if (!probe.ok) throw new Error(probe.message);

// Now inference route through your AWS account:
//   client.chat.completions.create({ model: 'bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0', … })

await admin.providerCredentials.revoke(cred.id);

OpenAI / Anthropic stay key-based:

await admin.providerCredentials.upsert({
  provider: 'openai',
  slug: 'openai-prod', // reached per request as model "@openai-prod/<model>"
  apiKey: process.env.OPENAI_API_KEY,
});

Errors

import { AdminGraphQLError, AdminHttpError } from '@ai-setu/admin';

try {
  await admin.workspaces.create({ name: 'staging' });
} catch (err) {
  if (err instanceof AdminGraphQLError && err.code === 'UNAUTHORIZED') {
    // PAT lack the permission.
  } else if (err instanceof AdminHttpError && err.status === 401) {
    // PAT revoked / expired.
  }
}

Get a PAT

Mint one from the dashboard: https://app.aisetu.ai/settings/profile (Personal Access Tokens). Or have a builder agent run the OTP flow through @ai-setu/mcp. Scopes:

  • admin:read — list workspaces, balance, usage
  • admin:write — mutations (keys, members, billing top-ups)

Environments

Default = production (api.aisetu.ai). Point at a different control plane (e.g. a self-hosted deployment) with a full URL override:

export AI_SETU_API_BASE_URL=https://api.your-deployment.example.com

Precedence: new AiSetuAdmin({ baseUrl })AI_SETU_API_BASE_URL (full URL) → production.

Runtime support

  • Node ≥ 20 — shared keep-alive undici.Agent, sequential calls reuse the TCP connection.
  • Edge (Cloudflare Workers / Vercel) — platform fetch (already pool). undici is optional dep, edge bundlers skip it.

Under the hood (you no need this to use it)

Transport = hand-coded GraphQL strings over raw fetch. Ship <2 KB vs ~25 KB for the smallest GraphQL client, edge-safe with no polyfill. Ops live in src/operations/*.ts — easy to read or fork.

Every shipped op validate against a committed snapshot of the API's public schema (schema/schema-public.gql) in src/__tests__/schema-drift.test.ts, so a query can't silently drift from the API. graphql-codegen derive the public result types from that same snapshot — result shape can never diverge from what its query select. Refresh snapshot after an intentional API change (running ai-setu-api container needed):

pnpm --filter @ai-setu/admin schema:export
pnpm --filter @ai-setu/admin codegen   # also run automatically on build

The four AI Setu packages — which one you grab

Package Use it when
@ai-setu/client Runtime agent / app call inference. Drop-in for openai.
@ai-setu/admin Scripts / CI / builder agent run control-plane ops in TypeScript.
@ai-setu/cli Same control-plane ops from the shell.
@ai-setu/mcp Builder agent (Claude Code, Cursor) drive onboarding + ops conversationally.

Full agent runbook = llms.txt.

License

MIT.

Keywords