Module: ClaudeMemory::MCP::Handlers::ManagementHandlers

Included in:
Tools
Defined in:
lib/claude_memory/mcp/handlers/management_handlers.rb

Overview

Management tool handlers (store_extraction, promote, sweep, changes, conflicts)

Instance Method Summary collapse

Instance Method Details

#changes(args) ⇒ Object



108
109
110
111
112
113
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 108

def changes(args)
  since = args["since"] || (Time.now - 86400 * 7).utc.iso8601
  scope = args["scope"] || "all"
  list = @recall.changes(since: since, limit: args["limit"] || 20, scope: scope)
  ResponseFormatter.format_changes(since, list)
end

#conflicts(args) ⇒ Object



115
116
117
118
119
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 115

def conflicts(args)
  scope = args["scope"] || "all"
  list = @recall.conflicts(scope: scope)
  ResponseFormatter.format_conflicts(list)
end

#mark_distilled(args) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 121

def mark_distilled(args)
  content_item_id = args["content_item_id"]
  facts_extracted = args["facts_extracted"] || 0

  store = find_store_for_content_item(content_item_id)
  return {error: "Content item #{content_item_id} not found"} unless store

  store.record_ingestion_metrics(
    content_item_id: content_item_id,
    input_tokens: 0,
    output_tokens: 0,
    facts_extracted: facts_extracted
  )

  {
    success: true,
    content_item_id: content_item_id,
    facts_extracted: facts_extracted
  }
end

#promote(args) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 51

def promote(args)
  return {error: "Promote requires StoreManager"} unless @manager

  fact_id = args["fact_id"]
  global_fact_id = @manager.promote_fact(fact_id)

  if global_fact_id
    {
      success: true,
      project_fact_id: fact_id,
      global_fact_id: global_fact_id,
      message: "Fact promoted to global memory"
    }
  else
    {error: "Fact #{fact_id} not found in project database"}
  end
end

#reject_fact(args) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 69

def reject_fact(args)
  scope = args["scope"] || "project"
  store = get_store_for_scope(scope)
  return {error: "Database not available"} unless store

  fact_id = args["fact_id"]
  if fact_id.nil? && args["docid"]
    row = store.find_fact_by_docid(args["docid"])
    fact_id = row && row[:id]
  end
  return {error: "fact_id or docid required"} if fact_id.nil?

  result = store.reject_fact(fact_id, reason: args["reason"])
  return {error: "Fact #{fact_id} not found in #{scope} database"} if result.nil?

  {
    success: true,
    scope: scope,
    fact_id: fact_id,
    conflicts_resolved: result[:conflicts_resolved],
    message: "Fact rejected"
  }
end

#store_extraction(args) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 8

def store_extraction(args)
  scope = args["scope"] || "project"
  store = get_store_for_scope(scope)
  return {error: "Database not available"} unless store

  entities = (args["entities"] || []).map { |e| symbolize_keys(e) }
  facts = (args["facts"] || []).map { |f| symbolize_keys(f) }
  decisions = (args["decisions"] || []).map { |d| symbolize_keys(d) }

  config = Configuration.new
  project_path = config.project_dir
  occurred_at = Time.now.utc.iso8601

  searchable_text = Core::TextBuilder.build_searchable_text(entities, facts, decisions)
  content_item_id = create_synthetic_content_item(store, searchable_text, project_path, occurred_at)
  index_content_item(store, content_item_id, searchable_text)

  extraction = Distill::Extraction.new(
    entities: entities,
    facts: facts,
    decisions: decisions,
    signals: []
  )

  resolver = Resolve::Resolver.new(store)
  result = resolver.apply(
    extraction,
    content_item_id: content_item_id,
    occurred_at: occurred_at,
    project_path: project_path,
    scope: scope
  )

  {
    success: true,
    scope: scope,
    entities_created: result[:entities_created],
    facts_created: result[:facts_created],
    facts_superseded: result[:facts_superseded],
    conflicts_created: result[:conflicts_created]
  }
end

#sweep_now(args) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/claude_memory/mcp/handlers/management_handlers.rb', line 93

def sweep_now(args)
  scope = args["scope"] || "project"
  store = get_store_for_scope(scope)
  return {error: "Database not available"} unless store

  sweeper = Sweep::Sweeper.new(store)
  budget = args["budget_seconds"] || 5
  stats = if args["escalate"]
    sweeper.run_with_escalation!(budget_seconds: budget)
  else
    sweeper.run!(budget_seconds: budget)
  end
  ResponseFormatter.format_sweep_stats(scope, stats)
end