@economic/agents 2.7.2 → 2.8.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 +18 -12
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +19 -1
- package/dist/{route-agent-request-D2ll--nF.d.mts → route-agent-request-8C2T8Mu0.d.mts} +2 -0
- package/dist/{route-agent-request-DBGSXu2O.mjs → route-agent-request-CYclS_5Q.mjs} +13 -1
- package/dist/v1.d.mts +1 -1
- package/dist/v1.mjs +19 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -501,6 +501,7 @@ export class SupportAgent extends Agent {
|
|
|
501
501
|
userGuid: payload.user_guid as string,
|
|
502
502
|
agreementNumber: payload.agreement_number as number,
|
|
503
503
|
}),
|
|
504
|
+
getActorId: (claims) => `${claims.agreementNumber}_${claims.userGuid}`,
|
|
504
505
|
};
|
|
505
506
|
}
|
|
506
507
|
|
|
@@ -508,6 +509,11 @@ export class SupportAgent extends Agent {
|
|
|
508
509
|
}
|
|
509
510
|
```
|
|
510
511
|
|
|
512
|
+
`getActorId` derives the authenticated actor from verified claims. It must exactly match the
|
|
513
|
+
actor that owns the requested Durable Object: the Assistant name, the root parent of a chat
|
|
514
|
+
facet, or the prefix in a standalone `${actorId}:${chatId}` name. A valid token belonging to
|
|
515
|
+
another actor is rejected with `4003` before the connection is established.
|
|
516
|
+
|
|
511
517
|
On failure the socket closes (`4001` unauthorized, `4003` forbidden) and status becomes `"unauthorized"`. The token is read from `Authorization: Bearer …`, then the `Sec-WebSocket-Protocol: bearer, <token>` header.
|
|
512
518
|
|
|
513
519
|
### User context
|
|
@@ -585,18 +591,18 @@ Imported from `@economic/agents` unless noted.
|
|
|
585
591
|
|
|
586
592
|
### Members
|
|
587
593
|
|
|
588
|
-
| Member | On | Description
|
|
589
|
-
| ---------------------------------------------- | ----------- |
|
|
590
|
-
| `getModel(ctx?)` | `Agent` | Required. Model for inference.
|
|
591
|
-
| `getSystemPrompt(ctx?)` | `Agent` | Required. System prompt.
|
|
592
|
-
| `getTools()` | `Agent` | Always-on tools (default `{}`).
|
|
593
|
-
| `getSkills()` | `Agent` | Local skills (default `[]`).
|
|
594
|
-
| `static getJwtAuthConfig(env)` | `Agent` | Optional JWT verification
|
|
595
|
-
| `getUserContext(jwtToken)` | `Agent` | Optional per-user context after auth.
|
|
596
|
-
| `submitMessageFeedback` / `getMessageFeedback` | `ChatAgent` | Callable message feedback.
|
|
597
|
-
| `agent` | `Assistant` | Required. Your `ChatAgent` subclass.
|
|
598
|
-
| `fastModel` | `Assistant` | Required. Cheap model for titles/summaries.
|
|
599
|
-
| `createChat` / `getChats` / `deleteChat` | `Assistant` | Callable chat management.
|
|
594
|
+
| Member | On | Description |
|
|
595
|
+
| ---------------------------------------------- | ----------- | -------------------------------------------- |
|
|
596
|
+
| `getModel(ctx?)` | `Agent` | Required. Model for inference. |
|
|
597
|
+
| `getSystemPrompt(ctx?)` | `Agent` | Required. System prompt. |
|
|
598
|
+
| `getTools()` | `Agent` | Always-on tools (default `{}`). |
|
|
599
|
+
| `getSkills()` | `Agent` | Local skills (default `[]`). |
|
|
600
|
+
| `static getJwtAuthConfig(env)` | `Agent` | Optional JWT verification and actor binding. |
|
|
601
|
+
| `getUserContext(jwtToken)` | `Agent` | Optional per-user context after auth. |
|
|
602
|
+
| `submitMessageFeedback` / `getMessageFeedback` | `ChatAgent` | Callable message feedback. |
|
|
603
|
+
| `agent` | `Assistant` | Required. Your `ChatAgent` subclass. |
|
|
604
|
+
| `fastModel` | `Assistant` | Required. Cheap model for titles/summaries. |
|
|
605
|
+
| `createChat` / `getChats` / `deleteChat` | `Assistant` | Callable chat management. |
|
|
600
606
|
|
|
601
607
|
### Package root (`@economic/agents`)
|
|
602
608
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-
|
|
1
|
+
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-8C2T8Mu0.mjs";
|
|
2
2
|
import { Agent as Agent$1, Connection, ConnectionContext, SubAgentClass } from "agents";
|
|
3
3
|
import { ChatResponseResult, PrepareStepContext, Session, Think, ToolCallContext, ToolCallDecision, TurnConfig, TurnContext, skills } from "@cloudflare/think";
|
|
4
4
|
import { JSONValue, LanguageModel, ModelMessage, Tool as Tool$1, UIMessage } from "ai";
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as isJwtActorAuthorized, i as extractTokenFromConnectRequest, n as createAgentTracer, o as verifyJwt, r as recordFeedbackAnalytics, t as routeAgentRequest } from "./route-agent-request-CYclS_5Q.mjs";
|
|
2
2
|
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
3
3
|
import { Think, skills } from "@cloudflare/think";
|
|
4
4
|
import { Output, convertToModelMessages, generateText, jsonSchema, pruneMessages, tool as tool$1 } from "ai";
|
|
@@ -359,6 +359,15 @@ var Agent = class extends Think {
|
|
|
359
359
|
connection.close(result.status === 401 ? 4001 : 4003, result.message);
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
|
+
if (!isJwtActorAuthorized(config, result.claims, {
|
|
363
|
+
durableObjectName: this.name,
|
|
364
|
+
parentPath: this.parentPath
|
|
365
|
+
})) {
|
|
366
|
+
sendConnectionStatus(connection, "unauthorized");
|
|
367
|
+
console.error("[Agent] JWT actor does not match the requested agent");
|
|
368
|
+
connection.close(4003, "Forbidden");
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
362
371
|
const token = extractTokenFromConnectRequest(ctx.request);
|
|
363
372
|
let effectiveToken = token;
|
|
364
373
|
const getTokenExchangeConfig = this.constructor.getTokenExchangeConfig;
|
|
@@ -1042,6 +1051,15 @@ var Assistant = class extends Agent$1 {
|
|
|
1042
1051
|
connection.close(result.status === 401 ? 4001 : 4003, result.message);
|
|
1043
1052
|
return;
|
|
1044
1053
|
}
|
|
1054
|
+
if (!isJwtActorAuthorized(config, result.claims, {
|
|
1055
|
+
durableObjectName: this.name,
|
|
1056
|
+
parentPath: this.parentPath
|
|
1057
|
+
})) {
|
|
1058
|
+
sendConnectionStatus(connection, "unauthorized");
|
|
1059
|
+
console.error("[Assistant] JWT actor does not match the requested assistant");
|
|
1060
|
+
connection.close(4003, "Forbidden");
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1045
1063
|
}
|
|
1046
1064
|
}
|
|
1047
1065
|
sendConnectionStatus(connection, "connected");
|
|
@@ -13,6 +13,8 @@ interface JwtAuthConfig<TClaims extends Record<string, unknown> = Record<string,
|
|
|
13
13
|
* These will be stored and made available in the agent's tool context.
|
|
14
14
|
*/
|
|
15
15
|
getClaims: (payload: Record<string, unknown>) => TClaims;
|
|
16
|
+
/** Derive the actor ID represented by the verified claims. */
|
|
17
|
+
getActorId: (claims: TClaims) => string;
|
|
16
18
|
}
|
|
17
19
|
//#endregion
|
|
18
20
|
//#region src/server/route-agent-request.d.ts
|
|
@@ -3,6 +3,18 @@ import { createRemoteJWKSet, decodeJwt, errors, jwtVerify } from "jose";
|
|
|
3
3
|
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
//#region src/server/features/auth/index.ts
|
|
5
5
|
const jwksByIssuer = /* @__PURE__ */ new Map();
|
|
6
|
+
/** Returns the actor portion of a top-level or parent-scoped agent name. */
|
|
7
|
+
function getTargetActorId(target) {
|
|
8
|
+
const rootName = target.parentPath?.[0]?.name ?? target.durableObjectName;
|
|
9
|
+
const separator = rootName.indexOf(":");
|
|
10
|
+
return separator === -1 ? rootName : rootName.slice(0, separator);
|
|
11
|
+
}
|
|
12
|
+
/** Checks that verified JWT claims belong to the addressed agent instance. */
|
|
13
|
+
function isJwtActorAuthorized(config, claims, target) {
|
|
14
|
+
if (typeof config.getActorId !== "function") return false;
|
|
15
|
+
const authenticatedActorId = config.getActorId(claims);
|
|
16
|
+
return typeof authenticatedActorId === "string" && authenticatedActorId.length > 0 && authenticatedActorId === getTargetActorId(target);
|
|
17
|
+
}
|
|
6
18
|
function getJwksForIssuer(issuer) {
|
|
7
19
|
const normalized = issuer.replace(/\/$/, "");
|
|
8
20
|
let jwks = jwksByIssuer.get(normalized);
|
|
@@ -465,4 +477,4 @@ async function routeAgentRequest$1(request, env, options) {
|
|
|
465
477
|
return response;
|
|
466
478
|
}
|
|
467
479
|
//#endregion
|
|
468
|
-
export {
|
|
480
|
+
export { isJwtActorAuthorized as a, extractTokenFromConnectRequest as i, createAgentTracer as n, verifyJwt as o, recordFeedbackAnalytics as r, routeAgentRequest$1 as t };
|
package/dist/v1.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-
|
|
1
|
+
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-8C2T8Mu0.mjs";
|
|
2
2
|
import { Agent as Agent$1, Connection, ConnectionContext } from "agents";
|
|
3
3
|
import { LanguageModel, StreamTextOnFinishCallback, ToolSet, UIMessage, generateText, streamText } from "ai";
|
|
4
4
|
import { AIChatAgent, ChatResponseResult, OnChatMessageOptions } from "@cloudflare/ai-chat";
|
package/dist/v1.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as isJwtActorAuthorized, i as extractTokenFromConnectRequest, n as createAgentTracer, o as verifyJwt, t as routeAgentRequest } from "./route-agent-request-CYclS_5Q.mjs";
|
|
2
2
|
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
3
3
|
import { Output, convertToModelMessages, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
4
4
|
import { AIChatAgent } from "@cloudflare/ai-chat";
|
|
@@ -312,6 +312,13 @@ var Agent = class extends Agent$1 {
|
|
|
312
312
|
connection.close(result.status === 401 ? 4001 : 4003, result.message);
|
|
313
313
|
return;
|
|
314
314
|
}
|
|
315
|
+
if (!isJwtActorAuthorized(config, result.claims, {
|
|
316
|
+
durableObjectName: this.name,
|
|
317
|
+
parentPath: this.parentPath
|
|
318
|
+
})) {
|
|
319
|
+
connection.close(4003, "Forbidden");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
315
322
|
const token = extractTokenFromConnectRequest(ctx.request);
|
|
316
323
|
if (token) {
|
|
317
324
|
const userContext = await this.getUserContext?.(token);
|
|
@@ -895,6 +902,17 @@ var ChatAgent = class extends AIChatAgent {
|
|
|
895
902
|
});
|
|
896
903
|
return;
|
|
897
904
|
}
|
|
905
|
+
if (!isJwtActorAuthorized(config, result.claims, {
|
|
906
|
+
durableObjectName: this.name,
|
|
907
|
+
parentPath: this.parentPath
|
|
908
|
+
})) {
|
|
909
|
+
connection.close(4003, "Forbidden");
|
|
910
|
+
this.setState({
|
|
911
|
+
type: "chat",
|
|
912
|
+
status: "unauthorized"
|
|
913
|
+
});
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
898
916
|
}
|
|
899
917
|
const token = extractTokenFromConnectRequest(ctx.request);
|
|
900
918
|
if (token) this._pendingUserContextRequest = this.getUserContext?.(token).then((userContext) => {
|