From deef4d2d7548495a3d66505ae07280ad7b5aad7f Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Thu, 29 Oct 2026 19:05:16 -0700 Subject: [PATCH] feat(bedrock): stream Converse tool arguments --- API.md | 9 + CHANGELOG.md | 1 + README.md | 1 + examples/tsconfig.json | 2 +- package.json | 1 + packages/core/package.json | 4 + packages/core/src/bedrock.d.ts | 31 +++ packages/core/src/bedrock.js | 51 +++++ packages/core/src/bedrock.test.js | 60 ++++++ pnpm-lock.yaml | 319 ++++++++++++++++++++++++++++++ tests/bedrock-sdk.ts | 13 ++ 11 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/bedrock.d.ts create mode 100644 packages/core/src/bedrock.js create mode 100644 packages/core/src/bedrock.test.js create mode 100644 tests/bedrock-sdk.ts diff --git a/API.md b/API.md index ff66ee4..1aa893e 100644 --- a/API.md +++ b/API.md @@ -332,6 +332,7 @@ composable integration value: | `streamfold/vercel-ai` | `vercelAI` | | `streamfold/openai` | `openAI` | | `streamfold/anthropic` | `anthropic` | +| `streamfold/bedrock` | `bedrock` | | `streamfold/gemini` | `gemini` | | `streamfold/langchain` | `langchain` | | `streamfold/ag-ui` | `agUI` | @@ -371,6 +372,14 @@ boundaries, `tool-input-end` continues to complete a call immediately. `tool-call` and UI `tool-input-available` events also work without preceding deltas. Repeated completion events do not emit duplicate results. +For Amazon Bedrock, pass the `stream` returned by `ConverseStreamCommand` to +`readStructured` with `integration: bedrock`. The adapter correlates tool-use +blocks by `contentBlockIndex` and exposes `toolUseId` as the call ID. Text, +reasoning, and metadata events are ignored. Calls complete at their block stop +or EOF; malformed or truncated JSON fails and releases active parsers. Service +error events also fail the integration. AWS SDK types are accepted directly, +but the AWS SDK is not a runtime dependency of Streamfold. + ### Errors and diagnostics ```ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e00533..a501457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Add a Bedrock ConverseStream adapter for streaming tool-use arguments. - Reuse the final frozen snapshot in immutable pool completions, avoiding a second JSON value tree while keeping live final values independently parsed. - Release consumed completion payloads in managed SDK readers while preserving diff --git a/README.md b/README.md index cf150ef..addf393 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Streamfold includes isolated adapters for decoded SDK events: | `streamfold/vercel-ai` | Vercel AI SDK | | `streamfold/openai` | OpenAI Responses | | `streamfold/anthropic` | Anthropic Messages | +| `streamfold/bedrock` | Amazon Bedrock ConverseStream | | `streamfold/gemini` | Gemini Interactions | | `streamfold/langchain` | LangChain message chunks | | `streamfold/ag-ui` | AG-UI events | diff --git a/examples/tsconfig.json b/examples/tsconfig.json index fe54bd6..23923e2 100644 --- a/examples/tsconfig.json +++ b/examples/tsconfig.json @@ -5,5 +5,5 @@ "checkJs": true, "skipLibCheck": true }, - "files": ["assistant-ui.mjs", "vercel-ai.mjs", "custom.mjs", "../tests/langchain-sdk.ts"] + "files": ["assistant-ui.mjs", "vercel-ai.mjs", "custom.mjs", "../tests/langchain-sdk.ts", "../tests/bedrock-sdk.ts"] } diff --git a/package.json b/package.json index a47a2e8..41fe5b4 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "verify": "pnpm check && pnpm pack:check && pnpm bench && pnpm bench:sdk" }, "devDependencies": { + "@aws-sdk/client-bedrock-runtime": "3.1159.0", "@langchain/core": "1.3.0", "ai": "7.0.152", "assistant-stream": "0.3.42", diff --git a/packages/core/package.json b/packages/core/package.json index 03d6158..7d0fe43 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -28,6 +28,10 @@ "types": "./src/anthropic.d.ts", "default": "./src/anthropic.js" }, + "./bedrock": { + "types": "./src/bedrock.d.ts", + "default": "./src/bedrock.js" + }, "./assistant-ui": { "types": "./src/assistant-ui.d.ts", "default": "./src/assistant-ui.js" diff --git a/packages/core/src/bedrock.d.ts b/packages/core/src/bedrock.d.ts new file mode 100644 index 0000000..699ab08 --- /dev/null +++ b/packages/core/src/bedrock.d.ts @@ -0,0 +1,31 @@ +import type { + BatchEventStructuredStream, + BatchStructuredStreamIntegration, + StructuredStreamIntegrationOptions, + StructuredStreamPool, +} from "./index.js"; + +export type BedrockToolCallEvent = + | { + readonly contentBlockStart?: { + readonly contentBlockIndex?: number | undefined; + readonly start?: { + readonly toolUse?: { readonly toolUseId?: string | undefined } | undefined; + } | undefined; + } | undefined; + readonly contentBlockDelta?: { + readonly contentBlockIndex?: number | undefined; + readonly delta?: { + readonly toolUse?: { readonly input?: string | undefined } | undefined; + } | undefined; + } | undefined; + readonly contentBlockStop?: { readonly contentBlockIndex?: number | undefined } | undefined; + } + | { readonly [key: string]: unknown }; + +export const bedrock: BatchStructuredStreamIntegration; + +export function createStructuredStream( + pool?: StructuredStreamPool, + options?: StructuredStreamIntegrationOptions, +): BatchEventStructuredStream; diff --git a/packages/core/src/bedrock.js b/packages/core/src/bedrock.js new file mode 100644 index 0000000..e1a94b7 --- /dev/null +++ b/packages/core/src/bedrock.js @@ -0,0 +1,51 @@ +import { createStructuredStreamPool } from "./index.js"; +import { createIntegration } from "./internal/integration.js"; + +export const bedrock = (pool = createStructuredStreamPool(), options) => { + const idsByIndex = new Map(); + return createIntegration( + pool, + (event, calls) => { + const failure = event.internalServerException ?? event.modelStreamErrorException ?? + event.validationException ?? event.throttlingException ?? event.serviceUnavailableException; + if (failure) throw failure instanceof Error ? failure : new Error(failure.message ?? "Bedrock stream failed"); + + const start = event.contentBlockStart; + if (start?.start?.toolUse) { + if (start.contentBlockIndex === undefined) { + calls.unmatched("Tool block start has no content block index"); + return undefined; + } + const id = start.start.toolUse.toolUseId; + if (id !== undefined) idsByIndex.set(start.contentBlockIndex, id); + return calls.start(id); + } + const delta = event.contentBlockDelta; + if (delta?.delta?.toolUse) { + const id = idsByIndex.get(delta.contentBlockIndex); + if (id === undefined) { + calls.unmatched("Arguments delta has no matching tool block index"); + return undefined; + } + return calls.push(id, delta.delta.toolUse.input ?? ""); + } + const stop = event.contentBlockStop; + if (stop) { + const id = idsByIndex.get(stop.contentBlockIndex); + if (id !== undefined) { + idsByIndex.delete(stop.contentBlockIndex); + return calls.complete(id); + } + } + return undefined; + }, + (complete) => { + for (const id of idsByIndex.values()) complete(id); + idsByIndex.clear(); + }, + "bedrock", + options, + ); +}; + +export { bedrock as createStructuredStream }; diff --git a/packages/core/src/bedrock.test.js b/packages/core/src/bedrock.test.js new file mode 100644 index 0000000..6b5607d --- /dev/null +++ b/packages/core/src/bedrock.test.js @@ -0,0 +1,60 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { createStructuredStreamPool, readStructured } from "./index.js"; +import { bedrock } from "./bedrock.js"; + +const start = (index, id) => ({ contentBlockStart: { contentBlockIndex: index, start: { toolUse: { toolUseId: id, name: "weather" } } } }); +const delta = (index, input) => ({ contentBlockDelta: { contentBlockIndex: index, delta: { toolUse: { input } } } }); +const stop = (index) => ({ contentBlockStop: { contentBlockIndex: index } }); + +test("Bedrock correlates interleaved tool blocks and ignores other content", async () => { + const events = [ + { messageStart: { role: "assistant" } }, + { contentBlockDelta: { contentBlockIndex: 0, delta: { text: "Checking weather" } } }, + stop(0), start(1, "paris"), start(2, "tokyo"), + delta(1, '{"city":"Pa'), delta(2, '{"city":"Tokyo"}'), delta(1, 'ris"}'), + stop(2), stop(1), stop(1), { messageStop: { stopReason: "tool_use" } }, + { metadata: { usage: { inputTokens: 10, outputTokens: 20 } } }, + ]; + const updates = []; + for await (const update of readStructured(events, { integration: bedrock, limits: { snapshots: "immutable" } })) updates.push(update); + assert.deepEqual(updates.map(({ type, id }) => [type, id]), [ + ["start", "paris"], ["start", "tokyo"], ["update", "paris"], ["update", "tokyo"], + ["update", "paris"], ["complete", "tokyo"], ["complete", "paris"], + ]); + assert.deepEqual(updates[2].partialValue, { city: "Pa" }); + assert.deepEqual(updates.slice(-2).map(({ value }) => value), [{ city: "Tokyo" }, { city: "Paris" }]); +}); + +test("Bedrock finalizes complete pending inputs at EOF and preserves manual history", () => { + const stream = bedrock(); + stream.push(start(0, "empty")); + stream.push(delta(0, "{}")); + assert.deepEqual(stream.finish().map(({ id, value }) => ({ id, value })), [{ id: "empty", value: {} }]); + assert.equal(stream.finish().length, 1); +}); + +test("Bedrock rejects truncation, parser limits, and service errors without retaining active calls", () => { + for (const [options, input, ending, message] of [ + [{}, '{"city":', stop(0), /complete|incomplete/i], + [{ maxBytes: 4 }, '{"city":"Paris"}', stop(0), /maxBytes/], + [{}, '{"city":"Paris"}', { modelStreamErrorException: { message: "model failed" } }, /model failed/], + ]) { + const pool = createStructuredStreamPool(options); + const stream = bedrock(pool); + stream.push(start(0, "first")); + stream.push(start(1, "second")); + assert.throws(() => { stream.push(delta(0, input)); stream.push(ending); }, message); + assert.equal(pool.size, 0); + assert.throws(() => stream.finish(), message); + } +}); + +test("Bedrock diagnoses uncorrelated deltas and missing block indexes", () => { + const diagnostics = []; + const stream = bedrock(undefined, { onDiagnostic: (diagnostic) => diagnostics.push(diagnostic) }); + stream.push({ contentBlockStart: { start: { toolUse: { toolUseId: "missing-index" } } } }); + stream.push(delta(8, "{}")); + assert.deepEqual(stream.finish(), []); + assert.equal(diagnostics.filter(({ code }) => code === "UNMATCHED_TOOL_EVENT").length, 2); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7381c13..64731cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + '@aws-sdk/client-bedrock-runtime': + specifier: 3.1159.0 + version: 3.1159.0 '@langchain/core': specifier: 1.3.0 version: 1.3.0 @@ -56,6 +59,82 @@ packages: resolution: {integrity: sha512-C6ylMuAXjgqKJllp6ODIJwUltK/tm3ZmIj4V2fqENP3Y8gif2DyeJSsTcDwFrXppgEKcrBisi/BWx2tYeoeCAw==} engines: {node: '>=22'} + '@aws-sdk/client-bedrock-runtime@3.1159.0': + resolution: {integrity: sha512-Zj744tR9wNs+jjvb7C8zDBDxjJhGJSMwIHnOc9zdsDdrRirai4CtR5iQ5BMP1qfazjH6jYKCxGpZC1BOUnslKg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.978.7': + resolution: {integrity: sha512-QsYdn5xhvEBzcDC6bgKuvPv87kFtXK/3f5NqKfR+eok5AAn7RaZnkgBKncX+UW3ZMcjSELyAMATN0iqgZmvWVg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.78': + resolution: {integrity: sha512-d8V47OxkM/FKe7bVfk5Rga4aNGUaQNk3ip1PFIYhxtup9r8SuNIHLs4HfBAmHT25ZbzowluMHp833UXfFMQbhA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.80': + resolution: {integrity: sha512-OQqanXiRhnl/wBIJc3TtA7TYmnN7VO0mP95eVoHsLXtPwHz6HeccMpi7cqtnhHw+K7p6VIoAt2IK4M9Ixd9uGg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.973.23': + resolution: {integrity: sha512-pTTRK7xoi8NNbrcjVUSd9YdMTUxiWEPfk8newBQCzV+VS5STh5sDPAy3iO29fSqipqNuCpILJcD6wAawxHvG+w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.85': + resolution: {integrity: sha512-UHjnTeS+5OBFfRL+BQwCGJPJvnzjhGD6dIwncBJDa+ziyQjPUte9Q0I4BCkybGrHotnyiiluXj13bgelP14J5Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.90': + resolution: {integrity: sha512-+McgOQuAUze95AumVmoOBRp++Z8IjsZ0qOASb6+igHdKNzA0FiIf5kbTFaZ64txfd9KTBDpgvlEDGQE41lSq/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.78': + resolution: {integrity: sha512-bzB92SriflYf6LVRJcDv/a9I87tmkdmdE8hAqT1oRGKFkEH2rxxHeHZVK/4vsiRsFi44cUj0J9+bUSmqYX+26w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.973.22': + resolution: {integrity: sha512-MXUkWHgcf6G+TowL+QPvn4kJTEYKd9qHKMV6eNGXSA5lilDgGRrP3EXPHChZ3eZ7z+oprn/ZvOovLoS2WR3D8g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.84': + resolution: {integrity: sha512-6I3zYcDHt5ZM0J4gEuRgCHgN505k5haUiiPM46iIQgrHm2p70zpnssHFVYqHYfgJe3Mf+a5+nsF3BZmW4xcZNg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.39': + resolution: {integrity: sha512-V+AvQ+KFWApgm9134igy78cgoCEAFfV8K3KmlVi511vjkRWAgvy0tGUePrZsER+9EvrmUWEsrA2NBQspiGVBMQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.35': + resolution: {integrity: sha512-JAyjfoYxHCXNnCXtbTviEpb1+gxe8tsWQ3URwZIT1Bqhrm4fgDDuCA72n4HVnHMNutBhZLXnYgc97ehkhfGpMA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.60': + resolution: {integrity: sha512-IgxzXK1c0r/2yjC/qJc06OZPzQ3FSxuIc/Au6chqMb0H60k1+sHIOgjcqsxl1BxUTGQr//BU5A3niytx0IvICA==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.997.52': + resolution: {integrity: sha512-/bNl6b3VEoWQg3Z8yHt3gzYjSFoOOv7+eUglzITmGP8H7jovN8c9NoOI+6bU25+lSLvyRpJOs4n8YSaX+BcUPg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.50': + resolution: {integrity: sha512-Ob9GCZ3YnGPws696zTYW/rLFYHa9QLh6DgTCnkHb+0jhHNBgHWM8Ui2b+yrIjkfDsRVsglyrOey6tOOG/VWxMA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1159.0': + resolution: {integrity: sha512-IJvghXXcEpqTWGjrjJwxBdEecHeXp+t9FaybRf8Zf0wYW84KN1snXBsYOdfDBBx78ChwfJxH8KIHqmhNZuDLcw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.975.0': + resolution: {integrity: sha512-WQlhs6juByzWOzj5fwxOx0mPJaEqMcG/sDpl3Id61B3XhKE63xY+0QWcnG+sWR/sCfprmreyUo1lM7IKZmHMzw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/xml-builder@3.972.42': + resolution: {integrity: sha512-smX8/gNP8Kjq+CWTBMZQLQ912vOQjiWExzwzvMO+eujPB5RY8IbtF0AGdUUXHKN7KoDWK9dIcuW0WG269kiP6w==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + engines: {node: '>=18.0.0'} + '@cfworker/json-schema@4.1.1': resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} @@ -66,6 +145,30 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@smithy/core@3.37.0': + resolution: {integrity: sha512-97imTcCyiPd8k0e9+ts/Sp0W65Dn9Ti357J7M09Ov4tI8Q1JDJVFSoAJtjEVKqfHEr3Pdo2jfolqKCaaiszH0g==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.5.2': + resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.8.0': + resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.13.0': + resolution: {integrity: sha512-/GGcPoNJ2nzGytdAanpbx7mpp9Coa8LP+/Rpmbktr8YeLuIXs9B0SEz+X3AeonHdyzOIFJdKbN7jOZ+Tj+pMGw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.7.4': + resolution: {integrity: sha512-tHy0K0VtqNd5Y7Y41h0a0Lhh0L1GzC08dTWg0F7vRJWFtTENg7IZikf3wQkanYIRdb7ngoIPMTmqgUi401fEeQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.19.0': + resolution: {integrity: sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==} + engines: {node: '>=18.0.0'} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -219,6 +322,9 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bowser@2.15.0: + resolution: {integrity: sha512-xic6KSZglg/I4ymp45fdM4GWfYpBK79Fxd/TOvJktlaPgQqqDxvmGwOPZl2V0dyeS3Lj5c180bLhXF43iyAjZQ==} + bumpp@12.3.0: resolution: {integrity: sha512-YgW09sgbIGQmAD/Jk7FEGP0tm0PeDz+Zgk+IAk+MOHhb/98pj/l3CgkxSjd7C1O99JPxTNwS+bPOTNaHuNh6lQ==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} @@ -339,6 +445,9 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} @@ -388,6 +497,179 @@ snapshots: dependencies: json-schema: 0.4.0 + '@aws-sdk/client-bedrock-runtime@3.1159.0': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/credential-provider-node': 3.972.90 + '@aws-sdk/eventstream-handler-node': 3.972.39 + '@aws-sdk/middleware-eventstream': 3.972.35 + '@aws-sdk/middleware-websocket': 3.972.60 + '@aws-sdk/token-providers': 3.1159.0 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.13.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/core@3.978.7': + dependencies: + '@aws-sdk/types': 3.975.0 + '@aws-sdk/xml-builder': 3.972.42 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.37.0 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + bowser: 2.15.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.78': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.80': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.13.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.973.23': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/credential-provider-env': 3.972.78 + '@aws-sdk/credential-provider-http': 3.972.80 + '@aws-sdk/credential-provider-login': 3.972.85 + '@aws-sdk/credential-provider-process': 3.972.78 + '@aws-sdk/credential-provider-sso': 3.973.22 + '@aws-sdk/credential-provider-web-identity': 3.972.84 + '@aws-sdk/nested-clients': 3.997.52 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.85': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/nested-clients': 3.997.52 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.90': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.78 + '@aws-sdk/credential-provider-http': 3.972.80 + '@aws-sdk/credential-provider-ini': 3.973.23 + '@aws-sdk/credential-provider-process': 3.972.78 + '@aws-sdk/credential-provider-sso': 3.973.22 + '@aws-sdk/credential-provider-web-identity': 3.972.84 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.78': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.973.22': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/nested-clients': 3.997.52 + '@aws-sdk/token-providers': 3.1159.0 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-web-identity@3.972.84': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/nested-clients': 3.997.52 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/eventstream-handler-node@3.972.39': + dependencies: + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.35': + dependencies: + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.60': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.52': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/signature-v4-multi-region': 3.996.50 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.13.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.50': + dependencies: + '@aws-sdk/types': 3.975.0 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1159.0': + dependencies: + '@aws-sdk/core': 3.978.7 + '@aws-sdk/nested-clients': 3.997.52 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/types@3.975.0': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.42': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.3.0': {} + '@cfworker/json-schema@4.1.1': {} '@langchain/core@1.3.0': @@ -410,6 +692,39 @@ snapshots: dependencies: quansync: 1.0.0 + '@smithy/core@3.37.0': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.5.2': + dependencies: + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.8.0': + dependencies: + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.13.0': + dependencies: + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.7.4': + dependencies: + '@smithy/core': 3.37.0 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/types@4.19.0': + dependencies: + tslib: 2.8.1 + '@standard-schema/spec@1.1.0': {} '@typescript/typescript-aix-ppc64@7.0.2': @@ -493,6 +808,8 @@ snapshots: base64-js@1.5.1: {} + bowser@2.15.0: {} + bumpp@12.3.0: dependencies: args-tokenizer: 0.3.0 @@ -573,6 +890,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.7) picomatch: 4.0.7 + tslib@2.8.1: {} + typescript@7.0.2: optionalDependencies: '@typescript/typescript-aix-ppc64': 7.0.2 diff --git a/tests/bedrock-sdk.ts b/tests/bedrock-sdk.ts new file mode 100644 index 0000000..7ba4fc9 --- /dev/null +++ b/tests/bedrock-sdk.ts @@ -0,0 +1,13 @@ +import { BedrockRuntimeClient, ConverseStreamCommand } from "@aws-sdk/client-bedrock-runtime"; +import { readStructured } from "streamfold"; +import { bedrock } from "streamfold/bedrock"; + +const client = new BedrockRuntimeClient({ region: "us-east-1" }); +const response = await client.send(new ConverseStreamCommand({ + modelId: "fixture", messages: [{ role: "user", content: [{ text: "Weather in Paris?" }] }], +})); +if (response.stream) { + readStructured(response.stream, { integration: bedrock }); + const stream = bedrock(); + for await (const event of response.stream) stream.pushAll(event); +}