mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-10-12 04:55:18 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
378e7dc489 | ||
|
|
c2c31c8c5d | ||
|
|
b396d05c0f | ||
|
|
66c53deb02 | ||
|
|
372942ec8b | ||
|
|
e3d3f2bb7b |
@@ -221,6 +221,35 @@ builds:
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
|
||||
# Hook: statusline
|
||||
- id: hook-statusline
|
||||
main: ./cmd/hooks/statusline
|
||||
binary: hooks/statusline
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
tags:
|
||||
- fts5
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w
|
||||
- -X main.Version={{.Version}}
|
||||
- -X github.com/lukaszraczylo/claude-mnemonic/pkg/hooks.Version={{.Version}}
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: amd64
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
|
||||
archives:
|
||||
- id: default
|
||||
formats:
|
||||
|
||||
+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
|
||||
}
|
||||
@@ -634,25 +642,57 @@ Your response:`,
|
||||
// rather than actual user work. These summaries should be filtered out.
|
||||
func isSelfReferentialSummary(summary *models.ParsedSummary) bool {
|
||||
// Combine all summary fields for checking
|
||||
content := strings.ToLower(summary.Request + " " + summary.Completed + " " + summary.Learned + " " + summary.NextSteps)
|
||||
content := strings.ToLower(summary.Request + " " + summary.Completed + " " + summary.Learned + " " + summary.NextSteps + " " + summary.Investigated + " " + summary.Notes)
|
||||
|
||||
// Indicators that the summary is about the memory agent, not user work
|
||||
selfReferentialPhrases := []string{
|
||||
// Agent references
|
||||
"memory extraction",
|
||||
"memory agent",
|
||||
"extraction agent",
|
||||
"hook execution",
|
||||
"hook mechanism",
|
||||
// Session meta-state
|
||||
"session initialization",
|
||||
"session setup",
|
||||
"session has just started",
|
||||
"session just started",
|
||||
"agent initialization",
|
||||
"no technical learnings",
|
||||
"no code or project work",
|
||||
// Waiting states
|
||||
"waiting for the user",
|
||||
"waiting for user",
|
||||
"awaiting actual",
|
||||
"awaiting claude code",
|
||||
"awaiting tool",
|
||||
"awaiting user",
|
||||
// Meta checkpoint references
|
||||
"progress checkpoint",
|
||||
"checkpoint request",
|
||||
// Common no-work phrases
|
||||
"no work has been completed",
|
||||
"no work completed",
|
||||
"no work done",
|
||||
"no actual work",
|
||||
"nothing has been completed",
|
||||
"nothing completed",
|
||||
// Role/guideline parroting
|
||||
"role definition",
|
||||
"operational guidelines",
|
||||
"providing role",
|
||||
"providing guidelines",
|
||||
// System prompt echoes
|
||||
"extract meaningful observations",
|
||||
"meaningful learnings",
|
||||
"analyze tool executions",
|
||||
"observations for future sessions",
|
||||
// Empty session indicators
|
||||
"empty session",
|
||||
"no substantive work",
|
||||
"no meaningful work",
|
||||
"just beginning",
|
||||
"just begun",
|
||||
}
|
||||
|
||||
matchCount := 0
|
||||
@@ -677,20 +717,33 @@ func hasMeaningfulContent(assistantMsg string) bool {
|
||||
|
||||
lowerMsg := strings.ToLower(assistantMsg)
|
||||
|
||||
// Skip messages that are primarily about system/hook status
|
||||
// Skip messages that are primarily about system/hook status or meta-instructions
|
||||
skipIndicators := []string{
|
||||
// System/hook markers
|
||||
"hook success",
|
||||
"callback hook",
|
||||
"session start",
|
||||
"sessionstart",
|
||||
"system-reminder",
|
||||
// Agent self-references
|
||||
"memory extraction agent",
|
||||
"memory agent",
|
||||
"extraction agent",
|
||||
// No-work indicators
|
||||
"no technical learnings",
|
||||
"waiting for",
|
||||
"waiting to",
|
||||
"no code or project work",
|
||||
"no substantive",
|
||||
"no work has been completed",
|
||||
"no work done",
|
||||
"awaiting tool",
|
||||
"awaiting user",
|
||||
// Meta-instruction echoes
|
||||
"role definition",
|
||||
"operational guidelines",
|
||||
"analyze tool executions",
|
||||
"extract meaningful observations",
|
||||
}
|
||||
|
||||
skipCount := 0
|
||||
@@ -727,6 +780,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:
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/lukaszraczylo/claude-mnemonic/pkg/models"
|
||||
)
|
||||
|
||||
func TestIsSelfReferentialSummary(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
summary *models.ParsedSummary
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "meta summary about memory agent role",
|
||||
summary: &models.ParsedSummary{
|
||||
Request: "Memory extraction agent role - analyze tool executions and extract meaningful observations for future sessions",
|
||||
Completed: "No work has been completed yet. The session has just started with the user providing role definition and operational guidelines.",
|
||||
Learned: "The system expects observations to be created from meaningful learnings during Claude Code sessions, with focus on decisions, bugs fixed, patterns discovered, project structure changes, and code modifications.",
|
||||
NextSteps: "Awaiting tool executions or user requests that contain actual work performed in a Claude Code session.",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "legitimate summary about code changes",
|
||||
summary: &models.ParsedSummary{
|
||||
Request: "Fix authentication bug in login handler",
|
||||
Completed: "Updated the auth middleware to properly validate JWT tokens and fixed the session expiry check.",
|
||||
Learned: "The JWT library requires explicit algorithm validation to prevent token substitution attacks.",
|
||||
NextSteps: "Add unit tests for the authentication flow.",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "awaiting user summary",
|
||||
summary: &models.ParsedSummary{
|
||||
Request: "Session initialization",
|
||||
Completed: "No work completed yet.",
|
||||
Learned: "Awaiting user input to begin work.",
|
||||
NextSteps: "Waiting for the user to provide instructions.",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "summary about refactoring",
|
||||
summary: &models.ParsedSummary{
|
||||
Request: "Refactor database connection pooling",
|
||||
Completed: "Implemented connection pooling using pgxpool with max 10 connections.",
|
||||
Learned: "pgxpool automatically handles connection reuse and health checks.",
|
||||
NextSteps: "Run benchmarks to verify performance improvement.",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "meta summary with extraction agent mention",
|
||||
summary: &models.ParsedSummary{
|
||||
Request: "Extraction agent initialization",
|
||||
Completed: "No substantive work has been done.",
|
||||
Learned: "The memory extraction agent analyzes tool executions.",
|
||||
NextSteps: "Awaiting tool results to extract observations.",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := isSelfReferentialSummary(tt.summary)
|
||||
if result != tt.expected {
|
||||
t.Errorf("isSelfReferentialSummary() = %v, want %v", result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasMeaningfulContent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "empty content",
|
||||
content: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "too short content",
|
||||
content: "Hello world",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "meta content about memory agent",
|
||||
content: `This is the memory extraction agent role definition.
|
||||
The system expects you to analyze tool executions and extract meaningful observations.
|
||||
No work has been completed yet. Awaiting tool results from the user's session.`,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "legitimate code discussion",
|
||||
content: `I've updated the handler.go file to fix the authentication bug.
|
||||
The function validateToken() was not checking token expiry correctly.
|
||||
I've added a check for exp claim and implemented proper error handling.
|
||||
The changes have been tested and the build passes.`,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "hook status messages",
|
||||
content: `SessionStart:Callback hook success: Success
|
||||
The memory agent is waiting for user input.
|
||||
System-reminder about available tools.
|
||||
No substantive work performed yet.`,
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := hasMeaningfulContent(tt.content)
|
||||
if result != tt.expected {
|
||||
t.Errorf("hasMeaningfulContent() = %v, want %v", result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+10
-15
@@ -13,7 +13,7 @@
|
||||
{
|
||||
"name": "claude-mnemonic",
|
||||
"description": "Persistent memory system for Claude Code - Go implementation with SQLite and ChromaDB vector search",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.8",
|
||||
"author": {
|
||||
"name": "lukaszraczylo",
|
||||
"url": "https://github.com/lukaszraczylo"
|
||||
@@ -23,30 +23,25 @@
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lukaszraczylo/claude-mnemonic",
|
||||
"releases": {
|
||||
"latest": "0.6.1",
|
||||
"latest": "0.6.8",
|
||||
"versions": {
|
||||
"0.6.1": {
|
||||
"releaseDate": "2025-12-15",
|
||||
"0.6.8": {
|
||||
"releaseDate": "2025-12-16",
|
||||
"downloads": {
|
||||
"darwin-amd64": {
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.1/claude-mnemonic_0.6.1_darwin_amd64.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"sha256": "98622f7606d5f1ec451c17bb5d3181b05ec4d0e7dd73d49d2a6493a9fe1ac911"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.1/claude-mnemonic_0.6.1_darwin_arm64.tar.gz",
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.8/claude-mnemonic_0.6.8_darwin_arm64.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"sha256": "bf9c060bf2a5759b9f28d30436673bf555ae614cfa0e3a0ebf2debca136e8dfd"
|
||||
"sha256": "1a796f9e47ee27e2d2c9425e1d1dea886771c9c3f0d4905dc414b5c0763665c6"
|
||||
},
|
||||
"linux-amd64": {
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.1/claude-mnemonic_0.6.1_linux_amd64.tar.gz",
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.8/claude-mnemonic_0.6.8_linux_amd64.tar.gz",
|
||||
"format": "tar.gz",
|
||||
"sha256": "f917be7e2f9f7b2dceee61649ad65c9f51b1d14acc3c76a307aacd0b89b77523"
|
||||
"sha256": "52221d0e0f10d312abd1d521840ac0ac8558145795b8fb63f60a411dd2331637"
|
||||
},
|
||||
"windows-amd64": {
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.1/claude-mnemonic_0.6.1_windows_amd64.zip",
|
||||
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/v0.6.8/claude-mnemonic_0.6.8_windows_amd64.zip",
|
||||
"format": "zip",
|
||||
"sha256": "51fd45ca2bb6c66c07b72a84ccb35ae4b09a64a7f28cc223543dcbc51ccfdb17"
|
||||
"sha256": "08af5820a48bda13d791c21d6e8cb47b0ddfbba101be47c0b8f1c03966749167"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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-11-gdb528b2-dirty",
|
||||
"version": "v0.6.4-2-gb396d05-dirty",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "claude-mnemonic-dashboard",
|
||||
"version": "v0.6.5-11-gdb528b2-dirty",
|
||||
"version": "v0.6.4-2-gb396d05-dirty",
|
||||
"dependencies": {
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mnemonic-dashboard",
|
||||
"version": "v0.6.5-11-gdb528b2-dirty",
|
||||
"version": "v0.6.4-2-gb396d05-dirty",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user