obsidian-tc 1.0.2 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ -- 20260519_002_entity_unique — F4: enforce the entity natural key
2
+ -- (vault_id, entity_type, name) at the DB level to close the create_entity
3
+ -- read-then-insert race. Pre-existing duplicates are merged into the earliest
4
+ -- (MIN rowid) row. Relations are repointed onto the survivor BEFORE the dedup
5
+ -- DELETE, so the ON DELETE CASCADE FKs do not drop edges that belonged to a
6
+ -- duplicate (review #5); then the unique index is created.
7
+
8
+ -- Repoint outgoing edges of a duplicate onto its surviving sibling. UPDATE OR IGNORE
9
+ -- drops a repoint that would collide with an existing (source,target,type) edge.
10
+ UPDATE OR IGNORE memory_relations
11
+ SET source_id = (
12
+ SELECT keep.id
13
+ FROM memory_entities dup
14
+ JOIN memory_entities keep
15
+ ON keep.vault_id = dup.vault_id
16
+ AND keep.entity_type = dup.entity_type
17
+ AND keep.name = dup.name
18
+ WHERE dup.id = memory_relations.source_id
19
+ ORDER BY keep.rowid
20
+ LIMIT 1
21
+ )
22
+ WHERE source_id IN (
23
+ SELECT id FROM memory_entities
24
+ WHERE rowid NOT IN (SELECT MIN(rowid) FROM memory_entities GROUP BY vault_id, entity_type, name)
25
+ );
26
+
27
+ -- Repoint incoming edges likewise.
28
+ UPDATE OR IGNORE memory_relations
29
+ SET target_id = (
30
+ SELECT keep.id
31
+ FROM memory_entities dup
32
+ JOIN memory_entities keep
33
+ ON keep.vault_id = dup.vault_id
34
+ AND keep.entity_type = dup.entity_type
35
+ AND keep.name = dup.name
36
+ WHERE dup.id = memory_relations.target_id
37
+ ORDER BY keep.rowid
38
+ LIMIT 1
39
+ )
40
+ WHERE target_id IN (
41
+ SELECT id FROM memory_entities
42
+ WHERE rowid NOT IN (SELECT MIN(rowid) FROM memory_entities GROUP BY vault_id, entity_type, name)
43
+ );
44
+
45
+ DELETE FROM memory_entities
46
+ WHERE rowid NOT IN (
47
+ SELECT MIN(rowid) FROM memory_entities GROUP BY vault_id, entity_type, name
48
+ );
49
+
50
+ CREATE UNIQUE INDEX idx_memory_entities_natural_key
51
+ ON memory_entities(vault_id, entity_type, name);
package/dist/schema.sql CHANGED
@@ -139,6 +139,9 @@ CREATE TABLE memory_entities (
139
139
 
140
140
  CREATE INDEX idx_memory_entities_vault_type ON memory_entities(vault_id, entity_type);
141
141
  CREATE INDEX idx_memory_entities_name ON memory_entities(vault_id, name);
142
+ -- Natural key (F4): (vault_id, entity_type, name) is unique — closes the create_entity
143
+ -- read-then-insert race. Migration 20260519_002 dedups + adds this on existing DBs.
144
+ CREATE UNIQUE INDEX idx_memory_entities_natural_key ON memory_entities(vault_id, entity_type, name);
142
145
 
143
146
  CREATE TABLE memory_relations (
144
147
  source_id TEXT NOT NULL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obsidian-tc",
3
- "version": "1.0.2",
3
+ "version": "1.2.1",
4
4
  "description": "MCP server for Obsidian — comprehensive tool surface for humans and autonomous agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -8,7 +8,11 @@
8
8
  "bin": {
9
9
  "obsidian-tc": "./dist/cli.js"
10
10
  },
11
- "files": ["dist", "README.md", "LICENSE"],
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
12
16
  "scripts": {
13
17
  "build": "bun build ./src/index.ts ./src/cli.ts --outdir ./dist --target node && bun scripts/copy-assets.mjs",
14
18
  "typecheck": "tsc --noEmit",
@@ -19,30 +23,36 @@
19
23
  "dependencies": {
20
24
  "@hono/node-server": "^2.0.5",
21
25
  "@modelcontextprotocol/sdk": "^1.0.0",
22
- "@the-40-thieves/obsidian-tc-native": "1.0.2",
23
- "@the-40-thieves/obsidian-tc-shared": "1.0.2",
26
+ "@the-40-thieves/obsidian-tc-native": "1.2.1",
27
+ "@the-40-thieves/obsidian-tc-shared": "1.2.1",
24
28
  "@opentelemetry/api": "^1.9.1",
25
29
  "@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
26
30
  "@opentelemetry/resources": "^2.8.0",
27
31
  "@opentelemetry/sdk-trace-node": "^2.8.0",
28
32
  "@opentelemetry/semantic-conventions": "^1.41.1",
29
- "better-sqlite3": "^11.5.0",
33
+ "better-sqlite3": "^12.11.1",
30
34
  "fetch-to-node": "^2.1.0",
31
35
  "hono": "^4.6.0",
32
36
  "jose": "^6.2.3",
33
37
  "prom-client": "^15.1.3",
34
38
  "sqlite-vec": "^0.1.9",
35
39
  "yaml": "^2.6.1",
36
- "zod": "^3.23.0",
37
- "zod-to-json-schema": "^3.24.0"
40
+ "zod": "^4.0.0"
38
41
  },
39
42
  "devDependencies": {
40
43
  "@types/better-sqlite3": "^7.6.0",
41
- "@types/node": "^22.0.0",
42
- "@vitest/coverage-v8": "^2.1.0",
43
- "vitest": "^2.1.0"
44
+ "@types/node": "^24.0.0",
45
+ "@vitest/coverage-v8": "^3.2.6",
46
+ "vitest": "^3.2.6"
44
47
  },
45
- "keywords": ["obsidian", "mcp", "model-context-protocol", "knowledge-management", "agent", "ai"],
48
+ "keywords": [
49
+ "obsidian",
50
+ "mcp",
51
+ "model-context-protocol",
52
+ "knowledge-management",
53
+ "agent",
54
+ "ai"
55
+ ],
46
56
  "repository": {
47
57
  "type": "git",
48
58
  "url": "https://github.com/The-40-Thieves/obsidian-tc.git",
@@ -51,5 +61,8 @@
51
61
  "exports": {
52
62
  ".": "./dist/index.js",
53
63
  "./package.json": "./package.json"
64
+ },
65
+ "engines": {
66
+ "node": ">=24"
54
67
  }
55
68
  }