mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-06-15 02:22:18 +00:00
Additional abstractions for both sqlite and chroma.
This commit is contained in:
@@ -2,9 +2,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/lukaszraczylo/claude-mnemonic/pkg/hooks"
|
||||
@@ -12,61 +10,29 @@ import (
|
||||
|
||||
// Input is the hook input from Claude Code.
|
||||
type Input struct {
|
||||
SessionID string `json:"session_id"`
|
||||
CWD string `json:"cwd"`
|
||||
PermissionMode string `json:"permission_mode"`
|
||||
HookEventName string `json:"hook_event_name"`
|
||||
ToolName string `json:"tool_name"`
|
||||
ToolInput interface{} `json:"tool_input"`
|
||||
ToolResponse interface{} `json:"tool_response"`
|
||||
ToolUseID string `json:"tool_use_id"`
|
||||
hooks.BaseInput
|
||||
ToolName string `json:"tool_name"`
|
||||
ToolInput interface{} `json:"tool_input"`
|
||||
ToolResponse interface{} `json:"tool_response"`
|
||||
ToolUseID string `json:"tool_use_id"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Skip if this is an internal call (from SDK processor)
|
||||
if os.Getenv("CLAUDE_MNEMONIC_INTERNAL") == "1" {
|
||||
hooks.WriteResponse("PostToolUse", true)
|
||||
return
|
||||
}
|
||||
|
||||
// Read input from stdin
|
||||
inputData, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
hooks.WriteError("PostToolUse", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var input Input
|
||||
if err := json.Unmarshal(inputData, &input); err != nil {
|
||||
hooks.WriteError("PostToolUse", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Ensure worker is running
|
||||
port, err := hooks.EnsureWorkerRunning()
|
||||
if err != nil {
|
||||
hooks.WriteError("PostToolUse", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
hooks.RunHook("PostToolUse", handlePostToolUse)
|
||||
}
|
||||
|
||||
func handlePostToolUse(ctx *hooks.HookContext, input *Input) (string, error) {
|
||||
fmt.Fprintf(os.Stderr, "[post-tool-use] %s\n", input.ToolName)
|
||||
|
||||
// Generate project ID from CWD (same logic as user-prompt hook)
|
||||
project := hooks.ProjectIDWithName(input.CWD)
|
||||
|
||||
// Send observation to worker
|
||||
_, err = hooks.POST(port, "/api/sessions/observations", map[string]interface{}{
|
||||
"claudeSessionId": input.SessionID,
|
||||
"project": project,
|
||||
_, err := hooks.POST(ctx.Port, "/api/sessions/observations", map[string]interface{}{
|
||||
"claudeSessionId": ctx.SessionID,
|
||||
"project": ctx.Project,
|
||||
"tool_name": input.ToolName,
|
||||
"tool_input": input.ToolInput,
|
||||
"tool_response": input.ToolResponse,
|
||||
"cwd": input.CWD,
|
||||
"cwd": ctx.CWD,
|
||||
})
|
||||
if err != nil {
|
||||
hooks.WriteError("PostToolUse", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
hooks.WriteResponse("PostToolUse", true)
|
||||
return "", err
|
||||
}
|
||||
|
||||
+9
-37
@@ -5,7 +5,6 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -14,10 +13,7 @@ import (
|
||||
|
||||
// Input is the hook input from Claude Code.
|
||||
type Input struct {
|
||||
SessionID string `json:"session_id"`
|
||||
CWD string `json:"cwd"`
|
||||
PermissionMode string `json:"permission_mode"`
|
||||
HookEventName string `json:"hook_event_name"`
|
||||
hooks.BaseInput
|
||||
StopHookActive bool `json:"stop_hook_active"`
|
||||
TranscriptPath string `json:"transcript_path"`
|
||||
}
|
||||
@@ -98,44 +94,20 @@ func parseTranscript(path string) (lastUser, lastAssistant string) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Skip if this is an internal call (from SDK processor)
|
||||
if os.Getenv("CLAUDE_MNEMONIC_INTERNAL") == "1" {
|
||||
hooks.WriteResponse("Stop", true)
|
||||
return
|
||||
}
|
||||
|
||||
// Read input from stdin
|
||||
inputData, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
hooks.WriteError("Stop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var input Input
|
||||
if err := json.Unmarshal(inputData, &input); err != nil {
|
||||
hooks.WriteError("Stop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Ensure worker is running
|
||||
port, err := hooks.EnsureWorkerRunning()
|
||||
if err != nil {
|
||||
hooks.WriteError("Stop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
hooks.RunHook("Stop", handleStop)
|
||||
}
|
||||
|
||||
func handleStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
||||
// Find session
|
||||
result, err := hooks.GET(port, fmt.Sprintf("/api/sessions?claudeSessionId=%s", input.SessionID))
|
||||
result, err := hooks.GET(ctx.Port, fmt.Sprintf("/api/sessions?claudeSessionId=%s", ctx.SessionID))
|
||||
if err != nil || result == nil {
|
||||
// Session might not exist, that's OK
|
||||
hooks.WriteResponse("Stop", true)
|
||||
return
|
||||
return "", nil
|
||||
}
|
||||
|
||||
sessionID, ok := result["id"].(float64)
|
||||
if !ok {
|
||||
hooks.WriteResponse("Stop", true)
|
||||
return
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Parse transcript to get last messages for summary context
|
||||
@@ -147,7 +119,7 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "[stop] Requesting summary for session %d (transcript: %v)\n", int64(sessionID), input.TranscriptPath != "")
|
||||
|
||||
// Request summary with message context from transcript
|
||||
_, err = hooks.POST(port, fmt.Sprintf("/sessions/%d/summarize", int64(sessionID)), map[string]interface{}{
|
||||
_, err = hooks.POST(ctx.Port, fmt.Sprintf("/sessions/%d/summarize", int64(sessionID)), map[string]interface{}{
|
||||
"lastUserMessage": lastUser,
|
||||
"lastAssistantMessage": lastAssistant,
|
||||
})
|
||||
@@ -155,5 +127,5 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "[stop] Warning: summary request failed: %v\n", err)
|
||||
}
|
||||
|
||||
hooks.WriteResponse("Stop", true)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/lukaszraczylo/claude-mnemonic/pkg/hooks"
|
||||
@@ -13,55 +11,27 @@ import (
|
||||
|
||||
// Input is the hook input from Claude Code.
|
||||
type Input struct {
|
||||
SessionID string `json:"session_id"`
|
||||
CWD string `json:"cwd"`
|
||||
PermissionMode string `json:"permission_mode"`
|
||||
HookEventName string `json:"hook_event_name"`
|
||||
StopHookActive bool `json:"stop_hook_active"`
|
||||
hooks.BaseInput
|
||||
StopHookActive bool `json:"stop_hook_active"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Skip if this is an internal call (from SDK processor)
|
||||
if os.Getenv("CLAUDE_MNEMONIC_INTERNAL") == "1" {
|
||||
hooks.WriteResponse("SubagentStop", true)
|
||||
return
|
||||
}
|
||||
hooks.RunHook("SubagentStop", handleSubagentStop)
|
||||
}
|
||||
|
||||
// Read input from stdin
|
||||
inputData, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
hooks.WriteError("SubagentStop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var input Input
|
||||
if err := json.Unmarshal(inputData, &input); err != nil {
|
||||
hooks.WriteError("SubagentStop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Ensure worker is running
|
||||
port, err := hooks.EnsureWorkerRunning()
|
||||
if err != nil {
|
||||
hooks.WriteError("SubagentStop", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Generate unique project ID from CWD
|
||||
project := hooks.ProjectIDWithName(input.CWD)
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[subagent-stop] Subagent completed in project %s\n", project)
|
||||
func handleSubagentStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
||||
fmt.Fprintf(os.Stderr, "[subagent-stop] Subagent completed in project %s\n", ctx.Project)
|
||||
|
||||
// Notify worker that a subagent completed
|
||||
// This can trigger processing of any queued observations from the subagent
|
||||
_, err = hooks.POST(port, "/api/sessions/subagent-complete", map[string]interface{}{
|
||||
"claudeSessionId": input.SessionID,
|
||||
"project": project,
|
||||
_, err := hooks.POST(ctx.Port, "/api/sessions/subagent-complete", map[string]interface{}{
|
||||
"claudeSessionId": ctx.SessionID,
|
||||
"project": ctx.Project,
|
||||
})
|
||||
if err != nil {
|
||||
// Non-fatal - just log warning
|
||||
fmt.Fprintf(os.Stderr, "[subagent-stop] Warning: failed to notify worker: %v\n", err)
|
||||
}
|
||||
|
||||
hooks.WriteResponse("SubagentStop", true)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user