agentfootprint 7.14.0 → 7.15.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.
Files changed (94) hide show
  1. package/dist/adapters/hosting/agentcore.js +350 -0
  2. package/dist/adapters/hosting/agentcore.js.map +1 -0
  3. package/dist/adapters/memory/agentcore.js +125 -1
  4. package/dist/adapters/memory/agentcore.js.map +1 -1
  5. package/dist/adapters/security/agentcore.js +0 -0
  6. package/dist/adapters/security/agentcore.js.map +1 -0
  7. package/dist/esm/adapters/hosting/agentcore.d.ts +199 -0
  8. package/dist/esm/adapters/hosting/agentcore.js +321 -0
  9. package/dist/esm/adapters/hosting/agentcore.js.map +1 -0
  10. package/dist/esm/adapters/memory/agentcore.d.ts +88 -2
  11. package/dist/esm/adapters/memory/agentcore.js +125 -1
  12. package/dist/esm/adapters/memory/agentcore.js.map +1 -1
  13. package/dist/esm/adapters/security/agentcore.d.ts +157 -0
  14. package/dist/esm/adapters/security/agentcore.js +0 -0
  15. package/dist/esm/adapters/security/agentcore.js.map +1 -0
  16. package/dist/esm/hosting/httpHost.d.ts +121 -0
  17. package/dist/esm/hosting/httpHost.js +248 -0
  18. package/dist/esm/hosting/httpHost.js.map +1 -0
  19. package/dist/esm/hosting/index.d.ts +8 -1
  20. package/dist/esm/hosting/index.js +7 -1
  21. package/dist/esm/hosting/index.js.map +1 -1
  22. package/dist/esm/hosting/nodeHost.d.ts +23 -16
  23. package/dist/esm/hosting/nodeHost.js +32 -199
  24. package/dist/esm/hosting/nodeHost.js.map +1 -1
  25. package/dist/esm/hosting-providers.d.ts +50 -0
  26. package/dist/esm/hosting-providers.js +50 -0
  27. package/dist/esm/hosting-providers.js.map +1 -0
  28. package/dist/esm/lib/mcp/gatewayTransport.d.ts +103 -0
  29. package/dist/esm/lib/mcp/gatewayTransport.js +123 -0
  30. package/dist/esm/lib/mcp/gatewayTransport.js.map +1 -0
  31. package/dist/esm/lib/mcp/index.d.ts +2 -1
  32. package/dist/esm/lib/mcp/index.js +1 -0
  33. package/dist/esm/lib/mcp/index.js.map +1 -1
  34. package/dist/esm/lib/mcp/mcpClient.js +10 -2
  35. package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
  36. package/dist/esm/lib/mcp/types.d.ts +45 -1
  37. package/dist/esm/memory/store/types.d.ts +22 -0
  38. package/dist/esm/memory-providers.d.ts +1 -1
  39. package/dist/esm/memory-providers.js.map +1 -1
  40. package/dist/esm/security/index.d.ts +10 -1
  41. package/dist/esm/security/index.js +14 -1
  42. package/dist/esm/security/index.js.map +1 -1
  43. package/dist/esm/tool-providers/index.d.ts +6 -2
  44. package/dist/esm/tool-providers/index.js +5 -1
  45. package/dist/esm/tool-providers/index.js.map +1 -1
  46. package/dist/hosting/httpHost.js +276 -0
  47. package/dist/hosting/httpHost.js.map +1 -0
  48. package/dist/hosting/index.js +10 -1
  49. package/dist/hosting/index.js.map +1 -1
  50. package/dist/hosting/nodeHost.js +34 -224
  51. package/dist/hosting/nodeHost.js.map +1 -1
  52. package/dist/hosting-providers.js +57 -0
  53. package/dist/hosting-providers.js.map +1 -0
  54. package/dist/lib/mcp/gatewayTransport.js +129 -0
  55. package/dist/lib/mcp/gatewayTransport.js.map +1 -0
  56. package/dist/lib/mcp/index.js +4 -1
  57. package/dist/lib/mcp/index.js.map +1 -1
  58. package/dist/lib/mcp/mcpClient.js +10 -2
  59. package/dist/lib/mcp/mcpClient.js.map +1 -1
  60. package/dist/memory-providers.js.map +1 -1
  61. package/dist/security/index.js +16 -2
  62. package/dist/security/index.js.map +1 -1
  63. package/dist/tool-providers/index.js +7 -1
  64. package/dist/tool-providers/index.js.map +1 -1
  65. package/dist/types/adapters/hosting/agentcore.d.ts +200 -0
  66. package/dist/types/adapters/hosting/agentcore.d.ts.map +1 -0
  67. package/dist/types/adapters/memory/agentcore.d.ts +88 -2
  68. package/dist/types/adapters/memory/agentcore.d.ts.map +1 -1
  69. package/dist/types/adapters/security/agentcore.d.ts +158 -0
  70. package/dist/types/adapters/security/agentcore.d.ts.map +1 -0
  71. package/dist/types/hosting/httpHost.d.ts +122 -0
  72. package/dist/types/hosting/httpHost.d.ts.map +1 -0
  73. package/dist/types/hosting/index.d.ts +8 -1
  74. package/dist/types/hosting/index.d.ts.map +1 -1
  75. package/dist/types/hosting/nodeHost.d.ts +23 -16
  76. package/dist/types/hosting/nodeHost.d.ts.map +1 -1
  77. package/dist/types/hosting-providers.d.ts +51 -0
  78. package/dist/types/hosting-providers.d.ts.map +1 -0
  79. package/dist/types/lib/mcp/gatewayTransport.d.ts +104 -0
  80. package/dist/types/lib/mcp/gatewayTransport.d.ts.map +1 -0
  81. package/dist/types/lib/mcp/index.d.ts +2 -1
  82. package/dist/types/lib/mcp/index.d.ts.map +1 -1
  83. package/dist/types/lib/mcp/mcpClient.d.ts.map +1 -1
  84. package/dist/types/lib/mcp/types.d.ts +45 -1
  85. package/dist/types/lib/mcp/types.d.ts.map +1 -1
  86. package/dist/types/memory/store/types.d.ts +22 -0
  87. package/dist/types/memory/store/types.d.ts.map +1 -1
  88. package/dist/types/memory-providers.d.ts +1 -1
  89. package/dist/types/memory-providers.d.ts.map +1 -1
  90. package/dist/types/security/index.d.ts +10 -1
  91. package/dist/types/security/index.d.ts.map +1 -1
  92. package/dist/types/tool-providers/index.d.ts +6 -2
  93. package/dist/types/tool-providers/index.d.ts.map +1 -1
  94. package/package.json +14 -1
