Forum teuk.org

๐Ÿช„๐Ÿงฌ MB699 โ€” Two providers, one spellbook, and a much cleaner castle ๐Ÿฐโš—๏ธ

in Mediabot ยท started by TeuK ยท 20h ago

TeuK ยท 20h ago

Some changes add commands.

Some changes add features.

And some changes quietly rearrange the foundations of the castle so the next ten rooms do not collapse into the dungeons. ๐Ÿš๏ธโžก๏ธ๐Ÿฐ

MB699 belongs to the third category.

Until now, Mediabotโ€™s OpenAI and Anthropic integrations had grown through two different historical paths.

Both worked.

Both had proved useful.

But each provider still carried parts of its own request building, HTTP handling, asynchronous execution, error parsing and runtime glue.

That was becoming increasingly difficult to justify.

So MB699 introduces something much more important than another AI command:

a single provider-neutral AI architecture for Mediabot.

The Sorting Hat can now choose the house without rebuilding Hogwarts every time. ๐ŸŽฉ๐Ÿงญ


๐Ÿงฉ A proper AI foundation

MB699 introduces a dedicated AI layer:

Mediabot::AI
Mediabot::AI::Request
Mediabot::AI::Transport
Mediabot::AI::Provider::Anthropic
Mediabot::AI::Provider::OpenAI
Mediabot::AI::Client

The central piece is:

Mediabot::AI::Client

Callers no longer need to understand the provider-specific transport details.

Instead, the flow becomes:

caller
  โ†“
AI::Request
  โ†“
AI::Client
  โ†“
provider adapter
  โ†“
AI::Transport
  โ†“
worker / HTTP

And on the way back:

normalized result
  โ†“
caller-owned history / cache / IRC delivery

One corridor.

One map.

Far fewer moving staircases. ๐Ÿ—บ๏ธ๐Ÿชœ


๐Ÿง™ Anthropic and OpenAI now speak the same architectural language

Both historical AI entry points have been migrated.

๐Ÿฆ‰ Claude / !ai

Claude now delegates its AI execution to Mediabot::AI::Client.

But all the things that genuinely belong to the caller remain there:

  • conversation history;
  • persona;
  • pinned context;
  • prompt cache;
  • rate limiting;
  • inflight protection;
  • history rollback on failure;
  • IRC delivery;
  • output pacing;
  • channel configuration.

The provider-neutral layer handles the AI mechanics.

The IRC layer still handles IRC.

A surprisingly effective spell called separation of concerns. ๐Ÿงน๐Ÿ“


๐Ÿ™ OpenAI / tellme

The historical OpenAI path has also moved behind the same client.

The visible command behavior stays intact, but the implementation now shares the common AI infrastructure.

OpenAI also runs asynchronously rather than blocking the IRC event loop during network calls.

So while an API request is travelling through the Floo Network, the rest of Mediabot can keep doing its job. ๐Ÿ”ฅ๐ŸŒ€


๐Ÿงญ Explicit providers remain explicit

MB699 deliberately avoids magical provider switching behind the userโ€™s back.

If a request explicitly asks for:

anthropic

it remains Anthropic.

If it asks for:

openai

it remains OpenAI.

Cross-provider fallback is reserved for the explicit future:

auto

policy.

In other words:

no Polyjuice Potion unless somebody actually asked for Polyjuice Potion. ๐Ÿงช๐Ÿซ—

OpenAI model fallback can still happen inside the OpenAI provider policy before any future cross-provider fallback is considered.


โš™๏ธ One shared asynchronous transport

Both providers now rely on a shared transport layer.

It handles:

  • JSON POST requests;
  • HTTP verification;
  • request timeouts;
  • normalized HTTP envelopes;
  • worker-safe transport;
  • asynchronous execution.

The providers still own their protocol-specific details:

  • endpoint;
  • headers;
  • payload format;
  • response parsing.

But they no longer reinvent the machinery around them.

That distinction matters.

The cauldron belongs to the transport layer.

The potion recipe belongs to the provider. โš—๏ธ๐Ÿ“œ


๐Ÿงน The legacy cupboard has been emptied

Once both real callers had been proven behind AI::Client, MB699 removed the obsolete duplicate transport paths.

Among the retired helpers:

_chatgpt_http_request
_chatgpt_decode_worker_content
_chatgpt_fallback_worthy
_chatgpt_transport_request
_chatgpt_accept_transport_result
_chatgpt_send_and_parse
_chatgpt_send_and_parse_async

_claude_build_payload
_claude_http_request
_claude_extract_answer
_claude_accept_http_result

External::Claude also no longer directly owns Mediabot::AsyncWorker.

And Anthropic credentials, endpoints and API-version information are no longer unnecessarily copied into the callerโ€™s transient request state.

Less duplication.

Less credential propagation.

Less code pretending it still owns something it no longer owns. ๐Ÿงน๐Ÿ—๏ธ


๐Ÿ–ผ๏ธ A couple of old portraits remain โ€” intentionally

Two Claude wrappers remain:

_claude_send_and_parse
_claude_send_and_parse_async

That is intentional.

They are no longer independent Anthropic transports.

They are compatibility wrappers backed by:

Mediabot::AI::Client

So yes, the portraits are still hanging in the corridor.

