@blueforge-studio/gas-client

Thin client for gamevault (GAS) generation models fronted by forge-gateway /v1/gas/* — submit, poll, fetch; typed retryable-vs-fatal errors. Design: docs/design/2026-10-20-federation-gamevault-model-gateway.md.

Package Info

Latest Version0.1.2
LicenseUNLICENSED
Keywords-
Repository-
Author-
Homepage-
Bugs-

Versions

VersionPublished
0.1.22026-10-21
0.1.12026-10-20
0.1.02026-10-20

Per-version supply chain

VersionSigSBOMAtt
0.1.2
0.1.1
0.1.0

Click a version to view its details.

Supply chain

Provenance

Published by
web:5
When
2026-10-21T12:47:56Z
sha256 (registry-computed)
bc507a2400911e59009d54e0197fbfa3ded47ab01858c5f025dd0129127e11c1

Observed by the registry at publish.

Claimed by the build

The publisher claimed nothing about its build.

Attachments

Signature
none
SBOM
none

Dependencies

Loading dependency graph...

README

@blueforge-studio/gas-client

Thin client for the gamevault (GAS) generation models as fronted by forge-gateway's /v1/gas/* route family.

  • Credential: a forge-gateway token (gw_… static or gwm_… per-mission). This package never sees a gamevault API key — that lives in the gateway's tenant vault.
  • Wire contracts: @blueforge-studio/vault7-api-schema (202 job envelope + job status).
  • No retries: the typed errors say what is retryable; your caller owns retry policy.

Design + impl spec: docs/design/2026-10-20-federation-gamevault-model-gateway.md (gamevault-studio).

Install

The package lives on the private packr registry, so the registry has to be mapped per scope — not globally:

# ~/.npmrc (or the consumer's project .npmrc)
@blueforge-studio:registry=https://api.packr.blueforge.studio
pnpm add @blueforge-studio/gas-client zod

Do not set the default registry to packr (--registry=https://api.packr… or registry= in .npmrc): packr proxies unscoped upstream packages under a /name identity (zod → /zod), which npm rejects with EINVALIDPACKAGENAME. zod is a peer dependency of @blueforge-studio/vault7-api-schema, so it must resolve from npmjs.org.

Usage

import { createGasClient, createGasClientFromEnv } from '@blueforge-studio/gas-client';

// Explicit config — baseUrl is the gateway origin + /v1/gas prefix.
const client = createGasClient({
  baseUrl: 'https://gateway.blueforge.studio/v1/gas',
  apiKey: process.env.GAS_API_KEY!, // gw_/gwm_ token, never a provider key
});

// Or the null-when-unset convention (GAS_BASE_URL + GAS_API_KEY):
const maybe = createGasClientFromEnv();
if (!maybe) throw new Error('gamevault generation not configured');

const job = await client.generateAndWait('image', { prompt: 'a castle, solid black background' });
if (job.status === 'completed') {
  console.log(job.result?.files[0]?.url); // capability URL, fetchable without auth
}

// Split form, when you want to submit and poll separately:
const accepted = await client.generate('audio', { text: 'line' }, { action: 'narrate' });
const done = await client.waitForJob(accepted.jobId, { timeoutMs: 120_000 });

// Discovery + cost (both unvalidated passthrough of the gateway echo):
const catalogue = await client.models();
const pricing = await client.pricing(); // credit costs; 100 credits = $1

Errors

ClassHTTPMeaningRetry?
GasAuthError401missing/expired/revoked tokenno — mint a new token
GasForbiddenError403media/action not allowed for this tenantno
GasBudgetError402/429budget exhausted / rate limitedlater (retryAfterMs)
GasRequestErrorother 4xxbad request / unknown routeno
GasUpstreamError5xx / network / timeoutgateway↔gamevault problemnow
GasJobFailedError—job reached faileddepends on the reason

All extend GasApiError (status, code). Error bodies are read from both envelope shapes the platform emits ({error} / {message} / gateway {error:{code,message}}).

Development

pnpm --filter @blueforge-studio/gas-client run test        # vitest
pnpm --filter @blueforge-studio/gas-client run typecheck
pnpm --filter @blueforge-studio/gas-client run build