@gnomondigital/nebulas-kit-core 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/a2a-client.d.ts +2 -3
- package/dist/a2a-client.d.ts.map +1 -1
- package/dist/a2a-client.js +9 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/server/auth-handler.d.ts.map +1 -1
- package/dist/server/auth-handler.js +9 -8
- package/dist/server/config-handler.js +2 -2
- package/dist/server/env-rop-token.d.ts +10 -0
- package/dist/server/env-rop-token.d.ts.map +1 -0
- package/dist/server/env-rop-token.js +37 -0
- package/dist/server/nextjs.d.ts +18 -0
- package/dist/server/nextjs.d.ts.map +1 -1
- package/dist/server/nextjs.js +86 -1
- package/dist/types.d.ts +7 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,10 +19,49 @@ npm install @gnomondigital/nebulas-kit-core
|
|
|
19
19
|
| `AUTH0_CLIENT_ID` | For client_credentials, ROP | Auth0 client ID |
|
|
20
20
|
| `AUTH0_CLIENT_SECRET` | For client_credentials, ROP | Auth0 client secret |
|
|
21
21
|
| `AUTH0_A2A_AUDIENCE` | For Auth0 strategies | API audience |
|
|
22
|
+
| `AUTH0_ROP_USERNAME` | For env ROP (`createA2AProxyHandlerFromEnvROP`) | Service user username (server secret) |
|
|
23
|
+
| `AUTH0_ROP_PASSWORD` | For env ROP | Service user password (server secret) |
|
|
22
24
|
| `NEBULAS_API_URL` | For Nebulas | Conversation API base URL |
|
|
23
25
|
| `NEBULAS_API_KEY` | For Nebulas proxy | x-api-key fallback when no session token |
|
|
24
26
|
| `NEBULAS_PROJECT_ID` | For Nebulas | Project ID |
|
|
25
27
|
|
|
28
|
+
## A2A proxy auth modes (Next.js)
|
|
29
|
+
|
|
30
|
+
| Mode | When to use | Exports |
|
|
31
|
+
|------|-------------|---------|
|
|
32
|
+
| **Auth0 session** | User signs in with `@auth0/nextjs-auth0`; access token for `AUTH0_A2A_AUDIENCE` comes from the session. | `createA2AProxyHandler`, `createGetHeadersForAuth0`, `handleA2AAuthNextJsPOST` (body ROP, optional) |
|
|
33
|
+
| **Env ROP** | No browser Auth0; a fixed **service user** in env performs Resource Owner Password; token is cached per process. | `createA2AProxyHandlerFromEnvROP`, `createGetHeadersFromEnvROP`, `getCachedAccessTokenFromEnvROP` |
|
|
34
|
+
|
|
35
|
+
Env ROP example:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// app/api/a2a/route.ts
|
|
39
|
+
import { createA2AProxyHandlerFromEnvROP } from "@gnomondigital/nebulas-kit-core";
|
|
40
|
+
|
|
41
|
+
export const POST = createA2AProxyHandlerFromEnvROP({
|
|
42
|
+
apiKey: process.env.A2A_API_KEY,
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// app/api/a2a/config/route.ts
|
|
48
|
+
import type { NextRequest } from "next/server";
|
|
49
|
+
import {
|
|
50
|
+
handleA2AConfigNextJsGET,
|
|
51
|
+
createGetHeadersFromEnvROP,
|
|
52
|
+
} from "@gnomondigital/nebulas-kit-core";
|
|
53
|
+
|
|
54
|
+
const getHeaders = createGetHeadersFromEnvROP({
|
|
55
|
+
apiKey: process.env.A2A_API_KEY,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export async function GET(request: NextRequest) {
|
|
59
|
+
return handleA2AConfigNextJsGET(request, { getHeaders });
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
See `apps/demo_rop` in the monorepo for a full app using env ROP.
|
|
64
|
+
|
|
26
65
|
## Usage
|
|
27
66
|
|
|
28
67
|
### Client: sendMessageStream
|
package/dist/a2a-client.d.ts
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
* A2A JSON-RPC client for AI Chat.
|
|
3
3
|
* Communicates with the A2A agent via proxy (configurable endpoint).
|
|
4
4
|
*/
|
|
5
|
+
import type { SendMessageStreamOptions } from "./types.js";
|
|
5
6
|
/**
|
|
6
7
|
* Send a message and stream the response via SSE.
|
|
7
8
|
*/
|
|
8
|
-
export declare function sendMessageStream(message: string, onDelta: (chunk: string) => void, signal?: AbortSignal, files?: File[], stream?: boolean, sessionId?: string, options?:
|
|
9
|
-
endpoint?: string;
|
|
10
|
-
}): Promise<string>;
|
|
9
|
+
export declare function sendMessageStream(message: string, onDelta: (chunk: string) => void, signal?: AbortSignal, files?: File[], stream?: boolean, sessionId?: string, options?: SendMessageStreamOptions): Promise<string>;
|
|
11
10
|
//# sourceMappingURL=a2a-client.d.ts.map
|
package/dist/a2a-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-client.d.ts","sourceRoot":"","sources":["../src/a2a-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"a2a-client.d.ts","sourceRoot":"","sources":["../src/a2a-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAY3D;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,KAAK,CAAC,EAAE,IAAI,EAAE,EACd,MAAM,UAAO,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,MAAM,CAAC,CAoIjB"}
|
package/dist/a2a-client.js
CHANGED
|
@@ -32,7 +32,15 @@ export async function sendMessageStream(message, onDelta, signal, files, stream
|
|
|
32
32
|
}
|
|
33
33
|
const method = stream ? "message/stream" : "message/send";
|
|
34
34
|
const messageId = crypto.randomUUID();
|
|
35
|
-
|
|
35
|
+
let extraHeaders = {};
|
|
36
|
+
if (options?.getHeaders) {
|
|
37
|
+
const h = options.getHeaders();
|
|
38
|
+
extraHeaders = h instanceof Promise ? await h : h;
|
|
39
|
+
}
|
|
40
|
+
const headers = {
|
|
41
|
+
...extraHeaders,
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
};
|
|
36
44
|
const res = await fetch(endpoint, {
|
|
37
45
|
method: "POST",
|
|
38
46
|
headers,
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export { getAuthStrategy, getAuthHeaders, type AuthStrategy, } from "./server/au
|
|
|
11
11
|
export { exchangePasswordForToken, type ROPAuthRequest, type ROPAuthResponse, } from "./server/auth-handler.js";
|
|
12
12
|
export { createConfigResponse, type ConfigResponse, type AgentCard, type AgentCardCapabilities, } from "./server/config-handler.js";
|
|
13
13
|
export { createA2AExpressRouter, type A2AExpressRouterOptions, } from "./server/express.js";
|
|
14
|
-
export { handleA2ANextJsPOST, handleA2AAuthNextJsPOST, handleA2AConfigNextJsGET, createGetHeadersForAuth0, createA2AProxyHandler, createNebulasProxyHandler, type HandleA2AConfigOptions, type Auth0ClientInterface, type CreateA2AProxyHandlerOptions, type CreateNebulasProxyHandlerOptions, } from "./server/nextjs.js";
|
|
14
|
+
export { handleA2ANextJsPOST, handleA2AAuthNextJsPOST, handleA2AConfigNextJsGET, createGetHeadersForAuth0, createGetHeadersFromEnvROP, createA2AProxyHandler, createA2AProxyHandlerFromEnvROP, createNebulasProxyHandler, type HandleA2AConfigOptions, type Auth0ClientInterface, type CreateA2AProxyHandlerOptions, type CreateA2AProxyHandlerFromEnvROPOptions, type CreateGetHeadersFromEnvROPOptions, type CreateNebulasProxyHandlerOptions, } from "./server/nextjs.js";
|
|
15
|
+
export { getCachedAccessTokenFromEnvROP } from "./server/env-rop-token.js";
|
|
15
16
|
export { handleNebulasProxy, isRefreshTokenInvalid, type NebulasProxyRequest, type NebulasProxyResponse, type NebulasProxyHandlerOptions, } from "./server/nebulas-proxy-handler.js";
|
|
16
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE5F,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,qBAAqB,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,GACtC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE5F,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,qBAAqB,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,+BAA+B,EAC/B,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,sCAAsC,EAC3C,KAAK,iCAAiC,EACtC,KAAK,gCAAgC,GACtC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAE3E,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,5 +11,6 @@ export { exchangePasswordForToken, } from "./server/auth-handler.js";
|
|
|
11
11
|
export { createConfigResponse, } from "./server/config-handler.js";
|
|
12
12
|
export { createA2AExpressRouter, } from "./server/express.js";
|
|
13
13
|
// Usage: import express from "express"; app.use("/api/a2a", createA2AExpressRouter(express));
|
|
14
|
-
export { handleA2ANextJsPOST, handleA2AAuthNextJsPOST, handleA2AConfigNextJsGET, createGetHeadersForAuth0, createA2AProxyHandler, createNebulasProxyHandler, } from "./server/nextjs.js";
|
|
14
|
+
export { handleA2ANextJsPOST, handleA2AAuthNextJsPOST, handleA2AConfigNextJsGET, createGetHeadersForAuth0, createGetHeadersFromEnvROP, createA2AProxyHandler, createA2AProxyHandlerFromEnvROP, createNebulasProxyHandler, } from "./server/nextjs.js";
|
|
15
|
+
export { getCachedAccessTokenFromEnvROP } from "./server/env-rop-token.js";
|
|
15
16
|
export { handleNebulasProxy, isRefreshTokenInvalid, } from "./server/nebulas-proxy-handler.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-handler.d.ts","sourceRoot":"","sources":["../../src/server/auth-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-handler.d.ts","sourceRoot":"","sources":["../../src/server/auth-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CA+B1B"}
|
|
@@ -13,17 +13,18 @@ export async function exchangePasswordForToken(username, password) {
|
|
|
13
13
|
if (!domain || !clientId || !clientSecret) {
|
|
14
14
|
throw new Error("AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET required for ROP");
|
|
15
15
|
}
|
|
16
|
+
const body = new URLSearchParams({
|
|
17
|
+
grant_type: "password",
|
|
18
|
+
username,
|
|
19
|
+
password,
|
|
20
|
+
client_id: clientId,
|
|
21
|
+
client_secret: clientSecret,
|
|
22
|
+
...(audience && { audience }),
|
|
23
|
+
});
|
|
16
24
|
const res = await fetch(`https://${domain}/oauth/token`, {
|
|
17
25
|
method: "POST",
|
|
18
26
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
19
|
-
body:
|
|
20
|
-
grant_type: "password",
|
|
21
|
-
username,
|
|
22
|
-
password,
|
|
23
|
-
client_id: clientId,
|
|
24
|
-
client_secret: clientSecret,
|
|
25
|
-
...(audience && { audience }),
|
|
26
|
-
}),
|
|
27
|
+
body: body.toString(),
|
|
27
28
|
});
|
|
28
29
|
if (!res.ok) {
|
|
29
30
|
const body = await res.json().catch(() => ({}));
|
|
@@ -34,11 +34,11 @@ export async function createConfigResponse(options) {
|
|
|
34
34
|
return {
|
|
35
35
|
nebulasProjectId,
|
|
36
36
|
agentCard: null,
|
|
37
|
-
streaming:
|
|
37
|
+
streaming: false,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
const agentCard = await fetchAgentCard(options?.headers);
|
|
41
|
-
const streaming = agentCard?.capabilities?.streaming ??
|
|
41
|
+
const streaming = agentCard?.capabilities?.streaming ?? false;
|
|
42
42
|
return {
|
|
43
43
|
nebulasProjectId,
|
|
44
44
|
agentCard: agentCard ?? null,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cached Auth0 Resource Owner Password token using credentials from environment.
|
|
3
|
+
* Single service user (AUTH0_ROP_USERNAME / AUTH0_ROP_PASSWORD); shared across requests per process.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Returns a valid access token, refreshing from Auth0 when near expiry.
|
|
7
|
+
* Concurrent callers share a single in-flight refresh.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getCachedAccessTokenFromEnvROP(): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=env-rop-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-rop-token.d.ts","sourceRoot":"","sources":["../../src/server/env-rop-token.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA8BH;;;GAGG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,MAAM,CAAC,CAiBtE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cached Auth0 Resource Owner Password token using credentials from environment.
|
|
3
|
+
* Single service user (AUTH0_ROP_USERNAME / AUTH0_ROP_PASSWORD); shared across requests per process.
|
|
4
|
+
*/
|
|
5
|
+
import { exchangePasswordForToken } from "./auth-handler.js";
|
|
6
|
+
const EXPIRY_SKEW_MS = 60000;
|
|
7
|
+
let cache = null;
|
|
8
|
+
let refreshPromise = null;
|
|
9
|
+
async function fetchAndCacheToken() {
|
|
10
|
+
const username = process.env.AUTH0_ROP_USERNAME;
|
|
11
|
+
const password = process.env.AUTH0_ROP_PASSWORD;
|
|
12
|
+
if (!username || !password) {
|
|
13
|
+
throw new Error("AUTH0_ROP_USERNAME and AUTH0_ROP_PASSWORD are required for env ROP token");
|
|
14
|
+
}
|
|
15
|
+
const data = await exchangePasswordForToken(username, password);
|
|
16
|
+
const expiresInSec = data.expires_in ?? 3600;
|
|
17
|
+
const expiresAtMs = Date.now() + expiresInSec * 1000;
|
|
18
|
+
cache = { token: data.access_token, expiresAtMs };
|
|
19
|
+
return data.access_token;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns a valid access token, refreshing from Auth0 when near expiry.
|
|
23
|
+
* Concurrent callers share a single in-flight refresh.
|
|
24
|
+
*/
|
|
25
|
+
export async function getCachedAccessTokenFromEnvROP() {
|
|
26
|
+
if (refreshPromise) {
|
|
27
|
+
return refreshPromise;
|
|
28
|
+
}
|
|
29
|
+
if (cache &&
|
|
30
|
+
Date.now() < cache.expiresAtMs - EXPIRY_SKEW_MS) {
|
|
31
|
+
return cache.token;
|
|
32
|
+
}
|
|
33
|
+
refreshPromise = fetchAndCacheToken().finally(() => {
|
|
34
|
+
refreshPromise = null;
|
|
35
|
+
});
|
|
36
|
+
return refreshPromise;
|
|
37
|
+
}
|
package/dist/server/nextjs.d.ts
CHANGED
|
@@ -72,6 +72,24 @@ export interface CreateA2AProxyHandlerOptions {
|
|
|
72
72
|
* export const POST = handler;
|
|
73
73
|
*/
|
|
74
74
|
export declare function createA2AProxyHandler(options: CreateA2AProxyHandlerOptions): (request: NextRequest) => Promise<Response>;
|
|
75
|
+
export interface CreateGetHeadersFromEnvROPOptions {
|
|
76
|
+
apiKey?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Builds Authorization from a cached env-based ROP token (AUTH0_ROP_USERNAME / AUTH0_ROP_PASSWORD).
|
|
80
|
+
* Optional request parameter reserved for future use (e.g. per-request context).
|
|
81
|
+
*/
|
|
82
|
+
export declare function createGetHeadersFromEnvROP(options?: CreateGetHeadersFromEnvROPOptions): (request?: NextRequest) => Promise<Record<string, string>>;
|
|
83
|
+
export interface CreateA2AProxyHandlerFromEnvROPOptions {
|
|
84
|
+
apiKey?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Next.js POST handler for the A2A proxy using env ROP (service user), not Auth0 session.
|
|
88
|
+
*
|
|
89
|
+
* Use in app/api/a2a/route.ts:
|
|
90
|
+
* export const POST = createA2AProxyHandlerFromEnvROP({ apiKey: process.env.A2A_API_KEY });
|
|
91
|
+
*/
|
|
92
|
+
export declare function createA2AProxyHandlerFromEnvROP(options?: CreateA2AProxyHandlerFromEnvROPOptions): (request: NextRequest) => Promise<Response>;
|
|
75
93
|
/**
|
|
76
94
|
* Options for the Nebulas API proxy handler.
|
|
77
95
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/server/nextjs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/server/nextjs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAkB9E;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,mBAAmB,qBA6B9B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,WAAW,qBAyBjE;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACxE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,sBAAsB,qBAqBjC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC7D,cAAc,CACZ,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GACzB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,KAAK,EAAE,oBAAoB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,CACF,OAAO,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE,YAAY,KACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoDnC;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,oBAAoB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,IAO3C,SAAS,WAAW,uBAuDnD;AAED,MAAM,WAAW,iCAAiC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,CAAC,EAAE,iCAAiC,GAC1C,CAAC,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsB5D;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,CAAC,EAAE,sCAAsC,IAIlB,SAAS,WAAW,uBAiDnD;AAED;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C,KAAK,EAAE,oBAAoB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,IAE/E,SAAS,WAAW,EACpB,KAAK;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,oCAkH/C"}
|
package/dist/server/nextjs.js
CHANGED
|
@@ -6,6 +6,7 @@ import { NextResponse } from "next/server";
|
|
|
6
6
|
import { handleA2AProxy } from "./proxy-handler.js";
|
|
7
7
|
import { handleNebulasProxy, isRefreshTokenInvalid, } from "./nebulas-proxy-handler.js";
|
|
8
8
|
import { exchangePasswordForToken } from "./auth-handler.js";
|
|
9
|
+
import { getCachedAccessTokenFromEnvROP } from "./env-rop-token.js";
|
|
9
10
|
import { createConfigResponse } from "./config-handler.js";
|
|
10
11
|
function headersFromRequest(req) {
|
|
11
12
|
const headers = {};
|
|
@@ -76,7 +77,15 @@ export async function handleA2AConfigNextJsGET(request, options) {
|
|
|
76
77
|
const includeAgentCard = request.nextUrl.searchParams.get("includeAgentCard") !== "false";
|
|
77
78
|
let headers;
|
|
78
79
|
if (options?.getHeaders && includeAgentCard) {
|
|
79
|
-
|
|
80
|
+
try {
|
|
81
|
+
headers = await options.getHeaders(request);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
if (e instanceof NextResponse) {
|
|
85
|
+
return e;
|
|
86
|
+
}
|
|
87
|
+
throw e;
|
|
88
|
+
}
|
|
80
89
|
}
|
|
81
90
|
const config = await createConfigResponse({ includeAgentCard, headers });
|
|
82
91
|
return new Response(JSON.stringify(config), {
|
|
@@ -199,6 +208,82 @@ export function createA2AProxyHandler(options) {
|
|
|
199
208
|
return new Response(null, { status: result.status, headers: responseHeaders });
|
|
200
209
|
};
|
|
201
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Builds Authorization from a cached env-based ROP token (AUTH0_ROP_USERNAME / AUTH0_ROP_PASSWORD).
|
|
213
|
+
* Optional request parameter reserved for future use (e.g. per-request context).
|
|
214
|
+
*/
|
|
215
|
+
export function createGetHeadersFromEnvROP(options) {
|
|
216
|
+
return async (_request) => {
|
|
217
|
+
const headers = {};
|
|
218
|
+
if (options?.apiKey) {
|
|
219
|
+
headers["x-api-key"] = options.apiKey;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const token = await getCachedAccessTokenFromEnvROP();
|
|
223
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
console.error("[Env ROP] Failed to get access token:", err);
|
|
227
|
+
throw new NextResponse(JSON.stringify({
|
|
228
|
+
error: "Unauthorized",
|
|
229
|
+
hint: "Check AUTH0_ROP_USERNAME, AUTH0_ROP_PASSWORD, AUTH0_DOMAIN, client credentials, and Auth0 ROP configuration.",
|
|
230
|
+
}), { status: 401, headers: { "Content-Type": "application/json" } });
|
|
231
|
+
}
|
|
232
|
+
return headers;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Next.js POST handler for the A2A proxy using env ROP (service user), not Auth0 session.
|
|
237
|
+
*
|
|
238
|
+
* Use in app/api/a2a/route.ts:
|
|
239
|
+
* export const POST = createA2AProxyHandlerFromEnvROP({ apiKey: process.env.A2A_API_KEY });
|
|
240
|
+
*/
|
|
241
|
+
export function createA2AProxyHandlerFromEnvROP(options) {
|
|
242
|
+
const getHeaders = createGetHeadersFromEnvROP(options);
|
|
243
|
+
return async function handler(request) {
|
|
244
|
+
let authHeaders;
|
|
245
|
+
try {
|
|
246
|
+
authHeaders = await getHeaders(request);
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
if (err instanceof NextResponse) {
|
|
250
|
+
return err;
|
|
251
|
+
}
|
|
252
|
+
throw err;
|
|
253
|
+
}
|
|
254
|
+
let body;
|
|
255
|
+
try {
|
|
256
|
+
const text = await request.text();
|
|
257
|
+
body = text.length > 0 ? text : undefined;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
|
|
261
|
+
}
|
|
262
|
+
const proxyReq = {
|
|
263
|
+
method: request.method,
|
|
264
|
+
headers: headersFromRequest(request),
|
|
265
|
+
body,
|
|
266
|
+
};
|
|
267
|
+
const result = await handleA2AProxy(proxyReq, { headers: authHeaders });
|
|
268
|
+
const responseHeaders = new Headers();
|
|
269
|
+
for (const [k, v] of Object.entries(result.headers)) {
|
|
270
|
+
responseHeaders.set(k, v);
|
|
271
|
+
}
|
|
272
|
+
if (typeof result.body === "string") {
|
|
273
|
+
return new Response(result.body, {
|
|
274
|
+
status: result.status,
|
|
275
|
+
headers: responseHeaders,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
if (result.body instanceof ReadableStream) {
|
|
279
|
+
return new Response(result.body, {
|
|
280
|
+
status: result.status,
|
|
281
|
+
headers: responseHeaders,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return new Response(null, { status: result.status, headers: responseHeaders });
|
|
285
|
+
};
|
|
286
|
+
}
|
|
202
287
|
/**
|
|
203
288
|
* Creates a Next.js App Router handler for the Nebulas API proxy (catch-all [...path]).
|
|
204
289
|
* Proxies requests to NEBULAS_API_URL with Auth0 session token or API key.
|
package/dist/types.d.ts
CHANGED
|
@@ -14,14 +14,13 @@ export interface ChatMessagePayload {
|
|
|
14
14
|
role: "user" | "assistant";
|
|
15
15
|
content: string;
|
|
16
16
|
}
|
|
17
|
+
/** Options for {@link import("./a2a-client.js").sendMessageStream}. */
|
|
17
18
|
export interface SendMessageStreamOptions {
|
|
18
|
-
endpoint
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
sessionId?: string;
|
|
25
|
-
getHeaders?: () => Promise<Record<string, string>>;
|
|
19
|
+
endpoint?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Extra headers merged before Content-Type (e.g. Authorization Bearer for ROP).
|
|
22
|
+
* Sync or async; Content-Type is always set to application/json after merge.
|
|
23
|
+
*/
|
|
24
|
+
getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
26
25
|
}
|
|
27
26
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,uEAAuE;AACvE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7E"}
|