feat: initial prototype
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 47s

This commit is contained in:
2026-01-14 20:56:28 -08:00
parent daf1bfecb8
commit f393dfb359
68 changed files with 9391 additions and 12 deletions
+136
View File
@@ -0,0 +1,136 @@
import type { CharacterState } from "$lib/types/states";
import type { ClaudeStreamMessage, ToolUseContentBlock } from "$lib/types/messages";
const SEARCH_TOOLS = ["Read", "Glob", "Grep", "WebSearch", "WebFetch"];
const CODING_TOOLS = ["Edit", "Write", "NotebookEdit"];
function getToolCategory(toolName: string): CharacterState {
if (SEARCH_TOOLS.includes(toolName)) {
return "searching";
}
if (CODING_TOOLS.includes(toolName)) {
return "coding";
}
if (toolName.startsWith("mcp__")) {
return "mcp";
}
if (toolName === "Task") {
return "thinking";
}
return "typing";
}
export function mapMessageToState(message: ClaudeStreamMessage): CharacterState | null {
switch (message.type) {
case "system":
if (message.subtype === "init") {
return "idle";
}
return null;
case "assistant": {
const toolUses = message.message.content.filter(
(block): block is ToolUseContentBlock => block.type === "tool_use"
);
if (toolUses.length > 0) {
const lastTool = toolUses[toolUses.length - 1];
return getToolCategory(lastTool.name);
}
const hasText = message.message.content.some((block) => block.type === "text");
if (hasText) {
return "typing";
}
const hasThinking = message.message.content.some((block) => block.type === "thinking");
if (hasThinking) {
return "thinking";
}
return null;
}
case "stream_event": {
const event = message.event;
if (event.type === "content_block_start") {
if (event.content_block?.type === "thinking") {
return "thinking";
}
if (event.content_block?.type === "text") {
return "typing";
}
if (event.content_block?.type === "tool_use") {
const toolBlock = event.content_block as ToolUseContentBlock;
return getToolCategory(toolBlock.name);
}
}
if (event.type === "content_block_delta") {
if (event.delta?.type === "thinking_delta") {
return "thinking";
}
if (event.delta?.type === "text_delta") {
return "typing";
}
}
return null;
}
case "result":
if (message.subtype === "success") {
return "success";
}
if (message.subtype.startsWith("error")) {
return "error";
}
return null;
case "user":
return null;
default:
return null;
}
}
export function extractTextFromMessage(message: ClaudeStreamMessage): string | null {
if (message.type === "assistant") {
const textBlocks = message.message.content
.filter((block) => block.type === "text")
.map((block) => (block as { type: "text"; text: string }).text);
return textBlocks.length > 0 ? textBlocks.join("\n") : null;
}
if (message.type === "stream_event" && message.event.delta?.text) {
return message.event.delta.text;
}
if (message.type === "result" && message.result) {
return message.result;
}
return null;
}
export function extractToolInfo(
message: ClaudeStreamMessage
): { name: string; input: Record<string, unknown> }[] {
if (message.type !== "assistant") {
return [];
}
return message.message.content
.filter((block): block is ToolUseContentBlock => block.type === "tool_use")
.map((block) => ({
name: block.name,
input: block.input,
}));
}