Skip to content

[integrations] Wearable capture core#48

Open
alanshurafa wants to merge 2 commits into
mainfrom
contrib/alanshurafa/wearable-capture-core
Open

[integrations] Wearable capture core#48
alanshurafa wants to merge 2 commits into
mainfrom
contrib/alanshurafa/wearable-capture-core

Conversation

@alanshurafa

Copy link
Copy Markdown
Owner

What

A reusable engine that turns any polling wearable (Omi, Limitless, future devices) into Open Brain thoughts. Per-device adapters implement a small four-method interface; the core owns everything they share.

Why

Always-on wearables expose your spoken life through a polling API, and each needs the same plumbing to reach the brain — pull recent records, skip already-captured ones, embed, insert. This packages that once so a new device is a ~40-line adapter, not a new pipeline.

How it works

  • Adapter contractsourceId, sourceType, listSince(sinceISO), recordId(record), recordToThoughts(record).
  • Engine (runWearableSync) — pulls a rolling window, dedups on the device's own record id stored in thoughts.metadata (idempotent, self-healing across outages, no local state file), maps via the adapter using the device's own structured output (no per-item LLM cost), embeds via OpenRouter, inserts into thoughts.

Guardrails

  • Additive only — no thoughts schema changes.
  • Secrets via Deno.env only (no keys in code).
  • deno check / deno lint / deno fmt clean.

Adapters (separate PRs, build on this)

  • [integrations] Omi wearable capture
  • [integrations] Limitless wearable capture

🤖 Generated with Claude Code

Reusable engine that turns any polling wearable (Omi, Limitless, future
devices) into Open Brain thoughts. Per-device adapters implement a four-method
WearableAdapter interface (sourceId, sourceType, listSince, recordId,
recordToThoughts); the core owns auth, idempotent dedup (on the device's own
record id, stored in thoughts.metadata — no local state file), OpenRouter
embedding, and inserts into thoughts. Additive only; no thoughts-schema changes;
secrets via Deno.env. Adapters: wearable-omi-capture, wearable-limitless-capture.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d225dae94b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +81 to +83
Copy [`wearable-sync.ts`](./wearable-sync.ts) from this folder to `supabase/functions/_shared/wearable-sync.ts`.

✅ **Done when:** `supabase/functions/_shared/wearable-sync.ts` exists and `deno check supabase/functions/_shared/wearable-sync.ts` is clean.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the import map in the install path

When users follow this install step in a Supabase project that does not already map @supabase/supabase-js, the copied _shared/wearable-sync.ts cannot be checked or deployed because its bare import relies on this integration folder's deno.json, which the instructions leave behind. Either use a fully qualified npm:/JSR/URL import in the shared file or document copying/adding the import map alongside it so the README's deno check supabase/functions/_shared/wearable-sync.ts condition can actually pass.

Useful? React with 👍 / 👎.

.contains("metadata", { wearable_source: adapter.sourceId, provider_event_id: providerEventId })
.limit(1);
if (selErr) throw selErr;
if (existing && existing.length > 0) { skipped++; continue; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve retries for multi-thought records

For adapters that return multiple thoughts for one provider record, the first successful insert stores this provider_event_id; if a later thought in the same loop fails during embedding or insert, the next sync sees that one existing row and skips the entire record, so the remaining thoughts are never retried. Include a per-thought sub-id/index in the idempotency key or make all thoughts for a record commit atomically before treating the provider event as captured.

Useful? React with 👍 / 👎.

Summary-per-recording capture lost the detail inside long voice
recordings. Rework the core to emit ATOMS (title, action items, events,
transcript chunks) using the device's own structure, so each becomes its
own searchable, individually-attributed thought — still no per-item LLM
cost. Replace device-id dedup with a salted per-atom fingerprint
sha256(source|provider_event_id|atom_index|content), deduped via a
GIN-indexed metadata containment query so it stays additive on the
baseline thoughts schema. Tag every atom with attribution
(self/other/mixed/machine/unknown) + attributed_to + generator, and add
a Retry-After-aware fetch helper so a 429 slows a pass instead of
aborting it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant