Skip to content

feat: shared @bragdoc/ai provider package (BYOK 1/4)#406

Open
edspencer wants to merge 3 commits into
mainfrom
byok/1-shared-ai-package
Open

feat: shared @bragdoc/ai provider package (BYOK 1/4)#406
edspencer wants to merge 3 commits into
mainfrom
byok/1-shared-ai-package

Conversation

@edspencer

Copy link
Copy Markdown
Owner

Part 1 of 4 of the BYOK stack (#405). Base: main.

Extracts the CLI's multi-provider LLM factory into a new shared packages/ai (@bragdoc/ai) package so the web app (PRs 2–3) can reuse it for per-user keys.

What's here

  • New packages/aiLLMProvider union, per-provider config interfaces, LLMConfig, DEFAULT_MODELS, PROVIDER_OPTIONS (names + signup URLs), createLLMFromConfig(), getLLMDisplayName(), isLLMConfigured(). Zod-free public surface (CLI is zod v4, web zod v3). tsc build to dist/ with declarations; published as public so the npm-published CLI can depend on it (workspace:*^0.1.0 at publish time).
  • Google provider fix — was mutating process.env.GOOGLE_GENERATIVE_AI_API_KEY (unsafe under server concurrency); now uses createGoogleGenerativeAI({ apiKey }). All providers use explicit instances; env-key fallback semantics preserved for the CLI.
  • New verifyLLMConfig(config) — tiny generateText probe with 15s timeout, returns { ok } | { ok: false, error }; used by the settings "Verify & Save" flow in PR 2.
  • CLI refactored to import from @bragdoc/ai; duplicated code deleted. config/types.ts re-exports the shared types so external consumers are unchanged. Also fixes lib/extraction.ts hard-requiring OPENAI_API_KEY even when another provider is configured.

Verification

  • pnpm build: 6/6 tasks pass (@bragdoc/ai builds before @bragdoc/cli)
  • CLI jest suite: 111 passed, 1 skipped
  • Full pnpm test: green (web: 330 passed)

Closes nothing on its own — see #405 for the full plan.

🤖 Generated with Claude Code

Introduce packages/ai (@bragdoc/ai), a shared multi-provider LLM
configuration and factory package consumed by both the CLI and (in
upcoming BYOK work) the web app. It contains the LLMProvider union,
per-provider config interfaces, LLMConfig, DEFAULT_MODELS,
PROVIDER_OPTIONS (names + signup URLs), createLLMFromConfig(),
getLLMDisplayName() and isLLMConfigured(), all moved from the CLI.
The public API is zod-free (CLI is on zod v4, web on zod v3), builds
to dist/ with declarations via tsc, and is published publicly so the
npm-published CLI can depend on it via workspace:*.

The Google provider path no longer mutates
process.env.GOOGLE_GENERATIVE_AI_API_KEY: it now uses
createGoogleGenerativeAI({ apiKey }), matching the explicit-instance
pattern already used for OpenAI, Anthropic and Ollama. This makes the
factory safe for concurrent server-side use while preserving the
config-or-environment-variable key fallback the CLI relies on.

New verifyLLMConfig(config) instantiates the configured model and runs
a tiny generateText probe (maxOutputTokens 8, 15s AbortSignal timeout),
returning { ok: true } or { ok: false, error } with a human-readable
provider error message. It never throws, so the upcoming settings
"verify & save" flow can surface failures directly.

The CLI now imports all of the above from @bragdoc/ai:
createLLMFromConfig/getLLMDisplayName take an LLMConfig (call sites
pass config.llm), config/types.ts re-exports the shared types, and the
duplicated provider/setup code is deleted. lib/extraction.ts no longer
hard-requires OPENAI_API_KEY when a different provider is configured;
missing credentials now fail at model creation with a provider-specific
message.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bragdoc-ai Ready Ready Preview, Comment Jul 7, 2026 3:14am

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Braintrust eval report

No experiments to report

edspencer and others added 2 commits July 6, 2026 23:10
The cli-test job installed dependencies only inside packages/cli, so the
new @bragdoc/ai workspace dependency was never built and its dist/ output
was missing, failing every suite that imports it. Install at the workspace
root and build the shared package first. The integration job similarly
built only the CLI package; use pnpm's dependency-inclusive filter so
workspace deps build in topological order.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keeps dist/ output fresh during turbo dev so the web app's compiled
workspace dependency never goes stale while developing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant