Skip to content

Implement Claude provider and foundation scaffold#2

Merged
ryaker merged 3 commits into
developfrom
feature/t1-claude-provider
Feb 12, 2026
Merged

Implement Claude provider and foundation scaffold#2
ryaker merged 3 commits into
developfrom
feature/t1-claude-provider

Conversation

@ryaker

@ryaker ryaker commented Feb 12, 2026

Copy link
Copy Markdown
Owner

User description

Summary

This PR implements Tier 1, Items 1–4 of the Zora WSJF Implementation Plan. It establishes the project foundation (type system, config engine, test infrastructure) and provides the first functional LLM provider implementation using the Claude Agent SDK.

Changes

1. Project Scaffolding

  • Established directory structure matching §4.3 of the spec.
  • Configured Node 20+, ESM, TypeScript 5.7, and Vitest.
  • Added essential developer tools and configurations (tsconfig.json, vitest.config.ts).

2. Core Type System (src/types.ts)

  • Implemented all v0.5 core interfaces: LLMProvider, AuthStatus, QuotaStatus, AgentEvent, TaskContext, etc.
  • Unified event stream and provider contract for all future integrations.

3. Config Engine (src/config/)

  • Implemented TOML parsing and validation using smol-toml.
  • Established default configuration values matching §7 of the spec.
  • Added deep-merge logic for user overrides.

4. Claude Provider (src/providers/claude-provider.ts)

  • Implemented ClaudeProvider backed by @anthropic-ai/claude-agent-sdk.
  • Supports Mac session token auth (no API key required).
  • Implements execute() as an AsyncGenerator<AgentEvent> for streaming.
  • Includes auth/quota error detection and abort() support.
  • Dependency-injected queryFn for clean unit testing.

5. Documentation

  • Added POLICY_PRESETS.md and WEB_ONBOARDING_SPEC.md.
  • Updated README.md and installation guides.

Testing

  • 70 passing tests across 4 suites:

    • defaults.test.ts (27): Config validation and defaults.
    • loader.test.ts (12): TOML loading and merging.
    • mock-provider.test.ts (23): Provider interface compliance.
    • claude-provider.test.ts (8): Claude-specific logic, error handling, and event mapping.
  • Clean tsc --noEmit (npm run lint).

  • Verified on macOS (darwin).

  • All tests passing

  • Linting clean

  • Documentation updated


CodeAnt-AI Description

Add Claude LLM provider, TOML config parsing, and unit tests

What Changed

  • Project foundation added (dependencies, lockfile, config defaults) so the package can be installed and run consistently.
  • New TOML config loader parses config files and strings, merges with defaults, and returns validated runtime configuration.
  • Validation now raises a ConfigError containing specific, user-facing messages for each invalid field.
  • Claude provider integrated and exported so the project can call the Claude LLM (supports Mac session token auth and streaming provider responses).
  • Unit tests added for config loading/parsing and provider behaviour to ensure configs load, defaults apply, and validation messages are produced.

Impact

✅ Can load TOML configs
✅ Clearer config validation errors
✅ Claude provider available for local Mac-session authentication

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai

codeant-ai Bot commented Feb 12, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Feb 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1-claude-provider

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @ryaker, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the essential groundwork for the Zora autonomous AI agent, focusing on establishing a robust and extensible foundation. It introduces the core TypeScript type system, a flexible TOML-based configuration engine with validation, and a comprehensive test infrastructure. Crucially, it also integrates the first functional LLM provider, Claude, demonstrating the agent's multi-provider architecture. This foundational work ensures that subsequent feature development can proceed on a stable and well-defined platform, without yet implementing the full agentic execution loop or tool functionalities.

Highlights

  • Project Scaffolding Established: The foundational project structure has been set up, including directory layout, Node.js 20+, ESM, TypeScript 5.7, and Vitest for testing. Essential developer tools and configurations like tsconfig.json and vitest.config.ts were added.
  • Core Type System Implemented: A comprehensive type system has been introduced in src/types.ts, defining core interfaces such as LLMProvider, AuthStatus, QuotaStatus, AgentEvent, TaskContext, and various configuration and policy types, unifying contracts for future integrations.
  • Config Engine Developed: A robust configuration engine has been implemented in src/config/, featuring TOML parsing and validation using smol-toml, establishment of default configuration values, and deep-merge logic for user overrides.
  • Claude Provider Integration: The first functional LLM provider, ClaudeProvider, has been integrated using the @anthropic-ai/claude-agent-sdk. It supports Mac session token authentication, implements execute() as an AsyncGenerator<AgentEvent> for streaming, and includes auth/quota error detection and abort support.
  • Extensive Test Infrastructure: A comprehensive test suite has been added, including a MockProvider for simulating LLM behavior and 70 passing tests across four suites covering config validation, TOML loading, provider interface compliance, and Claude-specific logic.
  • Documentation Updates: New documentation files (POLICY_PRESETS.md, WEB_ONBOARDING_SPEC.md) have been added, and existing ones (README.md, ONBOARDING_INSTALL.md) have been updated to reflect the new policy presets, onboarding steps, and web wizard specification.
