Skip to content

Commit 9d5daa7

Browse files
matthallett1claude
andcommitted
[docs] Add upsert_thought to core setup guide — fixes broken new installs
server/index.ts calls upsert_thought but the function was only defined in the optional content-fingerprint-dedup recipe, not in the core SQL setup. Every new user hit this error on their first capture_thought call. Added Step 2.6 with the content_fingerprint column, unique index, and upsert_thought function. Updated verify step to 2.7. Fixes #144, fixes #145 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0e41f62 commit 9d5daa7

1 file changed

Lines changed: 48 additions & 2 deletions

File tree

docs/01-getting-started.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,55 @@ grant select, insert, update, delete on table public.thoughts to service_role;
177177
> [!IMPORTANT]
178178
> This step is required. Supabase no longer grants full table permissions to `service_role` by default on new projects. Without this, your MCP server will return "permission denied for table thoughts" when trying to capture or search.
179179
180-
![2.6](https://img.shields.io/badge/2.6-Verify-555?style=for-the-badge&labelColor=F4511E)
180+
![2.6](https://img.shields.io/badge/2.6-Add_Deduplication-555?style=for-the-badge&labelColor=F4511E)
181181

182-
**Done when:** Table Editor shows the `thoughts` table with columns: id, content, embedding, metadata, created_at, updated_at. Database → Functions shows `match_thoughts`.
182+
New query → paste and Run:
183+
184+
<details>
185+
<summary>📋 <strong>SQL: Content fingerprint column + upsert function</strong> (click to expand)</summary>
186+
187+
```sql
188+
-- Add fingerprint column for deduplication
189+
ALTER TABLE thoughts ADD COLUMN content_fingerprint TEXT;
190+
191+
-- Unique index so duplicate content is detected
192+
CREATE UNIQUE INDEX idx_thoughts_fingerprint
193+
ON thoughts (content_fingerprint)
194+
WHERE content_fingerprint IS NOT NULL;
195+
196+
-- Upsert function: inserts new thoughts, merges metadata on duplicates
197+
CREATE OR REPLACE FUNCTION upsert_thought(p_content TEXT, p_payload JSONB DEFAULT '{}')
198+
RETURNS JSONB AS $$
199+
DECLARE
200+
v_fingerprint TEXT;
201+
v_result JSONB;
202+
v_id UUID;
203+
BEGIN
204+
v_fingerprint := encode(sha256(convert_to(
205+
lower(trim(regexp_replace(p_content, '\s+', ' ', 'g'))),
206+
'UTF8'
207+
)), 'hex');
208+
209+
INSERT INTO thoughts (content, content_fingerprint, metadata)
210+
VALUES (p_content, v_fingerprint, COALESCE(p_payload->'metadata', '{}'::jsonb))
211+
ON CONFLICT (content_fingerprint) DO UPDATE
212+
SET updated_at = now(),
213+
metadata = thoughts.metadata || COALESCE(EXCLUDED.metadata, '{}'::jsonb)
214+
RETURNING id INTO v_id;
215+
216+
v_result := jsonb_build_object('id', v_id, 'fingerprint', v_fingerprint);
217+
RETURN v_result;
218+
END;
219+
$$ LANGUAGE plpgsql;
220+
```
221+
222+
</details>
223+
224+
> This prevents duplicate thoughts from cluttering your database. When you capture the same thought twice, it merges the metadata instead of creating a second row.
225+
226+
![2.7](https://img.shields.io/badge/2.7-Verify-555?style=for-the-badge&labelColor=F4511E)
227+
228+
**Done when:** Table Editor shows the `thoughts` table with columns: id, content, embedding, metadata, content_fingerprint, created_at, updated_at. Database → Functions shows `match_thoughts` and `upsert_thought`.
183229

184230
---
185231

0 commit comments

Comments
 (0)