@effect-uai/anthropic 0.5.2 → 0.7.0
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/codec.d.mts +1 -1
- package/dist/codec.d.mts.map +1 -1
- package/dist/codec.mjs.map +1 -1
- package/package.json +2 -2
- package/src/codec.ts +22 -18
package/dist/codec.d.mts
CHANGED
|
@@ -101,7 +101,7 @@ type RequestBody = {
|
|
|
101
101
|
};
|
|
102
102
|
declare const buildRequestBody: (params: {
|
|
103
103
|
readonly model: string;
|
|
104
|
-
readonly history: ReadonlyArray<Items.
|
|
104
|
+
readonly history: ReadonlyArray<Items.HistoryItem>;
|
|
105
105
|
readonly maxTokens: number;
|
|
106
106
|
readonly temperature: Option.Option<number>;
|
|
107
107
|
readonly topP: Option.Option<number>;
|
package/dist/codec.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;;;cAiCa,gBAAA,EAAgB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;KAMjB,gBAAA,UAA0B,gBAAA,CAAiB,IAAA;AAAA,cAEjD,SAAA,EAAS,MAAA,CAAA,MAAA;EAAA;;;;;KAMH,SAAA,UAAmB,SAAA,CAAU,IAAA;AAAA,KAMpC,kBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAGN,wBAAA;EAAA,SACM,IAAA;EAAA,SACA,WAAA;EAAA,SACA,OAAA;AAAA;AAAA,KAGN,qBAAA;EAAA,SACM,IAAA;EAAA,SACA,EAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA;AAAA;AAAA,KAGN,sBAAA;EAAA,SACM,IAAA;EAAA,SACA,QAAA;EAAA,SACA,SAAA;AAAA;AAAA,KAGN,8BAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAGN,mBAAA;EAAA,SACM,IAAA;EAAA,SACA,MAAA;IAAA,SACM,IAAA;IAAA,SAAsB,GAAA;EAAA;IAAA,SACtB,IAAA;IAAA,SAAyB,UAAA;IAAA,SAA6B,IAAA;EAAA;AAAA;AAAA,KAGlE,uBAAA,GAA0B,kBAAA,GAAqB,wBAAA,GAA2B,mBAAA;AAAA,KAE1E,4BAAA,GACD,kBAAA,GACA,qBAAA,GACA,sBAAA,GACA,8BAAA;AAAA,KAEC,kBAAA;EAAA,SACM,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,uBAAA;AAAA;AAAA,KAG7B,uBAAA;EAAA,SACM,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,4BAAA;AAAA;AAAA,KAG7B,cAAA,GAAiB,kBAAA,GAAqB,uBAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":"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"}
|
package/dist/codec.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.mjs","names":["Arr"],"sources":["../src/codec.ts"],"sourcesContent":["import { Array as Arr, Encoding, Match, Option, Order, Result, Schema, pipe } from \"effect\"\nimport * as Items from \"@effect-uai/core/Items\"\nimport { JsonParseError } from \"@effect-uai/core/JSONL\"\nimport type { Turn } from \"@effect-uai/core/Turn\"\n\n// ---------------------------------------------------------------------------\n// Wire schemas - subset of Anthropic Messages API we consume.\n// Reference: https://platform.claude.com/docs/en/api/messages\n// ---------------------------------------------------------------------------\n\nconst WireTextBlock = Schema.Struct({\n type: Schema.Literal(\"text\"),\n text: Schema.String,\n})\n\nconst WireToolUseBlock = Schema.Struct({\n type: Schema.Literal(\"tool_use\"),\n id: Schema.String,\n name: Schema.String,\n input: Schema.Unknown,\n})\n\nconst WireThinkingBlock = Schema.Struct({\n type: Schema.Literal(\"thinking\"),\n thinking: Schema.String,\n signature: Schema.optional(Schema.String),\n})\n\nconst WireRedactedThinkingBlock = Schema.Struct({\n type: Schema.Literal(\"redacted_thinking\"),\n data: Schema.String,\n})\n\nexport const WireContentBlock = Schema.Union([\n WireTextBlock,\n WireToolUseBlock,\n WireThinkingBlock,\n WireRedactedThinkingBlock,\n])\nexport type WireContentBlock = typeof WireContentBlock.Type\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n cache_creation_input_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n cache_read_input_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\nexport type WireUsage = typeof WireUsage.Type\n\n// ---------------------------------------------------------------------------\n// History → request body\n// ---------------------------------------------------------------------------\n\ntype RequestTextContent = {\n readonly type: \"text\"\n readonly text: string\n}\n\ntype RequestToolResultContent = {\n readonly type: \"tool_result\"\n readonly tool_use_id: string\n readonly content: string\n}\n\ntype RequestToolUseContent = {\n readonly type: \"tool_use\"\n readonly id: string\n readonly name: string\n readonly input: unknown\n}\n\ntype RequestThinkingContent = {\n readonly type: \"thinking\"\n readonly thinking: string\n readonly signature?: string\n}\n\ntype RequestRedactedThinkingContent = {\n readonly type: \"redacted_thinking\"\n readonly data: string\n}\n\ntype RequestImageContent = {\n readonly type: \"image\"\n readonly source:\n | { readonly type: \"url\"; readonly url: string }\n | { readonly type: \"base64\"; readonly media_type: string; readonly data: string }\n}\n\ntype RequestUserContentBlock = RequestTextContent | RequestToolResultContent | RequestImageContent\n\ntype RequestAssistantContentBlock =\n | RequestTextContent\n | RequestToolUseContent\n | RequestThinkingContent\n | RequestRedactedThinkingContent\n\ntype RequestUserMessage = {\n readonly role: \"user\"\n readonly content: ReadonlyArray<RequestUserContentBlock>\n}\n\ntype RequestAssistantMessage = {\n readonly role: \"assistant\"\n readonly content: ReadonlyArray<RequestAssistantContentBlock>\n}\n\ntype RequestMessage = RequestUserMessage | RequestAssistantMessage\n\nconst blockText = Match.type<Items.ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) => b.text,\n input_image: () => \"\",\n output_text: (b) => b.text,\n refusal: (b) => b.text,\n }),\n)\n\nconst messageText = (message: Items.Message): string => message.content.map(blockText).join(\"\")\n\nconst imageSourceToWire = Match.type<Items.InputImage[\"source\"]>().pipe(\n Match.tag(\"url\", (s): RequestImageContent[\"source\"] => ({ type: \"url\", url: s.url })),\n Match.tag(\"base64\", (s): RequestImageContent[\"source\"] => ({\n type: \"base64\",\n media_type: s.mimeType,\n data: s.base64,\n })),\n Match.tag(\"bytes\", (s): RequestImageContent[\"source\"] => ({\n type: \"base64\",\n media_type: s.mimeType,\n data: Encoding.encodeBase64(s.bytes),\n })),\n Match.exhaustive,\n)\n\nconst userContentBlock = (\n block: Items.ContentBlock,\n): Result.Result<RequestUserContentBlock, void> =>\n Match.value(block).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) =>\n b.text.length === 0\n ? Result.failVoid\n : Result.succeed({ type: \"text\" as const, text: b.text }),\n input_image: (b) =>\n Result.succeed({ type: \"image\" as const, source: imageSourceToWire(b.source) }),\n // Assistant content; never appears on a user message in practice. Skip.\n output_text: () => Result.failVoid,\n refusal: () => Result.failVoid,\n }),\n )\n\nconst parseJson = (s: string): Result.Result<unknown, JsonParseError> =>\n Result.try({\n try: () => JSON.parse(s) as unknown,\n catch: (cause) => new JsonParseError({ line: s, cause }),\n })\n\ntype RoleBucket = \"user\" | \"assistant\" | \"system\"\n\nconst roleBucket = (item: Items.Item): RoleBucket =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m) => m.role,\n function_call: () => \"assistant\" as const,\n function_call_output: () => \"user\" as const,\n reasoning: () => \"assistant\" as const,\n }),\n )\n\nconst itemToUserBlocks = (item: Items.Item): ReadonlyArray<RequestUserContentBlock> =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m): ReadonlyArray<RequestUserContentBlock> =>\n m.role === \"user\" ? pipe(m.content, Arr.filterMap(userContentBlock)) : [],\n function_call: (): ReadonlyArray<RequestUserContentBlock> => [],\n function_call_output: (o): ReadonlyArray<RequestUserContentBlock> => [\n { type: \"tool_result\", tool_use_id: o.call_id, content: o.output },\n ],\n reasoning: (): ReadonlyArray<RequestUserContentBlock> => [],\n }),\n )\n\nconst itemToAssistantBlocks = (\n item: Items.Item,\n): Result.Result<ReadonlyArray<RequestAssistantContentBlock>, JsonParseError> =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m): Result.Result<ReadonlyArray<RequestAssistantContentBlock>, JsonParseError> => {\n const text = messageText(m)\n return Result.succeed(\n m.role === \"assistant\" && text.length > 0 ? [{ type: \"text\", text }] : [],\n )\n },\n function_call: (f) =>\n pipe(\n parseJson(f.arguments),\n Result.map(\n (input): ReadonlyArray<RequestAssistantContentBlock> => [\n { type: \"tool_use\", id: f.call_id, name: f.name, input },\n ],\n ),\n ),\n function_call_output: (): Result.Result<\n ReadonlyArray<RequestAssistantContentBlock>,\n JsonParseError\n > => Result.succeed([]),\n reasoning: (r) => {\n const blocks: ReadonlyArray<RequestAssistantContentBlock> =\n r.summary !== undefined\n ? [\n {\n type: \"thinking\",\n thinking: r.summary,\n ...(r.signature !== undefined && { signature: r.signature }),\n },\n ]\n : r.signature !== undefined\n ? [{ type: \"redacted_thinking\", data: r.signature }]\n : []\n return Result.succeed(blocks)\n },\n }),\n )\n\ntype GroupAcc = {\n readonly messages: ReadonlyArray<RequestMessage>\n readonly currentRole: Option.Option<\"user\" | \"assistant\">\n readonly userBuf: ReadonlyArray<RequestUserContentBlock>\n readonly assistantBuf: ReadonlyArray<RequestAssistantContentBlock>\n}\n\nconst flushAcc = (acc: GroupAcc): ReadonlyArray<RequestMessage> =>\n Option.match(acc.currentRole, {\n onNone: () => acc.messages,\n onSome: (role) =>\n role === \"user\" && acc.userBuf.length > 0\n ? [...acc.messages, { role: \"user\", content: acc.userBuf }]\n : role === \"assistant\" && acc.assistantBuf.length > 0\n ? [...acc.messages, { role: \"assistant\", content: acc.assistantBuf }]\n : acc.messages,\n })\n\nconst appendUser = (acc: GroupAcc, blocks: ReadonlyArray<RequestUserContentBlock>): GroupAcc =>\n blocks.length === 0\n ? acc\n : Option.isSome(acc.currentRole) && acc.currentRole.value === \"user\"\n ? { ...acc, userBuf: [...acc.userBuf, ...blocks] }\n : {\n messages: flushAcc(acc),\n currentRole: Option.some(\"user\"),\n userBuf: blocks,\n assistantBuf: [],\n }\n\nconst appendAssistant = (\n acc: GroupAcc,\n blocks: ReadonlyArray<RequestAssistantContentBlock>,\n): GroupAcc =>\n blocks.length === 0\n ? acc\n : Option.isSome(acc.currentRole) && acc.currentRole.value === \"assistant\"\n ? { ...acc, assistantBuf: [...acc.assistantBuf, ...blocks] }\n : {\n messages: flushAcc(acc),\n currentRole: Option.some(\"assistant\"),\n userBuf: [],\n assistantBuf: blocks,\n }\n\nconst groupStep = (acc: GroupAcc, item: Items.Item): Result.Result<GroupAcc, JsonParseError> => {\n const bucket = roleBucket(item)\n if (bucket === \"system\") return Result.succeed(acc)\n if (bucket === \"user\") {\n return Result.succeed(appendUser(acc, itemToUserBlocks(item)))\n }\n return pipe(\n itemToAssistantBlocks(item),\n Result.map((blocks) => appendAssistant(acc, blocks)),\n )\n}\n\n/**\n * Group consecutive same-role items into Anthropic-shaped messages.\n * Anthropic requires strict user/assistant alternation; consecutive items\n * from the same role are folded into one message's `content`. Fails if any\n * `function_call.arguments` is not valid JSON, since Anthropic's wire shape\n * requires an object input.\n */\nconst groupedMessages = (\n history: ReadonlyArray<Items.Item>,\n): Result.Result<ReadonlyArray<RequestMessage>, JsonParseError> => {\n const initial: Result.Result<GroupAcc, JsonParseError> = Result.succeed({\n messages: [],\n currentRole: Option.none(),\n userBuf: [],\n assistantBuf: [],\n })\n return pipe(\n Arr.reduce(history, initial, (acc, item) => Result.flatMap(acc, (a) => groupStep(a, item))),\n Result.map(flushAcc),\n )\n}\n\nconst isSystemMessage = (item: Items.Item): item is Items.Message =>\n item.type === \"message\" && item.role === \"system\"\n\nconst systemFromHistory = (history: ReadonlyArray<Items.Item>): Option.Option<string> => {\n const texts = pipe(\n history,\n Arr.filterMap((item) =>\n isSystemMessage(item) ? Result.succeed(messageText(item)) : Result.failVoid,\n ),\n Arr.filter((s) => s.length > 0),\n )\n return texts.length === 0 ? Option.none() : Option.some(texts.join(\"\\n\"))\n}\n\nexport type ThinkingConfig = {\n readonly type: \"enabled\"\n readonly budget_tokens: number\n}\n\nexport type RequestBody = {\n readonly model: string\n readonly messages: ReadonlyArray<RequestMessage>\n readonly max_tokens: number\n readonly system?: string\n readonly temperature?: number\n readonly top_p?: number\n readonly top_k?: number\n readonly stop_sequences?: ReadonlyArray<string>\n readonly thinking?: ThinkingConfig\n readonly tools?: ReadonlyArray<Record<string, unknown>>\n readonly tool_choice?: Record<string, unknown>\n readonly metadata?: { readonly user_id: string }\n readonly output_config?: Record<string, unknown>\n readonly stream: true\n}\n\nexport const buildRequestBody = (params: {\n readonly model: string\n readonly history: ReadonlyArray<Items.Item>\n readonly maxTokens: number\n readonly temperature: Option.Option<number>\n readonly topP: Option.Option<number>\n readonly topK: Option.Option<number>\n readonly stopSequences: Option.Option<ReadonlyArray<string>>\n readonly thinking: Option.Option<ThinkingConfig>\n readonly tools: Option.Option<ReadonlyArray<Record<string, unknown>>>\n readonly toolChoice: Option.Option<Record<string, unknown>>\n readonly userId: Option.Option<string>\n readonly outputConfig: Option.Option<Record<string, unknown>>\n}): Result.Result<RequestBody, JsonParseError> =>\n pipe(\n groupedMessages(params.history),\n Result.map(\n (messages): RequestBody => ({\n model: params.model,\n messages,\n max_tokens: params.maxTokens,\n ...Option.match(systemFromHistory(params.history), {\n onNone: () => ({}),\n onSome: (system) => ({ system }),\n }),\n ...Option.match(params.temperature, {\n onNone: () => ({}),\n onSome: (temperature) => ({ temperature }),\n }),\n ...Option.match(params.topP, {\n onNone: () => ({}),\n onSome: (top_p) => ({ top_p }),\n }),\n ...Option.match(params.topK, {\n onNone: () => ({}),\n onSome: (top_k) => ({ top_k }),\n }),\n ...Option.match(params.stopSequences, {\n onNone: () => ({}),\n onSome: (stop_sequences) => ({ stop_sequences }),\n }),\n ...Option.match(params.thinking, {\n onNone: () => ({}),\n onSome: (thinking) => ({ thinking }),\n }),\n ...Option.match(params.tools, {\n onNone: () => ({}),\n onSome: (tools) => ({ tools }),\n }),\n ...Option.match(params.toolChoice, {\n onNone: () => ({}),\n onSome: (tool_choice) => ({ tool_choice }),\n }),\n ...Option.match(params.userId, {\n onNone: () => ({}),\n onSome: (user_id) => ({ metadata: { user_id } }),\n }),\n ...Option.match(params.outputConfig, {\n onNone: () => ({}),\n onSome: (output_config) => ({ output_config }),\n }),\n stream: true,\n }),\n ),\n )\n\n// ---------------------------------------------------------------------------\n// Stream-level state - assemble content blocks index-by-index, then emit\n// our `Items.Item[]` when `message_stop` lands.\n// ---------------------------------------------------------------------------\n\ntype BlockBuffer = {\n readonly type: WireContentBlock[\"type\"]\n readonly text: string\n readonly inputJson: string\n readonly thinking: string\n readonly signature: string\n readonly id: Option.Option<string>\n readonly name: Option.Option<string>\n readonly redactedData: Option.Option<string>\n}\n\nconst emptyBlock = (type: WireContentBlock[\"type\"]): BlockBuffer => ({\n type,\n text: \"\",\n inputJson: \"\",\n thinking: \"\",\n signature: \"\",\n id: Option.none(),\n name: Option.none(),\n redactedData: Option.none(),\n})\n\nexport type Accumulator = {\n readonly blocks: Readonly<Record<number, BlockBuffer>>\n readonly stopReason: Option.Option<string>\n readonly usage: Items.Usage\n}\n\nexport const emptyAccumulator: Accumulator = {\n blocks: {},\n stopReason: Option.none(),\n usage: {},\n}\n\nconst replaceBlock = (acc: Accumulator, index: number, block: BlockBuffer): Accumulator => ({\n ...acc,\n blocks: { ...acc.blocks, [index]: block },\n})\n\nconst updateBlock = (\n acc: Accumulator,\n index: number,\n patch: (block: BlockBuffer) => BlockBuffer,\n): Accumulator => replaceBlock(acc, index, patch(acc.blocks[index] ?? emptyBlock(\"text\")))\n\nexport const startBlock = (acc: Accumulator, index: number, block: WireContentBlock): Accumulator =>\n Match.value(block).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n text: () => replaceBlock(acc, index, emptyBlock(\"text\")),\n tool_use: (b) =>\n replaceBlock(acc, index, {\n ...emptyBlock(\"tool_use\"),\n id: Option.some(b.id),\n name: Option.some(b.name),\n inputJson: typeof b.input === \"string\" ? b.input : \"\",\n }),\n thinking: () => replaceBlock(acc, index, emptyBlock(\"thinking\")),\n redacted_thinking: (b) =>\n replaceBlock(acc, index, {\n ...emptyBlock(\"redacted_thinking\"),\n redactedData: Option.some(b.data),\n }),\n }),\n )\n\nexport const appendTextDelta = (acc: Accumulator, index: number, text: string): Accumulator =>\n updateBlock(acc, index, (b) => ({ ...b, text: b.text + text }))\n\nexport const appendInputJsonDelta = (\n acc: Accumulator,\n index: number,\n partial: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, inputJson: b.inputJson + partial }))\n\nexport const appendThinkingDelta = (\n acc: Accumulator,\n index: number,\n thinking: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, thinking: b.thinking + thinking }))\n\nexport const appendSignatureDelta = (\n acc: Accumulator,\n index: number,\n signature: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, signature: b.signature + signature }))\n\nexport const setStopReason = (acc: Accumulator, reason: string): Accumulator => ({\n ...acc,\n stopReason: Option.some(reason),\n})\n\nconst cachedFromWire = (wire: WireUsage): Option.Option<number> =>\n Option.fromNullishOr(wire.cache_read_input_tokens)\n\nexport const mergeUsage = (acc: Accumulator, wire: WireUsage): Accumulator => {\n const cached = cachedFromWire(wire)\n const usage: Items.Usage = {\n ...acc.usage,\n ...(wire.input_tokens !== undefined && { input_tokens: wire.input_tokens }),\n ...(wire.output_tokens !== undefined && { output_tokens: wire.output_tokens }),\n ...(wire.input_tokens !== undefined &&\n wire.output_tokens !== undefined && {\n total_tokens: wire.input_tokens + wire.output_tokens,\n }),\n ...Option.match(cached, {\n onNone: () => ({}),\n onSome: (cached_tokens) => ({ input_tokens_details: { cached_tokens } }),\n }),\n }\n return { ...acc, usage }\n}\n\nconst stopReasonFromAnthropic = (reason: Option.Option<string>): Turn[\"stop_reason\"] =>\n Option.match(reason, {\n onNone: () => \"stop\" as const,\n onSome: (r) =>\n Match.value(r).pipe(\n Match.when(\"tool_use\", () => \"tool_calls\" as const),\n Match.when(\"max_tokens\", () => \"max_tokens\" as const),\n Match.orElse(() => \"stop\" as const),\n ),\n })\n\nconst blocksByIndex = (acc: Accumulator): ReadonlyArray<BlockBuffer> =>\n pipe(\n Object.keys(acc.blocks),\n Arr.map((k) => Number(k)),\n Arr.sort(Order.Number),\n Arr.map((i) => acc.blocks[i]!),\n )\n\nconst blockToItems = (block: BlockBuffer): ReadonlyArray<Items.Item> =>\n Match.value(block.type).pipe(\n Match.when(\n \"text\",\n (): ReadonlyArray<Items.Item> =>\n block.text.length === 0\n ? []\n : [\n {\n type: \"message\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: block.text }],\n },\n ],\n ),\n Match.when(\n \"tool_use\",\n (): ReadonlyArray<Items.Item> => [\n {\n type: \"function_call\",\n call_id: Option.getOrElse(block.id, () => \"\"),\n name: Option.getOrElse(block.name, () => \"\"),\n arguments: block.inputJson,\n },\n ],\n ),\n Match.when(\n \"thinking\",\n (): ReadonlyArray<Items.Item> => [\n {\n type: \"reasoning\",\n ...(block.thinking.length > 0 && { summary: block.thinking }),\n ...(block.signature.length > 0 && { signature: block.signature }),\n },\n ],\n ),\n Match.when(\n \"redacted_thinking\",\n (): ReadonlyArray<Items.Item> => [\n {\n type: \"reasoning\",\n ...Option.match(block.redactedData, {\n onNone: () => ({}),\n onSome: (signature) => ({ signature }),\n }),\n },\n ],\n ),\n Match.exhaustive,\n )\n\ntype MergeAcc = {\n readonly out: ReadonlyArray<Items.Item>\n}\n\nconst mergeStep = (acc: MergeAcc, item: Items.Item): MergeAcc => {\n const last = Arr.last(acc.out)\n if (\n Option.isSome(last) &&\n last.value.type === \"message\" &&\n last.value.role === \"assistant\" &&\n item.type === \"message\" &&\n item.role === \"assistant\"\n ) {\n const merged: Items.Message = {\n ...last.value,\n content: [...last.value.content, ...item.content],\n }\n return { out: [...acc.out.slice(0, -1), merged] }\n }\n return { out: [...acc.out, item] }\n}\n\nconst mergeAdjacentAssistantText = (items: ReadonlyArray<Items.Item>): ReadonlyArray<Items.Item> =>\n Arr.reduce(items, { out: [] } as MergeAcc, mergeStep).out\n\nexport const accumulatorToTurn = (acc: Accumulator): Turn => ({\n items: pipe(blocksByIndex(acc), Arr.flatMap(blockToItems), mergeAdjacentAssistantText),\n usage: acc.usage,\n stop_reason: stopReasonFromAnthropic(acc.stopReason),\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"codec.mjs","names":["Arr"],"sources":["../src/codec.ts"],"sourcesContent":["import { Array as Arr, Encoding, Match, Option, Order, Result, Schema, pipe } from \"effect\"\nimport * as Items from \"@effect-uai/core/Items\"\nimport { JsonParseError } from \"@effect-uai/core/JSONL\"\nimport type { Turn } from \"@effect-uai/core/Turn\"\n\n// ---------------------------------------------------------------------------\n// Wire schemas - subset of Anthropic Messages API we consume.\n// Reference: https://platform.claude.com/docs/en/api/messages\n// ---------------------------------------------------------------------------\n\nconst WireTextBlock = Schema.Struct({\n type: Schema.Literal(\"text\"),\n text: Schema.String,\n})\n\nconst WireToolUseBlock = Schema.Struct({\n type: Schema.Literal(\"tool_use\"),\n id: Schema.String,\n name: Schema.String,\n input: Schema.Unknown,\n})\n\nconst WireThinkingBlock = Schema.Struct({\n type: Schema.Literal(\"thinking\"),\n thinking: Schema.String,\n signature: Schema.optional(Schema.String),\n})\n\nconst WireRedactedThinkingBlock = Schema.Struct({\n type: Schema.Literal(\"redacted_thinking\"),\n data: Schema.String,\n})\n\nexport const WireContentBlock = Schema.Union([\n WireTextBlock,\n WireToolUseBlock,\n WireThinkingBlock,\n WireRedactedThinkingBlock,\n])\nexport type WireContentBlock = typeof WireContentBlock.Type\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n cache_creation_input_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n cache_read_input_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\nexport type WireUsage = typeof WireUsage.Type\n\n// ---------------------------------------------------------------------------\n// History → request body\n// ---------------------------------------------------------------------------\n\ntype RequestTextContent = {\n readonly type: \"text\"\n readonly text: string\n}\n\ntype RequestToolResultContent = {\n readonly type: \"tool_result\"\n readonly tool_use_id: string\n readonly content: string\n}\n\ntype RequestToolUseContent = {\n readonly type: \"tool_use\"\n readonly id: string\n readonly name: string\n readonly input: unknown\n}\n\ntype RequestThinkingContent = {\n readonly type: \"thinking\"\n readonly thinking: string\n readonly signature?: string\n}\n\ntype RequestRedactedThinkingContent = {\n readonly type: \"redacted_thinking\"\n readonly data: string\n}\n\ntype RequestImageContent = {\n readonly type: \"image\"\n readonly source:\n | { readonly type: \"url\"; readonly url: string }\n | { readonly type: \"base64\"; readonly media_type: string; readonly data: string }\n}\n\ntype RequestUserContentBlock = RequestTextContent | RequestToolResultContent | RequestImageContent\n\ntype RequestAssistantContentBlock =\n | RequestTextContent\n | RequestToolUseContent\n | RequestThinkingContent\n | RequestRedactedThinkingContent\n\ntype RequestUserMessage = {\n readonly role: \"user\"\n readonly content: ReadonlyArray<RequestUserContentBlock>\n}\n\ntype RequestAssistantMessage = {\n readonly role: \"assistant\"\n readonly content: ReadonlyArray<RequestAssistantContentBlock>\n}\n\ntype RequestMessage = RequestUserMessage | RequestAssistantMessage\n\nconst blockText = Match.type<Items.ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) => b.text,\n input_image: () => \"\",\n output_text: (b) => b.text,\n refusal: (b) => b.text,\n }),\n)\n\nconst messageText = (message: Items.Message): string => message.content.map(blockText).join(\"\")\n\nconst imageSourceToWire = Match.type<Items.InputImage[\"source\"]>().pipe(\n Match.tag(\"url\", (s): RequestImageContent[\"source\"] => ({ type: \"url\", url: s.url })),\n Match.tag(\"base64\", (s): RequestImageContent[\"source\"] => ({\n type: \"base64\",\n media_type: s.mimeType,\n data: s.base64,\n })),\n Match.tag(\"bytes\", (s): RequestImageContent[\"source\"] => ({\n type: \"base64\",\n media_type: s.mimeType,\n data: Encoding.encodeBase64(s.bytes),\n })),\n Match.exhaustive,\n)\n\nconst userContentBlock = (\n block: Items.ContentBlock,\n): Result.Result<RequestUserContentBlock, void> =>\n Match.value(block).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) =>\n b.text.length === 0\n ? Result.failVoid\n : Result.succeed({ type: \"text\" as const, text: b.text }),\n input_image: (b) =>\n Result.succeed({ type: \"image\" as const, source: imageSourceToWire(b.source) }),\n // Assistant content; never appears on a user message in practice. Skip.\n output_text: () => Result.failVoid,\n refusal: () => Result.failVoid,\n }),\n )\n\nconst parseJson = (s: string): Result.Result<unknown, JsonParseError> =>\n Result.try({\n try: () => JSON.parse(s) as unknown,\n catch: (cause) => new JsonParseError({ line: s, cause }),\n })\n\ntype RoleBucket = \"user\" | \"assistant\" | \"system\"\n\nconst roleBucket = (item: Items.HistoryItem): RoleBucket =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m) => m.role,\n function_call: () => \"assistant\" as const,\n function_call_output: () => \"user\" as const,\n reasoning: () => \"assistant\" as const,\n }),\n )\n\nconst itemToUserBlocks = (item: Items.HistoryItem): ReadonlyArray<RequestUserContentBlock> =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m): ReadonlyArray<RequestUserContentBlock> =>\n m.role === \"user\" ? pipe(m.content, Arr.filterMap(userContentBlock)) : [],\n function_call: (): ReadonlyArray<RequestUserContentBlock> => [],\n function_call_output: (o): ReadonlyArray<RequestUserContentBlock> => [\n { type: \"tool_result\", tool_use_id: o.call_id, content: o.output },\n ],\n reasoning: (): ReadonlyArray<RequestUserContentBlock> => [],\n }),\n )\n\nconst itemToAssistantBlocks = (\n item: Items.HistoryItem,\n): Result.Result<ReadonlyArray<RequestAssistantContentBlock>, JsonParseError> =>\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m): Result.Result<ReadonlyArray<RequestAssistantContentBlock>, JsonParseError> => {\n const text = messageText(m)\n return Result.succeed(\n m.role === \"assistant\" && text.length > 0 ? [{ type: \"text\", text }] : [],\n )\n },\n function_call: (f) =>\n pipe(\n parseJson(f.arguments),\n Result.map(\n (input): ReadonlyArray<RequestAssistantContentBlock> => [\n { type: \"tool_use\", id: f.call_id, name: f.name, input },\n ],\n ),\n ),\n function_call_output: (): Result.Result<\n ReadonlyArray<RequestAssistantContentBlock>,\n JsonParseError\n > => Result.succeed([]),\n reasoning: (r) => {\n const blocks: ReadonlyArray<RequestAssistantContentBlock> =\n r.summary !== undefined\n ? [\n {\n type: \"thinking\",\n thinking: r.summary,\n ...(r.signature !== undefined && { signature: r.signature }),\n },\n ]\n : r.signature !== undefined\n ? [{ type: \"redacted_thinking\", data: r.signature }]\n : []\n return Result.succeed(blocks)\n },\n }),\n )\n\ntype GroupAcc = {\n readonly messages: ReadonlyArray<RequestMessage>\n readonly currentRole: Option.Option<\"user\" | \"assistant\">\n readonly userBuf: ReadonlyArray<RequestUserContentBlock>\n readonly assistantBuf: ReadonlyArray<RequestAssistantContentBlock>\n}\n\nconst flushAcc = (acc: GroupAcc): ReadonlyArray<RequestMessage> =>\n Option.match(acc.currentRole, {\n onNone: () => acc.messages,\n onSome: (role) =>\n role === \"user\" && acc.userBuf.length > 0\n ? [...acc.messages, { role: \"user\", content: acc.userBuf }]\n : role === \"assistant\" && acc.assistantBuf.length > 0\n ? [...acc.messages, { role: \"assistant\", content: acc.assistantBuf }]\n : acc.messages,\n })\n\nconst appendUser = (acc: GroupAcc, blocks: ReadonlyArray<RequestUserContentBlock>): GroupAcc =>\n blocks.length === 0\n ? acc\n : Option.isSome(acc.currentRole) && acc.currentRole.value === \"user\"\n ? { ...acc, userBuf: [...acc.userBuf, ...blocks] }\n : {\n messages: flushAcc(acc),\n currentRole: Option.some(\"user\"),\n userBuf: blocks,\n assistantBuf: [],\n }\n\nconst appendAssistant = (\n acc: GroupAcc,\n blocks: ReadonlyArray<RequestAssistantContentBlock>,\n): GroupAcc =>\n blocks.length === 0\n ? acc\n : Option.isSome(acc.currentRole) && acc.currentRole.value === \"assistant\"\n ? { ...acc, assistantBuf: [...acc.assistantBuf, ...blocks] }\n : {\n messages: flushAcc(acc),\n currentRole: Option.some(\"assistant\"),\n userBuf: [],\n assistantBuf: blocks,\n }\n\nconst groupStep = (\n acc: GroupAcc,\n item: Items.HistoryItem,\n): Result.Result<GroupAcc, JsonParseError> => {\n const bucket = roleBucket(item)\n if (bucket === \"system\") return Result.succeed(acc)\n if (bucket === \"user\") {\n return Result.succeed(appendUser(acc, itemToUserBlocks(item)))\n }\n return pipe(\n itemToAssistantBlocks(item),\n Result.map((blocks) => appendAssistant(acc, blocks)),\n )\n}\n\n/**\n * Group consecutive same-role items into Anthropic-shaped messages.\n * Anthropic requires strict user/assistant alternation; consecutive items\n * from the same role are folded into one message's `content`. Fails if any\n * `function_call.arguments` is not valid JSON, since Anthropic's wire shape\n * requires an object input.\n */\nconst groupedMessages = (\n history: ReadonlyArray<Items.HistoryItem>,\n): Result.Result<ReadonlyArray<RequestMessage>, JsonParseError> => {\n const initial: Result.Result<GroupAcc, JsonParseError> = Result.succeed({\n messages: [],\n currentRole: Option.none(),\n userBuf: [],\n assistantBuf: [],\n })\n return pipe(\n Arr.reduce(history, initial, (acc, item) => Result.flatMap(acc, (a) => groupStep(a, item))),\n Result.map(flushAcc),\n )\n}\n\nconst isSystemMessage = (item: Items.HistoryItem): item is Items.Message =>\n item.type === \"message\" && item.role === \"system\"\n\nconst systemFromHistory = (history: ReadonlyArray<Items.HistoryItem>): Option.Option<string> => {\n const texts = pipe(\n history,\n Arr.filterMap((item) =>\n isSystemMessage(item) ? Result.succeed(messageText(item)) : Result.failVoid,\n ),\n Arr.filter((s) => s.length > 0),\n )\n return texts.length === 0 ? Option.none() : Option.some(texts.join(\"\\n\"))\n}\n\nexport type ThinkingConfig = {\n readonly type: \"enabled\"\n readonly budget_tokens: number\n}\n\nexport type RequestBody = {\n readonly model: string\n readonly messages: ReadonlyArray<RequestMessage>\n readonly max_tokens: number\n readonly system?: string\n readonly temperature?: number\n readonly top_p?: number\n readonly top_k?: number\n readonly stop_sequences?: ReadonlyArray<string>\n readonly thinking?: ThinkingConfig\n readonly tools?: ReadonlyArray<Record<string, unknown>>\n readonly tool_choice?: Record<string, unknown>\n readonly metadata?: { readonly user_id: string }\n readonly output_config?: Record<string, unknown>\n readonly stream: true\n}\n\nexport const buildRequestBody = (params: {\n readonly model: string\n readonly history: ReadonlyArray<Items.HistoryItem>\n readonly maxTokens: number\n readonly temperature: Option.Option<number>\n readonly topP: Option.Option<number>\n readonly topK: Option.Option<number>\n readonly stopSequences: Option.Option<ReadonlyArray<string>>\n readonly thinking: Option.Option<ThinkingConfig>\n readonly tools: Option.Option<ReadonlyArray<Record<string, unknown>>>\n readonly toolChoice: Option.Option<Record<string, unknown>>\n readonly userId: Option.Option<string>\n readonly outputConfig: Option.Option<Record<string, unknown>>\n}): Result.Result<RequestBody, JsonParseError> =>\n pipe(\n groupedMessages(params.history),\n Result.map(\n (messages): RequestBody => ({\n model: params.model,\n messages,\n max_tokens: params.maxTokens,\n ...Option.match(systemFromHistory(params.history), {\n onNone: () => ({}),\n onSome: (system) => ({ system }),\n }),\n ...Option.match(params.temperature, {\n onNone: () => ({}),\n onSome: (temperature) => ({ temperature }),\n }),\n ...Option.match(params.topP, {\n onNone: () => ({}),\n onSome: (top_p) => ({ top_p }),\n }),\n ...Option.match(params.topK, {\n onNone: () => ({}),\n onSome: (top_k) => ({ top_k }),\n }),\n ...Option.match(params.stopSequences, {\n onNone: () => ({}),\n onSome: (stop_sequences) => ({ stop_sequences }),\n }),\n ...Option.match(params.thinking, {\n onNone: () => ({}),\n onSome: (thinking) => ({ thinking }),\n }),\n ...Option.match(params.tools, {\n onNone: () => ({}),\n onSome: (tools) => ({ tools }),\n }),\n ...Option.match(params.toolChoice, {\n onNone: () => ({}),\n onSome: (tool_choice) => ({ tool_choice }),\n }),\n ...Option.match(params.userId, {\n onNone: () => ({}),\n onSome: (user_id) => ({ metadata: { user_id } }),\n }),\n ...Option.match(params.outputConfig, {\n onNone: () => ({}),\n onSome: (output_config) => ({ output_config }),\n }),\n stream: true,\n }),\n ),\n )\n\n// ---------------------------------------------------------------------------\n// Stream-level state - assemble content blocks index-by-index, then emit\n// our `Items.HistoryItem[]` when `message_stop` lands.\n// ---------------------------------------------------------------------------\n\ntype BlockBuffer = {\n readonly type: WireContentBlock[\"type\"]\n readonly text: string\n readonly inputJson: string\n readonly thinking: string\n readonly signature: string\n readonly id: Option.Option<string>\n readonly name: Option.Option<string>\n readonly redactedData: Option.Option<string>\n}\n\nconst emptyBlock = (type: WireContentBlock[\"type\"]): BlockBuffer => ({\n type,\n text: \"\",\n inputJson: \"\",\n thinking: \"\",\n signature: \"\",\n id: Option.none(),\n name: Option.none(),\n redactedData: Option.none(),\n})\n\nexport type Accumulator = {\n readonly blocks: Readonly<Record<number, BlockBuffer>>\n readonly stopReason: Option.Option<string>\n readonly usage: Items.Usage\n}\n\nexport const emptyAccumulator: Accumulator = {\n blocks: {},\n stopReason: Option.none(),\n usage: {},\n}\n\nconst replaceBlock = (acc: Accumulator, index: number, block: BlockBuffer): Accumulator => ({\n ...acc,\n blocks: { ...acc.blocks, [index]: block },\n})\n\nconst updateBlock = (\n acc: Accumulator,\n index: number,\n patch: (block: BlockBuffer) => BlockBuffer,\n): Accumulator => replaceBlock(acc, index, patch(acc.blocks[index] ?? emptyBlock(\"text\")))\n\nexport const startBlock = (acc: Accumulator, index: number, block: WireContentBlock): Accumulator =>\n Match.value(block).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n text: () => replaceBlock(acc, index, emptyBlock(\"text\")),\n tool_use: (b) =>\n replaceBlock(acc, index, {\n ...emptyBlock(\"tool_use\"),\n id: Option.some(b.id),\n name: Option.some(b.name),\n inputJson: typeof b.input === \"string\" ? b.input : \"\",\n }),\n thinking: () => replaceBlock(acc, index, emptyBlock(\"thinking\")),\n redacted_thinking: (b) =>\n replaceBlock(acc, index, {\n ...emptyBlock(\"redacted_thinking\"),\n redactedData: Option.some(b.data),\n }),\n }),\n )\n\nexport const appendTextDelta = (acc: Accumulator, index: number, text: string): Accumulator =>\n updateBlock(acc, index, (b) => ({ ...b, text: b.text + text }))\n\nexport const appendInputJsonDelta = (\n acc: Accumulator,\n index: number,\n partial: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, inputJson: b.inputJson + partial }))\n\nexport const appendThinkingDelta = (\n acc: Accumulator,\n index: number,\n thinking: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, thinking: b.thinking + thinking }))\n\nexport const appendSignatureDelta = (\n acc: Accumulator,\n index: number,\n signature: string,\n): Accumulator => updateBlock(acc, index, (b) => ({ ...b, signature: b.signature + signature }))\n\nexport const setStopReason = (acc: Accumulator, reason: string): Accumulator => ({\n ...acc,\n stopReason: Option.some(reason),\n})\n\nconst cachedFromWire = (wire: WireUsage): Option.Option<number> =>\n Option.fromNullishOr(wire.cache_read_input_tokens)\n\nexport const mergeUsage = (acc: Accumulator, wire: WireUsage): Accumulator => {\n const cached = cachedFromWire(wire)\n const usage: Items.Usage = {\n ...acc.usage,\n ...(wire.input_tokens !== undefined && { input_tokens: wire.input_tokens }),\n ...(wire.output_tokens !== undefined && { output_tokens: wire.output_tokens }),\n ...(wire.input_tokens !== undefined &&\n wire.output_tokens !== undefined && {\n total_tokens: wire.input_tokens + wire.output_tokens,\n }),\n ...Option.match(cached, {\n onNone: () => ({}),\n onSome: (cached_tokens) => ({ input_tokens_details: { cached_tokens } }),\n }),\n }\n return { ...acc, usage }\n}\n\nconst stopReasonFromAnthropic = (reason: Option.Option<string>): Turn[\"stop_reason\"] =>\n Option.match(reason, {\n onNone: () => \"stop\" as const,\n onSome: (r) =>\n Match.value(r).pipe(\n Match.when(\"tool_use\", () => \"tool_calls\" as const),\n Match.when(\"max_tokens\", () => \"max_tokens\" as const),\n Match.orElse(() => \"stop\" as const),\n ),\n })\n\nconst blocksByIndex = (acc: Accumulator): ReadonlyArray<BlockBuffer> =>\n pipe(\n Object.keys(acc.blocks),\n Arr.map((k) => Number(k)),\n Arr.sort(Order.Number),\n Arr.map((i) => acc.blocks[i]!),\n )\n\nconst blockToItems = (block: BlockBuffer): ReadonlyArray<Items.HistoryItem> =>\n Match.value(block.type).pipe(\n Match.when(\n \"text\",\n (): ReadonlyArray<Items.HistoryItem> =>\n block.text.length === 0\n ? []\n : [\n {\n type: \"message\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: block.text }],\n },\n ],\n ),\n Match.when(\n \"tool_use\",\n (): ReadonlyArray<Items.HistoryItem> => [\n {\n type: \"function_call\",\n call_id: Option.getOrElse(block.id, () => \"\"),\n name: Option.getOrElse(block.name, () => \"\"),\n arguments: block.inputJson,\n },\n ],\n ),\n Match.when(\n \"thinking\",\n (): ReadonlyArray<Items.HistoryItem> => [\n {\n type: \"reasoning\",\n ...(block.thinking.length > 0 && { summary: block.thinking }),\n ...(block.signature.length > 0 && { signature: block.signature }),\n },\n ],\n ),\n Match.when(\n \"redacted_thinking\",\n (): ReadonlyArray<Items.HistoryItem> => [\n {\n type: \"reasoning\",\n ...Option.match(block.redactedData, {\n onNone: () => ({}),\n onSome: (signature) => ({ signature }),\n }),\n },\n ],\n ),\n Match.exhaustive,\n )\n\ntype MergeAcc = {\n readonly out: ReadonlyArray<Items.HistoryItem>\n}\n\nconst mergeStep = (acc: MergeAcc, item: Items.HistoryItem): MergeAcc => {\n const last = Arr.last(acc.out)\n if (\n Option.isSome(last) &&\n last.value.type === \"message\" &&\n last.value.role === \"assistant\" &&\n item.type === \"message\" &&\n item.role === \"assistant\"\n ) {\n const merged: Items.Message = {\n ...last.value,\n content: [...last.value.content, ...item.content],\n }\n return { out: [...acc.out.slice(0, -1), merged] }\n }\n return { out: [...acc.out, item] }\n}\n\nconst mergeAdjacentAssistantText = (\n items: ReadonlyArray<Items.HistoryItem>,\n): ReadonlyArray<Items.HistoryItem> => Arr.reduce(items, { out: [] } as MergeAcc, mergeStep).out\n\nexport const accumulatorToTurn = (acc: Accumulator): Turn => ({\n items: pipe(blocksByIndex(acc), Arr.flatMap(blockToItems), mergeAdjacentAssistantText),\n usage: acc.usage,\n stop_reason: stopReasonFromAnthropic(acc.stopReason),\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-uai/anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Anthropic Messages API provider for @effect-uai/core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"effect": "4.0.0-beta.57",
|
|
47
47
|
"typescript": "^6.0.3",
|
|
48
|
-
"@effect-uai/core": "0.
|
|
48
|
+
"@effect-uai/core": "0.7.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@effect-uai/core": ">=0.2.0 <1",
|
package/src/codec.ts
CHANGED
|
@@ -158,7 +158,7 @@ const parseJson = (s: string): Result.Result<unknown, JsonParseError> =>
|
|
|
158
158
|
|
|
159
159
|
type RoleBucket = "user" | "assistant" | "system"
|
|
160
160
|
|
|
161
|
-
const roleBucket = (item: Items.
|
|
161
|
+
const roleBucket = (item: Items.HistoryItem): RoleBucket =>
|
|
162
162
|
Match.value(item).pipe(
|
|
163
163
|
Match.discriminatorsExhaustive("type")({
|
|
164
164
|
message: (m) => m.role,
|
|
@@ -168,7 +168,7 @@ const roleBucket = (item: Items.Item): RoleBucket =>
|
|
|
168
168
|
}),
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
const itemToUserBlocks = (item: Items.
|
|
171
|
+
const itemToUserBlocks = (item: Items.HistoryItem): ReadonlyArray<RequestUserContentBlock> =>
|
|
172
172
|
Match.value(item).pipe(
|
|
173
173
|
Match.discriminatorsExhaustive("type")({
|
|
174
174
|
message: (m): ReadonlyArray<RequestUserContentBlock> =>
|
|
@@ -182,7 +182,7 @@ const itemToUserBlocks = (item: Items.Item): ReadonlyArray<RequestUserContentBlo
|
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
const itemToAssistantBlocks = (
|
|
185
|
-
item: Items.
|
|
185
|
+
item: Items.HistoryItem,
|
|
186
186
|
): Result.Result<ReadonlyArray<RequestAssistantContentBlock>, JsonParseError> =>
|
|
187
187
|
Match.value(item).pipe(
|
|
188
188
|
Match.discriminatorsExhaustive("type")({
|
|
@@ -268,7 +268,10 @@ const appendAssistant = (
|
|
|
268
268
|
assistantBuf: blocks,
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
const groupStep = (
|
|
271
|
+
const groupStep = (
|
|
272
|
+
acc: GroupAcc,
|
|
273
|
+
item: Items.HistoryItem,
|
|
274
|
+
): Result.Result<GroupAcc, JsonParseError> => {
|
|
272
275
|
const bucket = roleBucket(item)
|
|
273
276
|
if (bucket === "system") return Result.succeed(acc)
|
|
274
277
|
if (bucket === "user") {
|
|
@@ -288,7 +291,7 @@ const groupStep = (acc: GroupAcc, item: Items.Item): Result.Result<GroupAcc, Jso
|
|
|
288
291
|
* requires an object input.
|
|
289
292
|
*/
|
|
290
293
|
const groupedMessages = (
|
|
291
|
-
history: ReadonlyArray<Items.
|
|
294
|
+
history: ReadonlyArray<Items.HistoryItem>,
|
|
292
295
|
): Result.Result<ReadonlyArray<RequestMessage>, JsonParseError> => {
|
|
293
296
|
const initial: Result.Result<GroupAcc, JsonParseError> = Result.succeed({
|
|
294
297
|
messages: [],
|
|
@@ -302,10 +305,10 @@ const groupedMessages = (
|
|
|
302
305
|
)
|
|
303
306
|
}
|
|
304
307
|
|
|
305
|
-
const isSystemMessage = (item: Items.
|
|
308
|
+
const isSystemMessage = (item: Items.HistoryItem): item is Items.Message =>
|
|
306
309
|
item.type === "message" && item.role === "system"
|
|
307
310
|
|
|
308
|
-
const systemFromHistory = (history: ReadonlyArray<Items.
|
|
311
|
+
const systemFromHistory = (history: ReadonlyArray<Items.HistoryItem>): Option.Option<string> => {
|
|
309
312
|
const texts = pipe(
|
|
310
313
|
history,
|
|
311
314
|
Arr.filterMap((item) =>
|
|
@@ -340,7 +343,7 @@ export type RequestBody = {
|
|
|
340
343
|
|
|
341
344
|
export const buildRequestBody = (params: {
|
|
342
345
|
readonly model: string
|
|
343
|
-
readonly history: ReadonlyArray<Items.
|
|
346
|
+
readonly history: ReadonlyArray<Items.HistoryItem>
|
|
344
347
|
readonly maxTokens: number
|
|
345
348
|
readonly temperature: Option.Option<number>
|
|
346
349
|
readonly topP: Option.Option<number>
|
|
@@ -406,7 +409,7 @@ export const buildRequestBody = (params: {
|
|
|
406
409
|
|
|
407
410
|
// ---------------------------------------------------------------------------
|
|
408
411
|
// Stream-level state - assemble content blocks index-by-index, then emit
|
|
409
|
-
// our `Items.
|
|
412
|
+
// our `Items.HistoryItem[]` when `message_stop` lands.
|
|
410
413
|
// ---------------------------------------------------------------------------
|
|
411
414
|
|
|
412
415
|
type BlockBuffer = {
|
|
@@ -540,11 +543,11 @@ const blocksByIndex = (acc: Accumulator): ReadonlyArray<BlockBuffer> =>
|
|
|
540
543
|
Arr.map((i) => acc.blocks[i]!),
|
|
541
544
|
)
|
|
542
545
|
|
|
543
|
-
const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.
|
|
546
|
+
const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.HistoryItem> =>
|
|
544
547
|
Match.value(block.type).pipe(
|
|
545
548
|
Match.when(
|
|
546
549
|
"text",
|
|
547
|
-
(): ReadonlyArray<Items.
|
|
550
|
+
(): ReadonlyArray<Items.HistoryItem> =>
|
|
548
551
|
block.text.length === 0
|
|
549
552
|
? []
|
|
550
553
|
: [
|
|
@@ -557,7 +560,7 @@ const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.Item> =>
|
|
|
557
560
|
),
|
|
558
561
|
Match.when(
|
|
559
562
|
"tool_use",
|
|
560
|
-
(): ReadonlyArray<Items.
|
|
563
|
+
(): ReadonlyArray<Items.HistoryItem> => [
|
|
561
564
|
{
|
|
562
565
|
type: "function_call",
|
|
563
566
|
call_id: Option.getOrElse(block.id, () => ""),
|
|
@@ -568,7 +571,7 @@ const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.Item> =>
|
|
|
568
571
|
),
|
|
569
572
|
Match.when(
|
|
570
573
|
"thinking",
|
|
571
|
-
(): ReadonlyArray<Items.
|
|
574
|
+
(): ReadonlyArray<Items.HistoryItem> => [
|
|
572
575
|
{
|
|
573
576
|
type: "reasoning",
|
|
574
577
|
...(block.thinking.length > 0 && { summary: block.thinking }),
|
|
@@ -578,7 +581,7 @@ const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.Item> =>
|
|
|
578
581
|
),
|
|
579
582
|
Match.when(
|
|
580
583
|
"redacted_thinking",
|
|
581
|
-
(): ReadonlyArray<Items.
|
|
584
|
+
(): ReadonlyArray<Items.HistoryItem> => [
|
|
582
585
|
{
|
|
583
586
|
type: "reasoning",
|
|
584
587
|
...Option.match(block.redactedData, {
|
|
@@ -592,10 +595,10 @@ const blockToItems = (block: BlockBuffer): ReadonlyArray<Items.Item> =>
|
|
|
592
595
|
)
|
|
593
596
|
|
|
594
597
|
type MergeAcc = {
|
|
595
|
-
readonly out: ReadonlyArray<Items.
|
|
598
|
+
readonly out: ReadonlyArray<Items.HistoryItem>
|
|
596
599
|
}
|
|
597
600
|
|
|
598
|
-
const mergeStep = (acc: MergeAcc, item: Items.
|
|
601
|
+
const mergeStep = (acc: MergeAcc, item: Items.HistoryItem): MergeAcc => {
|
|
599
602
|
const last = Arr.last(acc.out)
|
|
600
603
|
if (
|
|
601
604
|
Option.isSome(last) &&
|
|
@@ -613,8 +616,9 @@ const mergeStep = (acc: MergeAcc, item: Items.Item): MergeAcc => {
|
|
|
613
616
|
return { out: [...acc.out, item] }
|
|
614
617
|
}
|
|
615
618
|
|
|
616
|
-
const mergeAdjacentAssistantText = (
|
|
617
|
-
|
|
619
|
+
const mergeAdjacentAssistantText = (
|
|
620
|
+
items: ReadonlyArray<Items.HistoryItem>,
|
|
621
|
+
): ReadonlyArray<Items.HistoryItem> => Arr.reduce(items, { out: [] } as MergeAcc, mergeStep).out
|
|
618
622
|
|
|
619
623
|
export const accumulatorToTurn = (acc: Accumulator): Turn => ({
|
|
620
624
|
items: pipe(blocksByIndex(acc), Arr.flatMap(blockToItems), mergeAdjacentAssistantText),
|