Changelog
  • HANDOFF.md
    • Added a new handoff document detailing the project's initial foundation, including scaffolding, config system, core types, and test infrastructure.
  • PR_DESCRIPTION.md
    • Added a new, detailed pull request description outlining the foundation scaffold, type system, config engine, and test infrastructure.
  • README.md
    • Updated documentation links to include new onboarding and policy preset documents.
  • package-lock.json
    • Added a new package-lock.json file to reflect updated dependencies.
  • package.json
    • Added new dependencies including @anthropic-ai/claude-agent-sdk and smol-toml.
    • Added new development dependencies for TypeScript, tsx, and Vitest.
    • Configured build, dev, test, lint, and clean scripts.
  • specs/v5/docs/ONBOARDING_INSTALL.md
    • Updated the onboarding guide to include steps for choosing safety presets, scope selection, shell permissions, and dry-run preview.
    • Renumbered existing onboarding steps to accommodate new sections.
  • specs/v5/docs/POLICY_PRESETS.md
    • Added a new document defining 'Safe', 'Balanced', and 'Power' policy presets in TOML format.
  • specs/v5/docs/WEB_ONBOARDING_SPEC.md
    • Added a new document specifying the local web onboarding wizard's goals, architecture, UI components, data model, and security considerations.
  • src/config/defaults.ts
    • Added default configuration values for agent, routing, failover, memory, security, steering, and notifications.
    • Implemented validation functions for provider configurations and the overall Zora configuration.
  • src/config/index.ts
    • Added barrel exports for config defaults and loader modules.
  • src/config/loader.ts
    • Implemented a configuration loader with TOML parsing, deep-merge logic for defaults, and validation.
    • Introduced a custom ConfigError class for aggregated validation failures.
  • src/index.ts
    • Added the main entry point for the Zora agent, exporting core types and configuration/provider modules.
  • src/providers/claude-provider.ts
    • Implemented the ClaudeProvider class, integrating with the Claude Agent SDK.
    • Added functionality for authentication, quota status checks, event mapping from SDK messages to AgentEvents, and abort support.
    • Included heuristics for detecting auth and quota errors from SDK messages.
  • src/providers/index.ts
    • Added barrel exports for the ClaudeProvider and its related SDK types.
  • src/types.ts
    • Added core TypeScript interfaces and types for LLM providers, authentication, quota, agent events, task context, handoff bundles, audit events, and various configuration and policy structures.
  • tests/fixtures/mock-provider.ts
    • Added a mock LLM provider implementation for testing, allowing configurable behavior for availability, auth, quota, and execution flow.
  • tests/fixtures/sample-config.toml
    • Added a sample TOML configuration file for testing purposes, including agent and two provider configurations.
  • tests/fixtures/sample-policy.toml
    • Added a sample TOML policy file for testing filesystem, shell, actions, and network policies.
  • tests/unit/config/defaults.test.ts
    • Added unit tests for the default configuration values and the configuration validation functions.
  • tests/unit/config/loader.test.ts
    • Added unit tests for the configuration loader, covering file loading, string parsing, deep merging, and error handling.
  • tests/unit/providers/claude-provider.test.ts
    • Added unit tests for the ClaudeProvider, verifying SDK message mapping, error handling, and abort functionality.
  • tests/unit/providers/mock-provider.test.ts
    • Added unit tests for the MockProvider fixture, verifying its configurable behavior and interface compliance.
  • tsconfig.json
    • Added a TypeScript configuration file, setting up strict compilation, ESNext module resolution, and path aliases.
  • vitest.config.ts
    • Added a Vitest configuration file for testing, including global settings, coverage reporting, and path aliases.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Feb 12, 2026
@codeant-ai

codeant-ai Bot commented Feb 12, 2026

Copy link
Copy Markdown

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Loose assumptions about optional fields
    Several validations assume nested fields exist (e.g., config.agent.resources, config.routing.provider_only_name) without defensive checks. If the config object is partially populated, these accesses could produce misleading validation results or hide the root missing-field errors.

  • Provider capability types
    validateProviderConfig only ensures capabilities is a non-empty array but doesn't validate that each element is a string (or non-empty string). Non-string capability values could slip through and later cause runtime failures when capabilities are used.

  • Duplicate detection false positives
    Duplicate name/rank detection maps raw values directly (including undefined). If providers are missing name, rank, or enabled properties (or have them undefined), the duplicate-check logic can produce misleading duplicate errors (e.g. multiple undefined ranks/names).

  • Prototype pollution risk
    deepMerge iterates keys from parsed user input and assigns them into result without filtering special keys like 'proto' or 'constructor'. When merging untrusted TOML content this can allow prototype pollution and unexpected behavior. Add guards to skip dangerous keys.

  • Unsafe TOML result
    The code unconditionally casts the result of parseTOML(...) to Record<string, unknown> and assumes it's an object. If the parsed value is null, a primitive, or an array the code will continue and may produce runtime errors or invalid config objects. Validate the parsed root before using it.

  • Provider merging
    Provider array handling overrides config.providers only when raw['providers'] is present, and populates each provider with ad-hoc defaults (empty strings, 0, etc). This can lead to subtle invalid provider shapes and duplicates/conflicts with DEFAULT_CONFIG.providers. Consider merging per-provider defaults from DEFAULT_CONFIG and ensuring types/coercion are enforced.

@codeant-ai

codeant-ai Bot commented Feb 12, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This is an impressive foundational PR. It establishes a solid, well-architected base for the Zora project. The use of TypeScript with strict settings, dependency injection for testability, a clear type system, and a robust configuration engine are all excellent choices. The Claude provider implementation is particularly well-designed with its lazy-loading of the SDK and resilient error handling. The test coverage for the new components is also very thorough. I have a few suggestions for minor improvements regarding documentation consistency, algorithmic efficiency in one of the validation functions, a small refactoring in the Claude provider, and an incomplete test case. Overall, this is a high-quality submission that sets the project up for success.

Comment thread PR_DESCRIPTION.md
## Foundation scaffold: type system, config engine, and test infrastructure

> Tier 1, Items 1–3 of the [WSJF Implementation Plan](specs/v5/IMPLEMENTATION_PLAN.md)
> 35 files changed · 3,630 insertions · 62 tests passing · clean `tsc --noEmit`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

There are a couple of minor inconsistencies in the statistics mentioned here and in other documentation files:

  • This file states "62 tests passing", while the main PR body mentions "70 passing tests".
  • The toolchain is described as using "TypeScript 5.7", but package.json specifies ^5.7.0 and package-lock.json has resolved this to version 5.9.3.

Aligning these details across the documentation would improve clarity and prevent confusion.

Comment thread src/config/defaults.ts
Comment on lines +168 to +172
const names = config.providers.map((p) => p.name);
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
if (dupes.length > 0) {
errors.push(`Duplicate provider names: ${[...new Set(dupes)].join(', ')}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current implementation for finding duplicate provider names uses filter with indexOf, which has a time complexity of O(n²). While this is fine for a small number of providers, a more efficient O(n) approach using a Set would be more scalable and is generally better practice. The same applies to the duplicate rank check on lines 175-179.

A suggested refactoring for finding duplicate names:

const seenNames = new Set<string>();
const duplicateNames = new Set<string>();
for (const provider of config.providers) {
  if (seenNames.has(provider.name)) {
    duplicateNames.add(provider.name);
  } else {
    seenNames.add(provider.name);
  }
}
if (duplicateNames.size > 0) {
  errors.push(`Duplicate provider names: ${[...duplicateNames].join(', ')}`);
}

Comment on lines +170 to +176
if (options.queryFn) {
this._queryFn = options.queryFn;
} else {
// Lazy import to avoid requiring the SDK at construction time
// This will be resolved at first execute() call
this._queryFn = null as unknown as QueryFn;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The lazy initialization of _queryFn can be simplified to avoid type assertions and as any. By changing the property declaration on line 138 to private _queryFn: QueryFn | null;, you can simplify the constructor logic and the _resolveQueryFn method for better type safety and readability.

    this._queryFn = options.queryFn ?? null;

Comment on lines +244 to +263
it('aborts an active query', async () => {
const mockQuery = new MockSDKQuery([]);
const queryFn = vi.fn(() => mockQuery);
const provider = new ClaudeProvider({ config, queryFn });

const task = makeTask({ jobId: 'job-to-abort' });

// Start execution but don't await completion yet
const iterator = provider.execute(task);
const firstEventPromise = iterator.next();

await provider.abort('job-to-abort');

const result = await firstEventPromise;
expect(result.done).toBe(false); // Should have yielded 'done' or 'error' in finally block

// In our implementation, finally block yields 'done' or similar if not aborted?
// Wait, execute() yields done after loop.
// If we abort, the SDK query should stop yielding.
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This test case for aborting a query appears to be incomplete. It calls provider.abort() but doesn't have any assertions to verify that the query was actually aborted or that the execute generator behaved as expected after the abort signal. It would be great to complete this test to ensure the abort functionality works correctly. For example, you could assert that the abort method on the mock query was called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants