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
|
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)
|
text := extractTextContent(msg.Message.Content)
|
||||||
if text == "" {
|
if text == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch msg.Message.Role {
|
// Use the outer type field for role (message.role may differ)
|
||||||
|
switch msg.Type {
|
||||||
case "user":
|
case "user":
|
||||||
lastUser = text
|
lastUser = text
|
||||||
case "assistant":
|
case "assistant":
|
||||||
@@ -98,6 +101,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
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
|
// Find session
|
||||||
result, err := hooks.GET(ctx.Port, fmt.Sprintf("/api/sessions?claudeSessionId=%s", ctx.SessionID))
|
result, err := hooks.GET(ctx.Port, fmt.Sprintf("/api/sessions?claudeSessionId=%s", ctx.SessionID))
|
||||||
if err != nil || result == nil {
|
if err != nil || result == nil {
|
||||||
@@ -116,6 +122,17 @@ func handleStop(ctx *hooks.HookContext, input *Input) (string, error) {
|
|||||||
lastUser, lastAssistant = parseTranscript(input.TranscriptPath)
|
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 != "")
|
fmt.Fprintf(os.Stderr, "[stop] Requesting summary for session %d (transcript: %v)\n", int64(sessionID), input.TranscriptPath != "")
|
||||||
|
|
||||||
// Request summary with message context from transcript
|
// Request summary with message context from transcript
|
||||||
|
|||||||
@@ -175,6 +175,29 @@ func (s *ObservationStore) GetRecentObservations(ctx context.Context, project st
|
|||||||
return scanObservationRows(rows)
|
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).
|
// GetObservationCount returns the count of observations for a project (including global).
|
||||||
func (s *ObservationStore) GetObservationCount(ctx context.Context, project string) (int, error) {
|
func (s *ObservationStore) GetObservationCount(ctx context.Context, project string) (int, error) {
|
||||||
const query = `
|
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
|
// Fall back to SQLite if vector search not used
|
||||||
if !usedVector {
|
if !usedVector {
|
||||||
if project != "" {
|
if project != "" {
|
||||||
// Filter by project - includes project-scoped and global observations
|
// Strict project filtering for dashboard - only observations from this project
|
||||||
observations, err = s.observationStore.GetRecentObservations(r.Context(), project, limit)
|
observations, err = s.observationStore.GetObservationsByProjectStrict(r.Context(), project, limit)
|
||||||
} else {
|
} else {
|
||||||
// All projects
|
// All projects
|
||||||
observations, err = s.observationStore.GetAllRecentObservations(r.Context(), limit)
|
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.
|
// ProcessSummary processes a session summary request.
|
||||||
func (p *Processor) ProcessSummary(ctx context.Context, sessionDBID int64, sdkSessionID, project, userPrompt, lastUserMsg, lastAssistantMsg string) error {
|
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
|
// Skip summary generation if there's no meaningful assistant response
|
||||||
// This prevents generic "initial session setup" summaries
|
// This prevents generic "initial session setup" summaries
|
||||||
if !hasMeaningfulContent(lastAssistantMsg) {
|
if !hasMeaningfulContent(lastAssistantMsg) {
|
||||||
log.Info().
|
log.Info().
|
||||||
Int64("sessionId", sessionDBID).
|
Int64("sessionId", sessionDBID).
|
||||||
|
Int("msgLen", len(lastAssistantMsg)).
|
||||||
Msg("Skipping summary - no meaningful assistant response")
|
Msg("Skipping summary - no meaningful assistant response")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -727,6 +735,14 @@ func hasMeaningfulContent(assistantMsg string) bool {
|
|||||||
return matchCount >= 2
|
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.
|
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:
|
GUIDELINES:
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Download ONNX Runtime libraries for embedding
|
# 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)
|
# Platform: darwin-arm64, linux-amd64, windows-amd64, or "all" (default)
|
||||||
|
# Use --force to re-download even if libraries exist
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ONNX_VERSION="1.23.2"
|
ONNX_VERSION="1.23.2"
|
||||||
ASSETS_DIR="internal/embedding/assets/lib"
|
ASSETS_DIR="internal/embedding/assets/lib"
|
||||||
PLATFORM="${1:-all}"
|
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
|
# Auto-detect platform if not specified
|
||||||
if [ "$PLATFORM" = "auto" ]; then
|
if [ "$PLATFORM" = "auto" ]; then
|
||||||
@@ -31,12 +40,38 @@ fi
|
|||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
trap "rm -rf ${TEMP_DIR}" EXIT
|
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() {
|
download_darwin_arm64() {
|
||||||
echo "Downloading darwin-arm64..."
|
echo "Downloading darwin-arm64..."
|
||||||
mkdir -p "${ASSETS_DIR}/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"
|
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}"
|
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"
|
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() {
|
download_linux_amd64() {
|
||||||
@@ -46,6 +81,7 @@ download_linux_amd64() {
|
|||||||
tar -xzf "${TEMP_DIR}/linux-amd64.tgz" -C "${TEMP_DIR}"
|
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.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
|
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() {
|
download_linux_arm64() {
|
||||||
@@ -55,6 +91,7 @@ download_linux_arm64() {
|
|||||||
tar -xzf "${TEMP_DIR}/linux-arm64.tgz" -C "${TEMP_DIR}"
|
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.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
|
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() {
|
download_windows_amd64() {
|
||||||
@@ -66,6 +103,7 @@ download_windows_amd64() {
|
|||||||
echo "Downloaded file size: $(wc -c < "${TEMP_DIR}/windows-amd64.zip") bytes"
|
echo "Downloaded file size: $(wc -c < "${TEMP_DIR}/windows-amd64.zip") bytes"
|
||||||
unzip -q "${TEMP_DIR}/windows-amd64.zip" -d "${TEMP_DIR}"
|
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"
|
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
|
# Check if library already exists for a platform
|
||||||
@@ -79,19 +117,40 @@ lib_exists() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download only if not present
|
# Download only if not present or version mismatch
|
||||||
download_if_needed() {
|
download_if_needed() {
|
||||||
local plat="$1"
|
local plat="$1"
|
||||||
if lib_exists "$plat"; then
|
local need_download=false
|
||||||
echo "Library for ${plat} already exists, skipping download"
|
local reason=""
|
||||||
return 0
|
|
||||||
|
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
|
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}"
|
echo "ONNX Runtime v${ONNX_VERSION} - Platform: ${PLATFORM}"
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-mnemonic-dashboard",
|
"name": "claude-mnemonic-dashboard",
|
||||||
"version": "v0.6.5-23-g21bcbfa",
|
"version": "v0.6.5-25-g372942e-dirty",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "claude-mnemonic-dashboard",
|
"name": "claude-mnemonic-dashboard",
|
||||||
"version": "v0.6.5-23-g21bcbfa",
|
"version": "v0.6.5-25-g372942e-dirty",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vue": "^3.5.13"
|
"vue": "^3.5.13"
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-mnemonic-dashboard",
|
"name": "claude-mnemonic-dashboard",
|
||||||
"version": "v0.6.5-23-g21bcbfa",
|
"version": "v0.6.5-25-g372942e-dirty",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user