Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/features/characters/components/CharacterLibraryView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function CharacterLibraryDetailCard({
return (
<div className="space-y-4">
<div className="overflow-hidden rounded-[1.5rem] border border-[var(--border)]/50 bg-[var(--background)]/70 shadow-[0_24px_70px_-40px_rgba(15,23,42,0.95)] sm:rounded-[2rem]">
<div className="relative aspect-[4/3] overflow-hidden bg-gradient-to-br from-pink-400/25 via-rose-500/15 to-sky-400/15">
<div className="relative aspect-square overflow-hidden bg-gradient-to-br from-pink-400/25 via-rose-500/15 to-sky-400/15">
{character.avatarPath ? (
<img
src={character.avatarPath}
Expand Down Expand Up @@ -426,7 +426,7 @@ export function CharacterLibraryView() {
: "border-[var(--border)]/50",
)}
>
<div className="relative h-24 w-24 shrink-0 overflow-hidden bg-gradient-to-br from-pink-400/25 via-rose-500/15 to-sky-400/15 sm:h-auto sm:w-full sm:aspect-[4/3]">
<div className="relative h-24 w-24 shrink-0 overflow-hidden bg-gradient-to-br from-pink-400/25 via-rose-500/15 to-sky-400/15 sm:h-auto sm:w-full sm:aspect-square">
{char.avatarPath ? (
<img
src={char.avatarPath}
Expand Down
2 changes: 1 addition & 1 deletion src/features/settings/components/SettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3131,7 +3131,7 @@ function AdvancedSettings() {
label="Debug mode"
checked={debugMode}
onChange={setDebugMode}
help="Logs the prompt and response payloads sent to the local Tauri console for debugging."
help="Shows the in-app agent debug panel and logs LLM prompt/response payloads to the browser console."
/>

{/* ── Profile Export ── */}
Expand Down
22 changes: 19 additions & 3 deletions src/shared/api/llm-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LlmChunk, LlmGateway, LlmRequest } from "../../engine/capabilities/llm";
import { Channel } from "@tauri-apps/api/core";
import { logLlmCompleteResponse, logLlmRequest, logLlmStreamResponse } from "./llm-debug-logger";
import { invokeTauri } from "./tauri-client";

function createStreamId(): string {
Expand All @@ -8,13 +9,20 @@ function createStreamId(): string {
}

export const llmApi: LlmGateway = {
complete: (request: LlmRequest) =>
invokeTauri("llm_complete", {
complete: async (request: LlmRequest) => {
logLlmRequest("complete", request);
const response = await invokeTauri<string>("llm_complete", {
request,
}),
});
logLlmCompleteResponse(response);
return response;
},
stream: async function* (request: LlmRequest, signal?: AbortSignal): AsyncGenerator<LlmChunk> {
logLlmRequest("stream", request);
const streamId = createStreamId();
const queue: LlmChunk[] = [];
const debugChunks: LlmChunk[] = [];
let debugContent = "";
let completed = false;
let failure: unknown = null;
let wake: (() => void) | null = null;
Expand Down Expand Up @@ -60,11 +68,19 @@ export const llmApi: LlmGateway = {
continue;
}
const event = queue.shift()!;
debugChunks.push(event);
if ((event.type === "token" || event.type === "thinking") && event.text) {
debugContent += event.text;
}
if (event.type === "error") throw new Error(String(event.text ?? event.data ?? "LLM stream failed"));
yield event;
}
await command;
if (failure) throw failure;
logLlmStreamResponse(debugChunks, debugContent);
} catch (error) {
logLlmStreamResponse(debugChunks, debugContent, error);
throw error;
} finally {
signal?.removeEventListener("abort", abort);
}
Expand Down
50 changes: 50 additions & 0 deletions src/shared/api/llm-debug-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { LlmChunk, LlmRequest } from "../../engine/capabilities/llm";
import { useUIStore } from "../stores/ui.store";

type LlmDebugKind = "complete" | "stream";

function isDebugModeEnabled(): boolean {
try {
return useUIStore.getState().debugMode === true;
} catch {
return false;
}
}

function redactSensitiveValue(value: unknown): unknown {
if (Array.isArray(value)) return value.map(redactSensitiveValue);
if (!value || typeof value !== "object") return value;

const redacted: Record<string, unknown> = {};
for (const [key, entry] of Object.entries(value)) {
if (/(token|secret|password|api[_-]?key|authorization|cookie|credential)/i.test(key)) {
redacted[key] = "[REDACTED]";
continue;
}
redacted[key] = redactSensitiveValue(entry);
}
return redacted;
}

function logDebugGroup(label: string, payload: Record<string, unknown>) {
if (!isDebugModeEnabled()) return;
console.groupCollapsed(label);
console.log(redactSensitiveValue(payload));
console.groupEnd();
}

export function logLlmRequest(kind: LlmDebugKind, request: LlmRequest) {
logDebugGroup(`[Marinara debug] LLM ${kind} request`, { request });
}

export function logLlmCompleteResponse(response: string) {
logDebugGroup("[Marinara debug] LLM complete response", { response });
}

export function logLlmStreamResponse(chunks: LlmChunk[], content: string, error?: unknown) {
logDebugGroup("[Marinara debug] LLM stream response", {
content,
chunks,
...(error ? { error: error instanceof Error ? error.message : String(error) } : {}),
});
}
35 changes: 35 additions & 0 deletions updates/people/promansis.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Current Work

- GitHub issue #34: Debug Mode contract mismatch.
- Status: Locally verified
- Last updated: 2026-05-21
- Current path: `src/shared/api/llm-api.ts` debug logging and Settings copy.
- Result: shared LLM complete/stream calls now emit redacted prompt and response payloads to the browser console when Debug mode is enabled, while the in-app agent debug panel remains tied to the same setting.
- Next step: smoke a real generation path with Debug mode enabled and confirm the console groups appear.

- Message translation failures leave no visible error
- Status: Fixed locally on `fix/bug-19-translation-errors`
- Impact area: UI, shared/api, Rust capability error surface
Expand All @@ -10,6 +17,34 @@

## Owned Bugs

## Debug Mode contract mismatch

- Status: Locally verified
- Owner: Promansis
- Impact area: shared/api
- Reported: 2026-05-21
- Last updated: 2026-05-21

### Steps

1. Enable Debug mode in settings.
2. Run a generation path.
3. Compare the Settings help text against the runtime debug output.

### Expected

Debug mode should match its documented contract.

### Actual

The in-app agent debug panel is wired, but prompt/response console logging is not consistently owned by a shared LLM helper.

### Notes

- Upstream issue: https://github.com/Pasta-Devs/Marinara-Engine-Refactor/issues/34
- Fix: centralized redacted LLM request/response console logging in `src/shared/api/llm-api.ts` while preserving the agent debug panel.
- Verification: `pnpm typecheck` and `pnpm check` passed.

## Message translation failures leave no visible error

- Status: Fixed locally on `fix/bug-19-translation-errors`
Expand Down