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
TypeScript
/**
* 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>;