@openclaw/amazon-bedrock-provider 2026.7.2-beta.1 → 2026.7.2-beta.3
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.
- package/dist/control-plane.js +29 -0
- package/dist/discovery.js +43 -60
- package/dist/embedding-provider.js +2 -1
- package/dist/register.sync.runtime.js +24 -8
- package/dist/stream.runtime.js +46 -19
- package/npm-shrinkwrap.json +2 -2
- package/package.json +4 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
|
|
2
|
+
//#region extensions/amazon-bedrock/control-plane.ts
|
|
3
|
+
const BEDROCK_CONTROL_PLANE_REQUEST_TIMEOUT_MS = 3e4;
|
|
4
|
+
async function loadBedrockControlPlaneSdk() {
|
|
5
|
+
const { BedrockClient, GetInferenceProfileCommand, ListFoundationModelsCommand, ListInferenceProfilesCommand } = await import("@aws-sdk/client-bedrock");
|
|
6
|
+
return {
|
|
7
|
+
createClient: (region) => new BedrockClient(region ? { region } : {}),
|
|
8
|
+
createGetInferenceProfileCommand: (input) => new GetInferenceProfileCommand(input),
|
|
9
|
+
createListFoundationModelsCommand: () => new ListFoundationModelsCommand({}),
|
|
10
|
+
createListInferenceProfilesCommand: (input) => new ListInferenceProfilesCommand(input)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
async function runBedrockControlPlaneRequest(params) {
|
|
14
|
+
const { signal, cleanup } = buildTimeoutAbortSignal({
|
|
15
|
+
timeoutMs: BEDROCK_CONTROL_PLANE_REQUEST_TIMEOUT_MS,
|
|
16
|
+
signal: params.signal,
|
|
17
|
+
operation: params.operation
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
signal?.throwIfAborted();
|
|
21
|
+
const response = await params.send({ abortSignal: signal });
|
|
22
|
+
signal?.throwIfAborted();
|
|
23
|
+
return response;
|
|
24
|
+
} finally {
|
|
25
|
+
cleanup();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { loadBedrockControlPlaneSdk, runBedrockControlPlaneRequest };
|
package/dist/discovery.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { refreshAwsSharedConfigCacheForBedrock } from "./aws-credential-refresh.js";
|
|
2
|
+
import { loadBedrockControlPlaneSdk, runBedrockControlPlaneRequest } from "./control-plane.js";
|
|
2
3
|
import { resolveBedrockConfigApiKey } from "./discovery-shared.js";
|
|
3
4
|
import { resolveBedrockNativeThinkingLevelMap } from "./thinking-policy.js";
|
|
4
5
|
import { resolveClaudeFable5ModelIdentity, resolveClaudeModelIdentity, resolveClaudeMythos5ModelIdentity, resolveClaudeSonnet5ModelIdentity, supportsClaudeAdaptiveThinking } from "openclaw/plugin-sdk/provider-model-shared";
|
|
@@ -35,9 +36,7 @@ const KNOWN_CONTEXT_WINDOWS = {
|
|
|
35
36
|
"anthropic.claude-opus-4-8": 1e6,
|
|
36
37
|
"anthropic.claude-opus-4-7": 1e6,
|
|
37
38
|
"anthropic.claude-opus-4-6-v1": 1e6,
|
|
38
|
-
"anthropic.claude-opus-4-6-v1:0": 1e6,
|
|
39
39
|
"anthropic.claude-sonnet-4-6": 1e6,
|
|
40
|
-
"anthropic.claude-sonnet-4-6-v1:0": 1e6,
|
|
41
40
|
"anthropic.claude-sonnet-4-5-20250929-v1:0": 2e5,
|
|
42
41
|
"anthropic.claude-sonnet-4-20250514-v1:0": 2e5,
|
|
43
42
|
"anthropic.claude-opus-4-5-20251101-v1:0": 2e5,
|
|
@@ -119,33 +118,6 @@ const DEFAULT_COST = {
|
|
|
119
118
|
cacheRead: 0,
|
|
120
119
|
cacheWrite: 0
|
|
121
120
|
};
|
|
122
|
-
async function loadBedrockDiscoverySdk() {
|
|
123
|
-
const { BedrockClient, ListFoundationModelsCommand, ListInferenceProfilesCommand } = await import("@aws-sdk/client-bedrock");
|
|
124
|
-
return {
|
|
125
|
-
createClient: (region) => new BedrockClient({ region }),
|
|
126
|
-
createListFoundationModelsCommand: () => new ListFoundationModelsCommand({}),
|
|
127
|
-
createListInferenceProfilesCommand: (input) => new ListInferenceProfilesCommand(input)
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function createInjectedClientDiscoverySdk() {
|
|
131
|
-
class ListFoundationModelsCommand {
|
|
132
|
-
constructor(input = {}) {
|
|
133
|
-
this.input = input;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
class ListInferenceProfilesCommand {
|
|
137
|
-
constructor(input = {}) {
|
|
138
|
-
this.input = input;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return {
|
|
142
|
-
createClient() {
|
|
143
|
-
throw new Error("clientFactory is required for injected Bedrock discovery commands");
|
|
144
|
-
},
|
|
145
|
-
createListFoundationModelsCommand: () => new ListFoundationModelsCommand({}),
|
|
146
|
-
createListInferenceProfilesCommand: (input) => new ListInferenceProfilesCommand(input)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
121
|
const discoveryCache = /* @__PURE__ */ new Map();
|
|
150
122
|
let hasLoggedBedrockError = false;
|
|
151
123
|
function normalizeProviderFilter(filter) {
|
|
@@ -248,7 +220,11 @@ async function fetchInferenceProfileSummaries(client, createListInferenceProfile
|
|
|
248
220
|
const profiles = [];
|
|
249
221
|
let nextToken;
|
|
250
222
|
do {
|
|
251
|
-
const
|
|
223
|
+
const command = createListInferenceProfilesCommand({ nextToken });
|
|
224
|
+
const response = await runBedrockControlPlaneRequest({
|
|
225
|
+
operation: "Bedrock ListInferenceProfiles",
|
|
226
|
+
send: (options) => client.send(command, options)
|
|
227
|
+
});
|
|
252
228
|
for (const summary of response.inferenceProfileSummaries ?? []) profiles.push(summary);
|
|
253
229
|
nextToken = response.nextToken;
|
|
254
230
|
} while (nextToken);
|
|
@@ -328,44 +304,51 @@ async function discoverBedrockModels(params) {
|
|
|
328
304
|
}
|
|
329
305
|
if (cached) discoveryCache.delete(cacheKey);
|
|
330
306
|
}
|
|
331
|
-
const sdk =
|
|
307
|
+
const sdk = await loadBedrockControlPlaneSdk();
|
|
332
308
|
const clientFactory = params.clientFactory ?? ((region) => sdk.createClient(region));
|
|
333
309
|
if (!params.clientFactory) await refreshAwsSharedConfigCacheForBedrock();
|
|
334
310
|
const client = clientFactory(params.region);
|
|
335
311
|
const discoveryPromise = (async () => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const
|
|
312
|
+
try {
|
|
313
|
+
const foundationCommand = sdk.createListFoundationModelsCommand();
|
|
314
|
+
const [foundationResponse, profileSummaries] = await Promise.all([runBedrockControlPlaneRequest({
|
|
315
|
+
operation: "Bedrock ListFoundationModels",
|
|
316
|
+
send: (options) => client.send(foundationCommand, options)
|
|
317
|
+
}), fetchInferenceProfileSummaries(client, (input) => sdk.createListInferenceProfilesCommand(input))]);
|
|
318
|
+
const discovered = [];
|
|
319
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
320
|
+
const foundationModels = /* @__PURE__ */ new Map();
|
|
321
|
+
for (const summary of foundationResponse.modelSummaries ?? []) {
|
|
322
|
+
if (!shouldIncludeSummary(summary, providerFilter)) continue;
|
|
323
|
+
const def = toModelDefinition(summary, {
|
|
324
|
+
contextWindow: defaultContextWindow,
|
|
325
|
+
maxTokens: defaultMaxTokens
|
|
326
|
+
});
|
|
327
|
+
discovered.push(def);
|
|
328
|
+
const normalizedId = normalizeLowercaseStringOrEmpty(def.id);
|
|
329
|
+
seenIds.add(normalizedId);
|
|
330
|
+
foundationModels.set(normalizedId, def);
|
|
331
|
+
}
|
|
332
|
+
const inferenceProfiles = resolveInferenceProfiles(profileSummaries, {
|
|
344
333
|
contextWindow: defaultContextWindow,
|
|
345
334
|
maxTokens: defaultMaxTokens
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
contextWindow: defaultContextWindow,
|
|
354
|
-
maxTokens: defaultMaxTokens
|
|
355
|
-
}, providerFilter, foundationModels);
|
|
356
|
-
for (const profile of inferenceProfiles) {
|
|
357
|
-
const normalizedId = normalizeLowercaseStringOrEmpty(profile.id);
|
|
358
|
-
if (!seenIds.has(normalizedId)) {
|
|
359
|
-
discovered.push(profile);
|
|
360
|
-
seenIds.add(normalizedId);
|
|
335
|
+
}, providerFilter, foundationModels);
|
|
336
|
+
for (const profile of inferenceProfiles) {
|
|
337
|
+
const normalizedId = normalizeLowercaseStringOrEmpty(profile.id);
|
|
338
|
+
if (!seenIds.has(normalizedId)) {
|
|
339
|
+
discovered.push(profile);
|
|
340
|
+
seenIds.add(normalizedId);
|
|
341
|
+
}
|
|
361
342
|
}
|
|
343
|
+
return discovered.toSorted((a, b) => {
|
|
344
|
+
const aGlobal = a.id.startsWith("global.") ? 0 : 1;
|
|
345
|
+
const bGlobal = b.id.startsWith("global.") ? 0 : 1;
|
|
346
|
+
if (aGlobal !== bGlobal) return aGlobal - bGlobal;
|
|
347
|
+
return a.name.localeCompare(b.name);
|
|
348
|
+
});
|
|
349
|
+
} finally {
|
|
350
|
+
client.destroy();
|
|
362
351
|
}
|
|
363
|
-
return discovered.toSorted((a, b) => {
|
|
364
|
-
const aGlobal = a.id.startsWith("global.") ? 0 : 1;
|
|
365
|
-
const bGlobal = b.id.startsWith("global.") ? 0 : 1;
|
|
366
|
-
if (aGlobal !== bGlobal) return aGlobal - bGlobal;
|
|
367
|
-
return a.name.localeCompare(b.name);
|
|
368
|
-
});
|
|
369
352
|
})();
|
|
370
353
|
if (refreshIntervalSeconds > 0) {
|
|
371
354
|
const expiresAt = resolveExpiresAtMsFromDurationSeconds(refreshIntervalSeconds, { nowMs: now });
|
|
@@ -216,6 +216,7 @@ const testing = {
|
|
|
216
216
|
parseSingle,
|
|
217
217
|
stripInferenceProfilePrefix
|
|
218
218
|
};
|
|
219
|
+
if (process.env.VITEST === "true") Reflect.set(globalThis, Symbol.for("openclaw.amazonBedrockEmbeddingTestApi"), testing);
|
|
219
220
|
async function createBedrockEmbeddingProvider(options) {
|
|
220
221
|
const client = resolveBedrockEmbeddingClient(options);
|
|
221
222
|
const { BedrockRuntimeClient, InvokeModelCommand } = await loadSdk();
|
|
@@ -304,4 +305,4 @@ async function hasAwsCredentials(env = process.env, loadCredentialProvider = loa
|
|
|
304
305
|
}
|
|
305
306
|
}
|
|
306
307
|
//#endregion
|
|
307
|
-
export { DEFAULT_BEDROCK_EMBEDDING_MODEL,
|
|
308
|
+
export { DEFAULT_BEDROCK_EMBEDDING_MODEL, createBedrockEmbeddingProvider, hasAwsCredentials };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { refreshAwsSharedConfigCacheForBedrock } from "./aws-credential-refresh.js";
|
|
2
2
|
import { supportsBedrockPromptCaching } from "./bedrock-options.js";
|
|
3
|
+
import { loadBedrockControlPlaneSdk, runBedrockControlPlaneRequest } from "./control-plane.js";
|
|
3
4
|
import { mergeImplicitBedrockProvider, resolveBedrockConfigApiKey } from "./discovery-shared.js";
|
|
4
5
|
import { bedrockMemoryEmbeddingProviderAdapter } from "./memory-embedding-adapter.js";
|
|
5
6
|
import { isLatestAdaptiveBedrockModelRef, isOpus47OrNewerBedrockModelRef, resolveBedrockClaudeThinkingProfile, resolveBedrockNativeThinkingLevelMap, supportsBedrockNativeMaxEffort } from "./thinking-policy.js";
|
|
6
7
|
import { streamBedrock, streamSimpleBedrock } from "./stream.runtime.js";
|
|
7
8
|
import { registerApiProvider, streamSimple } from "openclaw/plugin-sdk/llm";
|
|
8
9
|
import { resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
9
|
-
import {
|
|
10
|
+
import { buildProviderReplayFamilyHooks, normalizeProviderId, resolveClaudeFable5ModelIdentity, resolveClaudeModelIdentity, resolveClaudeMythos5ModelIdentity, resolveClaudeSonnet5ModelIdentity } from "openclaw/plugin-sdk/provider-model-shared";
|
|
10
11
|
import { streamWithPayloadPatch } from "openclaw/plugin-sdk/provider-stream-shared";
|
|
11
12
|
//#region extensions/amazon-bedrock/register.sync.runtime.ts
|
|
12
13
|
function normalizeBedrockResolvedModel({ modelId, model }) {
|
|
@@ -129,14 +130,23 @@ function resolvedModelSupportsCaching(modelArn) {
|
|
|
129
130
|
return supportsBedrockPromptCaching(modelArn);
|
|
130
131
|
}
|
|
131
132
|
const appProfileTraitsCache = /* @__PURE__ */ new Map();
|
|
132
|
-
async function resolveAppProfileTraits(modelId, fallbackRegion) {
|
|
133
|
+
async function resolveAppProfileTraits(modelId, fallbackRegion, signal) {
|
|
133
134
|
const cached = appProfileTraitsCache.get(modelId);
|
|
134
135
|
if (cached) return cached;
|
|
136
|
+
let client;
|
|
135
137
|
try {
|
|
138
|
+
signal?.throwIfAborted();
|
|
136
139
|
const region = extractRegionFromArn(modelId) ?? fallbackRegion;
|
|
137
|
-
await
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
+
const sdk = await loadBedrockControlPlaneSdk();
|
|
141
|
+
signal?.throwIfAborted();
|
|
142
|
+
const controlPlaneClient = sdk.createClient(region);
|
|
143
|
+
client = controlPlaneClient;
|
|
144
|
+
const command = sdk.createGetInferenceProfileCommand({ inferenceProfileIdentifier: modelId });
|
|
145
|
+
const models = (await runBedrockControlPlaneRequest({
|
|
146
|
+
operation: "Bedrock GetInferenceProfile",
|
|
147
|
+
signal,
|
|
148
|
+
send: (options) => controlPlaneClient.send(command, options)
|
|
149
|
+
})).models ?? [];
|
|
140
150
|
const modelArns = models.map((model) => model.modelArn ?? "");
|
|
141
151
|
const traits = {
|
|
142
152
|
cacheEligible: models.length > 0 && modelArns.every((modelArn) => resolvedModelSupportsCaching(modelArn)),
|
|
@@ -145,10 +155,13 @@ async function resolveAppProfileTraits(modelId, fallbackRegion) {
|
|
|
145
155
|
appProfileTraitsCache.set(modelId, traits);
|
|
146
156
|
return traits;
|
|
147
157
|
} catch {
|
|
158
|
+
signal?.throwIfAborted();
|
|
148
159
|
return {
|
|
149
160
|
cacheEligible: isAnthropicBedrockModel(modelId),
|
|
150
161
|
omitTemperature: isOpus47OrNewerBedrockModelRef(modelId)
|
|
151
162
|
};
|
|
163
|
+
} finally {
|
|
164
|
+
client?.destroy();
|
|
152
165
|
}
|
|
153
166
|
}
|
|
154
167
|
function hasCachePoint(blocks) {
|
|
@@ -196,7 +209,7 @@ function registerAmazonBedrockPlugin(api) {
|
|
|
196
209
|
/ModelStreamErrorException.*(?:Input is too long|too many input tokens)/i
|
|
197
210
|
];
|
|
198
211
|
const deprecatedTemperatureValidationRe = /ValidationException[\s\S]*(?:invalid_request_error[\s\S]*)?temperature[\s\S]*deprecated|ValidationException[\s\S]*deprecated[\s\S]*temperature/i;
|
|
199
|
-
const anthropicByModelReplayHooks =
|
|
212
|
+
const anthropicByModelReplayHooks = buildProviderReplayFamilyHooks({ family: "anthropic-by-model" });
|
|
200
213
|
const startupPluginConfig = api.pluginConfig ?? {};
|
|
201
214
|
registerApiProvider({
|
|
202
215
|
api: "bedrock-converse-stream",
|
|
@@ -233,7 +246,10 @@ function registerAmazonBedrockPlugin(api) {
|
|
|
233
246
|
return {
|
|
234
247
|
...options,
|
|
235
248
|
onPayload: async (payload, payloadModel) => {
|
|
249
|
+
const signal = options.signal;
|
|
250
|
+
signal?.throwIfAborted();
|
|
236
251
|
await refreshAwsSharedConfigCacheForBedrock();
|
|
252
|
+
signal?.throwIfAborted();
|
|
237
253
|
return originalOnPayload?.(payload, payloadModel);
|
|
238
254
|
}
|
|
239
255
|
};
|
|
@@ -347,7 +363,7 @@ function registerAmazonBedrockPlugin(api) {
|
|
|
347
363
|
if (shouldPatchMaxThinking) patchMaxThinkingEffort(payloadRecord);
|
|
348
364
|
if (shouldOmitTemperature) omitUnsupportedClaudePayloadTemperature(payloadRecord);
|
|
349
365
|
else if (mayNeedTemperatureTrait) {
|
|
350
|
-
if ((await resolveAppProfileTraits(modelId, region)).omitTemperature) omitUnsupportedClaudePayloadTemperature(payloadRecord);
|
|
366
|
+
if ((await resolveAppProfileTraits(modelId, region, merged.signal)).omitTemperature) omitUnsupportedClaudePayloadTemperature(payloadRecord);
|
|
351
367
|
}
|
|
352
368
|
}
|
|
353
369
|
return originalOnPayload?.(payload, payloadModel);
|
|
@@ -357,7 +373,7 @@ function registerAmazonBedrockPlugin(api) {
|
|
|
357
373
|
return underlying(streamModel, context, withAwsCredentialRefreshOnPayload({
|
|
358
374
|
...merged,
|
|
359
375
|
onPayload: async (payload, payloadModel) => {
|
|
360
|
-
const traits = await resolveAppProfileTraits(modelId, region);
|
|
376
|
+
const traits = await resolveAppProfileTraits(modelId, region, merged.signal);
|
|
361
377
|
if (payload && typeof payload === "object") {
|
|
362
378
|
const payloadRecord = payload;
|
|
363
379
|
if (traits.cacheEligible) injectBedrockCachePoints(payloadRecord, cacheRetention);
|
package/dist/stream.runtime.js
CHANGED
|
@@ -6,6 +6,7 @@ import { applyAnthropicRefusal, createDeferredEventBuffer, notifyLlmRequestActiv
|
|
|
6
6
|
import { BedrockRuntimeClient, BedrockRuntimeServiceException, CachePointType, CacheTTL, ConversationRole, ConverseStreamCommand, ImageFormat, StopReason, ToolResultStatus } from "@aws-sdk/client-bedrock-runtime";
|
|
7
7
|
import { NodeHttpHandler } from "@smithy/node-http-handler";
|
|
8
8
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
9
|
+
import { describeToolResultMediaPlaceholder } from "openclaw/plugin-sdk/provider-transport-runtime";
|
|
9
10
|
//#region extensions/amazon-bedrock/stream.runtime.ts
|
|
10
11
|
/**
|
|
11
12
|
* Amazon Bedrock Converse streaming runtime. It maps OpenClaw messages/tools,
|
|
@@ -71,14 +72,15 @@ const streamBedrock = (model, context, options = {}) => {
|
|
|
71
72
|
const eventSink = refusalBuffer ?? stream;
|
|
72
73
|
const config = { profile: options.profile };
|
|
73
74
|
const configuredRegion = getConfiguredBedrockRegion(options);
|
|
75
|
+
const requestRegion = options.region || getBedrockModelArnRegion(model.id) || configuredRegion;
|
|
74
76
|
const hasConfiguredProfile = hasConfiguredBedrockProfile(options);
|
|
75
77
|
const endpointRegion = getStandardBedrockEndpointRegion(model.baseUrl);
|
|
76
|
-
const useExplicitEndpoint = shouldUseExplicitBedrockEndpoint(model.baseUrl,
|
|
78
|
+
const useExplicitEndpoint = shouldUseExplicitBedrockEndpoint(model.baseUrl, requestRegion, hasConfiguredProfile);
|
|
77
79
|
if (useExplicitEndpoint) config.endpoint = model.baseUrl;
|
|
78
80
|
const bearerToken = options.bearerToken || process.env.AWS_BEARER_TOKEN_BEDROCK || void 0;
|
|
79
81
|
const useBearerToken = bearerToken !== void 0 && process.env.AWS_BEDROCK_SKIP_AUTH !== "1";
|
|
80
82
|
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
|
81
|
-
if (
|
|
83
|
+
if (requestRegion) config.region = requestRegion;
|
|
82
84
|
else if (endpointRegion && useExplicitEndpoint) config.region = endpointRegion;
|
|
83
85
|
else if (!hasConfiguredProfile) config.region = "us-east-1";
|
|
84
86
|
if (process.env.AWS_BEDROCK_SKIP_AUTH === "1") config.credentials = {
|
|
@@ -88,7 +90,7 @@ const streamBedrock = (model, context, options = {}) => {
|
|
|
88
90
|
const proxyAgents = createHttpProxyAgentsForTarget(model.baseUrl);
|
|
89
91
|
if (proxyAgents) config.requestHandler = new NodeHttpHandler(proxyAgents);
|
|
90
92
|
else if (process.env.AWS_BEDROCK_FORCE_HTTP1 === "1") config.requestHandler = new NodeHttpHandler();
|
|
91
|
-
} else config.region =
|
|
93
|
+
} else config.region = requestRegion || (endpointRegion && useExplicitEndpoint ? endpointRegion : void 0) || "us-east-1";
|
|
92
94
|
if (useBearerToken) {
|
|
93
95
|
config.token = { token: bearerToken };
|
|
94
96
|
config.authSchemePreference = ["httpBearerAuth"];
|
|
@@ -137,7 +139,11 @@ const streamBedrock = (model, context, options = {}) => {
|
|
|
137
139
|
else if (item.messageStop) {
|
|
138
140
|
sawMessageStop = true;
|
|
139
141
|
if (item.messageStop.stopReason === "refusal") applyAnthropicRefusal(output, readBedrockStopDetails(item.messageStop.additionalModelResponseFields), model.provider);
|
|
140
|
-
else
|
|
142
|
+
else {
|
|
143
|
+
const mappedStop = mapStopReason(item.messageStop.stopReason);
|
|
144
|
+
output.stopReason = mappedStop.stopReason;
|
|
145
|
+
if (mappedStop.errorMessage) output.errorMessage = mappedStop.errorMessage;
|
|
146
|
+
}
|
|
141
147
|
} else if (item.metadata) handleMetadata(item.metadata, model, output);
|
|
142
148
|
else if (item.internalServerException) throw item.internalServerException;
|
|
143
149
|
else if (item.modelStreamErrorException) throw item.modelStreamErrorException;
|
|
@@ -474,6 +480,21 @@ function normalizeToolCallId(id) {
|
|
|
474
480
|
const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
475
481
|
return sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
|
|
476
482
|
}
|
|
483
|
+
function createBedrockToolResult(message) {
|
|
484
|
+
const content = [];
|
|
485
|
+
for (const block of message.content) {
|
|
486
|
+
if (block.type === "text") {
|
|
487
|
+
content.push({ text: sanitizeSurrogates(block.text) });
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
if (describeToolResultMediaPlaceholder([block])) content.push({ image: createImageBlock(block.mimeType, block.data) });
|
|
491
|
+
}
|
|
492
|
+
return { toolResult: {
|
|
493
|
+
toolUseId: message.toolCallId,
|
|
494
|
+
content: content.length > 0 ? content : [{ text: "(no output)" }],
|
|
495
|
+
status: message.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS
|
|
496
|
+
} };
|
|
497
|
+
}
|
|
477
498
|
function convertMessages(context, model, cacheRetention) {
|
|
478
499
|
const result = [];
|
|
479
500
|
const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
|
|
@@ -541,20 +562,12 @@ function convertMessages(context, model, cacheRetention) {
|
|
|
541
562
|
}
|
|
542
563
|
case "toolResult": {
|
|
543
564
|
const toolResults = [];
|
|
544
|
-
toolResults.push(
|
|
545
|
-
toolUseId: m.toolCallId,
|
|
546
|
-
content: m.content.map((c) => c.type === "image" ? { image: createImageBlock(c.mimeType, c.data) } : { text: sanitizeSurrogates(c.text) }),
|
|
547
|
-
status: m.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS
|
|
548
|
-
} });
|
|
565
|
+
toolResults.push(createBedrockToolResult(m));
|
|
549
566
|
let j = i + 1;
|
|
550
567
|
while (true) {
|
|
551
568
|
const nextMsg = transformedMessages.at(j);
|
|
552
569
|
if (nextMsg?.role !== "toolResult") break;
|
|
553
|
-
toolResults.push(
|
|
554
|
-
toolUseId: nextMsg.toolCallId,
|
|
555
|
-
content: nextMsg.content.map((c) => c.type === "image" ? { image: createImageBlock(c.mimeType, c.data) } : { text: sanitizeSurrogates(c.text) }),
|
|
556
|
-
status: nextMsg.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS
|
|
557
|
-
} });
|
|
570
|
+
toolResults.push(createBedrockToolResult(nextMsg));
|
|
558
571
|
j++;
|
|
559
572
|
}
|
|
560
573
|
i = j - 1;
|
|
@@ -601,13 +614,26 @@ function convertToolConfig(tools, toolChoice) {
|
|
|
601
614
|
function mapStopReason(reason) {
|
|
602
615
|
switch (reason) {
|
|
603
616
|
case StopReason.END_TURN:
|
|
604
|
-
case StopReason.STOP_SEQUENCE: return "stop";
|
|
617
|
+
case StopReason.STOP_SEQUENCE: return { stopReason: "stop" };
|
|
605
618
|
case StopReason.MAX_TOKENS:
|
|
606
|
-
case StopReason.MODEL_CONTEXT_WINDOW_EXCEEDED: return "length";
|
|
607
|
-
case StopReason.TOOL_USE: return "toolUse";
|
|
608
|
-
|
|
619
|
+
case StopReason.MODEL_CONTEXT_WINDOW_EXCEEDED: return { stopReason: "length" };
|
|
620
|
+
case StopReason.TOOL_USE: return { stopReason: "toolUse" };
|
|
621
|
+
case StopReason.CONTENT_FILTERED:
|
|
622
|
+
case StopReason.GUARDRAIL_INTERVENED:
|
|
623
|
+
case StopReason.MALFORMED_MODEL_OUTPUT:
|
|
624
|
+
case StopReason.MALFORMED_TOOL_USE: return {
|
|
625
|
+
stopReason: "error",
|
|
626
|
+
errorMessage: reason
|
|
627
|
+
};
|
|
628
|
+
default: return reason ? {
|
|
629
|
+
stopReason: "error",
|
|
630
|
+
errorMessage: reason
|
|
631
|
+
} : { stopReason: "error" };
|
|
609
632
|
}
|
|
610
633
|
}
|
|
634
|
+
function getBedrockModelArnRegion(modelId) {
|
|
635
|
+
return /^arn:aws(?:-[a-z0-9-]+)?:bedrock:([a-z0-9-]+):/.exec(modelId)?.[1];
|
|
636
|
+
}
|
|
611
637
|
function getConfiguredBedrockRegion(options) {
|
|
612
638
|
if (typeof process === "undefined") return options.region;
|
|
613
639
|
return options.region || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || void 0;
|
|
@@ -704,5 +730,6 @@ const testing = {
|
|
|
704
730
|
resolveSimpleBedrockOptions,
|
|
705
731
|
shouldUseExplicitBedrockEndpoint
|
|
706
732
|
};
|
|
733
|
+
if (process.env.VITEST === "true") Reflect.set(globalThis, Symbol.for("openclaw.amazonBedrockStreamTestApi"), testing);
|
|
707
734
|
//#endregion
|
|
708
|
-
export { streamBedrock, streamSimpleBedrock
|
|
735
|
+
export { streamBedrock, streamSimpleBedrock };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/amazon-bedrock-provider",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/amazon-bedrock-provider",
|
|
9
|
-
"version": "2026.7.2-beta.
|
|
9
|
+
"version": "2026.7.2-beta.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@aws-sdk/client-bedrock": "3.1078.0",
|
|
12
12
|
"@aws-sdk/client-bedrock-runtime": "3.1078.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/amazon-bedrock-provider",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"description": "OpenClaw Amazon Bedrock provider plugin with model discovery, embeddings, and guardrail support.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"minHostVersion": ">=2026.5.12-beta.1"
|
|
26
26
|
},
|
|
27
27
|
"compat": {
|
|
28
|
-
"pluginApi": ">=2026.7.2-beta.
|
|
28
|
+
"pluginApi": ">=2026.7.2-beta.3"
|
|
29
29
|
},
|
|
30
30
|
"build": {
|
|
31
|
-
"openclawVersion": "2026.7.2-beta.
|
|
31
|
+
"openclawVersion": "2026.7.2-beta.3",
|
|
32
32
|
"bundledDist": false
|
|
33
33
|
},
|
|
34
34
|
"release": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"README.md"
|
|
47
47
|
],
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"openclaw": ">=2026.7.2-beta.
|
|
49
|
+
"openclaw": ">=2026.7.2-beta.3"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"openclaw": {
|