Skip to content

fix: migrate bub-tapestore-otel and bub-tapestore-sqlite from republic to bub.tape#49

Open
CorrectRoadH wants to merge 4 commits into
bubbuild:mainfrom
CorrectRoadH:fix/tapestore-otel-tape-entry-validation
Open

fix: migrate bub-tapestore-otel and bub-tapestore-sqlite from republic to bub.tape#49
CorrectRoadH wants to merge 4 commits into
bubbuild:mainfrom
CorrectRoadH:fix/tapestore-otel-tape-entry-validation

Conversation

@CorrectRoadH

@CorrectRoadH CorrectRoadH commented Jun 28, 2026

Copy link
Copy Markdown

Root cause

bub replaced republic with its own tape implementation in commit 04960b1 (feat: replace republic with any-llm-sdk). Both plugins still imported TapeEntry, TapeStore, TapeQuery etc. from republic, so:
close #43 #48

Fix

Migrate both plugins from republic to bub.tape / bub.runtime. No workarounds needed.

bub-tapestore-otel (closes #47):

  • from republic import TapeEntryfrom bub.tape import TapeEntry in exporter.py
  • All republic tape imports → from bub.tape import ... in store.py
  • Remove republic>=0.5.7 from pyproject.toml
  • Remove the SkipValidation workaround (class identity is now correct)

bub-tapestore-sqlite (closes #43):

  • Replace republic imports with bub.tape / bub.runtime
  • RepublicErrorBubError, ErrorKind from bub.runtime
  • Rewrite _build_embedding_client to use the public AnyLLM.create(provider, **settings.model_client_kwargs(provider)) API — no more _core.get_client private access
  • _embedding_client: AnyLLM | None (properly typed)
  • _compute_embedding calls client.aembedding directly
  • Replace republic>=0.5.7 with bub in pyproject.toml

Test results

bub-tapestore-otel:    7 passed
bub-tapestore-sqlite: 11 passed

Both test suites run against local bub HEAD (/Users/ctrdh/Code/bub).

🤖 Generated with Claude Code

https://claude.ai/code/session_01EcGvz588KPpJVkEP2eaDby

…ve TapeEntry class drift

When bub resolves to git HEAD instead of the workspace-locked commit,
TapeEntry instances fail pydantic's isinstance check against the TapeEntry
class captured at schema-build time, causing every append to raise a
ValidationError that the exporter silently swallows — resulting in zero
exported spans.

Use SkipValidation[list[TapeEntry]] on TraceProjection.entries so pydantic
bypasses the isinstance check entirely.  The field is internal-only and
never needs runtime coercion, so skipping validation is safe and is the
explicit recommendation from the pydantic docs for this class of problem.

Adds a regression test that feeds build_tape_trace entries whose class
object differs from republic.TapeEntry to guard against future drift.

Closes bubbuild#47

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcGvz588KPpJVkEP2eaDby
@CorrectRoadH CorrectRoadH marked this pull request as draft June 28, 2026 12:59
…uild_llm dependency

SQLiteTapeStore.__init__ imported and called bub.builtin.agent._build_llm,
a private helper that was removed in bub >= 0.3.10.dev2. This caused an
ImportError before any tape operation could run, even when the store was
used without semantic search.

Fixes:
- Remove the _build_llm call from __init__; initialize self._llm = None
- Add a module-level _build_embedding_client() that uses the public
  AnyLLM.create() and bub.ensure_config(AgentSettings) API, with a
  model_client_kwargs() fallback for newer bub versions
- Build the client lazily in _compute_embedding(), only when semantic
  search is actually invoked
- Update tests to mock _build_embedding_client in bub_tapestore_sqlite.store
  instead of the removed bub.builtin.agent._build_llm

Non-semantic store operations (append, fetch_all without query, list_tapes,
reset) now work against any bub version without touching the LLM layer.

Closes bubbuild#43

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcGvz588KPpJVkEP2eaDby
@CorrectRoadH CorrectRoadH changed the title fix(bub-tapestore-otel): skip pydantic validation on entries to survive TapeEntry class drift fix: resolve bub version drift in bub-tapestore-otel and bub-tapestore-sqlite Jun 28, 2026
bub replaced republic with its own tape implementation (commit 04960b1).
Plugins still imported from republic, so bub.tape.TapeEntry instances
passed at runtime failed pydantic's isinstance check against
republic.TapeEntry — causing ValidationError in otel and ImportError
in sqlite (from the now-deleted _build_llm).

Changes across both plugins:
- Replace all `republic` imports with `bub.tape` / `bub.runtime`
- bub-tapestore-otel: remove SkipValidation workaround (no longer needed
  now that the TapeEntry class identity is correct)
- bub-tapestore-sqlite: replace RepublicError→BubError, ErrorKind from
  bub.runtime; rewrite _build_embedding_client to use the public
  AnyLLM.create(provider, **settings.model_client_kwargs(provider)) API;
  type _embedding_client as AnyLLM|None; simplify _compute_embedding to
  call client.aembedding directly without _core.get_client
- Remove republic>=0.5.7 from both pyproject.toml; add bub to sqlite deps

Closes bubbuild#43
Closes bubbuild#47

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcGvz588KPpJVkEP2eaDby
@CorrectRoadH CorrectRoadH changed the title fix: resolve bub version drift in bub-tapestore-otel and bub-tapestore-sqlite fix: migrate bub-tapestore-otel and bub-tapestore-sqlite from republic to bub.tape Jun 28, 2026
@CorrectRoadH CorrectRoadH marked this pull request as ready for review June 28, 2026 13:20
@CorrectRoadH CorrectRoadH force-pushed the fix/tapestore-otel-tape-entry-validation branch from 5ccbfb8 to bab3d9d Compare June 29, 2026 04:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant