/** * agentCoreCodeRunner — AWS Bedrock AgentCore Code Interpreter behind the * {@link CodeRunner} port (peer-dep `@aws-sdk/client-bedrock-agentcore`). * * import { agentCoreCodeRunner } from 'agentfootprint/providers'; * const runner = agentCoreCodeRunner({ region: 'us-east-1', identifier: 'aws.codeinterpreter.v1' }); * * A REAL sandbox, which is the point: `localCodeRunner` gives you process * isolation on your own machine and says so; this gives you a managed, * network-and-filesystem-isolated environment, and the tool code is identical * across the swap. * * ── The three operations, verified against the SDK ────────────────────────── * Pinned in `test/adapters/aws/awsCommandPin.ts`, and verified against a real * install of `@aws-sdk/client-bedrock-agentcore` 3.1108.0: * * • `StartCodeInterpreterSessionCommand` * in `{ codeInterpreterIdentifier, name?, sessionTimeoutSeconds? }` * out `{ codeInterpreterIdentifier, sessionId, createdAt }` * • `InvokeCodeInterpreterCommand` * in `{ codeInterpreterIdentifier, sessionId, name: 'executeCode', * arguments: { code, language } }` * out `{ sessionId, stream }` — an **event stream**, not a body (below) * • `StopCodeInterpreterSessionCommand` * in `{ codeInterpreterIdentifier, sessionId }` ← the session ID, not a URI * out `{ codeInterpreterIdentifier, sessionId, lastUpdatedAt }` * * **`Invoke` answers with an `AsyncIterable`.** `InvokeCodeInterpreterResponse` * is `{ sessionId?, stream?: AsyncIterable }`, and * every member of that union is either `{ result }` or a modelled EXCEPTION — * `accessDeniedException`, `throttlingException`, `validationException`, and * four more. An adapter that read a `body` field would find `undefined` and * report an empty success on every call, and one that iterated only for * `result` would treat an AccessDenied as "the code printed nothing." So this * drains the stream, raises the exception members BY NAME, and folds the * result members into one `CodeResult`. * * The payload lands twice: `structuredContent` carries `{ stdout, stderr, * exitCode, executionTime }` and `content[]` carries typed blocks. The * structured half is preferred because it is typed; the text blocks are the * fallback for a response that only filled the other one. * * ── How this talks to the SDK (the 9.4.0 law) ─────────────────────────────── * Through `client.send(new SomeCommand(input))`, never a method on the client. * A bare `@aws-sdk/client-*` **Client is command-based**: its prototype carries * `send` and `destroy` and nothing else — verified again for this adapter * (`BedrockAgentCoreClient.prototype.startCodeInterpreterSession` is * `undefined`; the shortcut exists only on the aggregated `BedrockAgentCore`). * Three adapters have shipped that bug in this package. * * ── Credentials ───────────────────────────────────────────────────────────── * Standard AWS credential resolution (the SDK's own chain). A tool holding a * long-lived session must NOT cache a `Credential` object from `ctx.credential` * past the call that produced it — a session outliving a run outlives its * token. Re-resolve per execute through `ctx.credentials`. * * Pattern: Adapter (GoF) + lazy peer-dep load — the SDK is required only when * `start()` first runs (or never, if you inject `_client` / `_sdk`). */ import type { CodeRunner } from '../types.js'; export interface AgentCoreCodeRunnerOptions { readonly region?: string; /** * The code-interpreter resource to run in — AWS's built-in * (`'aws.codeinterpreter.v1'`) or your own custom interpreter's identifier. */ readonly identifier: string; /** * Session TTL in seconds. AgentCore terminates the session past it regardless * of activity. Service default 900 (15 min); max 28,800 (8 h). * * **This is why "already gone" is a normal outcome, not an incident**: the * far side reaps on its own schedule, so a `Stop` may arrive after AWS has * already collected the session. `stop()` treats that as done. */ readonly sessionTimeoutSeconds?: number; /** Default language when a call does not name one. `'python'` (the service * accepts `javascript`, `python`, `typescript`). */ readonly language?: string; /** Per-stream output ceiling, in characters. Default 8000; anything cut is * REPORTED on `CodeResult.truncated`, never dropped quietly. */ readonly maxOutputChars?: number; /** Stable id (default `'agentcore-code-runner'`). Rides the session events. */ readonly id?: string; /** Test seam — inject a client implementing {@link AgentCoreCodeClientLike}. * Bypasses the SDK entirely; the field mapping below is then yours. */ readonly _client?: AgentCoreCodeClientLike; /** @internal Test injection — the AWS SDK module, to exercise the real shim * (`send(new Command(...))`) with a fake SDK. */ readonly _sdk?: BedrockAgentCoreCodeSdkModule; } /** The operation-semantic surface this adapter calls. */ export interface AgentCoreCodeClientLike { startSession(input: { readonly codeInterpreterIdentifier: string; readonly name?: string; readonly sessionTimeoutSeconds?: number; }): Promise<{ readonly sessionId?: string; }>; invoke(input: { readonly codeInterpreterIdentifier: string; readonly sessionId: string; readonly name: string; readonly arguments: { readonly code: string; readonly language?: string; }; }): Promise; stopSession(input: { readonly codeInterpreterIdentifier: string; readonly sessionId: string; }): Promise; } /** What `invoke` reports back, already drained of its event stream. */ export interface AgentCoreInvokeAnswer { readonly stdout: string; readonly stderr: string; readonly exitCode?: number; readonly isError?: boolean; } /** The slice of `@aws-sdk/client-bedrock-agentcore` this shim touches. */ export interface BedrockAgentCoreCodeSdkModule { readonly BedrockAgentCoreClient?: new (config: { region?: string; }) => { send(cmd: unknown): Promise; }; readonly StartCodeInterpreterSessionCommand?: new (input: unknown) => unknown; readonly InvokeCodeInterpreterCommand?: new (input: unknown) => unknown; readonly StopCodeInterpreterSessionCommand?: new (input: unknown) => unknown; } export declare function agentCoreCodeRunner(options: AgentCoreCodeRunnerOptions): CodeRunner;