@gnomondigital/nebulas-kit-core
v0.5.1
Published
Framework-agnostic A2A chat client, Nebulas client, and server handlers.
Readme
@gnomondigital/nebulas-kit-core
Framework-agnostic A2A chat client, Nebulas client, and server handlers.
Install
npm install @gnomondigital/nebulas-kit-coreSubpath exports
| Import path | Use |
|-------------|-----|
| @gnomondigital/nebulas-kit-core | Framework-agnostic API (clients, shared handlers/types). |
| @gnomondigital/nebulas-kit-core/nextjs | Next.js route handlers and helpers (next/server based). |
| @gnomondigital/nebulas-kit-core/client | Browser-only: sendMessageStream, Nebulas client, types. Use from React/Vite so next/server is never bundled. |
| @gnomondigital/nebulas-kit-core/express | Express router only; no Next.js. |
@gnomondigital/nebulas-kit-react imports from /client internally.
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| A2A_URL | Yes | A2A agent base URL |
| A2A_AUTH_STRATEGY | Yes | session | client_credentials | resource_owner_password |
| A2A_API_KEY | Optional fallback | x-api-key header |
| AUTH0_DOMAIN | For Auth0 strategies | Auth0 tenant domain |
| AUTH0_CLIENT_ID | For client_credentials, ROP | Auth0 client ID |
| AUTH0_CLIENT_SECRET | For client_credentials, ROP | Auth0 client secret |
| AUTH0_A2A_AUDIENCE | For Auth0 strategies | API audience |
| AUTH0_ROP_USERNAME | For env ROP (createA2AProxyHandlerFromEnvROP) | Service user username (server secret) |
| AUTH0_ROP_PASSWORD | For env ROP | Service user password (server secret) |
| AUTH_PROVIDER | For env service auth | auth0 | entra |
| ENTRA_TENANT_ID | For Entra service auth | Entra tenant ID |
| ENTRA_CLIENT_ID | For Entra service auth | Entra app/client ID |
| ENTRA_CLIENT_SECRET | Optional for Entra service auth | Secret (if not using certificate) |
| ENTRA_CLIENT_CERTIFICATE / _PATH | Optional for Entra service auth | PEM certificate (inline or file path) |
| ENTRA_CLIENT_PRIVATE_KEY / _PATH | Optional for Entra service auth | PEM private key (inline or file path) |
| ENTRA_A2A_SCOPE | For Entra service auth | Scope for app/service token request (often api://<app-id>/.default) |
| ENTRA_OBO_SCOPE | For Entra OBO/session auth | Delegated downstream API scope for OBO (for example api://<app-id>/user_impersonation) |
| ENTRA_OBO_CLIENT_ID | For Entra OBO/session auth | client requesting OBO(upstream API) |
| ENTRA_OBO_CLIENT_SECRET | For Entra OBO/session auth | |
| NEBULAS_API_URL | For Nebulas | Conversation API base URL |
| NEBULAS_API_KEY | For Nebulas proxy | x-api-key fallback when no session token |
| NEBULAS_PROJECT_ID | For Nebulas | Project ID |
A2A proxy auth modes (Next.js)
| Mode | When to use | Exports |
|------|-------------|---------|
| Auth0 session | User signs in with @auth0/nextjs-auth0; access token for AUTH0_A2A_AUDIENCE comes from the session. | createA2AProxyHandler, createGetHeadersForSession |
| Env service auth | No browser session; uses Auth0 ROP service user (AUTH_PROVIDER=auth0) or Entra client credentials (AUTH_PROVIDER=entra, secret or certificate). Token is cached per process. | createA2AProxyHandlerFromEnvService, createGetHeadersFromEnvService, getCachedAccessTokenFromEnvService |
Env ROP example:
// app/api/a2a/route.ts
import { createA2AProxyHandlerFromEnvROP } from "@gnomondigital/nebulas-kit-core";
export const POST = createA2AProxyHandlerFromEnvROP({
apiKey: process.env.A2A_API_KEY,
});// app/api/a2a/config/route.ts
import type { NextRequest } from "next/server";
import {
handleA2AConfigNextJsGET,
createGetHeadersFromEnvService,
} from "@gnomondigital/nebulas-kit-core/nextjs";
const getHeaders = createGetHeadersFromEnvService({
apiKey: process.env.A2A_API_KEY,
});
export async function GET(request: NextRequest) {
return handleA2AConfigNextJsGET(request, { getHeaders });
}See apps/demo_rop in the monorepo for a full app using env ROP.
Usage
Client: sendMessageStream
import { sendMessageStream } from "@gnomondigital/nebulas-kit-core";
const content = await sendMessageStream(
"Hello",
(chunk) => console.log(chunk),
signal,
files,
true,
sessionId,
{ endpoint: "/api/a2a", getHeaders: async () => ({ Authorization: `Bearer ${token}` }) }
);Next.js App Router
// app/api/a2a/route.ts
import { handleA2ANextJsPOST } from "@gnomondigital/nebulas-kit-core/nextjs";
export async function POST(req: NextRequest) {
return handleA2ANextJsPOST(req);
}// app/api/a2a/config/route.ts
import { handleA2AConfigNextJsGET } from "@gnomondigital/nebulas-kit-core/nextjs";
export async function GET() {
return handleA2AConfigNextJsGET();
}// app/api/nebulas/[...path]/route.ts - proxies to Nebulas API (conversations, chat_messages)
import { createNebulasProxyHandler } from "@gnomondigital/nebulas-kit-core/nextjs";
import { auth0 } from "@/lib/auth";
const handler = createNebulasProxyHandler({
auth0,
audience: process.env.AUTH0_A2A_AUDIENCE,
apiKey: process.env.NEBULAS_API_KEY || process.env.A2A_API_KEY,
});
export const GET = handler;
export const POST = handler;
export const PUT = handler;
export const PATCH = handler;
export const DELETE = handler;Express
import express from "express";
import { createA2AExpressRouter } from "@gnomondigital/nebulas-kit-core/express";
const app = express();
app.use(express.json());
app.use("/api/a2a", createA2AExpressRouter(express));
app.listen(3000);Use @gnomondigital/nebulas-kit-core/express so the bundle does not load Next.js adapters (next/server).
Env ROP (service user in AUTH0_ROP_USERNAME / AUTH0_ROP_PASSWORD, same as Next.js createA2AProxyHandlerFromEnvROP):
app.use(
"/api/a2a",
createA2AExpressRouter(express, {
useEnvRop: true,
envRopApiKey: process.env.A2A_API_KEY,
})
);See apps/demo_express_rop in the monorepo for a full Express + Vite example.