@@ -0,0 +1,199 @@
1
+ /**
2
+ * adapters/hosting/agentcore — AWS Bedrock **AgentCore Runtime** adapters for
3
+ * the two hosting ports.
4
+ *
5
+ * import { agentCoreRuntimeHost, agentCoreSessions } from 'agentfootprint/hosting-providers';
6
+ * import { standingAgent } from 'agentfootprint/hosting';
7
+ *
8
+ * const handle = await standingAgent({
9
+ * agent,
10
+ * host: agentCoreRuntimeHost(),
11
+ * sessions: agentCoreSessions({ store: 'session-storage' }),
12
+ * });
13
+ *
14
+ * ── What this file actually is ───────────────────────────────────────────────
15
+ * Vendor paths, a header name, and two JSON body shapes. That is the whole
16
+ * adapter, and it is the claim the hosting ports were designed to make: a
17
+ * container runtime's contract is a CONFIGURATION of HTTP work that already
18
+ * exists, not a second implementation of it. Nothing here reaches into the
19
+ * ports, and nothing here needed the ports to change.
20
+ *
21
+ * AgentCore Runtime is a **container contract**: an ARM64 image serving HTTP on
22
+ * `0.0.0.0:8080` —
23
+ *
24
+ * POST /invocations JSON `{ "prompt": "..." }` → JSON `{ "response", "status" }`
25
+ * GET /ping → `{ "status": "Healthy", "time_of_last_update": <unix seconds> }`
26
+ *
27
+ * and the caller's conversation arrives in the
28
+ * `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header rather than in the body,
29
+ * which is the one thing paths-and-bodies configuration alone could not
30
+ * express before this release.
31
+ *
32
+ * ── Verification status, stated plainly ──────────────────────────────────────
33
+ * `agentCoreRuntimeHost` is **plain HTTP and is really verified**: it runs the
34
+ * same host conformance suite as `nodeHost`, over a real socket, in
35
+ * `test/hosting/host-contract.test.ts`. There is no AWS SDK on its path.
36
+ *
37
+ * `agentCoreSessions({ store: 'memory' })` is **contract-mapped and
38
+ * injection-tested**: its AgentCore Memory calls are exercised through the
39
+ * `_client` seam, never against AWS. Confirm the command and field names
40
+ * against your installed `@aws-sdk/client-bedrock-agentcore` before you rely
41
+ * on it; real-cloud verification lands with a field deployment.
42
+ *
43
+ * Pattern: Adapter (GoF). Role: outer ring. The file-backed session store uses
44
+ * `node:fs` and nothing else; the event-backed one lazy-loads the AWS SDK, so
45
+ * importing this module costs zero peer-dep load.
46
+ */
47
+ import type { HttpHost, HttpWire } from '../../hosting/httpHost.js';
48
+ import type { CheckpointEnvelope, SessionLifecycle } from '../../hosting/types.js';
49
+ /** Options for {@link agentCoreRuntimeHost}. */
50
+ export interface AgentCoreRuntimeHostOptions {
51
+ /**
52
+ * Port to bind. Default `8080` — the port the container contract specifies.
53
+ * Pass `0` in tests to take an ephemeral one.
54
+ */
55
+ readonly port?: number;
56
+ /**
57
+ * Interface to bind. Default `'0.0.0.0'`, which the contract requires: bind
58
+ * to loopback inside the container and the runtime's health probe cannot
59
+ * reach you.
60
+ */
61
+ readonly hostname?: string;
62
+ /**
63
+ * Report `'HealthyBusy'` instead of `'Healthy'` on the health path.
64
+ *
65
+ * A function, not a flag, because busy is a live fact about the process, not
66
+ * a setting: the runtime reads it on every probe to decide whether to send
67
+ * you more work. Omit it and the host reports `'Healthy'`, which is the
68
+ * honest answer for an agent that answers synchronously.
69
+ */
70
+ readonly busy?: () => boolean;
71
+ }
72
+ /**
73
+ * The AgentCore Runtime contract as an {@link HttpWire}.
74
+ *
75
+ * Exported so the body shapes are inspectable and testable without binding a
76
+ * socket, and so a deployment that must serve the same bodies from somewhere
77
+ * else can reuse them by name.
78
+ */
79
+ export declare function agentCoreRuntimeWire(busy?: () => boolean): HttpWire;
80
+ /**
81
+ * An `AgentHost` that speaks AgentCore Runtime's container contract.
82
+ *
83
+ * Passes the same conformance suite as `nodeHost` — it is the same HTTP host
84
+ * with this runtime's two paths, its header, and its two body shapes.
85
+ *
86
+ * @example The container's entry point
87
+ * const handle = await standingAgent({
88
+ * agent,
89
+ * host: agentCoreRuntimeHost(),
90
+ * sessions: agentCoreSessions({ store: 'session-storage' }),
91
+ * });
92
+ * process.on('SIGTERM', () => void handle.close());
93
+ */
94
+ export declare function agentCoreRuntimeHost(options?: AgentCoreRuntimeHostOptions): HttpHost;
95
+ /**
96
+ * Where {@link agentCoreSessions} keeps a conversation between requests.
97
+ *
98
+ * - `'session-storage'` — a JSON file under the container's own storage. The
99
+ * runtime keeps that storage for the life of a session, INCLUDING across a
100
+ * stop/resume of the container, so a conversation survives the thing most
101
+ * likely to interrupt it. It does not survive the session ending.
102
+ * - `'memory'` — one AgentCore Memory event per persist. Outlives the session,
103
+ * the container and the deployment; costs an API call per turn and the
104
+ * `@aws-sdk/client-bedrock-agentcore` peer dependency.
105
+ *
106
+ * Chosen at construction, never per call: a store that silently changed where
107
+ * it wrote would be a store you cannot reason about after an incident.
108
+ */
109
+ export type AgentCoreSessionStore = 'session-storage' | 'memory';
110
+ /** The default file the `'session-storage'` mode writes to. */
111
+ export declare const DEFAULT_SESSION_STORAGE_PATH = "/tmp/agentcore-session";
112
+ /** Options for the file-backed mode. */
113
+ export interface AgentCoreFileSessionsOptions {
114
+ readonly store: 'session-storage';
115
+ /**
116
+ * Where to write. Default {@link DEFAULT_SESSION_STORAGE_PATH}. One file
117
+ * holds every session this container has seen, keyed by session id — the
118
+ * runtime already gives each session its own storage, so the keying is
119
+ * belt-and-braces for the case where it does not.
120
+ */
121
+ readonly path?: string;
122
+ }
123
+ /** One AgentCore Memory event, as this adapter cares about it. */
124
+ export interface AgentCoreSessionEvent {
125
+ /** Server-assigned event id. */
126
+ readonly eventId: string;
127
+ /** The envelope decoded from the event's blob payload, or `null` when unreadable. */
128
+ readonly envelope: unknown;
129
+ }
130
+ /**
131
+ * The minimal AgentCore Memory surface the session store calls. The real SDK is
132
+ * adapted to this shape in one function below; tests inject a fake via
133
+ * `_client` and never touch AWS.
134
+ */
135
+ export interface AgentCoreSessionClientLike {
136
+ /** Append one envelope as an event (the server assigns the event id). */
137
+ createEvent(input: {
138
+ memoryId: string;
139
+ actorId: string;
140
+ sessionId: string;
141
+ envelope: CheckpointEnvelope;
142
+ }): Promise<void>;
143
+ /** The session's events, newest first — the adapter reads only the newest. */
144
+ listEvents(input: {
145
+ memoryId: string;
146
+ actorId: string;
147
+ sessionId: string;
148
+ maxResults?: number;
149
+ }): Promise<{
150
+ events: readonly AgentCoreSessionEvent[];
151
+ }>;
152
+ }
153
+ /** Options for the event-backed mode. */
154
+ export interface AgentCoreMemorySessionsOptions {
155
+ readonly store: 'memory';
156
+ /** AgentCore Memory ARN or id. Required. */
157
+ readonly memoryId: string;
158
+ /** AWS region, when the adapter constructs the SDK client itself. */
159
+ readonly region?: string;
160
+ /**
161
+ * The AgentCore `actorId` these conversations belong to. Default
162
+ * `'afp-standing-agent'`. One actor per deployed agent is the usual shape.
163
+ */
164
+ readonly actorId?: string;
165
+ /** Pre-built client, to share one SDK config across the host app. */
166
+ readonly client?: AgentCoreSessionClientLike;
167
+ /** @internal Test injection — skips the SDK require entirely. */
168
+ readonly _client?: AgentCoreSessionClientLike;
169
+ /** @internal Test injection — the AWS SDK module, to exercise the real shim with a fake SDK. */
170
+ readonly _sdk?: BedrockAgentCoreSessionSdkModule;
171
+ }
172
+ /** Options for {@link agentCoreSessions}. */
173
+ export type AgentCoreSessionsOptions = AgentCoreFileSessionsOptions | AgentCoreMemorySessionsOptions;
174
+ /**
175
+ * A `SessionLifecycle` backed by AgentCore, with the checkpoint's home chosen
176
+ * at construction.
177
+ *
178
+ * Both modes store the SAME `CheckpointEnvelope` the port defines, and both
179
+ * refuse an unknown `format` by name through the shared `readEnvelope` — a
180
+ * conversation written by a newer runtime is refused, never half-restored.
181
+ * That law is inherited, not re-implemented.
182
+ *
183
+ * @example Survive a stop/resume, no AWS SDK required
184
+ * agentCoreSessions({ store: 'session-storage' });
185
+ *
186
+ * @example Outlive the session entirely
187
+ * agentCoreSessions({ store: 'memory', memoryId: process.env.MEMORY_ID!, region: 'us-west-2' });
188
+ */
189
+ export declare function agentCoreSessions(options: AgentCoreSessionsOptions): SessionLifecycle;
190
+ /** The slice of `@aws-sdk/client-bedrock-agentcore` this shim touches. */
191
+ export interface BedrockAgentCoreSessionSdkModule {
192
+ readonly BedrockAgentCoreClient?: new (config: {
193
+ region?: string;
194
+ }) => {
195
+ send(cmd: unknown): Promise<unknown>;
196
+ };
197
+ readonly CreateEventCommand?: new (input: unknown) => unknown;
198
+ readonly ListEventsCommand?: new (input: unknown) => unknown;
199
+ }
@@ -0,0 +1,321 @@
1
+ /**
2
+ * adapters/hosting/agentcore — AWS Bedrock **AgentCore Runtime** adapters for
3
+ * the two hosting ports.
4
+ *
5
+ * import { agentCoreRuntimeHost, agentCoreSessions } from 'agentfootprint/hosting-providers';
6
+ * import { standingAgent } from 'agentfootprint/hosting';
7
+ *
8
+ * const handle = await standingAgent({
9
+ * agent,
10
+ * host: agentCoreRuntimeHost(),
11
+ * sessions: agentCoreSessions({ store: 'session-storage' }),
12
+ * });
13
+ *
14
+ * ── What this file actually is ───────────────────────────────────────────────
15
+ * Vendor paths, a header name, and two JSON body shapes. That is the whole
16
+ * adapter, and it is the claim the hosting ports were designed to make: a
17
+ * container runtime's contract is a CONFIGURATION of HTTP work that already
18
+ * exists, not a second implementation of it. Nothing here reaches into the
19
+ * ports, and nothing here needed the ports to change.
20
+ *
21
+ * AgentCore Runtime is a **container contract**: an ARM64 image serving HTTP on
22
+ * `0.0.0.0:8080` —
23
+ *
24
+ * POST /invocations JSON `{ "prompt": "..." }` → JSON `{ "response", "status" }`
25
+ * GET /ping → `{ "status": "Healthy", "time_of_last_update": <unix seconds> }`
26
+ *
27
+ * and the caller's conversation arrives in the
28
+ * `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header rather than in the body,
29
+ * which is the one thing paths-and-bodies configuration alone could not
30
+ * express before this release.
31
+ *
32
+ * ── Verification status, stated plainly ──────────────────────────────────────
33
+ * `agentCoreRuntimeHost` is **plain HTTP and is really verified**: it runs the
34
+ * same host conformance suite as `nodeHost`, over a real socket, in
35
+ * `test/hosting/host-contract.test.ts`. There is no AWS SDK on its path.
36
+ *
37
+ * `agentCoreSessions({ store: 'memory' })` is **contract-mapped and
38
+ * injection-tested**: its AgentCore Memory calls are exercised through the
39
+ * `_client` seam, never against AWS. Confirm the command and field names
40
+ * against your installed `@aws-sdk/client-bedrock-agentcore` before you rely
41
+ * on it; real-cloud verification lands with a field deployment.
42
+ *
43
+ * Pattern: Adapter (GoF). Role: outer ring. The file-backed session store uses
44
+ * `node:fs` and nothing else; the event-backed one lazy-loads the AWS SDK, so
45
+ * importing this module costs zero peer-dep load.
46
+ */
47
+ import { readEnvelope } from '../../hosting/envelope.js';
48
+ import { headerValue, httpHost } from '../../hosting/httpHost.js';
49
+ import { lazyRequire } from '../../lib/lazyRequire.js';
50
+ // ─── The runtime host ────────────────────────────────────────────────
51
+ const HOST_NAME = 'agentCoreRuntimeHost';
52
+ /** The runtime's container contract, as constants rather than as scattered literals. */
53
+ const INVOKE_PATH = '/invocations';
54
+ const HEALTH_PATH = '/ping';
55
+ const RUNTIME_PORT = 8080;
56
+ /**
57
+ * The header the runtime puts the caller's conversation in. Matched
58
+ * case-insensitively — HTTP header names are case-insensitive and a proxy in
59
+ * front of the container is free to re-case them.
60
+ */
61
+ const SESSION_HEADER = 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id';
62
+ /**
63
+ * The AgentCore Runtime contract as an {@link HttpWire}.
64
+ *
65
+ * Exported so the body shapes are inspectable and testable without binding a
66
+ * socket, and so a deployment that must serve the same bodies from somewhere
67
+ * else can reuse them by name.
68
+ */
69
+ export function agentCoreRuntimeWire(busy) {
70
+ return {
71
+ readRequest(facts) {
72
+ // `prompt` is the field the runtime's own quickstart and this repo's
73
+ // deploy template use. `input` is accepted too because the runtime passes
74
+ // the payload through verbatim — it is the CALLER who picks the field —
75
+ // and refusing a caller who used the port's own word would be a rule this
76
+ // adapter invented rather than one the contract imposes.
77
+ const prompt = facts.body.prompt ?? facts.body.input;
78
+ const input = typeof prompt === 'string' ? prompt : '';
79
+ // The conversation id arrives in a header, never in the body. It is
80
+ // caller-adjacent data, not identity — the port says so and it is just as
81
+ // true here.
82
+ const sessionId = headerValue(facts, SESSION_HEADER);
83
+ return sessionId !== undefined ? { input, sessionId } : { input };
84
+ },
85
+ // The runtime polls this to decide whether the container is ready and
86
+ // whether to send it more work. `time_of_last_update` is unix SECONDS.
87
+ health: () => ({
88
+ status: busy?.() === true ? 'HealthyBusy' : 'Healthy',
89
+ time_of_last_update: Math.floor(Date.now() / 1000),
90
+ }),
91
+ output: (response) => ({ response, status: 'success' }),
92
+ // The message only — never a stack. The runtime surfaces the status code;
93
+ // the body is read by whoever called the agent.
94
+ failure: (error, code) => ({ error, status: 'error', ...(code !== undefined && { code }) }),
95
+ // A distinct field from `response` on purpose: a caller concatenating
96
+ // stream frames must not be able to double-count the final answer by
97
+ // reading the same key twice.
98
+ chunk: (chunk) => ({ chunk }),
99
+ };
100
+ }
101
+ /**
102
+ * An `AgentHost` that speaks AgentCore Runtime's container contract.
103
+ *
104
+ * Passes the same conformance suite as `nodeHost` — it is the same HTTP host
105
+ * with this runtime's two paths, its header, and its two body shapes.
106
+ *
107
+ * @example The container's entry point
108
+ * const handle = await standingAgent({
109
+ * agent,
110
+ * host: agentCoreRuntimeHost(),
111
+ * sessions: agentCoreSessions({ store: 'session-storage' }),
112
+ * });
113
+ * process.on('SIGTERM', () => void handle.close());
114
+ */
115
+ export function agentCoreRuntimeHost(options = {}) {
116
+ return httpHost({
117
+ name: HOST_NAME,
118
+ wire: agentCoreRuntimeWire(options.busy),
119
+ invokePath: INVOKE_PATH,
120
+ healthPath: HEALTH_PATH,
121
+ port: options.port ?? RUNTIME_PORT,
122
+ hostname: options.hostname ?? '0.0.0.0',
123
+ });
124
+ }
125
+ /** The default file the `'session-storage'` mode writes to. */
126
+ export const DEFAULT_SESSION_STORAGE_PATH = '/tmp/agentcore-session';
127
+ /**
128
+ * A `SessionLifecycle` backed by AgentCore, with the checkpoint's home chosen
129
+ * at construction.
130
+ *
131
+ * Both modes store the SAME `CheckpointEnvelope` the port defines, and both
132
+ * refuse an unknown `format` by name through the shared `readEnvelope` — a
133
+ * conversation written by a newer runtime is refused, never half-restored.
134
+ * That law is inherited, not re-implemented.
135
+ *
136
+ * @example Survive a stop/resume, no AWS SDK required
137
+ * agentCoreSessions({ store: 'session-storage' });
138
+ *
139
+ * @example Outlive the session entirely
140
+ * agentCoreSessions({ store: 'memory', memoryId: process.env.MEMORY_ID!, region: 'us-west-2' });
141
+ */
142
+ export function agentCoreSessions(options) {
143
+ return options.store === 'memory' ? memoryEventSessions(options) : fileSessions(options);
144
+ }
145
+ function fileSessions(options) {
146
+ const path = options.path ?? DEFAULT_SESSION_STORAGE_PATH;
147
+ async function readFile() {
148
+ const { readFile: read } = await import('node:fs/promises');
149
+ let raw;
150
+ try {
151
+ raw = await read(path, 'utf8');
152
+ }
153
+ catch {
154
+ // No file yet is the ordinary first-request state, not an error.
155
+ return { version: 1, sessions: {} };
156
+ }
157
+ let parsed;
158
+ try {
159
+ parsed = JSON.parse(raw);
160
+ }
161
+ catch (err) {
162
+ throw new TypeError(`[hosting] the session file at '${path}' is not JSON (${err.message}). ` +
163
+ `Refusing rather than starting every conversation over silently — delete the file ` +
164
+ `to start fresh, or point 'path' somewhere else.`);
165
+ }
166
+ const sessions = parsed?.sessions;
167
+ return sessions && typeof sessions === 'object'
168
+ ? { version: 1, sessions: sessions }
169
+ : { version: 1, sessions: {} };
170
+ }
171
+ return {
172
+ async hydrate(sessionId) {
173
+ const file = await readFile();
174
+ const stored = file.sessions[sessionId];
175
+ if (stored === undefined)
176
+ return undefined;
177
+ // Validate HERE as well as in the composer, so a refusal points at the
178
+ // store that produced the bytes rather than at whoever read them next.
179
+ readEnvelope(stored);
180
+ return stored;
181
+ },
182
+ async persist(sessionId, envelope) {
183
+ const { writeFile, rename, mkdir } = await import('node:fs/promises');
184
+ const { dirname } = await import('node:path');
185
+ const file = await readFile();
186
+ const next = {
187
+ version: 1,
188
+ sessions: { ...file.sessions, [sessionId]: envelope },
189
+ };
190
+ await mkdir(dirname(path), { recursive: true }).catch(() => undefined);
191
+ // Write-then-rename: a container killed mid-write leaves the previous
192
+ // conversation intact rather than a truncated file that refuses to parse.
193
+ const temporary = `${path}.${process.pid}.tmp`;
194
+ await writeFile(temporary, JSON.stringify(next), 'utf8');
195
+ await rename(temporary, path);
196
+ },
197
+ };
198
+ }
199
+ // ─── 'memory': one AgentCore Memory event per persist ────────────────
200
+ const DEFAULT_ACTOR_ID = 'afp-standing-agent';
201
+ function memoryEventSessions(options) {
202
+ if (!options.memoryId) {
203
+ throw new Error(`agentCoreSessions({ store: 'memory' }) requires 'memoryId'.`);
204
+ }
205
+ const memoryId = options.memoryId;
206
+ const actorId = options.actorId ?? DEFAULT_ACTOR_ID;
207
+ const client = options._client ?? options.client ?? createSessionClient(options.region, options._sdk);
208
+ return {
209
+ async hydrate(sessionId) {
210
+ // AgentCore Memory is an append-only log and lists newest-first, so the
211
+ // newest readable event IS the conversation. Older ones are the earlier
212
+ // turns and deliberately left where they are — they are the audit trail.
213
+ const page = await client.listEvents({
214
+ memoryId,
215
+ actorId,
216
+ sessionId: safeSessionId(sessionId),
217
+ maxResults: 1,
218
+ });
219
+ const newest = page.events[0];
220
+ if (!newest || newest.envelope === null || newest.envelope === undefined)
221
+ return undefined;
222
+ readEnvelope(newest.envelope);
223
+ return newest.envelope;
224
+ },
225
+ async persist(sessionId, envelope) {
226
+ await client.createEvent({
227
+ memoryId,
228
+ actorId,
229
+ sessionId: safeSessionId(sessionId),
230
+ envelope,
231
+ });
232
+ },
233
+ };
234
+ }
235
+ const SESSION_ID_MAX = 99;
236
+ /** AgentCore ids accept `[A-Za-z0-9_-]`; a session id is caller data and need not. */
237
+ function safeSessionId(raw) {
238
+ const slug = raw.replace(/[^A-Za-z0-9_-]/g, '-');
239
+ if (slug.length <= SESSION_ID_MAX)
240
+ return slug;
241
+ // Keep a readable head plus a stable tail so two long ids stay distinct.
242
+ return `${slug.slice(0, SESSION_ID_MAX - 9)}-${fnv1a(raw)}`;
243
+ }
244
+ function fnv1a(s) {
245
+ let h = 0x811c9dc5;
246
+ for (let i = 0; i < s.length; i++) {
247
+ h ^= s.charCodeAt(i);
248
+ h = Math.imul(h, 0x01000193);
249
+ }
250
+ return (h >>> 0).toString(36);
251
+ }
252
+ /** Pull the envelope out of an event's `payload` (a single `blob` document). */
253
+ function envelopeFromPayload(payload) {
254
+ if (!Array.isArray(payload))
255
+ return null;
256
+ for (const part of payload) {
257
+ const blob = part?.blob;
258
+ if (blob && typeof blob === 'object')
259
+ return blob;
260
+ }
261
+ return null;
262
+ }
263
+ /**
264
+ * Map {@link AgentCoreSessionClientLike} onto the real SDK commands. If AWS
265
+ * renames a command, only this function changes — which is also why every test
266
+ * injects past it.
267
+ */
268
+ function createSessionClient(region, injected) {
269
+ let mod;
270
+ if (injected) {
271
+ mod = injected;
272
+ }
273
+ else {
274
+ try {
275
+ mod = lazyRequire('@aws-sdk/client-bedrock-agentcore');
276
+ }
277
+ catch {
278
+ throw new Error(`agentCoreSessions({ store: 'memory' }) requires the ` +
279
+ '`@aws-sdk/client-bedrock-agentcore` peer dependency.\n' +
280
+ ' Install: npm install @aws-sdk/client-bedrock-agentcore\n' +
281
+ " Or use { store: 'session-storage' }, which needs no SDK at all.");
282
+ }
283
+ }
284
+ if (!mod.BedrockAgentCoreClient) {
285
+ throw new Error('agentCoreSessions: `@aws-sdk/client-bedrock-agentcore` is installed but ' +
286
+ '`BedrockAgentCoreClient` was not found. Update the SDK.');
287
+ }
288
+ const sdk = new mod.BedrockAgentCoreClient({ ...(region && { region }) });
289
+ const send = async (Ctor, name, input) => {
290
+ if (!Ctor) {
291
+ throw new Error(`agentCoreSessions: \`@aws-sdk/client-bedrock-agentcore\` is missing ${name}. Upgrade the SDK.`);
292
+ }
293
+ return sdk.send(new Ctor(input));
294
+ };
295
+ return {
296
+ async createEvent({ memoryId, actorId, sessionId, envelope }) {
297
+ await send(mod.CreateEventCommand, 'CreateEventCommand', {
298
+ memoryId,
299
+ actorId,
300
+ sessionId,
301
+ eventTimestamp: new Date(),
302
+ payload: [{ blob: envelope }],
303
+ });
304
+ },
305
+ async listEvents({ memoryId, actorId, sessionId, maxResults }) {
306
+ const result = (await send(mod.ListEventsCommand, 'ListEventsCommand', {
307
+ memoryId,
308
+ actorId,
309
+ sessionId,
310
+ includePayloads: true,
311
+ ...(maxResults !== undefined && { maxResults }),
312
+ }));
313
+ const events = (result?.events ?? []).map((event) => ({
314
+ eventId: event.eventId ?? '',
315
+ envelope: envelopeFromPayload(event.payload),
316
+ }));
317
+ return { events };
318
+ },
319
+ };
320
+ }
321
+ //# sourceMappingURL=agentcore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../../src/adapters/hosting/agentcore.ts"],"names":[],"mappings":"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"}
@@ -27,14 +27,20 @@
27
27
  * AgentCore's ids are server-assigned. **O(events in session)** — fine for typical
