mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-10-17 05:59:36 +00:00
Merge origin/main into mnemonic-ralphised
Resolved conflicts in: - internal/config/config.go: Combined new bool fields with maintenance settings - internal/db/gorm/models.go: Merged field reordering with archival fields - internal/mcp/server.go: Merged field reordering with maintenanceService - internal/search/manager.go: Updated Metadata field to use 'any' type - internal/worker/handlers.go: Kept HEAD version - internal/worker/sdk/processor.go: Combined circuit breaker/dedup with claude path - internal/worker/service.go: Kept HEAD version - ui/src/components/Sidebar.vue: Combined new components with useGraphMetrics - ui/src/utils/api.ts: Combined new APIs with graph/vector metrics
This commit is contained in:
@@ -77,10 +77,10 @@ func TestParseObservations_TableDriven(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedCount int
|
||||
expectedType models.ObservationType
|
||||
expectedTitle string
|
||||
checkConcepts []string
|
||||
expectedCount int
|
||||
}{
|
||||
{
|
||||
name: "valid_bugfix_observation",
|
||||
@@ -300,9 +300,9 @@ func TestParseSummary_TableDriven(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedRequest string
|
||||
sessionID int64
|
||||
expectNil bool
|
||||
expectedRequest string
|
||||
}{
|
||||
{
|
||||
name: "empty_input",
|
||||
|
||||
@@ -208,24 +208,21 @@ type SyncSummaryFunc func(summary *models.SessionSummary)
|
||||
const MaxVectorSyncWorkers = 8
|
||||
|
||||
// Processor handles SDK agent processing of observations and summaries using Claude Code CLI.
|
||||
// Field order optimized for memory alignment (fieldalignment).
|
||||
type Processor struct {
|
||||
claudePath string
|
||||
model string
|
||||
observationStore *gorm.ObservationStore
|
||||
summaryStore *gorm.SummaryStore
|
||||
broadcastFunc BroadcastFunc
|
||||
syncObservationFunc SyncObservationFunc
|
||||
syncSummaryFunc SyncSummaryFunc
|
||||
// Semaphore to limit concurrent Claude CLI calls (prevents API overload)
|
||||
sem chan struct{}
|
||||
// Circuit breaker for CLI failures
|
||||
circuitBreaker *CircuitBreaker
|
||||
// Request deduplicator to prevent duplicate processing
|
||||
deduplicator *RequestDeduplicator
|
||||
// Bounded worker pool for vector sync operations
|
||||
vectorSyncChan chan *models.Observation
|
||||
vectorSyncWg sync.WaitGroup
|
||||
vectorSyncDone chan struct{}
|
||||
circuitBreaker *CircuitBreaker
|
||||
deduplicator *RequestDeduplicator
|
||||
vectorSyncChan chan *models.Observation
|
||||
vectorSyncDone chan struct{}
|
||||
sem chan struct{}
|
||||
claudePath string
|
||||
model string
|
||||
vectorSyncWg sync.WaitGroup
|
||||
}
|
||||
|
||||
// SetBroadcastFunc sets the broadcast callback for SSE events.
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
func TestIsSelfReferentialSummary(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
summary *models.ParsedSummary
|
||||
name string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
@@ -281,8 +281,8 @@ func TestTruncateForLog(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
maxLen int
|
||||
expected string
|
||||
maxLen int
|
||||
}{
|
||||
{
|
||||
name: "shorter_than_max",
|
||||
@@ -719,8 +719,8 @@ func TestShouldSkipTrivialOperation_EdgeCases(t *testing.T) {
|
||||
// TestIsSelfReferentialSummary_MoreCases tests additional self-referential detection cases.
|
||||
func TestIsSelfReferentialSummary_MoreCases(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
summary *models.ParsedSummary
|
||||
name string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -24,12 +24,12 @@ var ObservationConcepts = []string{
|
||||
|
||||
// ToolExecution represents a tool execution for observation.
|
||||
type ToolExecution struct {
|
||||
ID int64
|
||||
ToolName string
|
||||
ToolInput string
|
||||
ToolOutput string
|
||||
CreatedAtEpoch int64
|
||||
CWD string
|
||||
ID int64
|
||||
CreatedAtEpoch int64
|
||||
}
|
||||
|
||||
// BuildObservationPrompt builds a prompt for processing a tool observation.
|
||||
@@ -67,12 +67,12 @@ func BuildObservationPrompt(exec ToolExecution) string {
|
||||
|
||||
// SummaryRequest contains data for building a summary prompt.
|
||||
type SummaryRequest struct {
|
||||
SessionDBID int64
|
||||
SDKSessionID string
|
||||
Project string
|
||||
UserPrompt string
|
||||
LastUserMessage string
|
||||
LastAssistantMessage string
|
||||
SessionDBID int64
|
||||
}
|
||||
|
||||
// BuildSummaryPrompt builds a prompt requesting a session summary.
|
||||
|
||||
@@ -12,8 +12,8 @@ func TestTruncate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
maxLen int
|
||||
expected string
|
||||
maxLen int
|
||||
}{
|
||||
{
|
||||
name: "shorter_than_max",
|
||||
@@ -60,8 +60,8 @@ func TestBuildObservationPrompt(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
exec ToolExecution
|
||||
contains []string
|
||||
exec ToolExecution
|
||||
}{
|
||||
{
|
||||
name: "basic_read_tool",
|
||||
|
||||
@@ -21,11 +21,11 @@ const (
|
||||
|
||||
// ObservationData contains data for a tool observation.
|
||||
type ObservationData struct {
|
||||
ToolName string
|
||||
ToolInput interface{}
|
||||
ToolResponse interface{}
|
||||
PromptNumber int
|
||||
ToolName string
|
||||
CWD string
|
||||
PromptNumber int
|
||||
}
|
||||
|
||||
// SummarizeData contains data for a summarize request.
|
||||
@@ -36,30 +36,28 @@ type SummarizeData struct {
|
||||
|
||||
// PendingMessage represents a message queued for SDK processing.
|
||||
type PendingMessage struct {
|
||||
Type MessageType
|
||||
Observation *ObservationData
|
||||
Summarize *SummarizeData
|
||||
Type MessageType
|
||||
}
|
||||
|
||||
// ActiveSession represents an in-memory active session being processed.
|
||||
type ActiveSession struct {
|
||||
SessionDBID int64
|
||||
ClaudeSessionID string
|
||||
SDKSessionID string
|
||||
StartTime time.Time
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
notify chan struct{}
|
||||
Project string
|
||||
UserPrompt string
|
||||
SDKSessionID string
|
||||
ClaudeSessionID string
|
||||
pendingMessages []PendingMessage
|
||||
LastPromptNumber int
|
||||
StartTime time.Time
|
||||
CumulativeInputTokens int64
|
||||
CumulativeOutputTokens int64
|
||||
|
||||
// Concurrency control
|
||||
pendingMessages []PendingMessage
|
||||
messageMu sync.Mutex
|
||||
notify chan struct{}
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
generatorActive atomic.Bool
|
||||
SessionDBID int64
|
||||
messageMu sync.Mutex
|
||||
generatorActive atomic.Bool
|
||||
}
|
||||
|
||||
// SessionTimeout is how long an inactive session can exist before cleanup.
|
||||
@@ -70,15 +68,14 @@ const CleanupInterval = 5 * time.Minute
|
||||
|
||||
// Manager manages active session lifecycles.
|
||||
type Manager struct {
|
||||
sessionStore *gorm.SessionStore
|
||||
sessions map[int64]*ActiveSession
|
||||
mu sync.RWMutex
|
||||
onCreated func(int64)
|
||||
onDeleted func(int64)
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
// Global notification channel for immediate processing
|
||||
ctx context.Context
|
||||
sessionStore *gorm.SessionStore
|
||||
sessions map[int64]*ActiveSession
|
||||
onCreated func(int64)
|
||||
onDeleted func(int64)
|
||||
cancel context.CancelFunc
|
||||
ProcessNotify chan struct{}
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewManager creates a new session manager.
|
||||
|
||||
@@ -669,16 +669,16 @@ func TestActiveSessionCWD(t *testing.T) {
|
||||
// TestToolInputResponse tests various tool input/response types.
|
||||
func TestToolInputResponse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input interface{}
|
||||
response interface{}
|
||||
name string
|
||||
}{
|
||||
{"nil_values", nil, nil},
|
||||
{"string_values", "input string", "response string"},
|
||||
{"map_values", map[string]string{"key": "value"}, map[string]interface{}{"result": true}},
|
||||
{"slice_values", []string{"a", "b"}, []int{1, 2, 3}},
|
||||
{"int_values", 42, 100},
|
||||
{"bool_values", true, false},
|
||||
{name: "nil_values", input: nil, response: nil},
|
||||
{name: "string_values", input: "input string", response: "response string"},
|
||||
{name: "map_values", input: map[string]string{"key": "value"}, response: map[string]interface{}{"result": true}},
|
||||
{name: "slice_values", input: []string{"a", "b"}, response: []int{1, 2, 3}},
|
||||
{name: "int_values", input: 42, response: 100},
|
||||
{name: "bool_values", input: true, response: false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -19,10 +19,10 @@ const (
|
||||
|
||||
// Client represents a connected SSE client.
|
||||
type Client struct {
|
||||
ID string
|
||||
Writer http.ResponseWriter
|
||||
Flusher http.Flusher
|
||||
Done chan struct{}
|
||||
ID string
|
||||
}
|
||||
|
||||
// Broadcaster manages SSE client connections and message broadcasting.
|
||||
|
||||
@@ -256,8 +256,8 @@ func TestHandleSSE(t *testing.T) {
|
||||
// TestBroadcastJSON tests broadcasting various JSON types.
|
||||
func TestBroadcastJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data interface{}
|
||||
name string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user