Intent ergonomics overhaul: unified API, explainable outputs, and smarter Groq defaults - #4
Conversation
This refactors the public API from Reranker to Intent, consolidating context, extractors, and config into a single optional constructor options object. Notable changes: - Renamed core class/files/tests from reranker -> intent, and rerank() -> rank(). - Added default key/summary extractors (hash-based key + pretty JSON summary) and centralized JSON stringification helpers. - Adjusted config naming/usage to preserve UPPER_SNAKE_CASE env-backed CONFIG while exposing camelCase options. - Improved Groq provider testability by injecting an SDK factory, removing module-level mocking and enabling deterministic unit tests. - Updated schema/message building and tests accordingly; removed obsolete groq-default reranker test and added intent equivalent. Edge cases/behavior: - Preserves stable ordering on ties and returns original order on errors. - Validates relevancyThreshold is within 0–10 and errors early. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Problem - Groq occasionally returns output that is either invalid JSON or fails server-side json_schema validation (json_validate_failed), which currently bubbles up as a hard failure. Solution - Add configurable JSON repair retries to the Groq LlmClient. - On JSON.parse failure, capture the raw model output and append a repair turn (assistant raw output + user instruction with the parse error) and retry. - On json_validate_failed, attempt to extract the rejected generation from multiple groq-sdk error shapes (structured payloads and message-embedded payloads), then append a repair turn and retry. Configuration - Introduces GROQ_JSON_REPAIR_ATTEMPTS (default: 3, min: 0) and an override option jsonRepairAttempts on createDefaultGroqClient. Tests - Expands unit coverage to exercise parse + validation repair paths and error-shape parsing. - Adds an integration test that demonstrates repairing a schema-validation failure. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Change LLM response contract from Record<string, number> to Record<string, { explanation: string; score: number }> and update prompt/schema accordingly.
- Add rank(..., { explain: true }) overload returning { item, explanation }[]; default remains T[].
- Preserve existing safety behavior: stable sorting on ties; batch-level and top-level fallbacks return original order (with blank explanations when explain is enabled).
- Add unit + Groq integration test coverage, including schema property ordering (explanation before score) to encourage models to emit explanations first.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Add min/max score configuration (options + INTENT_MIN_SCORE/INTENT_MAX_SCORE) and validate threshold against the configured range. - Update prompts and schema generation to use the configured range; clamp returned scores to the range. - Remove JSON Schema minimum/maximum constraints on score for broader structured-output compatibility. - Stabilize Groq integration by increasing LLM call timeout and test timeout for the relevance sanity check. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add a broad set of unmocked integration tests for Intent that exercise production wire paths against the configured Groq provider. Coverage includes: - obvious-match ranking - threshold behavior for all-unrelated inputs - stable ordering for ties/near-ties (when all items are returned) - explain=true output shape and non-empty explanations - custom extractors for nested objects - unicode keys/summaries and punctuation/newline keys - batching behavior and larger stress case across multiple batches - per-call userId override Also refresh the Groq provider relevance sanity test candidates to reduce accidental topical overlap. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Introduce INTENT_PROVIDER (enum; currently only GROQ) and remove INTENT_MODEL. - Add enumString() config helper for validated enum env vars. - Make Intent provider-driven and source the model from GROQ defaults when provider=GROQ. - Update types and unit tests to cover provider parsing and model resolution. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add real-wire integration coverage for the simplest usage pattern (new Intent()) using primitive string items, validating that default extractors and provider wiring work end-to-end without any configuration. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Rename Intent integration tests to be clearer, more user-facing examples while keeping behavior unchanged. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add two new high-level Intent operations alongside rank(): - filter(query, candidates): boolean relevancy decisions per candidate; returns only relevant items while preserving input order, with optional per-item explanations. - choice(query, candidates): always returns exactly one winner; uses an enum-based selectedKey schema and a batched tournament strategy for large inputs, with optional explanation. Implementation includes new schema builders and prompt/message builders for the two operations, plus comprehensive unit coverage (100%) and stricter, deterministic real-wire integration assertions for rank/filter/choice behavior.
Replace the temperature-based tuning surface with Groq's reasoning_effort control to better match reasoning-style models. - Add GROQ_DEFAULT_REASONING_EFFORT (low|medium|high, default: medium) and remove GROQ_DEFAULT_TEMPERATURE - Update LlmCallConfig to accept reasoningEffort and plumb it through Intent + selectLlmClient - Update Groq provider request building to send reasoning_effort (while preserving strict JSON schema response_format) - Update unit/integration tests for config parsing and request shape changes Backwards compatibility is intentionally not preserved.
Update README to emphasize choice API, add a concise Quickstart example, and clarify configuration/performance knobs (relevancy threshold behavior, min/max score range, timeout, batching). Add an integration test that validates the README Quickstart example output. Refine system prompts for rank and choice to produce end-user-facing explanations (avoid prompt mechanics and first-person language).
Rename the npm package to the @with-logic scope and update README examples to import from the scoped name. Also set publishConfig.access=public so scoped publishes default to public access. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
|
Claude finished @stevekrenzel's task —— View job PR Review: Intent Ergonomics Overhaul ✅Comprehensive code review completed against Intent library engineering standards. Executive SummaryThis is a high-quality PR that delivers substantial improvements to the Intent library. The architectural changes are sound, documentation is comprehensive, and the code demonstrates strong engineering discipline. Tests pass with 100% coverage, and both linting and type checking succeed. However, there is one critical code style violation that must be addressed: several instances of single-line Critical Issues (Must Fix)1. Missing Braces on Single-Line If StatementsLocation: The code uses single-line // ❌ Current code (src/intent.ts:616)
if (data == null || typeof data !== "object") return null;
// ✅ Required style
if (data == null || typeof data !== "object") {
return null;
}Affected lines in intent.ts:
Affected lines in groq.ts:
Why this matters: The coding standards explicitly require braces on all if statements for consistency, readability, and to prevent future bugs when someone adds a second line without noticing the missing braces. The examples in CLAUDE.md show each brace on its own line. Code Quality Strengths✅ Excellent Function SizesAll functions are under 30 lines in the core implementation files (intent.ts, groq.ts, extractors.ts). This exceeds the target and demonstrates excellent code organization through small, focused functions. ✅ Comprehensive DocumentationEvery function has proper JSDoc with:
The documentation quality is exemplary, especially in ✅ Strong TypeScript Type Safety
✅ Excellent Error Handling
✅ Early Returns and Minimal NestingThe code consistently uses early returns for fast paths:
✅ 100% Test CoverageAll unit tests pass with complete statement, branch, function, and line coverage. Integration tests provide additional real-world validation with 165 tests passing. Architecture ReviewAPI Design: ExcellentThe refactoring from Particularly well-designed:
Provider Architecture: SolidThe Groq provider improvements are substantial:
Configuration System: ClearThe Minor Observations (Non-Blocking)File SizesTwo files exceed the 300-line guideline:
While these exceed the <300 line guideline, both files remain highly cohesive:
Recommendation: Accept as-is. Both files maintain single, clear purposes despite their length. Naming ClarityGenerally excellent, but one minor suggestion:
This is a nitpick and non-blocking. Test OrganizationTest files are well-structured with:
Summary and RecommendationsOverall Assessment: Strong PR with high code quality, comprehensive tests, and sound architecture. The refactoring from Must address before merge:
After addressing the bracing issue, this PR will be ready to merge. The bracing fix is straightforward and mechanical - no design changes needed. Final Checklist Against Requirements
Score: 11/12 - Excellent work! Just needs the bracing fix to meet 100% of the coding standards. |
Summary
This PR renames and consolidates the core reranking API around a single
Intentclass, adds higher-level helpers (filter()andchoice()), and introduces optionalper-item explanations for more transparent results. It also improves Groq provider behavior (reasoning effort + guided retries to repair invalid JSON), expands
configuration/provider selection, and significantly strengthens test coverage (unit + real-wire integration).
Key Changes
Reranker→Intentand unify constructor configuration into a single options object.filter()(relevancy subset) andchoice()(pick exactly one).minScore/maxScore) and relax schema constraints accordingly.INTENT_MODEL-style config with explicit provider selection + clearer defaults.reasoningEffort.@with-logic/intentand align prompts/naming references.Notes / Breaking Changes
Rerankeris removed in favor ofIntent(constructor shape and method names updated accordingly).temperature→reasoningEffort(Groq path).