They just stopped secretly governing the Ministry. ๐Ÿ–ผ๏ธ๐Ÿ›๏ธ


๐Ÿ“‰ A refactor that actually removes code

The tracked cleanup ended with:

520 insertions
1423 deletions

That is one of the parts I like most about MB699.

The new architecture did not merely pile another abstraction layer on top of the old one.

It allowed us to delete the obsolete architecture underneath it.

Net result:

fewer duplicated paths, clearer ownership, smaller maintenance surface.

A rare Defence Against the Dark Arts lesson where the monster genuinely disappears afterward. ๐Ÿโœจ


๐Ÿงช Validation before cleanup

Before removing the legacy transport paths, the new architecture was validated with:

Targeted : 752/752 PASS
Fast     : 6254/6254 PASS
Full     : 16365/16365 PASS

And both providers were exercised against their real APIs.

Not mocks.

Not optimistic assumptions.

Actual providers. ๐Ÿงซ๐Ÿ”ญ


๐Ÿ”ฌ Validation after cleanup

Once the old transport code had been removed:

Ownership sentinel : 86/86 PASS
Targeted           : 711/711 PASS
Fast               : 6205/6205 PASS
Full               : 16238/16238 PASS

Final repository hygiene:

RC_DIFF=0

The development bot was restarted with the cleaned architecture loaded:

ActiveState=active
SubState=running
ExecMainStatus=0
NRestarts=0

Startup integrity:

88 cross-module methods resolved OK

No Horcrux left unresolved. ๐Ÿชฆ๐Ÿ”Ž


๐ŸŒ Real post-cleanup runtime proof

The last gate was deliberately simple.

Ask the real providers a deterministic question through the real IRC commands.

๐Ÿชถ Anthropic

<Te[u]K> m ai Rรฉponds uniquement : MB699 J CLAUDE OK
<mediabotv3> MB699 J CLAUDE OK

Result:

CLAUDE_POST_CLEANUP_LIVE=PASS

๐Ÿ›ฐ๏ธ OpenAI

<Te[u]K> m tellme Rรฉponds uniquement : MB699 J OPENAI OK
<mediabotv3> MB699 J OPENAI OK

Result:

OPENAI_POST_CLEANUP_LIVE=PASS

And together:

MB699_RUNTIME_GATE=PASS

No Felix Felicis.

Just tests. ๐Ÿ€๐Ÿšซ


๐Ÿ” Secrets stayed out of the Marauderโ€™s Map

Because this work touches real AI credentials, the final candidate received a dedicated pre-commit audit.

Exactly 32 files belonged to MB699.

The audit verified:

  • exact candidate scope;
  • exact SHA256 of every validated file;
  • no accidental .env;
  • no configuration file;
  • no database dump;
  • no archive;
  • no log;
  • no MP3;
  • commit.sh still local and ignored;
  • no suspicious credential literals;
  • no accidental API token;
  • no private key material.

Gitleaks result:

no leaks found
RC_GITLEAKS=0

Final audit:

FAIL_COUNT=0
MB699_PRECOMMIT_AUDIT=PASS

The Marauderโ€™s Map shows code.

Not secrets. ๐Ÿ—บ๏ธ๐Ÿ”


๐Ÿ”ฎ And nowโ€ฆ +Wit

MB699 deliberately does not implement the future +Wit feature.

That comes next.

But it changes what +Wit can be built on.

The upcoming conversational layer will be able to use:

anthropic
openai
auto

without becoming intrinsically tied to one company or one API implementation.

The intended direction remains:

  • lightweight participation;
  • channel-local behavior;
  • language-aware replies;
  • restrained frequency;
  • safe social context;
  • explicit provider policy;
  • budget controls;
  • ability to choose NO_REPLY;
  • no privilege-bearing tools;
  • no aggressive behavior.

In other words, the goal is not to unleash Peeves with an API key. ๐Ÿ‘ป๐Ÿ”‘

The goal is something closer to a clever portrait in the common room:

sometimes useful,

sometimes funny,

and smart enough to know when to stay quiet. ๐Ÿ–ผ๏ธ๐Ÿ’ฌ๐ŸŒ™


๐Ÿ MB699 final scorecard

๐Ÿงฌ Provider-neutral AI foundation       PASS
๐Ÿฆ‰ Anthropic adapter                    PASS
๐Ÿ™ OpenAI adapter                       PASS
๐ŸŒ€ Shared asynchronous transport        PASS
๐Ÿงญ Provider-neutral AI client           PASS
๐Ÿ“จ tellme migration                     PASS
๐Ÿชถ Claude / !ai migration               PASS
๐Ÿงน Legacy transport cleanup             PASS
๐Ÿงช Targeted validation                  PASS
โšก Fast validation                      PASS
๐Ÿฐ Full regression suite                PASS
๐ŸŒ Real Anthropic runtime               PASS
๐Ÿ›ฐ๏ธ Real OpenAI runtime                  PASS
๐Ÿ” Secret audit                         PASS
๐Ÿฉบ Development service                  PASS

MB699 leaves Mediabot with one AI architecture instead of two historical tunnels.

The castle is cleaner.

The staircases finally lead somewhere predictable.

And somewhere behind the next door, +Wit is already knocking. ๐Ÿšชโœจ๐Ÿช„

You must be logged in to reply.