agentfootprint 6.21.0 → 6.22.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.
@@ -10,12 +10,30 @@
10
10
  * `GetResourceOauth2Token` (the SDK's `@requires_access_token` underneath):
11
11
  * - request.mode 'machine' → `M2M`; 'user' → `USER_FEDERATION`
12
12
  * - request.service → the configured OAuth2 credential-provider name
13
+ * - request.identity → (per-request workload identity scoping; see below)
13
14
  * - a returned access token → `{ status: 'issued', credential: bearer(token) }`
14
15
  * - a returned auth URL → `{ status: 'authorization-required' }` (3LO consent)
15
16
  *
16
17
  * The token vault + refresh-token handling live in AgentCore, so repeat calls
17
18
  * usually return a token directly (no consent round-trip).
18
19
  *
20
+ * **Per-request identity forwarding (workload identity scoping).**
21
+ * `GetResourceOauth2Token` carries NO user/tenant field — in AgentCore the
22
+ * user identity is bound EARLIER, at workload-token acquisition:
23
+ * `GetWorkloadAccessTokenForUserId(workloadName, userId)` returns a workload
24
+ * access token scoped to that user, and AgentCore keys its token vault + 3LO
25
+ * grants per (workload, user). So this adapter forwards `req.identity` (the
26
+ * `runIdentity` that the agent threads through `getCredential`) by resolving a
27
+ * per-user workload token first, then vending with it. Engages only when ALL of:
28
+ * - `req.mode === 'user'` (USER_FEDERATION — M2M is the workload's own identity),
29
+ * - a userId derives from `req.identity` (default `identity.principal`;
30
+ * override via `userIdFor`), and
31
+ * - `options.workloadName` is configured (the opt-in).
32
+ * Otherwise the static `options.workloadIdentityToken` flows exactly as before.
33
+ * `tenant` has no native AgentCore field and is NOT forwarded by default —
34
+ * tenant isolation derives from the workload identity itself (per-tenant
35
+ * workloads), or encode it via `userIdFor` (e.g. `${tenant}:${principal}`).
36
+ *
19
37
  * Pattern: Adapter (GoF) + lazy peer-dep load — the AWS SDK is required only when
20
38
  * `getCredential` first runs (or never, if you inject `_client`). NOTE: confirm
21
39
  * the SDK command/field names against your installed
@@ -44,28 +62,56 @@ function resolveClient(options) {
44
62
  }
45
63
  return {
46
64
  getResourceOauth2Token: (input) => client.getResourceOauth2Token(input),
65
+ // Duck-typed like the primary call — only wired when the SDK exposes it
66
+ // (used only when `workloadName` is configured).
67
+ ...(typeof client.getWorkloadAccessTokenForUserId === 'function' && {
68
+ getWorkloadAccessTokenForUserId: (input) => client.getWorkloadAccessTokenForUserId(input),
69
+ }),
47
70
  };
48
71
  }
72
+ const defaultUserIdFor = (identity) => identity.principal;
49
73
  /** Build a {@link CredentialProvider} backed by AWS Bedrock AgentCore Identity. */
50
74
  function agentCoreIdentity(options = {}) {
51
75
  let client;
52
76
  const getClient = () => (client ??= resolveClient(options));
77
+ const userIdFor = options.userIdFor ?? defaultUserIdFor;
78
+ // Per-request identity forwarding (workload identity scoping) — see module
79
+ // header. `GetResourceOauth2Token` has no user field; the user is bound at
80
+ // workload-token acquisition, so a `mode: 'user'` request carrying an
81
+ // identity exchanges (workloadName, userId) for a USER-SCOPED workload token
82
+ // and vends with that. Requires `workloadName` (the opt-in); without it the
83
+ // static `workloadIdentityToken` flows unchanged (pre-forwarding behavior).
84
+ const resolveWorkloadToken = async (req) => {
85
+ const userId = req.mode === 'user' && req.identity !== undefined ? userIdFor(req.identity) : undefined;
86
+ if (userId === undefined || !options.workloadName)
87
+ return options.workloadIdentityToken;
88
+ const c = getClient();
89
+ if (typeof c.getWorkloadAccessTokenForUserId !== 'function') {
90
+ // Explicit config must not silently degrade to workload-level tokens.
91
+ throw new Error('agentCoreIdentity: `workloadName` is configured for per-user workload scoping, ' +
92
+ 'but the client has no getWorkloadAccessTokenForUserId. Confirm the ' +
93
+ '@aws-sdk/client-bedrock-agentcore version, or pass `_client`.');
94
+ }
95
+ const res = await c.getWorkloadAccessTokenForUserId({
96
+ workloadName: options.workloadName,
97
+ userId,
98
+ });
99
+ if (!res.workloadAccessToken) {
100
+ throw new Error('agentCoreIdentity: GetWorkloadAccessTokenForUserId returned no workloadAccessToken ' +
101
+ 'for per-user scoped vending.');
102
+ }
103
+ return res.workloadAccessToken;
104
+ };
53
105
  return {
54
106
  id: options.id ?? 'agentcore-identity',
55
107
  async getCredential(req) {
56
- // NOTE: `req.identity` (principal/tenant) is intentionally NOT forwarded
57
- // yet — tenant isolation here derives solely from `workloadIdentityToken`
58
- // (the AgentCore-injected workload identity). Don't assume the threaded
59
- // principal/tenant is enforced at the IdP until a future release maps it
60
- // onto the user-federation subject.
108
+ const workloadIdentityToken = await resolveWorkloadToken(req);
61
109
  const res = await getClient().getResourceOauth2Token({
62
110
  resourceCredentialProviderName: req.service,
63
111
  scopes: req.scopes ?? [],
64
112
  oauth2Flow: req.mode === 'user' ? 'USER_FEDERATION' : 'M2M',
65
113
  forceAuthentication: req.forceReauth ?? false,
66
- ...(options.workloadIdentityToken && {
67
- workloadIdentityToken: options.workloadIdentityToken,
68
- }),
114
+ ...(workloadIdentityToken && { workloadIdentityToken }),
69
115
  });
70
116
  if (res.accessToken) {
71
117
  // AgentCore Identity vends OAuth access tokens → a bearer credential.
@@ -1 +1 @@
1
- {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;AAEH,6DAAuD;AAMvD,sDAAiD;AAkCjD,SAAS,aAAa,CAAC,OAAiC;IACtD,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAC5C,iFAAiF;IACjF,MAAM,GAAG,GAAG,IAAA,4BAAW,EAA0B,mCAAmC,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,GAAG,CAAC,sBAEJ,CAAC;IACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,8FAA8F;YAC5F,sEAAsE,CACzE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAE5E,CAAC;IACF,IAAI,OAAO,MAAM,CAAC,sBAAsB,KAAK,UAAU,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,+EAA+E;YAC7E,+DAA+D,CAClE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,sBAAsB,EAAE,CAAC,KAAK,EAAE,EAAE,CAChC,MAAM,CAAC,sBAAuB,CAAC,KAAK,CAAoC;KAC3E,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAgB,iBAAiB,CAAC,UAAoC,EAAE;IACtE,IAAI,MAA+C,CAAC;IACpD,MAAM,SAAS,GAAG,GAAgC,EAAE,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzF,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,oBAAoB;QACtC,KAAK,CAAC,aAAa,CAAC,GAAsB;YACxC,yEAAyE;YACzE,0EAA0E;YAC1E,wEAAwE;YACxE,yEAAyE;YACzE,oCAAoC;YACpC,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC,sBAAsB,CAAC;gBACnD,8BAA8B,EAAE,GAAG,CAAC,OAAO;gBAC3C,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;gBACxB,UAAU,EAAE,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK;gBAC3D,mBAAmB,EAAE,GAAG,CAAC,WAAW,IAAI,KAAK;gBAC7C,GAAG,CAAC,OAAO,CAAC,qBAAqB,IAAI;oBACnC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;iBACrD,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,sEAAsE;gBACtE,OAAO;oBACL,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,IAAA,iBAAM,EAAC,GAAG,CAAC,WAAW,CAAC;oBACnC,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;iBACjE,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACzB,OAAO;oBACL,MAAM,EAAE,wBAAwB;oBAChC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;oBACtC,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;iBAC/B,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kDAAkD,GAAG,CAAC,OAAO,qBAAqB;gBAChF,2CAA2C,CAC9C,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AA3CD,8CA2CC"}
1
+ {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,30 @@
9
9
  * `GetResourceOauth2Token` (the SDK's `@requires_access_token` underneath):
10
10
  * - request.mode 'machine' → `M2M`; 'user' → `USER_FEDERATION`
11
11
  * - request.service → the configured OAuth2 credential-provider name
12
+ * - request.identity → (per-request workload identity scoping; see below)
12
13
  * - a returned access token → `{ status: 'issued', credential: bearer(token) }`
13
14
  * - a returned auth URL → `{ status: 'authorization-required' }` (3LO consent)
14
15
  *
15
16
  * The token vault + refresh-token handling live in AgentCore, so repeat calls
16
17
  * usually return a token directly (no consent round-trip).
17
18
  *
19
+ * **Per-request identity forwarding (workload identity scoping).**
20
+ * `GetResourceOauth2Token` carries NO user/tenant field — in AgentCore the
21
+ * user identity is bound EARLIER, at workload-token acquisition:
22
+ * `GetWorkloadAccessTokenForUserId(workloadName, userId)` returns a workload
23
+ * access token scoped to that user, and AgentCore keys its token vault + 3LO
24
+ * grants per (workload, user). So this adapter forwards `req.identity` (the
25
+ * `runIdentity` that the agent threads through `getCredential`) by resolving a
26
+ * per-user workload token first, then vending with it. Engages only when ALL of:
27
+ * - `req.mode === 'user'` (USER_FEDERATION — M2M is the workload's own identity),
28
+ * - a userId derives from `req.identity` (default `identity.principal`;
29
+ * override via `userIdFor`), and
30
+ * - `options.workloadName` is configured (the opt-in).
31
+ * Otherwise the static `options.workloadIdentityToken` flows exactly as before.
32
+ * `tenant` has no native AgentCore field and is NOT forwarded by default —
33
+ * tenant isolation derives from the workload identity itself (per-tenant
34
+ * workloads), or encode it via `userIdFor` (e.g. `${tenant}:${principal}`).
35
+ *
18
36
  * Pattern: Adapter (GoF) + lazy peer-dep load — the AWS SDK is required only when
19
37
  * `getCredential` first runs (or never, if you inject `_client`). NOTE: confirm
20
38
  * the SDK command/field names against your installed
@@ -41,28 +59,56 @@ function resolveClient(options) {
41
59
  }
42
60
  return {
43
61
  getResourceOauth2Token: (input) => client.getResourceOauth2Token(input),
62
+ // Duck-typed like the primary call — only wired when the SDK exposes it
63
+ // (used only when `workloadName` is configured).
64
+ ...(typeof client.getWorkloadAccessTokenForUserId === 'function' && {
65
+ getWorkloadAccessTokenForUserId: (input) => client.getWorkloadAccessTokenForUserId(input),
66
+ }),
44
67
  };
45
68
  }
69
+ const defaultUserIdFor = (identity) => identity.principal;
46
70
  /** Build a {@link CredentialProvider} backed by AWS Bedrock AgentCore Identity. */
47
71
  export function agentCoreIdentity(options = {}) {
48
72
  let client;
49
73
  const getClient = () => (client ??= resolveClient(options));
74
+ const userIdFor = options.userIdFor ?? defaultUserIdFor;
75
+ // Per-request identity forwarding (workload identity scoping) — see module
76
+ // header. `GetResourceOauth2Token` has no user field; the user is bound at
77
+ // workload-token acquisition, so a `mode: 'user'` request carrying an
78
+ // identity exchanges (workloadName, userId) for a USER-SCOPED workload token
79
+ // and vends with that. Requires `workloadName` (the opt-in); without it the
80
+ // static `workloadIdentityToken` flows unchanged (pre-forwarding behavior).
81
+ const resolveWorkloadToken = async (req) => {
82
+ const userId = req.mode === 'user' && req.identity !== undefined ? userIdFor(req.identity) : undefined;
83
+ if (userId === undefined || !options.workloadName)
84
+ return options.workloadIdentityToken;
85
+ const c = getClient();
86
+ if (typeof c.getWorkloadAccessTokenForUserId !== 'function') {
87
+ // Explicit config must not silently degrade to workload-level tokens.
88
+ throw new Error('agentCoreIdentity: `workloadName` is configured for per-user workload scoping, ' +
89
+ 'but the client has no getWorkloadAccessTokenForUserId. Confirm the ' +
90
+ '@aws-sdk/client-bedrock-agentcore version, or pass `_client`.');
91
+ }
92
+ const res = await c.getWorkloadAccessTokenForUserId({
93
+ workloadName: options.workloadName,
94
+ userId,
95
+ });
96
+ if (!res.workloadAccessToken) {
97
+ throw new Error('agentCoreIdentity: GetWorkloadAccessTokenForUserId returned no workloadAccessToken ' +
98
+ 'for per-user scoped vending.');
99
+ }
100
+ return res.workloadAccessToken;
101
+ };
50
102
  return {
51
103
  id: options.id ?? 'agentcore-identity',
52
104
  async getCredential(req) {
53
- // NOTE: `req.identity` (principal/tenant) is intentionally NOT forwarded
54
- // yet — tenant isolation here derives solely from `workloadIdentityToken`
55
- // (the AgentCore-injected workload identity). Don't assume the threaded
56
- // principal/tenant is enforced at the IdP until a future release maps it
57
- // onto the user-federation subject.
105
+ const workloadIdentityToken = await resolveWorkloadToken(req);
58
106
  const res = await getClient().getResourceOauth2Token({
59
107
  resourceCredentialProviderName: req.service,
60
108
  scopes: req.scopes ?? [],
61
109
  oauth2Flow: req.mode === 'user' ? 'USER_FEDERATION' : 'M2M',
62
110
  forceAuthentication: req.forceReauth ?? false,
63
- ...(options.workloadIdentityToken && {
64
- workloadIdentityToken: options.workloadIdentityToken,
65
- }),
111
+ ...(workloadIdentityToken && { workloadIdentityToken }),
66
112
  });
67
113
  if (res.accessToken) {
68
114
  // AgentCore Identity vends OAuth access tokens → a bearer credential.
@@ -1 +1 @@
1
- {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAkCjD,SAAS,aAAa,CAAC,OAAiC;IACtD,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAC5C,iFAAiF;IACjF,MAAM,GAAG,GAAG,WAAW,CAA0B,mCAAmC,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,GAAG,CAAC,sBAEJ,CAAC;IACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,8FAA8F;YAC5F,sEAAsE,CACzE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAE5E,CAAC;IACF,IAAI,OAAO,MAAM,CAAC,sBAAsB,KAAK,UAAU,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,+EAA+E;YAC7E,+DAA+D,CAClE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,sBAAsB,EAAE,CAAC,KAAK,EAAE,EAAE,CAChC,MAAM,CAAC,sBAAuB,CAAC,KAAK,CAAoC;KAC3E,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,UAAoC,EAAE;IACtE,IAAI,MAA+C,CAAC;IACpD,MAAM,SAAS,GAAG,GAAgC,EAAE,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzF,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,oBAAoB;QACtC,KAAK,CAAC,aAAa,CAAC,GAAsB;YACxC,yEAAyE;YACzE,0EAA0E;YAC1E,wEAAwE;YACxE,yEAAyE;YACzE,oCAAoC;YACpC,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC,sBAAsB,CAAC;gBACnD,8BAA8B,EAAE,GAAG,CAAC,OAAO;gBAC3C,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;gBACxB,UAAU,EAAE,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK;gBAC3D,mBAAmB,EAAE,GAAG,CAAC,WAAW,IAAI,KAAK;gBAC7C,GAAG,CAAC,OAAO,CAAC,qBAAqB,IAAI;oBACnC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;iBACrD,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,sEAAsE;gBACtE,OAAO;oBACL,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;oBACnC,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;iBACjE,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACzB,OAAO;oBACL,MAAM,EAAE,wBAAwB;oBAChC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;oBACtC,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;iBAC/B,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kDAAkD,GAAG,CAAC,OAAO,qBAAqB;gBAChF,2CAA2C,CAC9C,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * withCredentialRetry — CredentialProvider decorator that retries transient
3
+ * `getCredential` failures with exponential backoff.
4
+ *
5
+ * Pattern: Decorator (GoF) — the credential twin of `withRetry` (resilience)
6
+ * for LLM providers. SAME option vocabulary (`maxAttempts` /
7
+ * `initialDelayMs` / `backoffFactor` / `maxDelayMs` / `shouldRetry` /
8
+ * `onRetry`) and the SAME default transience policy (the shared
9
+ * `defaultShouldRetry`: skip AbortError + 4xx except 429; retry 5xx,
10
+ * network errors, unknown shapes). AgentCore's documented transient
11
+ * errors (`InternalServerException` 500, `ThrottlingException` 429)
12
+ * retry out of the box.
13
+ *
14
+ * Why a decorator and not a reliability rule: the rules-based reliability
15
+ * subsystem (`Agent.create(...).reliability({...})`) is LLM-call-scoped —
16
+ * `ReliabilityScope` carries `request: LLMRequest` and the gate chart loops
17
+ * around the CallLLM stage with provider failover. Credential resolution
18
+ * happens at a different boundary (the tool-dispatch loop, declare-and-push);
19
+ * promoting it to a chart-level gate is the deferred `sf-credential` node.
20
+ * Until that exists, retry is a TRANSPORT property of the credential provider
21
+ * — exactly like `withRetry` is for LLM transports.
22
+ *
23
+ * Semantics:
24
+ * • Only THROWN errors retry. Both result branches return immediately:
25
+ * `issued` is success; `authorization-required` is a HUMAN flow (3LO
26
+ * consent), not a transient fault — retrying it would hammer the IdP
27
+ * without the user having authorized anything.
28
+ * • After retries exhaust, the LAST error is rethrown — the call site
29
+ * behaves byte-identically to an unwrapped provider (fail-closed:
30
+ * `agentfootprint.credential.failed` emit + error tool result; the tool
31
+ * does NOT run).
32
+ * • Visibility: the agent trace brackets the whole retried resolution with
33
+ * `credential.requested` → `credential.acquired` / `credential.failed`.
34
+ * Per-attempt visibility is consumer-wired via `onRetry` — the established
35
+ * decorator contract (same as `withRetry`; the `agentfootprint.error.*`
36
+ * event family is reserved for these decorators, see events/payloads.ts).
37
+ * No new event types.
38
+ *
39
+ * @example
40
+ * import { agentCoreIdentity, withCredentialRetry } from 'agentfootprint/identity';
41
+ *
42
+ * const credentials = withCredentialRetry(agentCoreIdentity({ region: 'us-east-1' }), {
43
+ * maxAttempts: 3,
44
+ * onRetry: (err, attempt, ms) => console.warn(`credential retry ${attempt} in ${ms}ms`, err),
45
+ * });
46
+ * const agent = Agent.create({ provider, model, credentials }).tools([...]).build();
47
+ */
48
+ import { defaultShouldRetry } from '../resilience/withRetry.js';
49
+ /**
50
+ * Wrap a {@link CredentialProvider} so transient `getCredential` failures
51
+ * retry with exponential backoff before failing closed.
52
+ *
53
+ * Defaults mirror `withRetry`: 3 attempts total, 200ms → 400ms → 800ms
54
+ * backoff capped at 10s, retry on 5xx/429/network/unknown, never on
55
+ * AbortError or other 4xx.
56
+ */
57
+ export function withCredentialRetry(provider, options = {}) {
58
+ const maxAttempts = Math.max(1, options.maxAttempts ?? 3);
59
+ const initialDelayMs = options.initialDelayMs ?? 200;
60
+ const backoffFactor = options.backoffFactor ?? 2;
61
+ const maxDelayMs = options.maxDelayMs ?? 10_000;
62
+ const shouldRetry = options.shouldRetry ?? defaultShouldRetry;
63
+ const onRetry = options.onRetry;
64
+ return {
65
+ id: `${provider.id}+retry`,
66
+ async getCredential(req) {
67
+ let lastError;
68
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
69
+ try {
70
+ // Both result branches return as-is (same object — the wrapper never
71
+ // clones or serializes the credential): `issued` is success;
72
+ // `authorization-required` is consent, not a fault — never retried.
73
+ return await provider.getCredential(req);
74
+ }
75
+ catch (err) {
76
+ lastError = err;
77
+ if (attempt >= maxAttempts || !shouldRetry(err, attempt)) {
78
+ throw err;
79
+ }
80
+ const delay = Math.min(maxDelayMs, initialDelayMs * Math.pow(backoffFactor, attempt - 1));
81
+ onRetry?.(err, attempt + 1, delay);
82
+ await sleep(delay);
83
+ }
84
+ }
85
+ // Unreachable — the last attempt either returned or threw above.
86
+ throw lastError;
87
+ },
88
+ };
89
+ }
90
+ // `CredentialRequest` carries no AbortSignal (port contract), so this sleep is
91
+ // the signal-less twin of withRetry's. If the port ever grows a signal, mirror
92
+ // withRetry's abort-aware sleep here.
93
+ function sleep(ms) {
94
+ if (ms <= 0)
95
+ return Promise.resolve();
96
+ return new Promise((resolve) => setTimeout(resolve, ms));
97
+ }
98
+ //# sourceMappingURL=withCredentialRetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withCredentialRetry.js","sourceRoot":"","sources":["../../../src/identity/withCredentialRetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,kBAAkB,EAAyB,MAAM,4BAA4B,CAAC;AAUvF;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAA4B,EAC5B,UAAsC,EAAE;IAExC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,GAAG,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,OAAO;QACL,EAAE,EAAE,GAAG,QAAQ,CAAC,EAAE,QAAQ;QAC1B,KAAK,CAAC,aAAa,CAAC,GAAsB;YACxC,IAAI,SAAkB,CAAC;YACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;gBACxD,IAAI,CAAC;oBACH,qEAAqE;oBACrE,6DAA6D;oBAC7D,oEAAoE;oBACpE,OAAO,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;gBAC3C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,SAAS,GAAG,GAAG,CAAC;oBAChB,IAAI,OAAO,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;wBACzD,MAAM,GAAG,CAAC;oBACZ,CAAC;oBACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC1F,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;oBACnC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,iEAAiE;YACjE,MAAM,SAAS,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,+EAA+E;AAC/E,sCAAsC;AACtC,SAAS,KAAK,CAAC,EAAU;IACvB,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -26,5 +26,6 @@
26
26
  export { isCredentialIssued, unconfiguredCredentialProvider } from './identity/types.js';
27
27
  export { bearer, apiKey, basic, headers, } from './identity/kinds.js';
28
28
  export { staticTokens } from './identity/staticTokens.js';
29
+ export { withCredentialRetry, } from './identity/withCredentialRetry.js';
29
30
  export { agentCoreIdentity, } from './adapters/identity/agentcore.js';
30
31
  //# sourceMappingURL=identity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAWH,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,GAKR,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA4B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,iBAAiB,GAIlB,MAAM,kCAAkC,CAAC"}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAWH,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,GAKR,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA4B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,iBAAiB,GAIlB,MAAM,kCAAkC,CAAC"}
@@ -75,8 +75,13 @@ export function withRetry(provider, options = {}) {
75
75
  * surface HTTP status should set `error.status` for this to work; the
76
76
  * predicate falls back to retrying when status is unknown (better to
77
77
  * retry once than to surface a flaky failure).
78
+ *
79
+ * Exported (module-level, NOT on the resilience barrel) as the single
80
+ * source of truth for the decorators' transience policy — shared by
81
+ * `withCredentialRetry` (identity) so "what counts as transient" never
82
+ * drifts between the LLM and credential retry wrappers.
78
83
  */
79
- function defaultShouldRetry(err, _attempt) {
84
+ export function defaultShouldRetry(err, _attempt) {
80
85
  if (isAbortError(err))
81
86
  return false;
82
87
  const status = err?.status ??
@@ -1 +1 @@
1
- {"version":3,"file":"withRetry.js","sourceRoot":"","sources":["../../../src/resilience/withRetry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"withRetry.js","sourceRoot":"","sources":["../../../src/resilience/withRetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * withCredentialRetry — CredentialProvider decorator that retries transient
4
+ * `getCredential` failures with exponential backoff.
5
+ *
6
+ * Pattern: Decorator (GoF) — the credential twin of `withRetry` (resilience)
7
+ * for LLM providers. SAME option vocabulary (`maxAttempts` /
8
+ * `initialDelayMs` / `backoffFactor` / `maxDelayMs` / `shouldRetry` /
9
+ * `onRetry`) and the SAME default transience policy (the shared
10
+ * `defaultShouldRetry`: skip AbortError + 4xx except 429; retry 5xx,
11
+ * network errors, unknown shapes). AgentCore's documented transient
12
+ * errors (`InternalServerException` 500, `ThrottlingException` 429)
13
+ * retry out of the box.
14
+ *
15
+ * Why a decorator and not a reliability rule: the rules-based reliability
16
+ * subsystem (`Agent.create(...).reliability({...})`) is LLM-call-scoped —
17
+ * `ReliabilityScope` carries `request: LLMRequest` and the gate chart loops
18
+ * around the CallLLM stage with provider failover. Credential resolution
19
+ * happens at a different boundary (the tool-dispatch loop, declare-and-push);
20
+ * promoting it to a chart-level gate is the deferred `sf-credential` node.
21
+ * Until that exists, retry is a TRANSPORT property of the credential provider
22
+ * — exactly like `withRetry` is for LLM transports.
23
+ *
24
+ * Semantics:
25
+ * • Only THROWN errors retry. Both result branches return immediately:
26
+ * `issued` is success; `authorization-required` is a HUMAN flow (3LO
27
+ * consent), not a transient fault — retrying it would hammer the IdP
28
+ * without the user having authorized anything.
29
+ * • After retries exhaust, the LAST error is rethrown — the call site
30
+ * behaves byte-identically to an unwrapped provider (fail-closed:
31
+ * `agentfootprint.credential.failed` emit + error tool result; the tool
32
+ * does NOT run).
33
+ * • Visibility: the agent trace brackets the whole retried resolution with
34
+ * `credential.requested` → `credential.acquired` / `credential.failed`.
35
+ * Per-attempt visibility is consumer-wired via `onRetry` — the established
36
+ * decorator contract (same as `withRetry`; the `agentfootprint.error.*`
37
+ * event family is reserved for these decorators, see events/payloads.ts).
38
+ * No new event types.
39
+ *
40
+ * @example
41
+ * import { agentCoreIdentity, withCredentialRetry } from 'agentfootprint/identity';
42
+ *
43
+ * const credentials = withCredentialRetry(agentCoreIdentity({ region: 'us-east-1' }), {
44
+ * maxAttempts: 3,
45
+ * onRetry: (err, attempt, ms) => console.warn(`credential retry ${attempt} in ${ms}ms`, err),
46
+ * });
47
+ * const agent = Agent.create({ provider, model, credentials }).tools([...]).build();
48
+ */
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.withCredentialRetry = void 0;
51
+ const withRetry_js_1 = require("../resilience/withRetry.js");
52
+ /**
53
+ * Wrap a {@link CredentialProvider} so transient `getCredential` failures
54
+ * retry with exponential backoff before failing closed.
55
+ *
56
+ * Defaults mirror `withRetry`: 3 attempts total, 200ms → 400ms → 800ms
57
+ * backoff capped at 10s, retry on 5xx/429/network/unknown, never on
58
+ * AbortError or other 4xx.
59
+ */
60
+ function withCredentialRetry(provider, options = {}) {
61
+ const maxAttempts = Math.max(1, options.maxAttempts ?? 3);
62
+ const initialDelayMs = options.initialDelayMs ?? 200;
63
+ const backoffFactor = options.backoffFactor ?? 2;
64
+ const maxDelayMs = options.maxDelayMs ?? 10_000;
65
+ const shouldRetry = options.shouldRetry ?? withRetry_js_1.defaultShouldRetry;
66
+ const onRetry = options.onRetry;
67
+ return {
68
+ id: `${provider.id}+retry`,
69
+ async getCredential(req) {
70
+ let lastError;
71
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
72
+ try {
73
+ // Both result branches return as-is (same object — the wrapper never
74
+ // clones or serializes the credential): `issued` is success;
75
+ // `authorization-required` is consent, not a fault — never retried.
76
+ return await provider.getCredential(req);
77
+ }
78
+ catch (err) {
79
+ lastError = err;
80
+ if (attempt >= maxAttempts || !shouldRetry(err, attempt)) {
81
+ throw err;
82
+ }
83
+ const delay = Math.min(maxDelayMs, initialDelayMs * Math.pow(backoffFactor, attempt - 1));
84
+ onRetry?.(err, attempt + 1, delay);
85
+ await sleep(delay);
86
+ }
87
+ }
88
+ // Unreachable — the last attempt either returned or threw above.
89
+ throw lastError;
90
+ },
91
+ };
92
+ }
93
+ exports.withCredentialRetry = withCredentialRetry;
94
+ // `CredentialRequest` carries no AbortSignal (port contract), so this sleep is
95
+ // the signal-less twin of withRetry's. If the port ever grows a signal, mirror
96
+ // withRetry's abort-aware sleep here.
97
+ function sleep(ms) {
98
+ if (ms <= 0)
99
+ return Promise.resolve();
100
+ return new Promise((resolve) => setTimeout(resolve, ms));
101
+ }
102
+ //# sourceMappingURL=withCredentialRetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withCredentialRetry.js","sourceRoot":"","sources":["../../src/identity/withCredentialRetry.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;;;AAEH,6DAAuF;AAUvF;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CACjC,QAA4B,EAC5B,UAAsC,EAAE;IAExC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,GAAG,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,iCAAkB,CAAC;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,OAAO;QACL,EAAE,EAAE,GAAG,QAAQ,CAAC,EAAE,QAAQ;QAC1B,KAAK,CAAC,aAAa,CAAC,GAAsB;YACxC,IAAI,SAAkB,CAAC;YACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;gBACxD,IAAI,CAAC;oBACH,qEAAqE;oBACrE,6DAA6D;oBAC7D,oEAAoE;oBACpE,OAAO,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;gBAC3C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,SAAS,GAAG,GAAG,CAAC;oBAChB,IAAI,OAAO,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;wBACzD,MAAM,GAAG,CAAC;oBACZ,CAAC;oBACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC1F,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;oBACnC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,iEAAiE;YACjE,MAAM,SAAS,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAnCD,kDAmCC;AAED,+EAA+E;AAC/E,+EAA+E;AAC/E,sCAAsC;AACtC,SAAS,KAAK,CAAC,EAAU;IACvB,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/dist/identity.js CHANGED
@@ -25,7 +25,7 @@
25
25
  * ```
26
26
  */
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.agentCoreIdentity = exports.staticTokens = exports.headers = exports.basic = exports.apiKey = exports.bearer = exports.unconfiguredCredentialProvider = exports.isCredentialIssued = void 0;
28
+ exports.agentCoreIdentity = exports.withCredentialRetry = exports.staticTokens = exports.headers = exports.basic = exports.apiKey = exports.bearer = exports.unconfiguredCredentialProvider = exports.isCredentialIssued = void 0;
29
29
  var types_js_1 = require("./identity/types.js");
30
30
  Object.defineProperty(exports, "isCredentialIssued", { enumerable: true, get: function () { return types_js_1.isCredentialIssued; } });
31
31
  Object.defineProperty(exports, "unconfiguredCredentialProvider", { enumerable: true, get: function () { return types_js_1.unconfiguredCredentialProvider; } });
@@ -36,6 +36,8 @@ Object.defineProperty(exports, "basic", { enumerable: true, get: function () { r
36
36
  Object.defineProperty(exports, "headers", { enumerable: true, get: function () { return kinds_js_1.headers; } });
37
37
  var staticTokens_js_1 = require("./identity/staticTokens.js");
38
38
  Object.defineProperty(exports, "staticTokens", { enumerable: true, get: function () { return staticTokens_js_1.staticTokens; } });
39
+ var withCredentialRetry_js_1 = require("./identity/withCredentialRetry.js");
40
+ Object.defineProperty(exports, "withCredentialRetry", { enumerable: true, get: function () { return withCredentialRetry_js_1.withCredentialRetry; } });
39
41
  var agentcore_js_1 = require("./adapters/identity/agentcore.js");
40
42
  Object.defineProperty(exports, "agentCoreIdentity", { enumerable: true, get: function () { return agentcore_js_1.agentCoreIdentity; } });
41
43
  //# sourceMappingURL=identity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAWH,gDAAyF;AAAhF,8GAAA,kBAAkB,OAAA;AAAE,0HAAA,8BAA8B,OAAA;AAC3D,gDAS6B;AAR3B,kGAAA,MAAM,OAAA;AACN,kGAAA,MAAM,OAAA;AACN,iGAAA,KAAK,OAAA;AACL,mGAAA,OAAO,OAAA;AAMT,8DAAoF;AAA3E,+GAAA,YAAY,OAAA;AACrB,iEAK0C;AAJxC,iHAAA,iBAAiB,OAAA"}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AAWH,gDAAyF;AAAhF,8GAAA,kBAAkB,OAAA;AAAE,0HAAA,8BAA8B,OAAA;AAC3D,gDAS6B;AAR3B,kGAAA,MAAM,OAAA;AACN,kGAAA,MAAM,OAAA;AACN,iGAAA,KAAK,OAAA;AACL,mGAAA,OAAO,OAAA;AAMT,8DAAoF;AAA3E,+GAAA,YAAY,OAAA;AACrB,4EAG2C;AAFzC,6HAAA,mBAAmB,OAAA;AAGrB,iEAK0C;AAJxC,iHAAA,iBAAiB,OAAA"}
@@ -20,7 +20,7 @@
20
20
  * network errors, and unknown shapes.
21
21
  */
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.withRetry = void 0;
23
+ exports.defaultShouldRetry = exports.withRetry = void 0;
24
24
  /**
25
25
  * Wrap a provider so its `complete()` retries transient failures.
26
26
  *
@@ -79,6 +79,11 @@ exports.withRetry = withRetry;
79
79
  * surface HTTP status should set `error.status` for this to work; the
80
80
  * predicate falls back to retrying when status is unknown (better to
81
81
  * retry once than to surface a flaky failure).
82
+ *
83
+ * Exported (module-level, NOT on the resilience barrel) as the single
84
+ * source of truth for the decorators' transience policy — shared by
85
+ * `withCredentialRetry` (identity) so "what counts as transient" never
86
+ * drifts between the LLM and credential retry wrappers.
82
87
  */
83
88
  function defaultShouldRetry(err, _attempt) {
84
89
  if (isAbortError(err))
@@ -91,6 +96,7 @@ function defaultShouldRetry(err, _attempt) {
91
96
  }
92
97
  return true;
93
98
  }
99
+ exports.defaultShouldRetry = defaultShouldRetry;
94
100
  function isAbortError(err) {
95
101
  if (!err || typeof err !== 'object')
96
102
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"withRetry.js","sourceRoot":"","sources":["../../src/resilience/withRetry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"withRetry.js","sourceRoot":"","sources":["../../src/resilience/withRetry.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,30 @@
9
9
  * `GetResourceOauth2Token` (the SDK's `@requires_access_token` underneath):
10
10
  * - request.mode 'machine' → `M2M`; 'user' → `USER_FEDERATION`
11
11
  * - request.service → the configured OAuth2 credential-provider name
12
+ * - request.identity → (per-request workload identity scoping; see below)
12
13
  * - a returned access token → `{ status: 'issued', credential: bearer(token) }`
13
14
  * - a returned auth URL → `{ status: 'authorization-required' }` (3LO consent)
14
15
  *
15
16
  * The token vault + refresh-token handling live in AgentCore, so repeat calls
16
17
  * usually return a token directly (no consent round-trip).
17
18
  *
19
+ * **Per-request identity forwarding (workload identity scoping).**
20
+ * `GetResourceOauth2Token` carries NO user/tenant field — in AgentCore the
21
+ * user identity is bound EARLIER, at workload-token acquisition:
22
+ * `GetWorkloadAccessTokenForUserId(workloadName, userId)` returns a workload
23
+ * access token scoped to that user, and AgentCore keys its token vault + 3LO
24
+ * grants per (workload, user). So this adapter forwards `req.identity` (the
25
+ * `runIdentity` that the agent threads through `getCredential`) by resolving a
26
+ * per-user workload token first, then vending with it. Engages only when ALL of:
27
+ * - `req.mode === 'user'` (USER_FEDERATION — M2M is the workload's own identity),
28
+ * - a userId derives from `req.identity` (default `identity.principal`;
29
+ * override via `userIdFor`), and
30
+ * - `options.workloadName` is configured (the opt-in).
31
+ * Otherwise the static `options.workloadIdentityToken` flows exactly as before.
32
+ * `tenant` has no native AgentCore field and is NOT forwarded by default —
33
+ * tenant isolation derives from the workload identity itself (per-tenant
34
+ * workloads), or encode it via `userIdFor` (e.g. `${tenant}:${principal}`).
35
+ *
18
36
  * Pattern: Adapter (GoF) + lazy peer-dep load — the AWS SDK is required only when
19
37
  * `getCredential` first runs (or never, if you inject `_client`). NOTE: confirm
20
38
  * the SDK command/field names against your installed
@@ -31,7 +49,8 @@ export interface AgentCoreOauthResponse {
31
49
  /** Unix seconds. */
32
50
  readonly expiresAt?: number;
33
51
  }
34
- /** The minimal client surface the adapter calls — wraps `GetResourceOauth2Token`.
52
+ /** The minimal client surface the adapter calls — wraps `GetResourceOauth2Token`
53
+ * and (for per-user workload scoping) `GetWorkloadAccessTokenForUserId`.
35
54
  * The real AWS SDK client is adapted to this; tests inject a fake via `_client`. */
36
55
  export interface AgentCoreIdentityClientLike {
37
56
  getResourceOauth2Token(input: {
@@ -41,12 +60,37 @@ export interface AgentCoreIdentityClientLike {
41
60
  readonly forceAuthentication: boolean;
42
61
  readonly workloadIdentityToken?: string;
43
62
  }): Promise<AgentCoreOauthResponse>;
63
+ /** Optional — required only when `workloadName` is configured. Exchanges
64
+ * (workloadName, userId) for a USER-SCOPED workload access token; AgentCore
65
+ * keys its token vault + 3LO grants per (workload, user). */
66
+ getWorkloadAccessTokenForUserId?(input: {
67
+ readonly workloadName: string;
68
+ readonly userId: string;
69
+ }): Promise<{
70
+ readonly workloadAccessToken?: string;
71
+ }>;
44
72
  }
45
73
  export interface AgentCoreIdentityOptions {
46
74
  readonly region?: string;
47
75
  /** The agent's workload access token (AgentCore Runtime injects one in-container;
48
- * supply it explicitly when running elsewhere). */
76
+ * supply it explicitly when running elsewhere). Used as-is unless a per-user
77
+ * workload token is resolved (see `workloadName`). */
49
78
  readonly workloadIdentityToken?: string;
79
+ /** The AgentCore workload identity name — the OPT-IN for per-request identity
80
+ * scoping. When set, `mode: 'user'` requests carrying `req.identity` resolve a
81
+ * per-user workload access token via `GetWorkloadAccessTokenForUserId(workloadName,
82
+ * userId)` before vending, so AgentCore's token vault + 3LO grants are keyed per
83
+ * (workload, user) instead of per workload. Omit → today's static-token behavior. */
84
+ readonly workloadName?: string;
85
+ /** Map `req.identity` → the AgentCore `userId`. Default: `identity.principal`.
86
+ * `tenant` has no native AgentCore field — encode it here if you need
87
+ * tenant-scoped vault entries (e.g. ``({ tenant, principal }) =>
88
+ * tenant && principal ? `${tenant}:${principal}` : principal``). Return
89
+ * `undefined` to skip per-user scoping for that request. */
90
+ readonly userIdFor?: (identity: {
91
+ readonly principal?: string;
92
+ readonly tenant?: string;
93
+ }) => string | undefined;
50
94
  /** Stable provider id (default 'agentcore-identity'). */
51
95
  readonly id?: string;
52
96
  /** Test seam — inject a client implementing {@link AgentCoreIdentityClientLike}. */
@@ -1 +1 @@
1
- {"version":3,"file":"agentcore.d.ts","sourceRoot":"","sources":["../../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,yBAAyB,CAAC;AAGjC,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB;IACpB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;qFACqF;AACrF,MAAM,WAAW,2BAA2B;IAC1C,sBAAsB,CAAC,KAAK,EAAE;QAC5B,QAAQ,CAAC,8BAA8B,EAAE,MAAM,CAAC;QAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,iBAAiB,CAAC;QAC/C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;QACtC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;KACzC,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;wDACoD;IACpD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,CAAC,EAAE,2BAA2B,CAAC;CAChD;AA8BD,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,kBAAkB,CA2C5F"}
1
+ {"version":3,"file":"agentcore.d.ts","sourceRoot":"","sources":["../../../../src/adapters/identity/agentcore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,yBAAyB,CAAC;AAGjC,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB;IACpB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;qFAEqF;AACrF,MAAM,WAAW,2BAA2B;IAC1C,sBAAsB,CAAC,KAAK,EAAE;QAC5B,QAAQ,CAAC,8BAA8B,EAAE,MAAM,CAAC;QAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,iBAAiB,CAAC;QAC/C,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;QACtC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;KACzC,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACpC;;kEAE8D;IAC9D,+BAA+B,CAAC,CAAC,KAAK,EAAE;QACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;2DAEuD;IACvD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC;;;;0FAIsF;IACtF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;iEAI6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE;QAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KAC1B,KAAK,MAAM,GAAG,SAAS,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,CAAC,EAAE,2BAA2B,CAAC;CAChD;AAwCD,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,kBAAkB,CAuE5F"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * withCredentialRetry — CredentialProvider decorator that retries transient
3
+ * `getCredential` failures with exponential backoff.
4
+ *
5
+ * Pattern: Decorator (GoF) — the credential twin of `withRetry` (resilience)
6
+ * for LLM providers. SAME option vocabulary (`maxAttempts` /
7
+ * `initialDelayMs` / `backoffFactor` / `maxDelayMs` / `shouldRetry` /
8
+ * `onRetry`) and the SAME default transience policy (the shared
9
+ * `defaultShouldRetry`: skip AbortError + 4xx except 429; retry 5xx,
10
+ * network errors, unknown shapes). AgentCore's documented transient
11
+ * errors (`InternalServerException` 500, `ThrottlingException` 429)
12
+ * retry out of the box.
13
+ *
14
+ * Why a decorator and not a reliability rule: the rules-based reliability
15
+ * subsystem (`Agent.create(...).reliability({...})`) is LLM-call-scoped —
16
+ * `ReliabilityScope` carries `request: LLMRequest` and the gate chart loops
17
+ * around the CallLLM stage with provider failover. Credential resolution
18
+ * happens at a different boundary (the tool-dispatch loop, declare-and-push);
19
+ * promoting it to a chart-level gate is the deferred `sf-credential` node.
20
+ * Until that exists, retry is a TRANSPORT property of the credential provider
21
+ * — exactly like `withRetry` is for LLM transports.
22
+ *
23
+ * Semantics:
24
+ * • Only THROWN errors retry. Both result branches return immediately:
25
+ * `issued` is success; `authorization-required` is a HUMAN flow (3LO
26
+ * consent), not a transient fault — retrying it would hammer the IdP
27
+ * without the user having authorized anything.
28
+ * • After retries exhaust, the LAST error is rethrown — the call site
29
+ * behaves byte-identically to an unwrapped provider (fail-closed:
30
+ * `agentfootprint.credential.failed` emit + error tool result; the tool
31
+ * does NOT run).
32
+ * • Visibility: the agent trace brackets the whole retried resolution with
33
+ * `credential.requested` → `credential.acquired` / `credential.failed`.
34
+ * Per-attempt visibility is consumer-wired via `onRetry` — the established
35
+ * decorator contract (same as `withRetry`; the `agentfootprint.error.*`
36
+ * event family is reserved for these decorators, see events/payloads.ts).
37
+ * No new event types.
38
+ *
39
+ * @example
40
+ * import { agentCoreIdentity, withCredentialRetry } from 'agentfootprint/identity';
41
+ *
42
+ * const credentials = withCredentialRetry(agentCoreIdentity({ region: 'us-east-1' }), {
43
+ * maxAttempts: 3,
44
+ * onRetry: (err, attempt, ms) => console.warn(`credential retry ${attempt} in ${ms}ms`, err),
45
+ * });
46
+ * const agent = Agent.create({ provider, model, credentials }).tools([...]).build();
47
+ */
48
+ import { type WithRetryOptions } from '../resilience/withRetry.js';
49
+ import type { CredentialProvider } from './types.js';
50
+ /**
51
+ * Same vocabulary as the LLM-provider `withRetry` — one retry language across
52
+ * both decorators. `shouldRetry` sees only THROWN errors (never an
53
+ * `authorization-required` result, which returns immediately).
54
+ */
55
+ export type WithCredentialRetryOptions = WithRetryOptions;
56
+ /**
57
+ * Wrap a {@link CredentialProvider} so transient `getCredential` failures
58
+ * retry with exponential backoff before failing closed.
59
+ *
60
+ * Defaults mirror `withRetry`: 3 attempts total, 200ms → 400ms → 800ms
61
+ * backoff capped at 10s, retry on 5xx/429/network/unknown, never on
62
+ * AbortError or other 4xx.
63
+ */
64
+ export declare function withCredentialRetry(provider: CredentialProvider, options?: WithCredentialRetryOptions): CredentialProvider;
65
+ //# sourceMappingURL=withCredentialRetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withCredentialRetry.d.ts","sourceRoot":"","sources":["../../../src/identity/withCredentialRetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAuC,MAAM,YAAY,CAAC;AAE1F;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,gBAAgB,CAAC;AAE1D;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,0BAA+B,GACvC,kBAAkB,CAgCpB"}
@@ -27,5 +27,6 @@ export type { Credential, CredentialProvider, CredentialRequest, CredentialResul
27
27
  export { isCredentialIssued, unconfiguredCredentialProvider } from './identity/types.js';
28
28
  export { bearer, apiKey, basic, headers, type BearerCredential, type ApiKeyCredential, type BasicCredential, type HeadersCredential, } from './identity/kinds.js';
29
29
  export { staticTokens, type StaticTokensOptions } from './identity/staticTokens.js';
30
+ export { withCredentialRetry, type WithCredentialRetryOptions, } from './identity/withCredentialRetry.js';
30
31
  export { agentCoreIdentity, type AgentCoreIdentityOptions, type AgentCoreIdentityClientLike, type AgentCoreOauthResponse, } from './adapters/identity/agentcore.js';
31
32
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,+BAA+B,EAC/B,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,GAC5B,MAAM,kCAAkC,CAAC"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,+BAA+B,EAC/B,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,GAC5B,MAAM,kCAAkC,CAAC"}
@@ -35,9 +35,11 @@ export interface WithRetryOptions {
35
35
  */
36
36
  readonly shouldRetry?: (error: unknown, attempt: number) => boolean;
37
37
  /**
38
- * Hook invoked before each retry. Useful for logging or
39
- * `agentfootprint.resilience.retry` emit. Receives the attempt
40
- * number that's about to start (so attempt 2 = first retry).
38
+ * Hook invoked before each retry. Useful for logging or an
39
+ * `agentfootprint.error.retried` emit (the event family reserved for
40
+ * the standalone provider decorators see events/payloads.ts).
41
+ * Receives the attempt number that's about to start (so attempt 2 =
42
+ * first retry).
41
43
  */
42
44
  readonly onRetry?: (error: unknown, attempt: number, delayMs: number) => void;
43
45
  }
@@ -54,4 +56,17 @@ export interface WithRetryOptions {
54
56
  * });
55
57
  */
56
58
  export declare function withRetry(provider: LLMProvider, options?: WithRetryOptions): LLMProvider;
59
+ /**
60
+ * Skip retry for AbortError + 4xx-class errors. Retry on everything
61
+ * else (network errors, 5xx, unknown shapes). Provider adapters that
62
+ * surface HTTP status should set `error.status` for this to work; the
63
+ * predicate falls back to retrying when status is unknown (better to
64
+ * retry once than to surface a flaky failure).
65
+ *
66
+ * Exported (module-level, NOT on the resilience barrel) as the single
67
+ * source of truth for the decorators' transience policy — shared by
68
+ * `withCredentialRetry` (identity) so "what counts as transient" never
69
+ * drifts between the LLM and credential retry wrappers.
70
+ */
71
+ export declare function defaultShouldRetry(err: unknown, _attempt: number): boolean;
57
72
  //# sourceMappingURL=withRetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withRetry.d.ts","sourceRoot":"","sources":["../../../src/resilience/withRetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAY,WAAW,EAA2B,MAAM,sBAAsB,CAAC;AAE3F,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,GAAE,gBAAqB,GAAG,WAAW,CAuC5F"}
1
+ {"version":3,"file":"withRetry.d.ts","sourceRoot":"","sources":["../../../src/resilience/withRetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAY,WAAW,EAA2B,MAAM,sBAAsB,CAAC;AAE3F,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACpE;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,GAAE,gBAAqB,GAAG,WAAW,CAuC5F;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAU1E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentfootprint",
3
- "version": "6.21.0",
3
+ "version": "6.22.0",
4
4
  "description": "The explainable agent framework — build AI agents you can explain, audit, and trust. Built on footprintjs.",
5
5
  "license": "MIT",
6
6
  "author": "Sanjay Krishna Anbalagan",