generated from nhcarrigan/template
feat: initial prototype
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 47s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 47s
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { writable, derived } from "svelte/store";
|
||||
import { CHARACTER_STATES, type CharacterState } from "$lib/types/states";
|
||||
|
||||
function createCharacterStore() {
|
||||
const { subscribe, set, update } = writable<CharacterState>("idle");
|
||||
|
||||
let stateTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
setState: (state: CharacterState) => {
|
||||
if (stateTimeout) {
|
||||
clearTimeout(stateTimeout);
|
||||
stateTimeout = null;
|
||||
}
|
||||
set(state);
|
||||
},
|
||||
setTemporaryState: (state: CharacterState, durationMs: number = 2000) => {
|
||||
if (stateTimeout) {
|
||||
clearTimeout(stateTimeout);
|
||||
}
|
||||
set(state);
|
||||
stateTimeout = setTimeout(() => {
|
||||
set("idle");
|
||||
stateTimeout = null;
|
||||
}, durationMs);
|
||||
},
|
||||
reset: () => {
|
||||
if (stateTimeout) {
|
||||
clearTimeout(stateTimeout);
|
||||
stateTimeout = null;
|
||||
}
|
||||
set("idle");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const characterState = createCharacterStore();
|
||||
|
||||
export const characterInfo = derived(characterState, ($state) => CHARACTER_STATES[$state]);
|
||||
@@ -0,0 +1,131 @@
|
||||
import { writable, derived } from "svelte/store";
|
||||
import type {
|
||||
ConnectionStatus,
|
||||
PermissionRequest,
|
||||
ClaudeStreamMessage,
|
||||
} from "$lib/types/messages";
|
||||
|
||||
export interface TerminalLine {
|
||||
id: string;
|
||||
type: "user" | "assistant" | "system" | "tool" | "error";
|
||||
content: string;
|
||||
timestamp: Date;
|
||||
toolName?: string;
|
||||
}
|
||||
|
||||
function createClaudeStore() {
|
||||
const connectionStatus = writable<ConnectionStatus>("disconnected");
|
||||
const sessionId = writable<string | null>(null);
|
||||
const currentWorkingDirectory = writable<string>("");
|
||||
const terminalLines = writable<TerminalLine[]>([]);
|
||||
const pendingPermission = writable<PermissionRequest | null>(null);
|
||||
const isProcessing = writable<boolean>(false);
|
||||
const grantedTools = writable<Set<string>>(new Set());
|
||||
const pendingRetryMessage = writable<string | null>(null);
|
||||
|
||||
let lineIdCounter = 0;
|
||||
|
||||
function generateLineId(): string {
|
||||
return `line-${Date.now()}-${lineIdCounter++}`;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionStatus: { subscribe: connectionStatus.subscribe },
|
||||
sessionId: { subscribe: sessionId.subscribe },
|
||||
currentWorkingDirectory: { subscribe: currentWorkingDirectory.subscribe },
|
||||
terminalLines: { subscribe: terminalLines.subscribe },
|
||||
pendingPermission: { subscribe: pendingPermission.subscribe },
|
||||
isProcessing: { subscribe: isProcessing.subscribe },
|
||||
grantedTools: { subscribe: grantedTools.subscribe },
|
||||
pendingRetryMessage: { subscribe: pendingRetryMessage.subscribe },
|
||||
|
||||
setConnectionStatus: (status: ConnectionStatus) => connectionStatus.set(status),
|
||||
setSessionId: (id: string | null) => sessionId.set(id),
|
||||
setWorkingDirectory: (dir: string) => currentWorkingDirectory.set(dir),
|
||||
setProcessing: (processing: boolean) => isProcessing.set(processing),
|
||||
|
||||
addLine: (type: TerminalLine["type"], content: string, toolName?: string) => {
|
||||
const line: TerminalLine = {
|
||||
id: generateLineId(),
|
||||
type,
|
||||
content,
|
||||
timestamp: new Date(),
|
||||
toolName,
|
||||
};
|
||||
terminalLines.update((lines) => [...lines, line]);
|
||||
return line.id;
|
||||
},
|
||||
|
||||
updateLine: (id: string, content: string) => {
|
||||
terminalLines.update((lines) =>
|
||||
lines.map((line) => (line.id === id ? { ...line, content } : line))
|
||||
);
|
||||
},
|
||||
|
||||
appendToLine: (id: string, additionalContent: string) => {
|
||||
terminalLines.update((lines) =>
|
||||
lines.map((line) =>
|
||||
line.id === id ? { ...line, content: line.content + additionalContent } : line
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
clearTerminal: () => terminalLines.set([]),
|
||||
|
||||
getConversationHistory: (): string => {
|
||||
let lines: TerminalLine[] = [];
|
||||
terminalLines.subscribe((l) => (lines = l))();
|
||||
|
||||
// Filter to just user and assistant messages, skip system/tool noise
|
||||
const relevantLines = lines.filter(
|
||||
(line) => line.type === "user" || line.type === "assistant"
|
||||
);
|
||||
|
||||
if (relevantLines.length === 0) return "";
|
||||
|
||||
return relevantLines
|
||||
.map((line) => {
|
||||
const role = line.type === "user" ? "User" : "Assistant";
|
||||
return `${role}: ${line.content}`;
|
||||
})
|
||||
.join("\n\n");
|
||||
},
|
||||
|
||||
requestPermission: (request: PermissionRequest) => pendingPermission.set(request),
|
||||
clearPermission: () => pendingPermission.set(null),
|
||||
|
||||
grantTool: (toolName: string) => {
|
||||
grantedTools.update((tools) => {
|
||||
const newTools = new Set(tools);
|
||||
newTools.add(toolName);
|
||||
return newTools;
|
||||
});
|
||||
},
|
||||
|
||||
getGrantedTools: (): string[] => {
|
||||
let tools: string[] = [];
|
||||
grantedTools.subscribe((t) => (tools = Array.from(t)))();
|
||||
return tools;
|
||||
},
|
||||
|
||||
setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message),
|
||||
|
||||
reset: () => {
|
||||
connectionStatus.set("disconnected");
|
||||
sessionId.set(null);
|
||||
currentWorkingDirectory.set("");
|
||||
terminalLines.set([]);
|
||||
pendingPermission.set(null);
|
||||
isProcessing.set(false);
|
||||
grantedTools.set(new Set());
|
||||
pendingRetryMessage.set(null);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const claudeStore = createClaudeStore();
|
||||
|
||||
export const hasPermissionPending = derived(
|
||||
claudeStore.pendingPermission,
|
||||
($permission) => $permission !== null
|
||||
);
|
||||
Reference in New Issue
Block a user