UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

194 lines (193 loc) • 7.67 kB
/** * The AgentCore Code Interpreter client seam: the operation-semantic surface * `agentCoreCodeRunner` calls, and its ONE mapping onto the real SDK. * * Two things this file owns and nothing else does: * * • the COMMAND FORM — a bare `@aws-sdk/client-*` client is command-based: * `client.send(new SomeCommand(input))`, never a method on the client * (the 9.4.0 law; `BedrockAgentCoreClient.prototype.startCodeInterpreterSession` * is `undefined`, the shortcut exists only on the aggregated client); * • the DRAIN of `InvokeCodeInterpreterResponse.stream`, an event stream * whose members are `{ result }` or a modelled EXCEPTION. * * The request and response shapes below were read off a real install of * `@aws-sdk/client-bedrock-agentcore` 3.1159.0 (`InvokeCodeInterpreterRequest`, * `ToolArguments`, `InputContentBlock`, `CodeInterpreterResult`, * `ResourceContent`, `ToolResultStructuredContent`) and are pinned against * transcribed copies of those types in * `test/type-regressions/AgentCoreCodeInterpreter.sdk.test.ts`. * * Pattern: Adapter (GoF) + lazy peer-dep load — the SDK is required only when * a session first starts (or never, if you inject `_client` / `_sdk`). */ /** The operation-semantic surface `agentCoreCodeRunner` calls. Inject your own as `_client`. */ export interface AgentCoreCodeClientLike { startSession(input: { readonly codeInterpreterIdentifier: string; readonly name?: string; readonly sessionTimeoutSeconds?: number; }): Promise<{ readonly sessionId?: string; }>; /** * One `InvokeCodeInterpreter` call, its event stream already drained. * * `options.abortSignal` cancels the request where the client can; the * adapter also stops WAITING when it fires, so a client that ignores it * cannot hold a caller open. */ invoke(input: AgentCoreInvokeInput, options?: { readonly abortSignal?: AbortSignal; }): Promise<AgentCoreInvokeAnswer>; stopSession(input: { readonly codeInterpreterIdentifier: string; readonly sessionId: string; }): Promise<void>; } /** Which interpreter, and which of its sessions, one invoke goes to. */ export interface AgentCoreInvokeTarget { readonly codeInterpreterIdentifier: string; readonly sessionId: string; } /** * One file for `writeFiles` — AgentCore's `InputContentBlock`: TEXT for a * string, BYTES for a `Uint8Array`, never both, and never bytes smuggled * through text as base64. */ export type AgentCoreFileContent = { readonly path: string; readonly text: string; readonly blob?: never; } | { readonly path: string; readonly blob: Uint8Array; readonly text?: never; }; /** * One `InvokeCodeInterpreter` request: the four of the service's tool names * this adapter sends, each with exactly the arguments AgentCore takes for it. */ export type AgentCoreInvokeInput = AgentCoreInvokeTarget & ({ readonly name: 'executeCode'; readonly arguments: { readonly code: string; readonly language?: string; }; } | { readonly name: 'executeCommand'; readonly arguments: { readonly command: string; }; } | { readonly name: 'writeFiles'; readonly arguments: { readonly content: readonly AgentCoreFileContent[]; }; } | { readonly name: 'readFiles'; readonly arguments: { readonly paths: readonly string[]; }; }); /** What `invoke` reports back, already drained of its event stream — only what the service sent. */ export interface AgentCoreInvokeAnswer { readonly stdout: string; readonly stderr: string; /** The exit status the service reported; absent when no result carried one. */ readonly exitCode?: number; /** * The service's own error flag: `true` when any result was flagged, `false` * when results said `false` and none said `true`, ABSENT when no result * carried the flag at all. Absent is not `false`. */ readonly isError?: boolean; /** Every embedded resource the answer carried, in order — what `readFiles` * answers with. Absent when there were none. */ readonly resources?: readonly AgentCoreResource[]; } /** One embedded resource (AgentCore's `ResourceContent`), as the service sent it. */ export interface AgentCoreResource { readonly uri?: string; readonly mimeType?: string; readonly text?: string; readonly blob?: Uint8Array; } /** The slice of `@aws-sdk/client-bedrock-agentcore` this shim touches. */ export interface BedrockAgentCoreCodeSdkModule { readonly BedrockAgentCoreClient?: new (config: { region?: string; }) => { send(cmd: unknown, options?: { abortSignal?: AbortSignal; }): Promise<unknown>; }; readonly StartCodeInterpreterSessionCommand?: new (input: unknown) => unknown; readonly InvokeCodeInterpreterCommand?: new (input: unknown) => unknown; readonly StopCodeInterpreterSessionCommand?: new (input: unknown) => unknown; } /** * Map {@link AgentCoreCodeClientLike} onto the real SDK commands. */ export declare function createCodeClient(options: { readonly region?: string; readonly _sdk?: BedrockAgentCoreCodeSdkModule; }): AgentCoreCodeClientLike; /** One event off `InvokeCodeInterpreterResponse.stream` — the fields this adapter reads. */ export interface CodeInterpreterStreamOutputLike { readonly result?: { readonly content?: readonly { readonly type?: string; readonly text?: string; readonly name?: string; readonly resource?: AgentCoreResource; }[]; readonly structuredContent?: { readonly stdout?: string; readonly stderr?: string; readonly exitCode?: number; }; readonly isError?: boolean; }; readonly accessDeniedException?: { readonly message?: string; }; readonly conflictException?: { readonly message?: string; }; readonly internalServerException?: { readonly message?: string; }; readonly resourceNotFoundException?: { readonly message?: string; }; readonly serviceQuotaExceededException?: { readonly message?: string; }; readonly throttlingException?: { readonly message?: string; }; readonly validationException?: { readonly message?: string; }; } /** Every modelled error member of the stream union, in SDK spelling. */ export declare const STREAM_ERROR_MEMBERS: readonly ["accessDeniedException", "conflictException", "internalServerException", "resourceNotFoundException", "serviceQuotaExceededException", "throttlingException", "validationException"]; /** * Drain the event stream into one answer. * * An ERROR MEMBER RAISES. This is the honesty line for this adapter: the SDK * models seven failure shapes as ordinary members of the stream union, so an * `AccessDeniedException` arrives as a value, not a rejection. Folding it in * as empty output would report a clean run in which the code "printed * nothing" — a silent success, at the exact moment an operator most needs the * word "AccessDenied". * * Nothing is filled in that the stream did not carry: no exit status, no * error flag. And a file operation whose stream ended with no result at all * (`requireResult`) is a broken call, not an empty answer. */ export declare function drainStream(stream: AsyncIterable<CodeInterpreterStreamOutputLike> | undefined, options: { readonly requireResult: boolean; readonly signal?: AbortSignal; }): Promise<AgentCoreInvokeAnswer>;