Hello from MCP server
<template>
<div v-if="sessionStore.debugMode" class="debug-toolbar">
<div class="debug-toolbar-row">
<span class="debug-label">Debug:</span>
<select v-model="selectedFunction" class="debug-select">
<option value="">-- Select Function --</option>
<optgroup v-for="group in functionGroups" :key="group.label" :label="group.label">
<option v-for="fn in group.functions" :key="fn.value" :value="fn.value">
{{ fn.label }}
</option>
</optgroup>
</select>
<button type="button" class="debug-btn" @click="showDebugInfo = !showDebugInfo">
{{ showDebugInfo ? 'Hide' : 'Show' }} State
</button>
</div>
<div v-if="showDebugInfo" class="debug-info">
<div class="debug-row">
<div class="debug-col">
<slot name="info-sections">
<div class="debug-section">
<strong>No info sections provided</strong>
</div>
</slot>
</div>
<div class="debug-col">
<div class="debug-section">
<strong>Lifecycle States:</strong>
</div>
<div v-for="(lc, idx) in lifecycleStates" :key="'lc-'+idx" class="debug-log-entry">
<span class="debug-time">{{ lc.time }}</span>
<span class="debug-lifecycle">{{ lc.state }}</span>
</div>
<div v-if="lifecycleStates.length === 0" class="debug-empty">No lifecycle events yet</div>
</div>
<div class="debug-col">
<div class="debug-section">
<strong>Function Executions:</strong>
</div>
<div v-for="(fn, idx) in functionExecutions" :key="'fn-'+idx" class="debug-log-entry">
<span class="debug-time">{{ fn.time }}</span>
<span class="debug-fn">{{ fn.name }}({{ fn.args || '' }})</span>
</div>
<div v-if="functionExecutions.length === 0" class="debug-empty">No function calls yet</div>
</div>
</div>
<!-- Reactive Variables JSON -->
<div class="debug-json-section">
<div class="debug-json-header">
<strong>Reactive Variables:</strong>
<button type="button" class="debug-btn-small" @click="jsonExpanded = !jsonExpanded; jsonKey++">
{{ jsonExpanded ? 'Collapse' : 'Expand' }}
</button>
</div>
<pre class="debug-json"><code><JsonViewer :key="jsonKey" :data="reactiveData" :start-collapsed="!jsonExpanded" :expand-all="jsonExpanded" /></code></pre>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import JsonViewer from "@/components/JsonViewer.vue";
import { useSessionStore } from "@/stores/session";
const sessionStore = useSessionStore();
export interface FunctionOption {
label: string;
value: string;
}
export interface FunctionGroup {
label: string;
functions: FunctionOption[];
}
interface FunctionExecution {
name: string;
time: string;
args?: string;
}
interface LifecycleState {
state: string;
time: string;
}
defineProps<{
functionGroups?: FunctionGroup[];
reactiveData?: Record<string, any>;
}>();
const selectedFunction = ref('');
const showDebugInfo = ref(false);
const jsonExpanded = ref(false);
const jsonKey = ref(0);
const functionExecutions = ref<FunctionExecution[]>([]);
const lifecycleStates = ref<LifecycleState[]>([]);
function logExecution(name: string, args?: any[]) {
const time = new Date().toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
fractionalSecondDigits: 3
});
const argsStr = args
? args.map(a => typeof a === 'object' ? JSON.stringify(a).slice(0, 50) : String(a)).join(', ')
: undefined;
functionExecutions.value.unshift({ name, time, args: argsStr });
if (functionExecutions.value.length > 20) functionExecutions.value.pop();
}
function logLifecycle(state: string) {
const time = new Date().toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
fractionalSecondDigits: 3
});
lifecycleStates.value.unshift({ state, time });
if (lifecycleStates.value.length > 10) lifecycleStates.value.pop();
}
defineExpose({
logExecution,
logLifecycle,
selectedFunction,
showDebugInfo,
});
</script>
<style scoped>
.debug-toolbar {
padding: 12px 16px;
margin: 0;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
font-family: system-ui, sans-serif;
font-size: 13px;
}
.debug-toolbar-row {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.debug-label {
font-weight: 600;
color: #000;
}
.debug-select {
flex: 1;
min-width: 200px;
max-width: 400px;
padding: 6px 10px;
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
color: #333;
cursor: pointer;
}
.debug-btn {
padding: 6px 14px;
font-size: 12px;
cursor: pointer;
background: #000;
color: #fff;
border: 1px solid #000;
border-radius: 4px;
}
.debug-btn:hover {
background: #333;
}
.debug-info {
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid #ddd;
}
.debug-row {
display: flex;
gap: 24px;
flex-wrap: wrap;
}
.debug-col {
flex: 1;
min-width: 200px;
max-width: 400px;
}
.debug-section {
padding: 4px 0;
font-size: 12px;
color: #333;
}
.debug-section strong {
color: #666;
}
.debug-job-chip {
display: inline-block;
margin-left: 6px;
padding: 2px 6px;
background: #e8e8e8;
color: #000;
border-radius: 3px;
font-family: monospace;
font-size: 11px;
}
.debug-log-entry {
display: flex;
gap: 8px;
padding: 2px 0;
font-size: 11px;
font-family: monospace;
}
.debug-time {
color: #999;
flex-shrink: 0;
}
.debug-lifecycle {
color: #9333ea;
font-weight: 500;
}
.debug-fn {
color: #000;
word-break: break-all;
}
.debug-empty {
font-size: 11px;
color: #999;
font-style: italic;
padding: 4px 0;
}
.debug-json-section {
margin-top: 16px;
padding-top: 12px;
border-top: 1px solid #ddd;
}
.debug-json-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 8px;
}
.debug-json-header strong {
color: #666;
font-size: 12px;
}
.debug-btn-small {
padding: 3px 8px;
font-size: 11px;
cursor: pointer;
background: #000;
color: #fff;
border: 1px solid #000;
border-radius: 3px;
}
.debug-btn-small:hover {
background: #333;
}
.debug-json {
margin: 0;
padding: 12px;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
overflow-x: auto;
max-height: 400px;
overflow-y: auto;
}
.debug-json code {
font-family: monospace;
font-size: 11px;
color: #333;
white-space: pre;
}
</style>