@brian/claude-chat-client (0.1.2)
Installation
@brian:registry=npm install @brian/claude-chat-client@0.1.2"@brian/claude-chat-client": "0.1.2"About this package
@brian/claude-chat-client
Shared Node/TypeScript Anthropic client for homeclaude and
kittycharactersheet's backends (both already use @anthropic-ai/sdk
directly). Owns the streaming request + tool-use round-trip loop; each app
still supplies its own API key, model, and tool implementations, so
per-app usage tracking is unchanged.
Usage
import { createClaudeClient } from "@brian/claude-chat-client";
const claude = createClaudeClient({
apiKey: config.anthropicApiKey, // this app's own key, unchanged
model: config.claudeModel, // this app's own model, unchanged
});
const result = await claude.chat(
{
system: "You are ...",
messages: conversationSoFar,
tools: MY_APP_TOOLS,
},
{
onTextDelta: (delta) => res.write(delta), // pipe into your existing SSE/NDJSON response
onToolUse: (call) => logger.info("tool call", call),
executeTool: async (call) => {
switch (call.name) {
case "create_calendar_event":
return await createCalendarEvent(call.input);
default:
throw new Error(`unknown tool ${call.name}`);
}
},
}
);
// result.messages -> persist as the new conversation history
// result.finalText -> full assistant text across all tool-loop rounds
Tool execution stays app-specific on purpose (calendar writes, dose logs,
character-sheet edits, ...) — this package only owns the loop that calls
the model, detects tool_use blocks, awaits your executeTool, and feeds
tool_result blocks back in until the model stops asking for tools or
maxToolRounds is hit (default 8).
Image attachments
imageContentBlock() builds a Claude image content block from base64 +
media type (mirrors homeclaude's own buildAttachmentBlock()), for
including in a user message's content array alongside a text block:
import { imageContentBlock, isSupportedImageType } from "@brian/claude-chat-client";
const content: Anthropic.MessageParam["content"] = [
{ type: "text", text: userText },
...images.map((img) => imageContentBlock({ mediaType: img.mediaType, base64: img.base64 })),
];
Only image/jpeg, image/png, image/gif, and image/webp are
supported (SUPPORTED_IMAGE_MEDIA_TYPES) — check with
isSupportedImageType() before calling imageContentBlock() on
user-supplied media types.
pdfContentBlock({ base64, title }) and textContentBlock({ text, title })
cover homeclaude's other two attachment kinds (PDF, and its fallback for
everything else — CSV, markdown, JSON, ... read as UTF-8 text):
import { pdfContentBlock, textContentBlock } from "@brian/claude-chat-client";
pdfContentBlock({ base64: pdfBytes.toString("base64"), title: "invoice.pdf" });
textContentBlock({ text: fileBytes.toString("utf8"), title: "notes.md" });
Dependencies
Dependencies
| ID | Version |
|---|---|
| @anthropic-ai/sdk | ^0.100.1 |
Development dependencies
| ID | Version |
|---|---|
| typescript | ^5.5.0 |