mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-06-05 23:03:55 +00:00
Fixes onnx version mismatch, vectordb not liking it and dashboard
Fixes summaries not being generated and timeline showing all observations despite of project filter being applied.
This commit is contained in:
+19
-2
@@ -75,13 +75,16 @@ func parseTranscript(path string) (lastUser, lastAssistant string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if msg.Type == "message" {
|
||||
// Transcript entries have type: "user" or "assistant" (not "message")
|
||||
// Check if this is a user/assistant message with content
|
||||
if msg.Type == "user" || msg.Type == "assistant" {
|
||||
text := extractTextContent(msg.Message.Content)
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch msg.Message.Role {
|
||||
// Use the outer type field for role (message.role may differ)
|
||||
switch msg.Type {
|
||||
case "user":
|
||||
lastUser = text
|
||||
case "assistant":
|
||||
@@ -98,6 +101,9 @@ func main() {
|
||||
}
|
||||
|
||||
func handleStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
||||
// Debug: dump raw input
|
||||
fmt.Fprintf(os.Stderr, "[stop] Raw input: %s\n", string(ctx.RawInput))
|
||||
|
||||
// Find session
|
||||
result, err := hooks.GET(ctx.Port, fmt.Sprintf("/api/sessions?claudeSessionId=%s", ctx.SessionID))
|
||||
if err != nil || result == nil {
|
||||
@@ -116,6 +122,17 @@ func handleStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
||||
lastUser, lastAssistant = parseTranscript(input.TranscriptPath)
|
||||
}
|
||||
|
||||
// Debug: log what we extracted
|
||||
fmt.Fprintf(os.Stderr, "[stop] Transcript path: %s\n", input.TranscriptPath)
|
||||
fmt.Fprintf(os.Stderr, "[stop] Last user message length: %d\n", len(lastUser))
|
||||
fmt.Fprintf(os.Stderr, "[stop] Last assistant message length: %d\n", len(lastAssistant))
|
||||
if len(lastAssistant) > 0 {
|
||||
preview := lastAssistant
|
||||
if len(preview) > 300 {
|
||||
preview = preview[:300] + "..."
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[stop] Last assistant preview: %s\n", preview)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[stop] Requesting summary for session %d (transcript: %v)\n", int64(sessionID), input.TranscriptPath != "")
|
||||
|
||||
// Request summary with message context from transcript
|
||||
|
||||
@@ -175,6 +175,29 @@ func (s *ObservationStore) GetRecentObservations(ctx context.Context, project st
|
||||
return scanObservationRows(rows)
|
||||
}
|
||||
|
||||
// GetObservationsByProjectStrict retrieves observations strictly for a specific project.
|
||||
// Unlike GetRecentObservations, this does NOT include global observations from other projects.
|
||||
// Use this for dashboard filtering where the user expects to see only that project's data.
|
||||
func (s *ObservationStore) GetObservationsByProjectStrict(ctx context.Context, project string, limit int) ([]*models.Observation, error) {
|
||||
const query = `
|
||||
SELECT id, sdk_session_id, project, COALESCE(scope, 'project') as scope, type, title, subtitle, facts, narrative,
|
||||
concepts, files_read, files_modified, file_mtimes, prompt_number, discovery_tokens,
|
||||
created_at, created_at_epoch
|
||||
FROM observations
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
`
|
||||
|
||||
rows, err := s.store.QueryContext(ctx, query, project, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return scanObservationRows(rows)
|
||||
}
|
||||
|
||||
// GetObservationCount returns the count of observations for a project (including global).
|
||||
func (s *ObservationStore) GetObservationCount(ctx context.Context, project string) (int, error) {
|
||||
const query = `
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1.23.2
|
||||
@@ -0,0 +1 @@
|
||||
1.23.2
|
||||
@@ -0,0 +1 @@
|
||||
1.23.2
|
||||
@@ -0,0 +1 @@
|
||||
1.23.2
|
||||
@@ -478,8 +478,8 @@ func (s *Service) handleGetObservations(w http.ResponseWriter, r *http.Request)
|
||||
// Fall back to SQLite if vector search not used
|
||||
if !usedVector {
|
||||
if project != "" {
|
||||
// Filter by project - includes project-scoped and global observations
|
||||
observations, err = s.observationStore.GetRecentObservations(r.Context(), project, limit)
|
||||
// Strict project filtering for dashboard - only observations from this project
|
||||
observations, err = s.observationStore.GetObservationsByProjectStrict(r.Context(), project, limit)
|
||||
} else {
|
||||
// All projects
|
||||
observations, err = s.observationStore.GetAllRecentObservations(r.Context(), limit)
|
||||
|
||||
@@ -234,11 +234,19 @@ func (p *Processor) ProcessObservation(ctx context.Context, sdkSessionID, projec
|
||||
|
||||
// ProcessSummary processes a session summary request.
|
||||
func (p *Processor) ProcessSummary(ctx context.Context, sessionDBID int64, sdkSessionID, project, userPrompt, lastUserMsg, lastAssistantMsg string) error {
|
||||
// Debug: log what we received
|
||||
log.Debug().
|
||||
Int64("sessionId", sessionDBID).
|
||||
Int("lastAssistantMsgLen", len(lastAssistantMsg)).
|
||||
Str("lastAssistantMsgPreview", truncateForLog(lastAssistantMsg, 200)).
|
||||
Msg("ProcessSummary called")
|
||||
|
||||
// Skip summary generation if there's no meaningful assistant response
|
||||
// This prevents generic "initial session setup" summaries
|
||||
if !hasMeaningfulContent(lastAssistantMsg) {
|
||||
log.Info().
|
||||
Int64("sessionId", sessionDBID).
|
||||
Int("msgLen", len(lastAssistantMsg)).
|
||||
Msg("Skipping summary - no meaningful assistant response")
|
||||
return nil
|
||||
}
|
||||
@@ -727,6 +735,14 @@ func hasMeaningfulContent(assistantMsg string) bool {
|
||||
return matchCount >= 2
|
||||
}
|
||||
|
||||
// truncateForLog truncates a string for logging purposes.
|
||||
func truncateForLog(s string, maxLen int) string {
|
||||
if len(s) <= maxLen {
|
||||
return s
|
||||
}
|
||||
return s[:maxLen] + "..."
|
||||
}
|
||||
|
||||
const systemPrompt = `You are a memory extraction agent for Claude Code sessions. Your job is to analyze tool executions and extract meaningful observations that would be useful for future sessions.
|
||||
|
||||
GUIDELINES:
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
#!/bin/bash
|
||||
# Download ONNX Runtime libraries for embedding
|
||||
# Usage: ./download-onnx-libs.sh [platform]
|
||||
# Usage: ./download-onnx-libs.sh [platform] [--force]
|
||||
# Platform: darwin-arm64, linux-amd64, windows-amd64, or "all" (default)
|
||||
# Use --force to re-download even if libraries exist
|
||||
|
||||
set -e
|
||||
|
||||
ONNX_VERSION="1.23.2"
|
||||
ASSETS_DIR="internal/embedding/assets/lib"
|
||||
PLATFORM="${1:-all}"
|
||||
FORCE_DOWNLOAD=false
|
||||
|
||||
# Check for --force flag
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = "--force" ]; then
|
||||
FORCE_DOWNLOAD=true
|
||||
fi
|
||||
done
|
||||
|
||||
# Auto-detect platform if not specified
|
||||
if [ "$PLATFORM" = "auto" ]; then
|
||||
@@ -31,12 +40,38 @@ fi
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
trap "rm -rf ${TEMP_DIR}" EXIT
|
||||
|
||||
# Get the installed version for a platform
|
||||
get_installed_version() {
|
||||
local plat="$1"
|
||||
local version_file="${ASSETS_DIR}/${plat}/.version"
|
||||
if [ -f "$version_file" ]; then
|
||||
cat "$version_file"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# Write version file after successful download
|
||||
write_version_file() {
|
||||
local plat="$1"
|
||||
echo "${ONNX_VERSION}" > "${ASSETS_DIR}/${plat}/.version"
|
||||
}
|
||||
|
||||
# Check if version matches
|
||||
version_matches() {
|
||||
local plat="$1"
|
||||
local installed_version
|
||||
installed_version=$(get_installed_version "$plat")
|
||||
[ "$installed_version" = "$ONNX_VERSION" ]
|
||||
}
|
||||
|
||||
download_darwin_arm64() {
|
||||
echo "Downloading darwin-arm64..."
|
||||
mkdir -p "${ASSETS_DIR}/darwin-arm64"
|
||||
curl -fsSL "https://github.com/microsoft/onnxruntime/releases/download/v${ONNX_VERSION}/onnxruntime-osx-arm64-${ONNX_VERSION}.tgz" -o "${TEMP_DIR}/darwin-arm64.tgz"
|
||||
tar -xzf "${TEMP_DIR}/darwin-arm64.tgz" -C "${TEMP_DIR}"
|
||||
cp "${TEMP_DIR}/onnxruntime-osx-arm64-${ONNX_VERSION}/lib/libonnxruntime.${ONNX_VERSION}.dylib" "${ASSETS_DIR}/darwin-arm64/libonnxruntime.dylib"
|
||||
write_version_file "darwin-arm64"
|
||||
}
|
||||
|
||||
download_linux_amd64() {
|
||||
@@ -46,6 +81,7 @@ download_linux_amd64() {
|
||||
tar -xzf "${TEMP_DIR}/linux-amd64.tgz" -C "${TEMP_DIR}"
|
||||
cp "${TEMP_DIR}/onnxruntime-linux-x64-${ONNX_VERSION}/lib/libonnxruntime.so.${ONNX_VERSION}" "${ASSETS_DIR}/linux-amd64/libonnxruntime.so"
|
||||
cp "${TEMP_DIR}/onnxruntime-linux-x64-${ONNX_VERSION}/lib/libonnxruntime_providers_shared.so" "${ASSETS_DIR}/linux-amd64/libonnxruntime_providers_shared.so" 2>/dev/null || true
|
||||
write_version_file "linux-amd64"
|
||||
}
|
||||
|
||||
download_linux_arm64() {
|
||||
@@ -55,6 +91,7 @@ download_linux_arm64() {
|
||||
tar -xzf "${TEMP_DIR}/linux-arm64.tgz" -C "${TEMP_DIR}"
|
||||
cp "${TEMP_DIR}/onnxruntime-linux-aarch64-${ONNX_VERSION}/lib/libonnxruntime.so.${ONNX_VERSION}" "${ASSETS_DIR}/linux-arm64/libonnxruntime.so"
|
||||
cp "${TEMP_DIR}/onnxruntime-linux-aarch64-${ONNX_VERSION}/lib/libonnxruntime_providers_shared.so" "${ASSETS_DIR}/linux-arm64/libonnxruntime_providers_shared.so" 2>/dev/null || true
|
||||
write_version_file "linux-arm64"
|
||||
}
|
||||
|
||||
download_windows_amd64() {
|
||||
@@ -66,6 +103,7 @@ download_windows_amd64() {
|
||||
echo "Downloaded file size: $(wc -c < "${TEMP_DIR}/windows-amd64.zip") bytes"
|
||||
unzip -q "${TEMP_DIR}/windows-amd64.zip" -d "${TEMP_DIR}"
|
||||
cp "${TEMP_DIR}/onnxruntime-win-x64-${ONNX_VERSION}/lib/onnxruntime.dll" "${ASSETS_DIR}/windows-amd64/onnxruntime.dll"
|
||||
write_version_file "windows-amd64"
|
||||
}
|
||||
|
||||
# Check if library already exists for a platform
|
||||
@@ -79,19 +117,40 @@ lib_exists() {
|
||||
esac
|
||||
}
|
||||
|
||||
# Download only if not present
|
||||
# Download only if not present or version mismatch
|
||||
download_if_needed() {
|
||||
local plat="$1"
|
||||
if lib_exists "$plat"; then
|
||||
echo "Library for ${plat} already exists, skipping download"
|
||||
return 0
|
||||
local need_download=false
|
||||
local reason=""
|
||||
|
||||
if [ "$FORCE_DOWNLOAD" = true ]; then
|
||||
need_download=true
|
||||
reason="forced"
|
||||
elif ! lib_exists "$plat"; then
|
||||
need_download=true
|
||||
reason="not found"
|
||||
elif ! version_matches "$plat"; then
|
||||
local installed_version
|
||||
installed_version=$(get_installed_version "$plat")
|
||||
need_download=true
|
||||
reason="version mismatch (installed: ${installed_version:-unknown}, required: ${ONNX_VERSION})"
|
||||
fi
|
||||
|
||||
if [ "$need_download" = true ]; then
|
||||
if [ -n "$reason" ] && [ "$reason" != "not found" ]; then
|
||||
echo "Re-downloading ${plat}: ${reason}"
|
||||
fi
|
||||
# Remove old library before downloading
|
||||
rm -rf "${ASSETS_DIR}/${plat}"
|
||||
case "$plat" in
|
||||
darwin-arm64) download_darwin_arm64 ;;
|
||||
linux-amd64) download_linux_amd64 ;;
|
||||
linux-arm64) download_linux_arm64 ;;
|
||||
windows-amd64) download_windows_amd64 ;;
|
||||
esac
|
||||
else
|
||||
echo "Library for ${plat} already exists (v${ONNX_VERSION}), skipping download"
|
||||
fi
|
||||
case "$plat" in
|
||||
darwin-arm64) download_darwin_arm64 ;;
|
||||
linux-amd64) download_linux_amd64 ;;
|
||||
linux-arm64) download_linux_arm64 ;;
|
||||
windows-amd64) download_windows_amd64 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
echo "ONNX Runtime v${ONNX_VERSION} - Platform: ${PLATFORM}"
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "claude-mnemonic-dashboard",
|
||||
"version": "v0.6.5-23-g21bcbfa",
|
||||
"version": "v0.6.5-25-g372942e-dirty",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "claude-mnemonic-dashboard",
|
||||
"version": "v0.6.5-23-g21bcbfa",
|
||||
"version": "v0.6.5-25-g372942e-dirty",
|
||||
"dependencies": {
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mnemonic-dashboard",
|
||||
"version": "v0.6.5-23-g21bcbfa",
|
||||
"version": "v0.6.5-25-g372942e-dirty",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user