feat: Rich hook forwarding, permission bridge, and toast notifications
Replace hardcoded PowerShell status hooks with stdin-forwarding hooks that send full Claude Code hook data (tool_input, tool_response, prompt, session_id, model, etc.) to /api/claude-hook endpoint. - PowerShell hooks read stdin JSON and POST to /api/claude-hook - Server derives status for backward-compat FAB animations - Server extracts assistant_response from transcript on Stop events - New /api/claude-permission endpoint with Promise-based allow/deny flow - HookNotifications.vue: toast system showing session, prompt, tool use, tool results, notifications, and final assistant response - WebSocket broadcast for claude-hook and claude-permission message types
This commit is contained in:
@@ -7,6 +7,7 @@ import FloatingTerminal from './components/FloatingTerminal.vue'
|
||||
import FloatingResponse from './components/FloatingResponse.vue'
|
||||
import FloatingVoice from './components/FloatingVoice.vue'
|
||||
import AgentBar from './components/AgentBar.vue'
|
||||
import HookNotifications from './components/HookNotifications.vue'
|
||||
import PwaInstallBanner from './components/PwaInstallBanner.vue'
|
||||
import { initWebMCP, getWebMCP } from './services/webmcp'
|
||||
import { initTorch, destroyTorch } from './services/torch'
|
||||
@@ -16,6 +17,7 @@ import { setTerminalControls } from './services/tools/handlers/terminalHandlers'
|
||||
import { setResponseControls } from './services/tools/handlers/responseHandlers'
|
||||
import { useCanvasStore } from './stores/canvas'
|
||||
import { useProjectCanvasStore } from './stores/projectCanvas'
|
||||
import { useClaudeHooksStore } from './stores/claude-hooks'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -68,6 +70,7 @@ const responseRef = ref<InstanceType<typeof FloatingResponse> | null>(null)
|
||||
const voiceRef = ref<InstanceType<typeof FloatingVoice> | null>(null)
|
||||
const canvasStore = useCanvasStore()
|
||||
const projectCanvasStore = useProjectCanvasStore()
|
||||
const hooksStore = useClaudeHooksStore()
|
||||
|
||||
// Voice FAB push-to-talk state
|
||||
const voicePTTActive = ref(false)
|
||||
@@ -231,6 +234,16 @@ function connectStatusWs() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Rich hook data → toast notifications
|
||||
if (msg.type === 'claude-hook') {
|
||||
hooksStore.processHook(msg)
|
||||
}
|
||||
|
||||
// Permission request → persistent toast with allow/deny
|
||||
if (msg.type === 'claude-permission') {
|
||||
hooksStore.processPermission(msg)
|
||||
}
|
||||
} catch { /* ignore non-JSON messages */ }
|
||||
}
|
||||
|
||||
@@ -528,6 +541,9 @@ watch(() => route.name, (newPage) => {
|
||||
<!-- Floating Response (Agent UI messages) -->
|
||||
<FloatingResponse ref="responseRef" />
|
||||
|
||||
<!-- Hook Notifications (toasts from Claude Code hooks) -->
|
||||
<HookNotifications />
|
||||
|
||||
<!-- Floating Voice Input -->
|
||||
<FloatingVoice ref="voiceRef" v-model="showVoice" />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user