28
28
  * window sizes; if you need O(1) keyed access at scale, use RedisStore.
29
29
  * • `forget` → `ListEvents` + `DeleteEvent` per event (no `DeleteSession` on AgentCore).
30
- * • `search` → still unwired (AgentCore's `RetrieveMemoryRecords` lands as a later helper).
30
+ * • `search` → `RetrieveMemoryRecords`, **text-in**. AgentCore embeds and ranks on its
31
+ * own side, so it takes a natural-language query; the port's `search()` takes a
32
+ * vector. Pass `options.text` and this store serves the query; omit it and it refuses
33
+ * by name rather than ranking an empty set. See `search()` below for the whole story.
31
34
  * • `putIfVersion` / `seen` / `feedback` → in-process emulation (AgentCore has no native
32
35
  * CAS / dedup / feedback primitive; these don't survive process restart).
36
+ * • no `stream()` — AgentCore Memory has no streaming data-plane operation, and the
37
+ * `MemoryStore` port has no streaming method to implement. Inventing one for a single
38
+ * backend is how a port stops being a port.
33
39
  *
34
40
  * Role: Outer ring. Lazy-requires the AWS SDK; zero runtime cost when another adapter is
35
41
  * in use. Emits: N/A (storage adapters don't emit).
36
42
  */
37
- import type { ListOptions, ListResult, MemoryStore, PutIfVersionResult } from '../../memory/store/types.js';
43
+ import type { ListOptions, ListResult, MemoryStore, PutIfVersionResult, ScoredEntry, SearchOptions } from '../../memory/store/types.js';
38
44
  import type { MemoryEntry } from '../../memory/entry/index.js';
39
45
  import type { MemoryIdentity } from '../../memory/identity/index.js';
40
46
  /** One event as the adapter cares about it: AgentCore's id + the decoded entry. */
@@ -75,6 +81,35 @@ export interface AgentCoreLikeClient {
75
81
  sessionId: string;
76
82
  eventId: string;
77
83
  }): Promise<void>;
84
+ /**
85
+ * Server-side semantic retrieval (`RetrieveMemoryRecords`). Optional: a client
86
+ * built before this existed still satisfies the interface, and `search()`
87
+ * feature-detects it rather than assuming.
88
+ */
89
+ retrieveRecords?(input: {
90
+ memoryId: string;
91
+ namespace: string;
92
+ searchQuery: string;
93
+ maxResults?: number;
94
+ memoryStrategyId?: string;
95
+ }): Promise<{
96
+ records: readonly AgentCoreMemoryRecord[];
97
+ }>;
98
+ }
99
+ /** One record as `RetrieveMemoryRecords` returns it. */
100
+ export interface AgentCoreMemoryRecord {
101
+ /** AgentCore's own record id. */
102
+ readonly memoryRecordId: string;
103
+ /** The record's text content. */
104
+ readonly content: string;
105
+ /** Relevance as AgentCore scored it, when it reports one. */
106
+ readonly score?: number;
107
+ /** Which strategy produced the record (semantic, summary, user-preference, …). */
108
+ readonly memoryStrategyId?: string;
109
+ /** The namespace it was found in. */
110
+ readonly namespace?: string;
111
+ /** When AgentCore created it (unix ms), when reported. */
112
+ readonly createdAt?: number;
78
113
  }
79
114
  export interface AgentCoreStoreOptions {
80
115
  /** AgentCore Memory ARN or id. Required. */
@@ -85,6 +120,27 @@ export interface AgentCoreStoreOptions {
85
120
  readonly client?: AgentCoreLikeClient;
86
121
  /** Page size for `listEvents`. Default 100. */
87
122
  readonly pageSize?: number;
123
+ /**
124
+ * Where `search()` looks. AgentCore organises extracted memory records into
125
+ * namespaces configured on the Memory resource's strategies (commonly
126
+ * something like `/strategies/{strategyId}/actors/{actorId}`).
127
+ *
128
+ * A function, because the namespace usually contains the actor: it is handed
129
+ * the resolved AgentCore ids for the identity being searched. Default:
130
+ * `/actors/{actorId}/sessions/{sessionId}` — the session's own records.
131
+ */
132
+ readonly searchNamespace?: (scope: {
133
+ readonly actorId: string;
134
+ readonly sessionId: string;
135
+ }) => string;
136
+ /**
137
+ * Restrict `search()` to one extraction strategy (semantic, summary,
138
+ * user-preference…). Omit to search across all of them.
139
+ *
140
+ * This is the metadata filter that reaches AgentCore's own side; `tiers` /
141
+ * `minScore` / `k` from {@link SearchOptions} are applied to what comes back.
142
+ */
143
+ readonly searchStrategyId?: string;
88
144
  /** @internal Test injection — skips the SDK require entirely. */
89
145
  readonly _client?: AgentCoreLikeClient;
90
146
  /** @internal Test injection — the AWS SDK module (to exercise the real shim with a mock SDK). */
@@ -100,6 +156,8 @@ export declare class AgentCoreStore implements MemoryStore {
100
156
  private readonly client;
101
157
  private readonly memoryId;
102
158
  private readonly pageSize;
159
+ private readonly searchNamespace;
160
+ private readonly searchStrategyId;
103
161
  private closed;
104
162
  private readonly signatures;
105
163
  private readonly feedbackBag;
@@ -130,6 +188,33 @@ export declare class AgentCoreStore implements MemoryStore {
130
188
  } | null>;
131
189
  /** GDPR "everything for this identity, gone." No DeleteSession on AgentCore → delete every event. */
132
190
  forget(identity: MemoryIdentity): Promise<void>;
191
+ /**
192
+ * Server-side semantic retrieval over AgentCore's extracted memory records
193
+ * (`RetrieveMemoryRecords`).
194
+ *
195
+ * ── Read this before you call it ─────────────────────────────────────────
196
+ * **It takes TEXT, not the vector.** AgentCore embeds and ranks on its own
197
+ * side, so `query` — the port's vector — is unusable here, and the query it
198
+ * actually needs travels in `options.text`. Omit that and this method throws
199
+ * a corrective error naming what is missing, because the alternative is
200
+ * ranking nothing and handing back `[]`, which reads as "no matches" when it
201
+ * really means "wrong query form". Pass both and every store can serve you:
202
+ * local-ranking backends use the vector and ignore the text.
203
+ *
204
+ * **It searches a DIFFERENT population than `list()`.** `list` returns the
205
+ * events this store wrote. This returns the records AgentCore's extraction
206
+ * strategies derived FROM those events — summaries, semantic facts, user
207
+ * preferences. The ids therefore belong to AgentCore, not to entries you
208
+ * `put()`, and `store.get(entry.id)` will not find them. They arrive as
209
+ * entries so ranking code needs no special case, with `metadata.source`
210
+ * saying plainly where they came from.
211
+ *
212
+ * Filters: `searchStrategyId` and the namespace reach AgentCore's own side;
213
+ * `k`, `minScore` and `tiers` are applied to what comes back.
214
+ *
215
+ * @throws when `options.text` is absent, or when the client cannot retrieve.
216
+ */
217
+ search<T = unknown>(identity: MemoryIdentity, query: readonly number[], options?: SearchOptions): Promise<readonly ScoredEntry<T>[]>;
133
218
  close(): Promise<void>;
134
219
  private ensureOpen;
135
220
  }
@@ -143,4 +228,5 @@ export interface BedrockAgentCoreSdkModule {
143
228
  readonly CreateEventCommand?: new (input: unknown) => unknown;
144
229
  readonly ListEventsCommand?: new (input: unknown) => unknown;
145
230
  readonly DeleteEventCommand?: new (input: unknown) => unknown;
231
+ readonly RetrieveMemoryRecordsCommand?: new (input: unknown) => unknown;
146
232
  }