Module: McpDiff::Core::Diff
- Defined in:
- lib/mcp_diff/core/diff.rb
Overview
Structural diff between two snapshots. Emits typed Change hashes (symbol keys); no severities. Port of core/src/diff.ts. Entity payloads (before/ after) keep their string-keyed entry shape.
Class Method Summary collapse
- .capability_changes(before_caps, after_caps) ⇒ Object
- .diff(before, after) ⇒ Object
- .entity_changes(before, after, key, kinds, key_field) ⇒ Object
- .scalar_changes(before, after) ⇒ Object
Class Method Details
.capability_changes(before_caps, after_caps) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/mcp_diff/core/diff.rb', line 49 def capability_changes(before_caps, after_caps) changes = [] (before_caps.keys | after_caps.keys).sort.each do |k| b_present = before_caps.key?(k) a_present = after_caps.key?(k) if !b_present && a_present changes << { kind: "capability-added", capability: k, after: after_caps[k] } elsif b_present && !a_present changes << { kind: "capability-removed", capability: k, before: before_caps[k] } elsif b_present && a_present && !Canonical.deep_equal(before_caps[k], after_caps[k]) changes << { kind: "capability-modified", capability: k, before: before_caps[k], after: after_caps[k] } end end changes end |
.diff(before, after) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/mcp_diff/core/diff.rb', line 13 def diff(before, after) changes = [] changes.concat(entity_changes(before["tools"], after["tools"], "name", { added: "tool-added", removed: "tool-removed", modified: "tool-modified" }, :name)) changes.concat(entity_changes(before["resources"], after["resources"], "uri", { added: "resource-added", removed: "resource-removed", modified: "resource-modified" }, :uri)) changes.concat(entity_changes(before["resourceTemplates"], after["resourceTemplates"], "uriTemplate", { added: "resource-template-added", removed: "resource-template-removed", modified: "resource-template-modified" }, :uriTemplate)) changes.concat(entity_changes(before["prompts"], after["prompts"], "name", { added: "prompt-added", removed: "prompt-removed", modified: "prompt-modified" }, :name)) changes.concat(capability_changes(before["capabilities"] || {}, after["capabilities"] || {})) changes.concat(scalar_changes(before, after)) changes end |
.entity_changes(before, after, key, kinds, key_field) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/mcp_diff/core/diff.rb', line 28 def entity_changes(before, after, key, kinds, key_field) before ||= [] after ||= [] before_map = before.to_h { |item| [item[key], item] } after_map = after.to_h { |item| [item[key], item] } changes = [] before_map.each do |k, item| nxt = after_map[k] if nxt.nil? && !after_map.key?(k) changes << { kind: kinds[:removed], key_field => k, before: item } elsif !Canonical.deep_equal(item, nxt) changes << { kind: kinds[:modified], key_field => k, before: item, after: nxt } end end after_map.each do |k, item| changes << { kind: kinds[:added], key_field => k, after: item } unless before_map.key?(k) end changes end |
.scalar_changes(before, after) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/mcp_diff/core/diff.rb', line 65 def scalar_changes(before, after) changes = [] unless before["instructions"] == after["instructions"] changes << { kind: "instructions-changed", before: before["instructions"], after: after["instructions"] } end unless Canonical.deep_equal(before["server"], after["server"]) changes << { kind: "server-info-changed", before: before["server"], after: after["server"] } end unless before["protocolVersion"] == after["protocolVersion"] changes << { kind: "protocol-version-changed", before: before["protocolVersion"], after: after["protocolVersion"] } end changes end |