@opencode-ai/ai
Advanced tools
@@ -140,2 +140,3 @@ import { Schema } from "effect"; | ||
| readonly reasoningSignatures: Readonly<Record<number, string>>; | ||
| readonly reasoningRedactedContent: Readonly<Record<number, ReadonlyArray<Uint8Array>>>; | ||
| } | ||
@@ -142,0 +143,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
| import { Effect, Schema } from "effect"; | ||
| import { Effect, Encoding, Schema } from "effect"; | ||
| import { Route } from "../route/client.js"; | ||
@@ -187,10 +187,11 @@ import { Endpoint } from "../route/endpoint.js"; | ||
| const metadata = part.providerMetadata?.[providerMetadataKey]; | ||
| return (part.encrypted ?? | ||
| (ProviderShared.isRecord(metadata) && typeof metadata.signature === "string" ? metadata.signature : undefined)); | ||
| if (part.encrypted !== undefined) | ||
| return part.encrypted; | ||
| if (ProviderShared.isRecord(metadata) && typeof metadata.signature === "string") | ||
| return metadata.signature; | ||
| }; | ||
| const reasoningRedactedData = (part, providerMetadataKey) => { | ||
| const metadata = part.providerMetadata?.[providerMetadataKey]; | ||
| return ProviderShared.isRecord(metadata) && typeof metadata.redactedData === "string" | ||
| ? metadata.redactedData | ||
| : undefined; | ||
| if (ProviderShared.isRecord(metadata) && typeof metadata.redactedData === "string") | ||
| return metadata.redactedData; | ||
| }; | ||
@@ -334,4 +335,6 @@ const lowerToolCall = (part) => ({ | ||
| const breakpoints = BedrockCache.breakpoints(); | ||
| const toolConfig = request.tools.length > 0 | ||
| ? { | ||
| const toolConfig = (() => { | ||
| if (request.tools.length === 0) | ||
| return undefined; | ||
| return { | ||
| tools: lowerTools(request.model.compatibility?.toolSchema, breakpoints, request.tools), | ||
@@ -341,4 +344,4 @@ // Converse has no native "none". Keep definitions stable for prompt | ||
| toolChoice, | ||
| } | ||
| : undefined; | ||
| }; | ||
| })(); | ||
| const system = request.system.length === 0 ? undefined : lowerSystem(breakpoints, request.system); | ||
@@ -349,2 +352,15 @@ const messages = yield* lowerMessages(request, breakpoints); | ||
| } | ||
| const inferenceConfig = (() => { | ||
| if (generation?.maxTokens === undefined && | ||
| generation?.temperature === undefined && | ||
| generation?.topP === undefined && | ||
| (generation?.stop === undefined || generation.stop.length === 0)) | ||
| return undefined; | ||
| return { | ||
| maxTokens: generation?.maxTokens, | ||
| temperature: generation?.temperature, | ||
| topP: generation?.topP, | ||
| stopSequences: generation?.stop, | ||
| }; | ||
| })(); | ||
| return { | ||
@@ -354,13 +370,3 @@ modelId: request.model.id, | ||
| system, | ||
| inferenceConfig: generation?.maxTokens === undefined && | ||
| generation?.temperature === undefined && | ||
| generation?.topP === undefined && | ||
| (generation?.stop === undefined || generation.stop.length === 0) | ||
| ? undefined | ||
| : { | ||
| maxTokens: generation?.maxTokens, | ||
| temperature: generation?.temperature, | ||
| topP: generation?.topP, | ||
| stopSequences: generation?.stop, | ||
| }, | ||
| inferenceConfig, | ||
| toolConfig, | ||
@@ -402,2 +408,10 @@ // Converse's base inferenceConfig has no topK; Anthropic/Nova accept it | ||
| }; | ||
| const encodeRedactedContent = (chunks) => { | ||
| const bytes = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0)); | ||
| chunks.reduce((offset, chunk) => { | ||
| bytes.set(chunk, offset); | ||
| return offset + chunk.length; | ||
| }, 0); | ||
| return Encoding.encodeBase64(bytes); | ||
| }; | ||
| const step = (state, event) => Effect.gen(function* () { | ||
@@ -440,11 +454,31 @@ if (event.contentBlockStart?.start?.toolUse) { | ||
| const events = []; | ||
| const redactedData = reasoning.redactedContent ?? reasoning.data; | ||
| const metadata = reasoning.signature | ||
| ? providerMetadata(state.providerMetadataKey, { signature: reasoning.signature }) | ||
| : redactedData !== undefined | ||
| ? providerMetadata(state.providerMetadataKey, { redactedData }) | ||
| : undefined; | ||
| const lifecycle = reasoning.text !== undefined || metadata !== undefined | ||
| ? Lifecycle.reasoningDelta(state.lifecycle, events, `reasoning-${index}`, reasoning.text ?? "", metadata) | ||
| : state.lifecycle; | ||
| const redactedChunks = yield* (() => { | ||
| if (reasoning.redactedContent === undefined) | ||
| return Effect.succeed(undefined); | ||
| return Effect.fromResult(Encoding.decodeBase64(reasoning.redactedContent)).pipe(Effect.map((chunk) => [...(state.reasoningRedactedContent[index] ?? []), chunk]), Effect.mapError((cause) => ProviderShared.eventError(ADAPTER, "Bedrock Converse reasoningContent.redactedContent contains invalid base64 data", undefined, cause))); | ||
| })(); | ||
| const redactedData = redactedChunks === undefined ? reasoning.data : encodeRedactedContent(redactedChunks); | ||
| const metadata = (() => { | ||
| if (reasoning.signature) | ||
| return providerMetadata(state.providerMetadataKey, { signature: reasoning.signature }); | ||
| if (redactedData !== undefined) | ||
| return providerMetadata(state.providerMetadataKey, { redactedData }); | ||
| })(); | ||
| const lifecycle = (() => { | ||
| if (reasoning.text === undefined && metadata === undefined) | ||
| return state.lifecycle; | ||
| return Lifecycle.reasoningDelta(state.lifecycle, events, `reasoning-${index}`, reasoning.text ?? "", metadata); | ||
| })(); | ||
| const reasoningRedactedContent = (() => { | ||
| if (redactedChunks !== undefined) | ||
| return { ...state.reasoningRedactedContent, [index]: redactedChunks }; | ||
| if (reasoning.data === undefined) | ||
| return state.reasoningRedactedContent; | ||
| return Object.fromEntries(Object.entries(state.reasoningRedactedContent).filter(([key]) => key !== String(index))); | ||
| })(); | ||
| const reasoningSignatures = (() => { | ||
| if (!reasoning.signature) | ||
| return state.reasoningSignatures; | ||
| return { ...state.reasoningSignatures, [index]: reasoning.signature }; | ||
| })(); | ||
| return [ | ||
@@ -454,5 +488,4 @@ { | ||
| lifecycle, | ||
| reasoningSignatures: reasoning.signature | ||
| ? { ...state.reasoningSignatures, [index]: reasoning.signature } | ||
| : state.reasoningSignatures, | ||
| reasoningSignatures, | ||
| reasoningRedactedContent, | ||
| }, | ||
@@ -479,7 +512,17 @@ events, | ||
| const resultEvents = result.events ?? []; | ||
| const lifecycle = resultEvents.length | ||
| ? Lifecycle.stepStart(state.lifecycle, events) | ||
| : Lifecycle.reasoningEnd(Lifecycle.textEnd(state.lifecycle, events, `text-${index}`), events, `reasoning-${index}`, state.reasoningSignatures[index] | ||
| ? providerMetadata(state.providerMetadataKey, { signature: state.reasoningSignatures[index] }) | ||
| : undefined); | ||
| const lifecycle = (() => { | ||
| if (resultEvents.length) | ||
| return Lifecycle.stepStart(state.lifecycle, events); | ||
| const metadata = (() => { | ||
| const signature = state.reasoningSignatures[index]; | ||
| if (signature) | ||
| return providerMetadata(state.providerMetadataKey, { signature }); | ||
| const redactedContent = state.reasoningRedactedContent[index]; | ||
| if (redactedContent) | ||
| return providerMetadata(state.providerMetadataKey, { | ||
| redactedData: encodeRedactedContent(redactedContent), | ||
| }); | ||
| })(); | ||
| return Lifecycle.reasoningEnd(Lifecycle.textEnd(state.lifecycle, events, `text-${index}`), events, `reasoning-${index}`, metadata); | ||
| })(); | ||
| events.push(...resultEvents); | ||
@@ -495,2 +538,3 @@ return [ | ||
| reasoningSignatures: Object.fromEntries(Object.entries(state.reasoningSignatures).filter(([key]) => key !== String(index))), | ||
| reasoningRedactedContent: Object.fromEntries(Object.entries(state.reasoningRedactedContent).filter(([key]) => key !== String(index))), | ||
| }, | ||
@@ -544,17 +588,20 @@ events, | ||
| const framing = BedrockEventStream.framing(ADAPTER); | ||
| const onHalt = (state) => state.pendingFinish | ||
| ? (() => { | ||
| const events = []; | ||
| Lifecycle.finish(state.lifecycle, events, { | ||
| reason: { | ||
| ...state.pendingFinish.reason, | ||
| normalized: state.pendingFinish.reason.normalized === "stop" && state.hasToolCalls | ||
| ? "tool-calls" | ||
| : state.pendingFinish.reason.normalized, | ||
| }, | ||
| usage: state.pendingFinish.usage, | ||
| }); | ||
| return events; | ||
| })() | ||
| : []; | ||
| const onHalt = (state) => { | ||
| if (!state.pendingFinish) | ||
| return []; | ||
| const normalized = (() => { | ||
| if (state.pendingFinish.reason.normalized === "stop" && state.hasToolCalls) | ||
| return "tool-calls"; | ||
| return state.pendingFinish.reason.normalized; | ||
| })(); | ||
| const events = []; | ||
| Lifecycle.finish(state.lifecycle, events, { | ||
| reason: { | ||
| ...state.pendingFinish.reason, | ||
| normalized, | ||
| }, | ||
| usage: state.pendingFinish.usage, | ||
| }); | ||
| return events; | ||
| }; | ||
| // ============================================================================= | ||
@@ -583,2 +630,3 @@ // Protocol And Bedrock Route | ||
| reasoningSignatures: {}, | ||
| reasoningRedactedContent: {}, | ||
| }), | ||
@@ -585,0 +633,0 @@ step, |
+3
-3
| { | ||
| "$schema": "https://json.schemastore.org/package.json", | ||
| "version": "0.0.0-dev-18698", | ||
| "version": "0.0.0-dev-18699", | ||
| "name": "@opencode-ai/ai", | ||
@@ -33,3 +33,3 @@ "type": "module", | ||
| "@effect/platform-node": "4.0.0-rc.112", | ||
| "@opencode-ai/http-recorder": "0.0.0-dev-18698", | ||
| "@opencode-ai/http-recorder": "0.0.0-dev-18699", | ||
| "@tsconfig/bun": "1.0.9", | ||
@@ -43,3 +43,3 @@ "@types/bun": "1.3.13", | ||
| "@smithy/util-utf8": "4.2.2", | ||
| "@opencode-ai/schema": "0.0.0-dev-18698", | ||
| "@opencode-ai/schema": "0.0.0-dev-18699", | ||
| "aws4fetch": "1.0.20", | ||
@@ -46,0 +46,0 @@ "effect": "4.0.0-rc.112", |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1545507
0.15%35638
0.14%+ Added
- Removed